diff --git a/.changelog/791.txt b/.changelog/791.txt new file mode 100644 index 000000000..03fa3f077 --- /dev/null +++ b/.changelog/791.txt @@ -0,0 +1,11 @@ +```release-note:breaking-change +Removed `hcp_packer_iteration` data source, previously deprecated and replaced by `hcp_packer_version` in [v0.82.0](https://github.com/hashicorp/terraform-provider-hcp/releases/tag/v0.82.0). +``` + +```release-note:breaking-change +Removed `hcp_packer_image` data source, previously deprecated and replaced by `hcp_packer_artifact` in [v0.82.0](https://github.com/hashicorp/terraform-provider-hcp/releases/tag/v0.82.0). +``` + +```release-note:breaking-change +Removed `iteration_fingerprint` attribute from `hcp_packer_channel_assignment` resource, previously deprecated and replaced by `version_fingerprint` in [v0.82.0](https://github.com/hashicorp/terraform-provider-hcp/releases/tag/v0.82.0). +``` \ No newline at end of file diff --git a/docs/data-sources/packer_image.md b/docs/data-sources/packer_image.md deleted file mode 100644 index fe114bb95..000000000 --- a/docs/data-sources/packer_image.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -page_title: "Data Source hcp_packer_image - terraform-provider-hcp" -subcategory: "HCP Packer" -description: |- - The Packer Image data source gets an image associated with an iteration, either from a specific iteration or from the iteration assigned to a given Channel. ---- - -# hcp_packer_image (Data Source) - -The Packer Image data source gets an image associated with an iteration, either from a specific iteration or from the iteration assigned to a given Channel. - -~> **Deprecated:** This data source is deprecated and will be removed in a future release. Please use the [`hcp_packer_artifact`](./packer_artifact) data source instead. - - -## Schema - -### Required - -- `bucket_name` (String) The slug of the HCP Packer Registry bucket where this image is located. -- `cloud_provider` (String) Name of the cloud provider where this image is stored. -- `region` (String) The Region where this image is stored, if any. - -### 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. -- `project_id` (String) The ID of the HCP project where the HCP Packer Registry image is located. -If not specified, the project specified in the HCP Provider config block will be used, if configured. -If a project is not configured in the HCP Provider config block, the oldest project in the organization will be used. -- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) - -### Read-Only - -- `build_id` (String) HCP ID of the build containing this image. -- `cloud_image_id` (String) Cloud Image ID or URL string identifying this image for the builder that built it. -- `created_at` (String) Creation time of this image. -- `id` (String) The ID of this resource. -- `labels` (Map of String) Labels associated with the build containing this image. -- `organization_id` (String) The ID of the organization where this image is located. -- `packer_run_uuid` (String) UUID of the build containing this image. -- `revoke_at` (String) The revocation time of the iteration containing this image. This field will be null for any iteration that has not been revoked or scheduled for revocation. - - -### Nested Schema for `timeouts` - -Optional: - -- `default` (String) diff --git a/docs/data-sources/packer_iteration.md b/docs/data-sources/packer_iteration.md deleted file mode 100644 index e41d665fb..000000000 --- a/docs/data-sources/packer_iteration.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -page_title: "hcp_packer_iteration Data Source - terraform-provider-hcp" -subcategory: "HCP Packer" -description: |- - The Packer Image data source iteration gets the most recent iteration (or build) of an image, given a channel. ---- - -# hcp_packer_iteration (Data Source) - -The Packer Image data source iteration gets the most recent iteration (or build) of an image, given a channel. - -~> **Deprecated:** This data source is deprecated and will be removed in a future release. Please use the [`hcp_packer_version`](./packer_version) data source instead. - - -## Schema - -### Required - -- `bucket_name` (String) The slug of the HCP Packer Registry bucket to pull from. -- `channel` (String) The channel that points to the version of the image you want. - -### Optional - -- `project_id` (String) The ID of the HCP project where the HCP Packer Registry is located. -If not specified, the project specified in the HCP Provider config block will be used, if configured. -If a project is not configured in the HCP Provider config block, the oldest project in the organization will be used. -- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) - -### Read-Only - -- `author_id` (String) The name of the person who created this iteration. -- `created_at` (String) Creation time of this iteration -- `fingerprint` (String) The unique fingerprint associated with this iteration; often a git sha. -- `id` (String) The ID of this resource. -- `organization_id` (String) The ID of the organization this HCP Packer registry is located in. -- `revoke_at` (String) The revocation time of this iteration. This field will be null for any iteration that has not been revoked or scheduled for revocation. -- `ulid` (String) The ULID of this iteration. -- `updated_at` (String) Time this build was last updated. - - -### Nested Schema for `timeouts` - -Optional: - -- `default` (String) diff --git a/docs/resources/packer_channel_assignment.md b/docs/resources/packer_channel_assignment.md index 8415f16c0..ee79eae54 100644 --- a/docs/resources/packer_channel_assignment.md +++ b/docs/resources/packer_channel_assignment.md @@ -36,7 +36,6 @@ resource "hcp_packer_channel_assignment" "staging" { ### Optional -- `iteration_fingerprint` (String, Deprecated) The fingerprint of the version assigned to the channel. - `project_id` (String) The ID of the HCP project where the channel is located. If not specified, the project specified in the HCP Provider config block will be used, if configured. If a project is not configured in the HCP Provider config block, the oldest project in the organization will be used. diff --git a/internal/clients/packerv1/packer.go b/internal/clients/packerv1/packer.go deleted file mode 100644 index 7d25d8ee4..000000000 --- a/internal/clients/packerv1/packer.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package packerv1 - -import ( - "context" - "errors" - "fmt" - - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service" - packermodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - sharedmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models" - "github.com/hashicorp/terraform-provider-hcp/internal/clients" -) - -// GetPackerChannelBySlug queries the HCP Packer registry for the channel -// associated with the given channel name. -func GetPackerChannelBySlug(ctx context.Context, client *clients.Client, loc *sharedmodels.HashicorpCloudLocationLocation, - bucketName string, channelName string) (*packermodels.HashicorpCloudPackerChannel, error) { - - getParams := packer_service.NewPackerServiceGetChannelParamsWithContext(ctx) - getParams.BucketSlug = bucketName - getParams.Slug = channelName - getParams.LocationOrganizationID = loc.OrganizationID - getParams.LocationProjectID = loc.ProjectID - - getResp, err := client.Packer.PackerServiceGetChannel(getParams, nil) - if err != nil { - if err, ok := err.(*packer_service.PackerServiceGetChannelDefault); ok { - return nil, errors.New(err.Payload.Message) - } - return nil, fmt.Errorf("unexpected error format received by GetPackerChannelBySlug. Got: %v", err) - } - - return getResp.Payload.Channel, nil -} - -// GetIterationFromID queries the HCP Packer registry for an existing bucket iteration using its ULID. -func GetIterationFromID(ctx context.Context, client *clients.Client, loc *sharedmodels.HashicorpCloudLocationLocation, - bucketSlug string, iterationID string) (*packermodels.HashicorpCloudPackerIteration, error) { - params := newGetIterationParams(ctx, loc, bucketSlug) - params.IterationID = &iterationID - return getIteration(client, params) -} - -// GetIterationFromFingerprint queries the HCP Packer registry for an existing bucket iteration using its fingerprint. -func GetIterationFromFingerprint(ctx context.Context, client *clients.Client, loc *sharedmodels.HashicorpCloudLocationLocation, - bucketSlug string, iterationFingerprint string) (*packermodels.HashicorpCloudPackerIteration, error) { - params := newGetIterationParams(ctx, loc, bucketSlug) - params.Fingerprint = &iterationFingerprint - return getIteration(client, params) -} - -func newGetIterationParams(ctx context.Context, loc *sharedmodels.HashicorpCloudLocationLocation, - bucketslug string) *packer_service.PackerServiceGetIterationParams { - params := packer_service.NewPackerServiceGetIterationParamsWithContext(ctx) - params.LocationOrganizationID = loc.OrganizationID - params.LocationProjectID = loc.ProjectID - params.BucketSlug = bucketslug - return params -} - -func getIteration(client *clients.Client, params *packer_service.PackerServiceGetIterationParams) (*packermodels.HashicorpCloudPackerIteration, error) { - it, err := client.Packer.PackerServiceGetIteration(params, nil) - if err != nil { - if err, ok := err.(*packer_service.PackerServiceGetIterationDefault); ok { - return nil, errors.New(err.Payload.Message) - } - return nil, fmt.Errorf("unexpected error format received by getIteration. Got: %v", err) - } - - return it.Payload.Iteration, nil -} diff --git a/internal/provider/packer/testutils/configbuilder/builder.go b/internal/provider/packer/testutils/configbuilder/builder.go index 0c57adc2d..c4e2d87cf 100644 --- a/internal/provider/packer/testutils/configbuilder/builder.go +++ b/internal/provider/packer/testutils/configbuilder/builder.go @@ -94,7 +94,7 @@ type HasBlockName interface { // // Example: // `hcp_packer_channel.prod` (a resource) or - // `data.hcp_packer_iteration.latest` (a data source) + // `data.hcp_packer_version.latest` (a data source) BlockName() string } diff --git a/internal/providersdkv2/data_source_packer_bucket_names.go b/internal/providersdkv2/data_source_packer_bucket_names.go index 0ace48012..480b0ec7d 100644 --- a/internal/providersdkv2/data_source_packer_bucket_names.go +++ b/internal/providersdkv2/data_source_packer_bucket_names.go @@ -6,6 +6,7 @@ package providersdkv2 import ( "context" "log" + "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -14,6 +15,8 @@ import ( "github.com/hashicorp/terraform-provider-hcp/internal/clients/packerv2" ) +var defaultPackerTimeout = time.Minute + func dataSourcePackerBucketNames() *schema.Resource { return &schema.Resource{ Description: "The Packer Bucket Names data source gets the names of all of the buckets in a single HCP Packer registry.", diff --git a/internal/providersdkv2/data_source_packer_image.go b/internal/providersdkv2/data_source_packer_image.go deleted file mode 100644 index b79db8143..000000000 --- a/internal/providersdkv2/data_source_packer_image.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package providersdkv2 - -import ( - "context" - "log" - "time" - - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/hashicorp/terraform-provider-hcp/internal/clients" - "github.com/hashicorp/terraform-provider-hcp/internal/clients/packerv1" - "golang.org/x/exp/slices" -) - -var defaultPackerTimeout = time.Minute - -func dataSourcePackerImage() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "This data source has been deprecated. Use the new `hcp_packer_artifact` data source instead.", - Description: "The Packer Image data source gets an image associated with an iteration, either from a specific iteration or from the iteration assigned to a given Channel.", - ReadContext: dataSourcePackerImageRead, - Timeouts: &schema.ResourceTimeout{ - Default: &defaultPackerTimeout, - }, - Schema: map[string]*schema.Schema{ - // Required inputs - "bucket_name": { - Description: "The slug of the HCP Packer Registry bucket where this image is located.", - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: validateSlugID, - }, - "cloud_provider": { - Description: "Name of the cloud provider where this image is stored.", - Type: schema.TypeString, - Required: true, - }, - "region": { - Description: "The Region where this image is stored, if any.", - Type: schema.TypeString, - Required: true, - }, - // Optional inputs - "project_id": { - Description: ` -The ID of the HCP project where the HCP Packer Registry image is located. -If not specified, the project specified in the HCP Provider config block will be used, if configured. -If a project is not configured in the HCP Provider config block, the oldest project in the organization will be used.`, - Type: schema.TypeString, - Computed: true, - Optional: true, - ValidateFunc: validation.IsUUID, - }, - "iteration_id": { - Description: "The iteration from which to get the image. Either this or `channel` must be specified.", - Type: schema.TypeString, - Optional: true, - Computed: true, - ExactlyOneOf: []string{"iteration_id", "channel"}, - }, - "channel": { - Description: "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", - Type: schema.TypeString, - Optional: true, - ExactlyOneOf: []string{"iteration_id", "channel"}, - }, - "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 where this image is located.", - Type: schema.TypeString, - Computed: true, - }, - "created_at": { - Description: "Creation time of this image.", - Type: schema.TypeString, - Computed: true, - }, - "build_id": { - Description: "HCP ID of the build containing this image.", - Type: schema.TypeString, - Computed: true, - }, - "cloud_image_id": { - Description: "Cloud Image ID or URL string identifying this image for the builder that built it.", - Type: schema.TypeString, - Computed: true, - }, - "packer_run_uuid": { - Description: "UUID of the build containing this image.", - Type: schema.TypeString, - Computed: true, - }, - "labels": { - Description: "Labels associated with the build containing this image.", - Type: schema.TypeMap, - Computed: true, - }, - "revoke_at": { - Description: "The revocation time of the iteration containing this image. This field will be null for any iteration that has not been revoked or scheduled for revocation.", - Type: schema.TypeString, - Computed: true, - }, - }, - } -} - -func dataSourcePackerImageRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*clients.Client) - loc, err := getAndUpdateLocationResourceData(d, client) - if err != nil { - return diag.FromErr(err) - } - - bucketName := d.Get("bucket_name").(string) - channelSlug := d.Get("channel").(string) - iterationID := d.Get("iteration_id").(string) - componentType := d.Get("component_type").(string) - cloudProvider := d.Get("cloud_provider").(string) - region := d.Get("region").(string) - - log.Printf("[INFO] Reading HCP Packer registry (%s) [project_id=%s, organization_id=%s, channel=%s/iteration_id=%s]", bucketName, loc.ProjectID, loc.OrganizationID, channelSlug, iterationID) - - var iteration *models.HashicorpCloudPackerIteration - - if iterationID != "" { - iteration, err = packerv1.GetIterationFromID( - ctx, - client, - loc, - bucketName, - iterationID, - ) - if err != nil { - return diag.FromErr(err) - } - } - - if channelSlug != "" { - channel, err := packerv1.GetPackerChannelBySlug( - ctx, - client, - loc, - bucketName, - channelSlug, - ) - if err != nil { - return diag.FromErr(err) - } - if channel.Iteration == nil { - return diag.Errorf("Channel does not have an assigned iteration (channel: %s)", channelSlug) - } - iteration = channel.Iteration - } - - var build *models.HashicorpCloudPackerBuild - var image *models.HashicorpCloudPackerImage - for _, b := range iteration.Builds { - if b.CloudProvider != cloudProvider { - continue - } - if componentType != "" && b.ComponentType != componentType { - continue - } - index := slices.IndexFunc( - b.Images, - func(image *models.HashicorpCloudPackerImage) bool { - return image.Region == region - }, - ) - if index >= 0 { - build = b - image = b.Images[index] - break - } - } - if build == nil || image == nil { - return diag.Errorf("Could not find image with attributes (region: %q cloud: %q, iteration: %q, component_type: %q).", region, cloudProvider, iterationID, componentType) - } - - d.SetId(image.ID) - if err := d.Set("component_type", build.ComponentType); err != nil { - return diag.FromErr(err) - } - if err := d.Set("created_at", image.CreatedAt.String()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("build_id", build.ID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("cloud_image_id", image.ImageID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("iteration_id", iteration.ID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("packer_run_uuid", build.PackerRunUUID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("labels", build.Labels); err != nil { - return diag.FromErr(err) - } - if !iteration.RevokeAt.IsZero() { - if err := d.Set("revoke_at", iteration.RevokeAt.String()); err != nil { - return diag.FromErr(err) - } - } - - return nil -} diff --git a/internal/providersdkv2/data_source_packer_image_test.go b/internal/providersdkv2/data_source_packer_image_test.go deleted file mode 100644 index 51cd40e37..000000000 --- a/internal/providersdkv2/data_source_packer_image_test.go +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package providersdkv2 - -import ( - "fmt" - "regexp" - "testing" - "time" - - "github.com/go-openapi/strfmt" - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" -) - -func TestAcc_dataSourcePackerImage_Simple(t *testing.T) { - bucketSlug := testAccCreateSlug("ImageSimple") - channelSlug := bucketSlug // No need for a different slug - - buildOptions := buildOptions{ - cloudProvider: "aws", - componentType: "amazon-ebs.example", - images: []*models.HashicorpCloudPackerImageCreateBody{ - { - ImageID: "image1", - Region: "us-east-1", - }, - { - ImageID: "image1", - Region: "us-west-1", - }, - }, - labels: map[string]string{"test123": "test456"}, - } - region := buildOptions.images[0].Region - - imageConfig := testAccPackerDataImageBuilder( - "simple", - fmt.Sprintf("%q", bucketSlug), - fmt.Sprintf("%q", channelSlug), - ``, - fmt.Sprintf("%q", buildOptions.cloudProvider), - fmt.Sprintf("%q", region), - fmt.Sprintf("%q", buildOptions.componentType), - ) - errorImageConfig := testAccPackerDataImageBuilderFromImage( - "error", imageConfig, - fmt.Sprintf("%q", buildOptions.cloudProvider), - fmt.Sprintf("%q", region), - fmt.Sprintf("%q", "NotRealComponentType"), - ) - - var iteration *models.HashicorpCloudPackerIteration - var build *models.HashicorpCloudPackerBuild - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - iteration, build = upsertCompleteIteration(t, bucketSlug, "1234", &buildOptions) - upsertChannel(t, bucketSlug, channelSlug, iteration.ID) - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { - Config: testConfig(testAccConfigBuildersToString(imageConfig)), - Check: testAccCheckPackerImageState(t, imageConfig.BlockName(), bucketSlug, &iteration, &build, region), - }, - { - // Test that references to `revoked_at` don't error when the - // the iteration is not revoked or scheduled for revocation. - // - // Checked in this manner because you cant check for attributes - // set to empty strings with `resource.TestCheckResourceAttr` - Config: testConfig(testAccConfigBuildersToString( - imageConfig, - testAccOutputBuilder("revoke_at", imageConfig.AttributeRef("revoke_at")), - )), - }, - { // Testing that filtering non-existent image fails properly - PlanOnly: true, - Config: testConfig(testAccConfigBuildersToString(errorImageConfig)), - ExpectError: regexp.MustCompile("Could not find image"), - }, - }, - }) -} - -func TestAcc_dataSourcePackerImage_IterationID(t *testing.T) { - bucketSlug := testAccCreateSlug("ImageFromIterationId") - channelSlug := bucketSlug // No need for a different slug - - buildOptions := defaultBuildOptions - region := buildOptions.images[0].Region - - iterationConfig := testAccPackerDataIterationBuilder( - "iteration", - fmt.Sprintf("%q", bucketSlug), - fmt.Sprintf("%q", channelSlug), - ) - imageConfig := testAccPackerDataImageBuilderWithIterationReference( - "from_iteration_id", - iterationConfig, - fmt.Sprintf("%q", buildOptions.cloudProvider), - fmt.Sprintf("%q", region), - fmt.Sprintf("%q", buildOptions.componentType), - ) - - var iteration *models.HashicorpCloudPackerIteration - var build *models.HashicorpCloudPackerBuild - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - iteration, build = upsertCompleteIteration(t, bucketSlug, "1234", &buildOptions) - upsertChannel(t, bucketSlug, channelSlug, iteration.ID) - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { - // Check that everything works when using `iteration_id` since - // the simple test uses `channel` to avoid having a data source - Config: testConfig(testAccConfigBuildersToString(iterationConfig, imageConfig)), - Check: testAccCheckPackerImageState(t, imageConfig.BlockName(), bucketSlug, &iteration, &build, region), - }, - }, - }) -} - -func TestAcc_dataSourcePackerImage_revokedIteration(t *testing.T) { - bucketSlug := testAccCreateSlug("ImageRevoked") - channelSlug := bucketSlug // No need for a different slug - - revokeAt := strfmt.DateTime(time.Now().UTC().Add(24 * time.Hour)) - - buildOptions := defaultBuildOptions - region := buildOptions.images[0].Region - config := testAccPackerDataImageBuilder( - "revoked", - fmt.Sprintf("%q", bucketSlug), - fmt.Sprintf("%q", channelSlug), - ``, - fmt.Sprintf("%q", buildOptions.cloudProvider), - fmt.Sprintf("%q", region), - fmt.Sprintf("%q", buildOptions.componentType), - ) - - var iteration *models.HashicorpCloudPackerIteration - var build *models.HashicorpCloudPackerBuild - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - iteration, build = upsertCompleteIteration(t, bucketSlug, "1234", &buildOptions) - upsertChannel(t, bucketSlug, channelSlug, iteration.ID) - revokeIteration(t, iteration.ID, bucketSlug, revokeAt) - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { - Config: testConfig(testAccConfigBuildersToString(config)), - Check: resource.ComposeTestCheckFunc( - testAccCheckPackerImageState(t, config.BlockName(), bucketSlug, &iteration, &build, region), - resource.TestCheckResourceAttr(config.BlockName(), "revoke_at", revokeAt.String()), - ), - }, - }, - }) -} - -func TestAcc_dataSourcePackerImage_emptyChannel(t *testing.T) { - bucketSlug := testAccCreateSlug("ImageEmptyChannel") - channelSlug := bucketSlug // No need for a different slug - - config := testAccPackerDataImageBuilder( - "empty_channel", - fmt.Sprintf("%q", bucketSlug), - fmt.Sprintf("%q", channelSlug), - ``, - fmt.Sprintf("%q", "someProvider"), - fmt.Sprintf("%q", "someRegion"), - ``, - ) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - upsertChannel(t, bucketSlug, channelSlug, "") - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { - Config: testConfig(testAccConfigBuildersToString(config)), - ExpectError: regexp.MustCompile(`.*Channel does not have an assigned iteration.*`), - }, - { // Create a dummy non-empty state so that `CheckDestroy` will run. - Config: testAccConfigDummyNonemptyState, - }, - }, - }) -} - -func TestAcc_dataSourcePackerImage_channelAndIterationIDReject(t *testing.T) { - config := testAccPackerDataImageBuilder( - "invalid_args", - fmt.Sprintf("%q", "someBucketSlug"), - fmt.Sprintf("%q", "someChannelSlug"), - fmt.Sprintf("%q", "someIterationID"), - fmt.Sprintf("%q", "someProvider"), - fmt.Sprintf("%q", "someRegion"), - ``, - ) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testConfig(testAccConfigBuildersToString(config)), - ExpectError: regexp.MustCompile("Error: Invalid combination of arguments"), - }, - }, - }) -} - -func testAccPackerDataImageBuilder(uniqueName, bucketName, - channelName, iterationID, - cloudProvider, region, componentType string) testAccConfigBuilderInterface { - - return &testAccResourceConfigBuilder{ - isData: true, - resourceType: "hcp_packer_image", - uniqueName: uniqueName, - attributes: map[string]string{ - "bucket_name": bucketName, - "channel": channelName, - "iteration_id": iterationID, - "cloud_provider": cloudProvider, - "region": region, - "component_type": componentType, - }, - } -} - -func testAccPackerDataImageBuilderWithIterationReference(uniqueName string, iteration testAccConfigBuilderInterface, - cloudProvider, region, componentType string) testAccConfigBuilderInterface { - - return testAccPackerDataImageBuilder( - uniqueName, - iteration.AttributeRef("bucket_name"), - ``, - iteration.AttributeRef("ulid"), - cloudProvider, - region, - componentType, - ) -} - -func testAccPackerDataImageBuilderFromImage(uniqueName string, image testAccConfigBuilderInterface, - cloudProvider, region, componentType string) testAccConfigBuilderInterface { - - return testAccPackerDataImageBuilder( - uniqueName, - image.Attributes()["bucket_name"], - image.Attributes()["channel"], - image.Attributes()["iteration_id"], - cloudProvider, - region, - componentType, - ) -} - -func testAccCheckPackerImageState(t *testing.T, resourceName, bucketName string, iterationPtr **models.HashicorpCloudPackerIteration, - buildPtr **models.HashicorpCloudPackerBuild, region string) resource.TestCheckFunc { - - return func(state *terraform.State) error { - var iteration *models.HashicorpCloudPackerIteration - if iterationPtr != nil { - iteration = *iterationPtr - } - if iteration == nil { - iteration = &models.HashicorpCloudPackerIteration{} - } - - var build *models.HashicorpCloudPackerBuild - if buildPtr != nil { - build = *buildPtr - } - if build == nil { - build = &models.HashicorpCloudPackerBuild{} - } - - var matchingImages []*models.HashicorpCloudPackerImage - for _, image := range build.Images { - if image.Region == region { - matchingImages = append(matchingImages, image) - } - } - if len(matchingImages) == 0 { - return fmt.Errorf("didn't find any images in the provided build in the specified region") - } - var image = matchingImages[0] - if len(matchingImages) > 1 { - t.Logf("found %d images in the provided build in the specified region, the first will be used", len(matchingImages)) - } - - checks := []resource.TestCheckFunc{ - resource.TestCheckResourceAttrSet(resourceName, "organization_id"), - resource.TestCheckResourceAttrSet(resourceName, "project_id"), - resource.TestCheckResourceAttr(resourceName, "bucket_name", bucketName), - resource.TestCheckResourceAttr(resourceName, "iteration_id", iteration.ID), - resource.TestCheckResourceAttr(resourceName, "build_id", build.ID), - resource.TestCheckResourceAttr(resourceName, "id", image.ID), - resource.TestCheckResourceAttr(resourceName, "packer_run_uuid", build.PackerRunUUID), - resource.TestCheckResourceAttr(resourceName, "cloud_provider", build.CloudProvider), - resource.TestCheckResourceAttr(resourceName, "component_type", build.ComponentType), - resource.TestCheckResourceAttr(resourceName, "region", image.Region), - resource.TestCheckResourceAttr(resourceName, "cloud_image_id", image.ImageID), - resource.TestCheckResourceAttr(resourceName, "created_at", image.CreatedAt.String()), - } - - if !iteration.RevokeAt.IsZero() { - checks = append(checks, resource.TestCheckResourceAttr(resourceName, "revoke_at", iteration.RevokeAt.String())) - } - - for key, value := range build.Labels { - checks = append(checks, resource.TestCheckResourceAttr( - resourceName, fmt.Sprintf("labels.%s", key), value, - )) - } - - return resource.ComposeAggregateTestCheckFunc(checks...)(state) - } -} diff --git a/internal/providersdkv2/data_source_packer_iteration.go b/internal/providersdkv2/data_source_packer_iteration.go deleted file mode 100644 index 5e01fa76b..000000000 --- a/internal/providersdkv2/data_source_packer_iteration.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package providersdkv2 - -import ( - "context" - "log" - "time" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/hashicorp/terraform-provider-hcp/internal/clients" - "github.com/hashicorp/terraform-provider-hcp/internal/clients/packerv1" -) - -func dataSourcePackerIteration() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "This data source has been deprecated. Use the new `hcp_packer_version` data source instead.", - Description: "The Packer Image data source iteration gets the most recent iteration (or build) of an image, given a channel.", - ReadContext: dataSourcePackerIterationRead, - Timeouts: &schema.ResourceTimeout{ - Default: &defaultPackerTimeout, - }, - Schema: map[string]*schema.Schema{ - // Required inputs - "bucket_name": { - Description: "The slug of the HCP Packer Registry bucket to pull from.", - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: validateSlugID, - }, - "channel": { - Description: "The channel that points to the version of the image you want.", - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: validateSlugID, - }, - // Optional inputs - "project_id": { - Description: ` -The ID of the HCP project where the HCP Packer Registry is located. -If not specified, the project specified in the HCP Provider config block will be used, if configured. -If a project is not configured in the HCP Provider config block, the oldest project in the organization will be used.`, - Type: schema.TypeString, - Computed: true, - Optional: true, - ValidateFunc: validation.IsUUID, - }, - // computed outputs - "author_id": { - Description: "The name of the person who created this iteration.", - Type: schema.TypeString, - Computed: true, - }, - "organization_id": { - Description: "The ID of the organization this HCP Packer registry is located in.", - Type: schema.TypeString, - Computed: true, - }, - "fingerprint": { - Description: "The unique fingerprint associated with this iteration; often a git sha.", - Type: schema.TypeString, - Computed: true, - }, - "ulid": { - Description: "The ULID of this iteration.", - Type: schema.TypeString, - Computed: true, - }, - "created_at": { - Description: "Creation time of this iteration", - Type: schema.TypeString, - Computed: true, - }, - "updated_at": { - Description: "Time this build was last updated.", - Type: schema.TypeString, - Computed: true, - }, - "revoke_at": { - Description: "The revocation time of this iteration. This field will be null for any iteration that has not been revoked or scheduled for revocation.", - Type: schema.TypeString, - Computed: true, - }, - }, - } -} - -func dataSourcePackerIterationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*clients.Client) - loc, err := getAndUpdateLocationResourceData(d, client) - if err != nil { - return diag.FromErr(err) - } - - bucketName := d.Get("bucket_name").(string) - channelSlug := d.Get("channel").(string) - - log.Printf("[INFO] Reading HCP Packer registry (%s) [project_id=%s, organization_id=%s, channel=%s]", bucketName, loc.ProjectID, loc.OrganizationID, channelSlug) - - channel, err := packerv1.GetPackerChannelBySlug(ctx, client, loc, bucketName, channelSlug) - if err != nil { - return diag.FromErr(err) - } - - if channel.Iteration == nil { - return diag.Errorf("no iteration information found for the specified channel %s", channelSlug) - } - - iteration := channel.Iteration - - d.SetId(iteration.ID) - - if err := d.Set("author_id", iteration.AuthorID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("bucket_name", iteration.BucketSlug); err != nil { - return diag.FromErr(err) - } - if err := d.Set("created_at", iteration.CreatedAt.String()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("fingerprint", iteration.Fingerprint); err != nil { - return diag.FromErr(err) - } - if err := d.Set("ulid", iteration.ID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("updated_at", iteration.UpdatedAt.String()); err != nil { - return diag.FromErr(err) - } - if !time.Time(iteration.RevokeAt).IsZero() { - if err := d.Set("revoke_at", iteration.RevokeAt.String()); err != nil { - return diag.FromErr(err) - } - } - - return nil -} diff --git a/internal/providersdkv2/data_source_packer_iteration_test.go b/internal/providersdkv2/data_source_packer_iteration_test.go deleted file mode 100644 index 49338da35..000000000 --- a/internal/providersdkv2/data_source_packer_iteration_test.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package providersdkv2 - -import ( - "fmt" - "testing" - "time" - - "github.com/go-openapi/strfmt" - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" -) - -func TestAcc_dataSourcePackerIteration_Simple(t *testing.T) { - bucketSlug := testAccCreateSlug("IterationSimple") - channelSlug := bucketSlug // No need for a different slug - - config := testAccPackerDataIterationBuilder("Simple", fmt.Sprintf("%q", bucketSlug), fmt.Sprintf("%q", channelSlug)) - - var iteration *models.HashicorpCloudPackerIteration - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - iteration, _ = upsertCompleteIteration(t, bucketSlug, "1234", nil) - upsertChannel(t, bucketSlug, channelSlug, iteration.ID) - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { - Config: testConfig(testAccConfigBuildersToString(config)), - Check: resource.ComposeTestCheckFunc( - testAccCheckIterationState(config.BlockName(), bucketSlug, channelSlug), - testAccCheckIterationStateMatchesIteration(config.BlockName(), &iteration), - ), - }, - { - // Test that references to `revoked_at` don't error when the - // the iteration is not revoked or scheduled for revocation. - // - // Checked in this manner because you cant check for attributes - // set to empty strings with `resource.TestCheckResourceAttr` - Config: testConfig(testAccConfigBuildersToString( - config, - testAccOutputBuilder("revoke_at", config.AttributeRef("revoke_at")), - )), - }, - }, - }) -} - -func TestAcc_dataSourcePackerIteration_revokedIteration(t *testing.T) { - bucketSlug := testAccCreateSlug("IterationRevoked") - channelSlug := bucketSlug // No need for a different slug - revokeAt := strfmt.DateTime(time.Now().UTC().Add(24 * time.Hour)) - - config := testAccPackerDataIterationBuilder("Revoked", fmt.Sprintf("%q", bucketSlug), fmt.Sprintf("%q", channelSlug)) - - var revokedIteration *models.HashicorpCloudPackerIteration - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - unrevokedIteration, _ := upsertCompleteIteration(t, bucketSlug, "1234", nil) - upsertChannel(t, bucketSlug, channelSlug, unrevokedIteration.ID) - revokedIteration = revokeIteration(t, unrevokedIteration.ID, bucketSlug, revokeAt) - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { - Config: testConfig(testAccConfigBuildersToString(config)), - Check: resource.ComposeTestCheckFunc( - testAccCheckIterationState(config.BlockName(), bucketSlug, channelSlug), - resource.TestCheckResourceAttr(config.BlockName(), "revoke_at", revokeAt.String()), - testAccCheckIterationStateMatchesIteration(config.BlockName(), &revokedIteration), - ), - }, - }, - }) -} - -func testAccPackerDataIterationBuilder(uniqueName string, bucketName string, channelName string) testAccConfigBuilderInterface { - return &testAccResourceConfigBuilder{ - isData: true, - resourceType: "hcp_packer_iteration", - uniqueName: uniqueName, - attributes: map[string]string{ - "bucket_name": bucketName, - "channel": channelName, - }, - } -} - -func testAccCheckIterationState(resourceName, bucketName, channelName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet(resourceName, "organization_id"), - resource.TestCheckResourceAttrSet(resourceName, "project_id"), - resource.TestCheckResourceAttr(resourceName, "bucket_name", bucketName), - resource.TestCheckResourceAttr(resourceName, "channel", channelName), - ) -} - -func testAccCheckIterationStateMatchesIteration(resourceName string, iterationPtr **models.HashicorpCloudPackerIteration) resource.TestCheckFunc { - return func(state *terraform.State) error { - var iteration *models.HashicorpCloudPackerIteration - if iterationPtr != nil { - iteration = *iterationPtr - } - if iteration == nil { - iteration = &models.HashicorpCloudPackerIteration{} - } - - checks := []resource.TestCheckFunc{ - resource.TestCheckResourceAttr(resourceName, "bucket_name", iteration.BucketSlug), - resource.TestCheckResourceAttr(resourceName, "ulid", iteration.ID), - resource.TestCheckResourceAttr(resourceName, "fingerprint", iteration.Fingerprint), - resource.TestCheckResourceAttr(resourceName, "author_id", iteration.AuthorID), - resource.TestCheckResourceAttr(resourceName, "created_at", iteration.CreatedAt.String()), - resource.TestCheckResourceAttr(resourceName, "updated_at", iteration.UpdatedAt.String()), - } - - if !iteration.RevokeAt.IsZero() { - checks = append(checks, resource.TestCheckResourceAttr(resourceName, "revoke_at", iteration.RevokeAt.String())) - } - - return resource.ComposeAggregateTestCheckFunc(checks...)(state) - } -} diff --git a/internal/providersdkv2/provider.go b/internal/providersdkv2/provider.go index eaaae57d6..6fb10fba5 100644 --- a/internal/providersdkv2/provider.go +++ b/internal/providersdkv2/provider.go @@ -34,8 +34,6 @@ func New() func() *schema.Provider { "hcp_hvn_peering_connection": dataSourceHvnPeeringConnection(), "hcp_hvn_route": dataSourceHVNRoute(), "hcp_packer_bucket_names": dataSourcePackerBucketNames(), - "hcp_packer_image": dataSourcePackerImage(), - "hcp_packer_iteration": dataSourcePackerIteration(), "hcp_packer_run_task": dataSourcePackerRunTask(), "hcp_vault_cluster": dataSourceVaultCluster(), "hcp_vault_plugin": dataSourceVaultPlugin(), diff --git a/internal/providersdkv2/resource_packer_channel_assignment.go b/internal/providersdkv2/resource_packer_channel_assignment.go index 3c450fe9b..0f84ecc24 100644 --- a/internal/providersdkv2/resource_packer_channel_assignment.go +++ b/internal/providersdkv2/resource_packer_channel_assignment.go @@ -30,7 +30,6 @@ func resourcePackerChannelAssignment() *schema.Resource { DeleteContext: resourcePackerChannelAssignmentDelete, ReadContext: resourcePackerChannelAssignmentRead, UpdateContext: resourcePackerChannelAssignmentUpdate, - CustomizeDiff: resourcePackerChannelAssignmentCustomizeDiff, Timeouts: &schema.ResourceTimeout{ Create: &defaultPackerTimeout, Default: &defaultPackerTimeout, @@ -57,22 +56,11 @@ func resourcePackerChannelAssignment() *schema.Resource { ValidateDiagFunc: validateSlugID, }, // Optional inputs - "iteration_fingerprint": { - Description: "The fingerprint of the version assigned to the channel.", - Type: schema.TypeString, - Optional: true, - Computed: true, - ExactlyOneOf: []string{"iteration_fingerprint", "version_fingerprint"}, - ValidateFunc: validation.StringIsNotEmpty, - Deprecated: "This attribute has been renamed to 'version_fingerprint`. The `iteration_fingerprint` attribute is deprecated and will be removed in a future release. " + - "The `iteration_fingerprint` attribute will act as an alias for `version_fingerprint` during the deprecation period.", - }, "version_fingerprint": { Description: "The fingerprint of the version assigned to the channel.", Type: schema.TypeString, Optional: true, Computed: true, - ExactlyOneOf: []string{"iteration_fingerprint", "version_fingerprint"}, ValidateFunc: validation.StringIsNotEmpty, }, "project_id": { @@ -158,9 +146,6 @@ func resourcePackerChannelAssignmentCreate(ctx context.Context, d *schema.Resour } versionFingerprint := d.Get("version_fingerprint").(string) - if versionFingerprint == "" { - versionFingerprint = d.Get("iteration_fingerprint").(string) - } if versionFingerprint == unassignString { versionFingerprint = "" } @@ -189,9 +174,6 @@ func resourcePackerChannelAssignmentUpdate(ctx context.Context, d *schema.Resour channelName := d.Get("channel_name").(string) versionFingerprint := d.Get("version_fingerprint").(string) - if versionFingerprint == "" { - versionFingerprint = d.Get("iteration_fingerprint").(string) - } if versionFingerprint == unassignString { versionFingerprint = "" } @@ -317,23 +299,6 @@ func setPackerChannelAssignmentVersionData(d *schema.ResourceData, v *packermode if err := d.Set("version_fingerprint", fingerprint); err != nil { return err } - if err := d.Set("iteration_fingerprint", fingerprint); err != nil { - return err - } - - return nil -} - -func resourcePackerChannelAssignmentCustomizeDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { - if rawFingerprint, ok := d.GetOk("version_fingerprint"); ok && d.HasChange("version_fingerprint") && d.NewValueKnown("version_fingerprint") { - if err := d.SetNew("iteration_fingerprint", rawFingerprint.(string)); err != nil { - return err - } - } else if rawFingerprint, ok := d.GetOk("iteration_fingerprint"); ok && d.HasChange("iteration_fingerprint") && d.NewValueKnown("iteration_fingerprint") { - if err := d.SetNew("version_fingerprint", rawFingerprint.(string)); err != nil { - return err - } - } return nil } diff --git a/internal/providersdkv2/resource_packer_channel_assignment_test.go b/internal/providersdkv2/resource_packer_channel_assignment_test.go index 4311d98c3..d385acd90 100644 --- a/internal/providersdkv2/resource_packer_channel_assignment_test.go +++ b/internal/providersdkv2/resource_packer_channel_assignment_test.go @@ -86,7 +86,7 @@ func TestAccPackerChannelAssignment_AssignLatest(t *testing.T) { uniqueName := "AssignLatest" // This config creates a data source that is read before apply time - beforeVersion := testAccPackerDataIterationBuilder( + beforeVersion := testAccPackerDataVersionBuilder( uniqueName, fmt.Sprintf("%q", bucketSlug), `"latest"`, @@ -109,7 +109,7 @@ func TestAccPackerChannelAssignment_AssignLatest(t *testing.T) { fmt.Sprintf("%q", channelSlug), fmt.Sprintf("%q", bucketSlug), ) - afterVersion := testAccPackerDataIterationBuilder( + afterVersion := testAccPackerDataVersionBuilder( uniqueName, afterChannel.AttributeRef("bucket_name"), `"latest"`, @@ -191,21 +191,8 @@ func TestAccPackerChannelAssignment_InvalidInputs(t *testing.T) { ), generateStep( `"doesNotExist"`, - // TODO: Update to "version" once the new API is implemented for this resource. `.*version with fingerprint \(fingerprint: doesNotExist\) does not exist.*`, ), - // TODO: Remove once the iteration_fingerprint attribute is removed - { - Config: fmt.Sprintf(` -resource "hcp_packer_channel_assignment" "InvalidInputs" { - bucket_name = %q - channel_name = %q - iteration_fingerprint = "someVersion" - version_fingerprint = "someVersion" -} - `, bucketSlug, channelSlug), - ExpectError: regexp.MustCompile(`.*only one of.*\n.*can be specified.*`), - }, { // Create a dummy non-empty state so that `CheckDestroy` will run. Config: testAccConfigDummyNonemptyState, }, @@ -366,79 +353,6 @@ func TestAccPackerChannelAssignment_EnforceNull(t *testing.T) { }) } -// TODO: Remove once the iteration_fingerprint attribute is removed -// Test that migration from `iteration_fingerprint` to `version_fingerprint` works properly -func TestAccPackerChannelAssignment_AliasMigration(t *testing.T) { - bucketSlug := testAccCreateSlug("AssignmentAliasMigration") - channelSlug := bucketSlug // No need for a different slug - versionFingerprint := "1" - - var version *models.HashicorpCloudPacker20230101Version - - baseAssignment := testAccPackerAssignmentBuilderBase("AliasMigration", fmt.Sprintf("%q", bucketSlug), fmt.Sprintf("%q", channelSlug)) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t, map[string]bool{"aws": false, "azure": false}) - upsertRegistry(t) - upsertBucket(t, bucketSlug) - createOrUpdateChannel(t, bucketSlug, channelSlug, "") - version, _ = upsertCompleteVersion(t, bucketSlug, versionFingerprint, nil) - }, - ProtoV6ProviderFactories: testProtoV6ProviderFactories, - CheckDestroy: func(state *terraform.State) error { - deleteBucket(t, bucketSlug, true) - return nil - }, - Steps: []resource.TestStep{ - { // Set channel assignment to the version using `iteration_fingerprint` - Config: testConfig(testAccConfigBuildersToString(testAccPackerAssignmentBuilderFromAssignmentWithIterationFingerprint( - baseAssignment, - fmt.Sprintf("%q", versionFingerprint), - ))), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAssignmentStateBucketAndChannelName(baseAssignment.BlockName(), bucketSlug, channelSlug), - testAccCheckAssignmentStateMatchesVersion(baseAssignment.BlockName(), &version), - testAccCheckAssignmentStateMatchesAPI(baseAssignment.BlockName()), - ), - }, - { // Set channel assignment to the version using `version_fingerprint` - Config: testConfig(testAccConfigBuildersToString(testAccPackerAssignmentBuilderFromAssignment( - baseAssignment, - fmt.Sprintf("%q", versionFingerprint), - ))), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAssignmentStateBucketAndChannelName(baseAssignment.BlockName(), bucketSlug, channelSlug), - testAccCheckAssignmentStateMatchesVersion(baseAssignment.BlockName(), &version), - testAccCheckAssignmentStateMatchesAPI(baseAssignment.BlockName()), - ), - }, - { // Set channel assignment to null with `iteration_fingerprint` - Config: testConfig(testAccConfigBuildersToString(testAccPackerAssignmentBuilderFromAssignmentWithIterationFingerprint( - baseAssignment, - fmt.Sprintf("%q", unassignString), - ))), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAssignmentStateBucketAndChannelName(baseAssignment.BlockName(), bucketSlug, channelSlug), - testAccCheckAssignmentStateMatchesVersion(baseAssignment.BlockName(), nil), - testAccCheckAssignmentStateMatchesAPI(baseAssignment.BlockName()), - ), - }, - { // Set channel assignment to null with `version_fingerprint` - Config: testConfig(testAccConfigBuildersToString(testAccPackerAssignmentBuilderFromAssignment( - baseAssignment, - fmt.Sprintf("%q", unassignString), - ))), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAssignmentStateBucketAndChannelName(baseAssignment.BlockName(), bucketSlug, channelSlug), - testAccCheckAssignmentStateMatchesVersion(baseAssignment.BlockName(), nil), - testAccCheckAssignmentStateMatchesAPI(baseAssignment.BlockName()), - ), - }, - }, - }) -} - // An AssignmentBuilder without any version fields set. // To be used downstream by other assignments to ensure core settings aren't changed. func testAccPackerAssignmentBuilderBase(uniqueName string, bucketName string, channelName string) testAccConfigBuilderInterface { @@ -479,19 +393,6 @@ func testAccPackerAssignmentBuilderFromAssignment(oldAssignment testAccConfigBui ) } -// TODO: Remove once the iteration_fingerprint attribute is removed -func testAccPackerAssignmentBuilderFromAssignmentWithIterationFingerprint(oldAssignment testAccConfigBuilderInterface, fingerprint string) testAccConfigBuilderInterface { - return &testAccResourceConfigBuilder{ - resourceType: "hcp_packer_channel_assignment", - uniqueName: oldAssignment.UniqueName(), - attributes: map[string]string{ - "bucket_name": oldAssignment.Attributes()["bucket_name"], - "channel_name": oldAssignment.Attributes()["channel_name"], - "iteration_fingerprint": fingerprint, - }, - } -} - func testAccPackerAssignmentBuilderWithChannelReference(uniqueName string, channel testAccConfigBuilderInterface, fingerprint string) testAccConfigBuilderInterface { return testAccPackerAssignmentBuilder( uniqueName, @@ -535,7 +436,6 @@ func testAccCheckAssignmentStateMatchesVersion(resourceName string, versionPtr * return resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "version_fingerprint", versionFingerprint), - resource.TestCheckResourceAttr(resourceName, "iteration_fingerprint", versionFingerprint), )(state) } } @@ -591,3 +491,15 @@ func testAccCheckAssignmentDestroyed(resourceName string) resource.TestCheckFunc return nil } } + +func testAccPackerDataVersionBuilder(uniqueName string, bucketName string, channelName string) testAccConfigBuilderInterface { + return &testAccResourceConfigBuilder{ + isData: true, + resourceType: "hcp_packer_version", + uniqueName: uniqueName, + attributes: map[string]string{ + "bucket_name": bucketName, + "channel_name": channelName, + }, + } +} diff --git a/internal/providersdkv2/test_deprecated_helpers_packer_test.go b/internal/providersdkv2/test_deprecated_helpers_packer_test.go deleted file mode 100644 index f9accec11..000000000 --- a/internal/providersdkv2/test_deprecated_helpers_packer_test.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package providersdkv2 - -import ( - "context" - "net/http" - "testing" - - "github.com/go-openapi/strfmt" - "github.com/google/uuid" - - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service" - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - sharedmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models" - "github.com/hashicorp/terraform-provider-hcp/internal/clients" - "github.com/hashicorp/terraform-provider-hcp/internal/clients/packerv1" - "google.golang.org/grpc/codes" -) - -func upsertIteration(t *testing.T, bucketSlug, fingerprint string) *models.HashicorpCloudPackerIteration { - t.Helper() - - client := testAccProvider.Meta().(*clients.Client) - loc := &sharedmodels.HashicorpCloudLocationLocation{ - OrganizationID: client.Config.OrganizationID, - ProjectID: client.Config.ProjectID, - } - - createItParams := packer_service.NewPackerServiceCreateIterationParams() - createItParams.LocationOrganizationID = loc.OrganizationID - createItParams.LocationProjectID = loc.ProjectID - createItParams.BucketSlug = bucketSlug - createItParams.Body = packer_service.PackerServiceCreateIterationBody{ - Fingerprint: fingerprint, - } - - iterationResp, err := client.Packer.PackerServiceCreateIteration(createItParams, nil) - if err == nil { - return iterationResp.Payload.Iteration - } else if err, ok := err.(*packer_service.PackerServiceCreateIterationDefault); ok { - switch err.Code() { - case int(codes.AlreadyExists), http.StatusConflict: - // all good here ! - getItParams := packer_service.NewPackerServiceGetIterationParams() - getItParams.LocationOrganizationID = createItParams.LocationOrganizationID - getItParams.LocationProjectID = createItParams.LocationProjectID - getItParams.BucketSlug = createItParams.BucketSlug - getItParams.Fingerprint = &createItParams.Body.Fingerprint - iterationResp, err := client.Packer.PackerServiceGetIteration(getItParams, nil) - if err != nil { - t.Errorf("unexpected GetIteration error, expected nil. Got %v", err) - return nil - } - return iterationResp.Payload.Iteration - } - } - - t.Errorf("unexpected CreateIteration error, expected nil or 409. Got %v", err) - return nil -} - -func upsertCompleteIteration(t *testing.T, bucketSlug, fingerprint string, options *buildOptions) (*models.HashicorpCloudPackerIteration, *models.HashicorpCloudPackerBuild) { - iteration := upsertIteration(t, bucketSlug, fingerprint) - if t.Failed() || iteration == nil { - return nil, nil - } - build := upsertCompleteBuildDeprecated(t, bucketSlug, iteration.Fingerprint, iteration.ID, options) - if t.Failed() { - return nil, nil - } - - client := testAccProvider.Meta().(*clients.Client) - loc := &sharedmodels.HashicorpCloudLocationLocation{ - OrganizationID: client.Config.OrganizationID, - ProjectID: client.Config.ProjectID, - } - iteration, err := packerv1.GetIterationFromFingerprint(context.Background(), client, loc, bucketSlug, iteration.Fingerprint) - if err != nil { - t.Errorf("Complete iteration not found after upserting, received unexpected error. Got %v", err) - return nil, nil - } - - return iteration, build -} - -func revokeIteration(t *testing.T, iterationID, bucketSlug string, revokeAt strfmt.DateTime) *models.HashicorpCloudPackerIteration { - t.Helper() - client := testAccProvider.Meta().(*clients.Client) - loc := &sharedmodels.HashicorpCloudLocationLocation{ - OrganizationID: client.Config.OrganizationID, - ProjectID: client.Config.ProjectID, - } - - params := packer_service.NewPackerServiceUpdateIterationParams() - params.LocationOrganizationID = loc.OrganizationID - params.LocationProjectID = loc.ProjectID - params.IterationID = iterationID - params.Body = packer_service.PackerServiceUpdateIterationBody{ - BucketSlug: bucketSlug, - RevokeAt: revokeAt, - } - - resp, err := client.Packer.PackerServiceUpdateIteration(params, nil) - if err != nil { - t.Fatal(err) - } - if resp == nil { - t.Fatal("expected non-nil response from UpdateIteration, got nil") - } else if resp.Payload == nil { - t.Fatal("expected non-nil Payload in response from UpdateIteration, got nil") - } - - return resp.Payload.Iteration -} - -type buildOptions struct { - labels map[string]string - cloudProvider string - componentType string - images []*models.HashicorpCloudPackerImageCreateBody -} - -// Basic options for a build with a single image -var defaultBuildOptions = buildOptions{ - cloudProvider: "aws", - componentType: "amazon-ebs.example", - images: []*models.HashicorpCloudPackerImageCreateBody{ - { - ImageID: "ami-1234", - Region: "us-east-1", - }, - }, -} - -func upsertCompleteBuildDeprecated(t *testing.T, bucketSlug, fingerprint, iterationID string, optionsPtr *buildOptions) *models.HashicorpCloudPackerBuild { - var options = defaultBuildOptions - if optionsPtr != nil { - options = *optionsPtr - } - - client := testAccProvider.Meta().(*clients.Client) - - createBuildParams := packer_service.NewPackerServiceCreateBuildParams() - loc := &sharedmodels.HashicorpCloudLocationLocation{ - OrganizationID: client.Config.OrganizationID, - ProjectID: client.Config.ProjectID, - } - createBuildParams.LocationOrganizationID = loc.OrganizationID - createBuildParams.LocationProjectID = loc.ProjectID - createBuildParams.BucketSlug = bucketSlug - createBuildParams.IterationID = iterationID - - status := models.HashicorpCloudPackerBuildStatusRUNNING - createBuildParams.Body = packer_service.PackerServiceCreateBuildBody{ - Build: &models.HashicorpCloudPackerBuildCreateBody{ - CloudProvider: options.cloudProvider, - ComponentType: options.componentType, - PackerRunUUID: uuid.New().String(), - Status: &status, - Labels: options.labels, - }, - Fingerprint: fingerprint, - } - - var build *models.HashicorpCloudPackerBuild - - if createResp, err := client.Packer.PackerServiceCreateBuild(createBuildParams, nil); err != nil { - createErr, ok := err.(*packer_service.PackerServiceCreateBuildDefault) - if !ok || !(createErr.Code() == int(codes.Aborted) || createErr.Code() == http.StatusConflict) { - t.Fatalf("unexpected CreateBuild error, expected nil. Got %v", createErr) - } - - getResp, err := client.Packer.PackerServiceGetBuild(&packer_service.PackerServiceGetBuildParams{}, nil) - if err != nil { - t.Fatalf("unexpected GetBuild error, expected nil. Got %v", err) - } - if getResp == nil { - t.Fatalf("unexpected GetBuild response, expected non nil. Got nil.") - } else if getResp.Payload == nil { - t.Fatalf("unexpected GetBuild response payload, expected non nil. Got nil.") - } - build = getResp.Payload.Build - } else { - if createResp == nil { - t.Fatalf("unexpected CreateBuild response, expected non nil. Got nil.") - } else if createResp.Payload == nil { - t.Fatalf("unexpected CreateBuild response payload, expected non nil. Got nil.") - } - build = createResp.Payload.Build - } - - // Iterations are currently only assigned an incremental version when publishing image metadata on update. - // Incremental versions are a requirement for assigning the channel. - updateBuildParams := packer_service.NewPackerServiceUpdateBuildParams() - updateBuildParams.LocationOrganizationID = loc.OrganizationID - updateBuildParams.LocationProjectID = loc.ProjectID - updateBuildParams.BuildID = build.ID - updatesStatus := models.HashicorpCloudPackerBuildStatusDONE - updateBuildParams.Body = packer_service.PackerServiceUpdateBuildBody{ - Updates: &models.HashicorpCloudPackerBuildUpdates{ - Status: &updatesStatus, - Images: options.images, - }, - } - updateResp, err := client.Packer.PackerServiceUpdateBuild(updateBuildParams, nil) - if err != nil { - t.Errorf("unexpected UpdateBuild error, expected nil. Got %v", err) - } - if updateResp == nil { - t.Fatalf("unexpected UpdateBuild response, expected non nil. Got nil.") - } else if updateResp.Payload == nil { - t.Fatalf("unexpected UpdateBuild response payload, expected non nil. Got nil.") - } - return updateResp.Payload.Build -} - -func upsertChannel(t *testing.T, bucketSlug, channelSlug, iterationID string) { - t.Helper() - - client := testAccProvider.Meta().(*clients.Client) - loc := &sharedmodels.HashicorpCloudLocationLocation{ - OrganizationID: client.Config.OrganizationID, - ProjectID: client.Config.ProjectID, - } - - createChParams := packer_service.NewPackerServiceCreateChannelParams() - createChParams.LocationOrganizationID = loc.OrganizationID - createChParams.LocationProjectID = loc.ProjectID - createChParams.BucketSlug = bucketSlug - createChParams.Body = packer_service.PackerServiceCreateChannelBody{ - Slug: channelSlug, - IterationID: iterationID, - } - - _, err := client.Packer.PackerServiceCreateChannel(createChParams, nil) - if err == nil { - return - } - if err, ok := err.(*packer_service.PackerServiceCreateChannelDefault); ok { - switch err.Code() { - case int(codes.AlreadyExists), http.StatusConflict: - // all good here ! - updateChannelAssignmentDeprecated(t, bucketSlug, channelSlug, &models.HashicorpCloudPackerIteration{ID: iterationID}) - return - } - } - t.Errorf("unexpected CreateChannel error, expected nil. Got %v", err) -} - -func updateChannelAssignmentDeprecated(t *testing.T, bucketSlug string, channelSlug string, iteration *models.HashicorpCloudPackerIteration) { - t.Helper() - - client := testAccProvider.Meta().(*clients.Client) - loc := &sharedmodels.HashicorpCloudLocationLocation{ - OrganizationID: client.Config.OrganizationID, - ProjectID: client.Config.ProjectID, - } - - params := packer_service.NewPackerServiceUpdateChannelParams() - params.LocationOrganizationID = loc.OrganizationID - params.LocationProjectID = loc.ProjectID - params.BucketSlug = bucketSlug - params.Slug = channelSlug - - if iteration != nil { - switch { - case iteration.ID != "": - params.Body.IterationID = iteration.ID - case iteration.Fingerprint != "": - params.Body.Fingerprint = iteration.Fingerprint - case iteration.IncrementalVersion > 0: - params.Body.IncrementalVersion = iteration.IncrementalVersion - } - } - - _, err := client.Packer.PackerServiceUpdateChannel(params, nil) - if err == nil { - return - } - t.Errorf("unexpected UpdateChannel error, expected nil. Got %v", err) -} diff --git a/internal/providersdkv2/test_helpers_for_packer_test.go b/internal/providersdkv2/test_helpers_for_packer_test.go index bae56e2fc..1ab62f3c5 100644 --- a/internal/providersdkv2/test_helpers_for_packer_test.go +++ b/internal/providersdkv2/test_helpers_for_packer_test.go @@ -333,7 +333,7 @@ func upsertCompleteBuild( build = createResp.Payload.Build } - // Iterations are currently only assigned an incremental version when publishing image metadata on update. + // Versions are currently only assigned an incremental name when publishing artifact metadata on update. // Incremental versions are a requirement for assigning the channel. updateBuildParams := packerservice.NewPackerServiceUpdateBuildParams() updateBuildParams.LocationOrganizationID = loc.OrganizationID diff --git a/internal/providersdkv2/test_helpers_test.go b/internal/providersdkv2/test_helpers_test.go index 63736b170..3271a6742 100644 --- a/internal/providersdkv2/test_helpers_test.go +++ b/internal/providersdkv2/test_helpers_test.go @@ -115,7 +115,7 @@ func testAccCreateSlug(testName string) string { type testAccConfigBuilderInterface interface { // The fully-qualified name of a block that can be referenced, like // `hcp_packer_channel.prod` (a resource) or - // `data.hcp_packer_iteration.latest` (a data source). + // `data.hcp_packer_version.latest` (a data source). // Panics if the block cannot be referenced. BlockName() string // Unquoted Block identifier, like `resource`, `data`, or `output` @@ -163,17 +163,6 @@ func testAccConfigBuildersToString(builders ...testAccConfigBuilderInterface) st return config } -func testAccOutputBuilder(uniqueName string, value string) testAccConfigBuilderInterface { - return &testAccGenericNamedBlockConfigBuilder{ - canReference: false, - blockIdentifier: "output", - uniqueName: uniqueName, - attributes: map[string]string{ - "value": value, - }, - } -} - // Generic ConfigBuilder for Blocks that have a UniqueName and no other labels // like `output` and `variable` type testAccGenericNamedBlockConfigBuilder struct { diff --git a/templates/data-sources/packer_image.md.tmpl b/templates/data-sources/packer_image.md.tmpl deleted file mode 100644 index 25a30ecb5..000000000 --- a/templates/data-sources/packer_image.md.tmpl +++ /dev/null @@ -1,14 +0,0 @@ ---- -page_title: "{{.Type}} {{.Name}} - {{.ProviderName}}" -subcategory: "HCP Packer" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} ---- - -# {{.Name}} ({{.Type}}) - -{{ .Description | trimspace }} - -~> **Deprecated:** This data source is deprecated and will be removed in a future release. Please use the [`hcp_packer_artifact`](./packer_artifact) data source instead. - -{{ .SchemaMarkdown | trimspace }} diff --git a/templates/data-sources/packer_iteration.md.tmpl b/templates/data-sources/packer_iteration.md.tmpl deleted file mode 100644 index c6c88764c..000000000 --- a/templates/data-sources/packer_iteration.md.tmpl +++ /dev/null @@ -1,14 +0,0 @@ ---- -page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" -subcategory: "HCP Packer" -description: |- -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} ---- - -# {{.Name}} ({{.Type}}) - -{{ .Description | trimspace }} - -~> **Deprecated:** This data source is deprecated and will be removed in a future release. Please use the [`hcp_packer_version`](./packer_version) data source instead. - -{{ .SchemaMarkdown | trimspace }}