From fdcf66c8ed14ec4394d8889c1b820caa89648fe8 Mon Sep 17 00:00:00 2001 From: Isaac Calligeros <101079287+IsaacCalligeros95@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:34:53 +0930 Subject: [PATCH 1/3] Chore!: Migrate docker container registry (#702) * Migrate docker container registry * Tidy up * Rename APIVersion * Fix descriptions --- docs/data-sources/feeds.md | 35 ++-- docs/data-sources/library_variable_sets.md | 4 +- docs/resources/artifactory_generic_feed.md | 4 +- .../aws_elastic_container_registry.md | 6 +- docs/resources/docker_container_registry.md | 6 +- docs/resources/github_repository_feed.md | 4 +- docs/resources/helm_feed.md | 8 +- docs/resources/library_variable_set.md | 4 +- docs/resources/maven_feed.md | 4 +- docs/resources/nuget_feed.md | 6 +- octopusdeploy/provider.go | 1 - .../resource_docker_container_registry.go | 104 ---------- .../schema_docker_container_registry.go | 104 ---------- octopusdeploy_framework/framework_provider.go | 3 +- .../resource_artifactory_generic_feed.go | 3 +- ...resource_aws_elastic_container_registry.go | 3 +- .../resource_docker_container_registry.go | 183 ++++++++++++++++++ ...resource_docker_container_registry_test.go | 11 +- .../resource_github_repository_feed.go | 3 +- octopusdeploy_framework/resource_helm_feed.go | 3 +- .../resource_maven_feed.go | 3 +- .../resource_nuget_feed.go | 3 +- .../schemas/docker_container_registry_feed.go | 39 ++++ .../schemas/library_variable_set.go | 4 +- 24 files changed, 286 insertions(+), 262 deletions(-) delete mode 100644 octopusdeploy/resource_docker_container_registry.go delete mode 100644 octopusdeploy/schema_docker_container_registry.go create mode 100644 octopusdeploy_framework/resource_docker_container_registry.go rename {octopusdeploy => octopusdeploy_framework}/resource_docker_container_registry_test.go (94%) create mode 100644 octopusdeploy_framework/schemas/docker_container_registry_feed.go diff --git a/docs/data-sources/feeds.md b/docs/data-sources/feeds.md index 623ec5593..91fde3c96 100644 --- a/docs/data-sources/feeds.md +++ b/docs/data-sources/feeds.md @@ -27,37 +27,40 @@ data "octopusdeploy_feeds" "example" { ### Optional - `feed_type` (String) A filter to search by feed type. Valid feed types are `AwsElasticContainerRegistry`, `BuiltIn`, `Docker`, `GitHub`, `Helm`, `Maven`, `NuGet`, or `OctopusProject`. +- `feeds` (Block List) (see [below for nested schema](#nestedblock--feeds)) +- `id` (String) The unique ID for this resource. - `ids` (List of String) A filter to search by a list of IDs. -- `name` (String) A filter to search by name. -- `partial_name` (String) A filter to search by the partial match of a name. +- `name` (String) The name of this resource. +- `partial_name` (String) A filter to search by a partial name. - `skip` (Number) A filter to specify the number of items to skip in the response. -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this feeds. - `take` (Number) A filter to specify the number of items to take (or return) in the response. -### Read-Only - -- `feeds` (Block List) A list of feeds that match the filter(s). (see [below for nested schema](#nestedblock--feeds)) -- `id` (String) The ID of this resource. - ### Nested Schema for `feeds` -Read-Only: +Required: + +- `access_key` (String) The AWS access key to use when authenticating against Amazon Web Services. +- `feed_uri` (String) +- `name` (String) The name of this resource. + +Optional: -- `access_key` (String) - `api_version` (String) - `delete_unreleased_packages_after_days` (Number) - `download_attempts` (Number) The number of times a deployment should attempt to download a package from this feed before failing. - `download_retry_backoff_seconds` (Number) The number of seconds to apply as a linear back off between download attempts. -- `feed_type` (String) -- `feed_uri` (String) +- `feed_type` (String) A filter to search by feed type. Valid feed types are `AwsElasticContainerRegistry`, `BuiltIn`, `Docker`, `GitHub`, `Helm`, `Maven`, `NuGet`, or `OctopusProject`. - `id` (String) The unique ID for this resource. - `is_enhanced_mode` (Boolean) -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. -- `region` (String) - `registry_path` (String) - `secret_key` (String, Sensitive) -- `space_id` (String) The space ID associated with this resource. -- `username` (String, Sensitive) The username associated with this resource. \ No newline at end of file +- `space_id` (String) The space ID associated with this feeds. +- `username` (String, Sensitive) The username associated with this resource. + +Read-Only: + +- `region` (String) \ No newline at end of file diff --git a/docs/data-sources/library_variable_sets.md b/docs/data-sources/library_variable_sets.md index da636ab68..8b6eeb19f 100644 --- a/docs/data-sources/library_variable_sets.md +++ b/docs/data-sources/library_variable_sets.md @@ -3,12 +3,12 @@ page_title: "octopusdeploy_library_variable_sets Data Source - terraform-provider-octopusdeploy" subcategory: "" description: |- - + Provides information about existing library variable sets. --- # octopusdeploy_library_variable_sets (Data Source) - +Provides information about existing library variable sets. diff --git a/docs/resources/artifactory_generic_feed.md b/docs/resources/artifactory_generic_feed.md index 3d46c6eec..07ea676ce 100644 --- a/docs/resources/artifactory_generic_feed.md +++ b/docs/resources/artifactory_generic_feed.md @@ -29,7 +29,7 @@ resource "octopusdeploy_artifactory_generic_feed" "example" { ### Required - `feed_uri` (String) -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `name` (String) The name of this resource. - `repository` (String) ### Optional @@ -38,7 +38,7 @@ resource "octopusdeploy_artifactory_generic_feed" "example" { - `layout_regex` (String) - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this helm feed. - `username` (String, Sensitive) The username associated with this resource. ## Import diff --git a/docs/resources/aws_elastic_container_registry.md b/docs/resources/aws_elastic_container_registry.md index 5549897ea..e0b4f802f 100644 --- a/docs/resources/aws_elastic_container_registry.md +++ b/docs/resources/aws_elastic_container_registry.md @@ -25,15 +25,15 @@ resource "octopusdeploy_aws_elastic_container_registry" "example" { ### Required - `access_key` (String) The AWS access key to use when authenticating against Amazon Web Services. -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `name` (String) The name of this resource. - `region` (String) The AWS region where the registry resides. - `secret_key` (String, Sensitive) The AWS secret key to use when authenticating against Amazon Web Services. ### Optional -- `id` (String) The unique ID for this feed. +- `id` (String) The unique ID for this resource. - `package_acquisition_location_options` (List of String) -- `space_id` (String) The space ID associated with this feed. +- `space_id` (String) The space ID associated with this aws elastic container registry. ## Import diff --git a/docs/resources/docker_container_registry.md b/docs/resources/docker_container_registry.md index ebc6b68cb..8a59fe071 100644 --- a/docs/resources/docker_container_registry.md +++ b/docs/resources/docker_container_registry.md @@ -25,8 +25,8 @@ resource "octopusdeploy_docker_container_registry" "example" { ### Required -- `feed_uri` (String) The URL to a Docker repository. -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `feed_uri` (String) +- `name` (String) The name of this resource. ### Optional @@ -35,7 +35,7 @@ resource "octopusdeploy_docker_container_registry" "example" { - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. - `registry_path` (String) -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this docker container registry feed. - `username` (String, Sensitive) The username associated with this resource. ## Import diff --git a/docs/resources/github_repository_feed.md b/docs/resources/github_repository_feed.md index c743a47dd..37e9601c1 100644 --- a/docs/resources/github_repository_feed.md +++ b/docs/resources/github_repository_feed.md @@ -27,7 +27,7 @@ resource "octopusdeploy_github_repository_feed" "example" { ### Required - `feed_uri` (String) -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `name` (String) The name of this resource. ### Optional @@ -36,7 +36,7 @@ resource "octopusdeploy_github_repository_feed" "example" { - `id` (String) The unique ID for this resource. - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this github repository feed. - `username` (String, Sensitive) The username associated with this resource. ## Import diff --git a/docs/resources/helm_feed.md b/docs/resources/helm_feed.md index 037bc5888..5eed44882 100644 --- a/docs/resources/helm_feed.md +++ b/docs/resources/helm_feed.md @@ -2,12 +2,12 @@ page_title: "octopusdeploy_helm_feed Resource - terraform-provider-octopusdeploy" subcategory: "Feeds" description: |- - This resource manages a Helm feed in Octopus Deploy. + This resource manages a Helm Feed in Octopus Deploy. --- # octopusdeploy_helm_feed (Resource) -This resource manages a Helm feed in Octopus Deploy. +This resource manages a Helm Feed in Octopus Deploy. ## Example Usage @@ -25,14 +25,14 @@ resource "octopusdeploy_helm_feed" "example" { ### Required - `feed_uri` (String) -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `name` (String) The name of this resource. ### Optional - `id` (String) The unique ID for this resource. - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this helm feed. - `username` (String, Sensitive) The username associated with this resource. ## Import diff --git a/docs/resources/library_variable_set.md b/docs/resources/library_variable_set.md index b30fd3f1f..9bff4bf78 100644 --- a/docs/resources/library_variable_set.md +++ b/docs/resources/library_variable_set.md @@ -3,12 +3,12 @@ page_title: "octopusdeploy_library_variable_set Resource - terraform-provider-octopusdeploy" subcategory: "" description: |- - + This resource manages library variable sets in Octopus Deploy. --- # octopusdeploy_library_variable_set (Resource) - +This resource manages library variable sets in Octopus Deploy. diff --git a/docs/resources/maven_feed.md b/docs/resources/maven_feed.md index a589dc13f..1c01d16e8 100644 --- a/docs/resources/maven_feed.md +++ b/docs/resources/maven_feed.md @@ -27,7 +27,7 @@ resource "octopusdeploy_maven_feed" "example" { ### Required - `feed_uri` (String) -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `name` (String) The name of this resource. ### Optional @@ -36,7 +36,7 @@ resource "octopusdeploy_maven_feed" "example" { - `id` (String) The unique ID for this resource. - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this maven feed. - `username` (String, Sensitive) The username associated with this resource. ## Import diff --git a/docs/resources/nuget_feed.md b/docs/resources/nuget_feed.md index 0444d55ba..b5758af66 100644 --- a/docs/resources/nuget_feed.md +++ b/docs/resources/nuget_feed.md @@ -27,8 +27,8 @@ resource "octopusdeploy_nuget_feed" "example" { ### Required -- `feed_uri` (String) The feed URI can be a URL or a folder path. -- `name` (String) A short, memorable, unique name for this feed. Example: ACME Builds. +- `feed_uri` (String) +- `name` (String) The name of this resource. ### Optional @@ -38,7 +38,7 @@ resource "octopusdeploy_nuget_feed" "example" { - `is_enhanced_mode` (Boolean) This will improve performance of the NuGet feed but may not be supported by some older feeds. Disable if the operation, Create Release does not return the latest version for a package. - `package_acquisition_location_options` (List of String) - `password` (String, Sensitive) The password associated with this resource. -- `space_id` (String) The space ID associated with this resource. +- `space_id` (String) The space ID associated with this nuget feed. - `username` (String, Sensitive) The username associated with this resource. ## Import diff --git a/octopusdeploy/provider.go b/octopusdeploy/provider.go index cd51d9521..07f503374 100644 --- a/octopusdeploy/provider.go +++ b/octopusdeploy/provider.go @@ -48,7 +48,6 @@ func Provider() *schema.Provider { "octopusdeploy_channel": resourceChannel(), "octopusdeploy_cloud_region_deployment_target": resourceCloudRegionDeploymentTarget(), "octopusdeploy_deployment_process": resourceDeploymentProcess(), - "octopusdeploy_docker_container_registry": resourceDockerContainerRegistry(), "octopusdeploy_dynamic_worker_pool": resourceDynamicWorkerPool(), "octopusdeploy_gcp_account": resourceGoogleCloudPlatformAccount(), "octopusdeploy_kubernetes_agent_deployment_target": resourceKubernetesAgentDeploymentTarget(), diff --git a/octopusdeploy/resource_docker_container_registry.go b/octopusdeploy/resource_docker_container_registry.go deleted file mode 100644 index bf5d1edd8..000000000 --- a/octopusdeploy/resource_docker_container_registry.go +++ /dev/null @@ -1,104 +0,0 @@ -package octopusdeploy - -import ( - "context" - "fmt" - - "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" - "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/feeds" - "github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal/errors" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func resourceDockerContainerRegistry() *schema.Resource { - return &schema.Resource{ - CreateContext: resourceDockerContainerRegistryCreate, - DeleteContext: resourceDockerContainerRegistryDelete, - Description: "This resource manages a Docker Container Registry in Octopus Deploy.", - Importer: getImporter(), - ReadContext: resourceDockerContainerRegistryRead, - Schema: getDockerContainerRegistrySchema(), - UpdateContext: resourceDockerContainerRegistryUpdate, - } -} - -func resourceDockerContainerRegistryCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - dockerContainerRegistry, err := expandDockerContainerRegistry(d) - if err != nil { - return diag.FromErr(err) - } - - tflog.Info(ctx, fmt.Sprintf("creating Docker container registry, %s", dockerContainerRegistry.GetName())) - - client := m.(*client.Client) - createdDockerContainerRegistry, err := feeds.Add(client, dockerContainerRegistry) - if err != nil { - return diag.FromErr(err) - } - - if err := setDockerContainerRegistry(ctx, d, createdDockerContainerRegistry.(*feeds.DockerContainerRegistry)); err != nil { - return diag.FromErr(err) - } - - d.SetId(createdDockerContainerRegistry.GetID()) - - tflog.Info(ctx, fmt.Sprintf("Docker container registry created (%s)", d.Id())) - return nil -} - -func resourceDockerContainerRegistryDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Info(ctx, fmt.Sprintf("deleting Docker container registry (%s)", d.Id())) - - client := m.(*client.Client) - err := client.Feeds.DeleteByID(d.Id()) - if err != nil { - return diag.FromErr(err) - } - - d.SetId("") - - tflog.Info(ctx, "Docker container registry deleted") - return nil -} - -func resourceDockerContainerRegistryRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - tflog.Info(ctx, fmt.Sprintf("reading Docker container registry (%s)", d.Id())) - - client := m.(*client.Client) - feed, err := feeds.GetByID(client, d.Get("space_id").(string), d.Id()) - if err != nil { - return errors.ProcessApiError(ctx, d, err, "Docker container registry") - } - - dockerContainerRegistry := feed.(*feeds.DockerContainerRegistry) - if err := setDockerContainerRegistry(ctx, d, dockerContainerRegistry); err != nil { - return diag.FromErr(err) - } - - tflog.Info(ctx, fmt.Sprintf("Docker container registry read (%s)", dockerContainerRegistry.GetID())) - return nil -} - -func resourceDockerContainerRegistryUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - feed, err := expandDockerContainerRegistry(d) - if err != nil { - return diag.FromErr(err) - } - - tflog.Info(ctx, fmt.Sprintf("updating Docker container registry (%s)", feed.GetID())) - - client := m.(*client.Client) - updatedFeed, err := feeds.Update(client, feed) - if err != nil { - return diag.FromErr(err) - } - - if err := setDockerContainerRegistry(ctx, d, updatedFeed.(*feeds.DockerContainerRegistry)); err != nil { - return diag.FromErr(err) - } - - tflog.Info(ctx, fmt.Sprintf("Docker container registry updated (%s)", d.Id())) - return nil -} diff --git a/octopusdeploy/schema_docker_container_registry.go b/octopusdeploy/schema_docker_container_registry.go deleted file mode 100644 index a28f565cd..000000000 --- a/octopusdeploy/schema_docker_container_registry.go +++ /dev/null @@ -1,104 +0,0 @@ -package octopusdeploy - -import ( - "context" - "fmt" - - "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core" - "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/feeds" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" -) - -func expandDockerContainerRegistry(d *schema.ResourceData) (*feeds.DockerContainerRegistry, error) { - name := d.Get("name").(string) - - feed, err := feeds.NewDockerContainerRegistry(name) - if err != nil { - return nil, err - } - - feed.ID = d.Id() - - if v, ok := d.GetOk("api_version"); ok { - feed.APIVersion = v.(string) - } - - if v, ok := d.GetOk("feed_uri"); ok { - feed.FeedURI = v.(string) - } - - if v, ok := d.GetOk("registry_path"); ok { - feed.RegistryPath = v.(string) - } - - if v, ok := d.GetOk("space_id"); ok { - feed.SpaceID = v.(string) - } - - if v, ok := d.GetOk("package_acquisition_location_options"); ok { - feed.PackageAcquisitionLocationOptions = getSliceFromTerraformTypeList(v) - } - - if v, ok := d.GetOk("password"); ok { - feed.Password = core.NewSensitiveValue(v.(string)) - } - - if v, ok := d.GetOk("username"); ok { - feed.Username = v.(string) - } - - return feed, nil -} - -func getDockerContainerRegistrySchema() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "api_version": { - Optional: true, - Type: schema.TypeString, - }, - "feed_uri": { - Description: "The URL to a Docker repository.", - Required: true, - Type: schema.TypeString, - ValidateDiagFunc: validation.ToDiagFunc(validation.IsURLWithHTTPorHTTPS), - }, - "id": getIDSchema(), - "name": { - Description: "A short, memorable, unique name for this feed. Example: ACME Builds.", - Required: true, - Type: schema.TypeString, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty), - }, - "password": getPasswordSchema(false), - "package_acquisition_location_options": { - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - Type: schema.TypeList, - }, - "registry_path": { - Optional: true, - Type: schema.TypeString, - }, - "space_id": getSpaceIDSchema(), - "username": getUsernameSchema(false), - } -} - -func setDockerContainerRegistry(ctx context.Context, d *schema.ResourceData, feed *feeds.DockerContainerRegistry) error { - d.Set("api_version", feed.APIVersion) - d.Set("feed_uri", feed.FeedURI) - d.Set("name", feed.Name) - d.Set("registry_path", feed.RegistryPath) - d.Set("space_id", feed.SpaceID) - d.Set("username", feed.Username) - - if err := d.Set("package_acquisition_location_options", feed.PackageAcquisitionLocationOptions); err != nil { - return fmt.Errorf("error setting package_acquisition_location_options: %s", err) - } - - d.SetId(feed.GetID()) - - return nil -} diff --git a/octopusdeploy_framework/framework_provider.go b/octopusdeploy_framework/framework_provider.go index 816b8f774..447f66237 100644 --- a/octopusdeploy_framework/framework_provider.go +++ b/octopusdeploy_framework/framework_provider.go @@ -2,9 +2,9 @@ package octopusdeploy_framework import ( "context" + "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util" "os" - "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/provider/schema" @@ -92,6 +92,7 @@ func (p *octopusDeployFrameworkProvider) Resources(ctx context.Context) []func() NewLibraryVariableSetFeedResource, NewVariableResource, NewProjectResource, + NewDockerContainerRegistryFeedResource, } } diff --git a/octopusdeploy_framework/resource_artifactory_generic_feed.go b/octopusdeploy_framework/resource_artifactory_generic_feed.go index e70900061..a1eb7ab58 100644 --- a/octopusdeploy_framework/resource_artifactory_generic_feed.go +++ b/octopusdeploy_framework/resource_artifactory_generic_feed.go @@ -29,7 +29,8 @@ func (r *artifactoryGenericFeedTypeResource) Metadata(ctx context.Context, req r func (r *artifactoryGenericFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: schemas.GetArtifactoryGenericFeedResourceSchema(), + Attributes: schemas.GetArtifactoryGenericFeedResourceSchema(), + Description: "This resource manages a Artifactory Generic feed in Octopus Deploy.", } } diff --git a/octopusdeploy_framework/resource_aws_elastic_container_registry.go b/octopusdeploy_framework/resource_aws_elastic_container_registry.go index 96f089a83..72cef3b51 100644 --- a/octopusdeploy_framework/resource_aws_elastic_container_registry.go +++ b/octopusdeploy_framework/resource_aws_elastic_container_registry.go @@ -28,7 +28,8 @@ func (r *awsElasticContainerRegistryFeedTypeResource) Metadata(ctx context.Conte func (r *awsElasticContainerRegistryFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: schemas.GetAwsElasticContainerRegistryFeedResourceSchema(), + Attributes: schemas.GetAwsElasticContainerRegistryFeedResourceSchema(), + Description: "This resource manages an AWS Elastic Container Registry in Octopus Deploy.", } } diff --git a/octopusdeploy_framework/resource_docker_container_registry.go b/octopusdeploy_framework/resource_docker_container_registry.go new file mode 100644 index 000000000..fa73ef902 --- /dev/null +++ b/octopusdeploy_framework/resource_docker_container_registry.go @@ -0,0 +1,183 @@ +package octopusdeploy_framework + +import ( + "context" + "fmt" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/feeds" + "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas" + "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +type dockerContainerRegistryFeedTypeResource struct { + *Config +} + +func NewDockerContainerRegistryFeedResource() resource.Resource { + return &dockerContainerRegistryFeedTypeResource{} +} + +func (r *dockerContainerRegistryFeedTypeResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = util.GetTypeName("docker_container_registry") +} + +func (r *dockerContainerRegistryFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: schemas.GetDockerContainerRegistryFeedResourceSchema(), + Description: "This resource manages a Docker Container Registry in Octopus Deploy.", + } +} + +func (r *dockerContainerRegistryFeedTypeResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + r.Config = ResourceConfiguration(req, resp) +} + +func (r *dockerContainerRegistryFeedTypeResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data *schemas.DockerContainerRegistryFeedTypeResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + dockerContainerRegistryFeed, err := createDockerContainerRegistryFeedResourceFromData(data) + if err != nil { + return + } + + tflog.Info(ctx, fmt.Sprintf("creating Docker Container Registry feed: %s", dockerContainerRegistryFeed.GetName())) + + client := r.Config.Client + createdFeed, err := feeds.Add(client, dockerContainerRegistryFeed) + if err != nil { + resp.Diagnostics.AddError("unable to create docker container registry feed", err.Error()) + return + } + + updateDataFromDockerContainerRegistryFeed(data, data.SpaceID.ValueString(), createdFeed.(*feeds.DockerContainerRegistry)) + + tflog.Info(ctx, fmt.Sprintf("Docker Container Registry feed created (%s)", data.ID)) + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *dockerContainerRegistryFeedTypeResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data *schemas.DockerContainerRegistryFeedTypeResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Info(ctx, fmt.Sprintf("reading Docker Container Registry feed (%s)", data.ID)) + + client := r.Config.Client + feed, err := feeds.GetByID(client, data.SpaceID.ValueString(), data.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError("unable to load docker container registry feed", err.Error()) + return + } + + dockerContainerRegistry := feed.(*feeds.DockerContainerRegistry) + updateDataFromDockerContainerRegistryFeed(data, data.SpaceID.ValueString(), dockerContainerRegistry) + + tflog.Info(ctx, fmt.Sprintf("Docker Container Registry feed read (%s)", dockerContainerRegistry.GetID())) + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *dockerContainerRegistryFeedTypeResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data, state *schemas.DockerContainerRegistryFeedTypeResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("updating docker container registry feed '%s'", data.ID.ValueString())) + + feed, err := createDockerContainerRegistryFeedResourceFromData(data) + feed.ID = state.ID.ValueString() + if err != nil { + resp.Diagnostics.AddError("unable to load docker container registry feed", err.Error()) + return + } + + tflog.Info(ctx, fmt.Sprintf("updating Docker Container Registry feed (%s)", data.ID)) + + client := r.Config.Client + updatedFeed, err := feeds.Update(client, feed) + if err != nil { + resp.Diagnostics.AddError("unable to update docker container registry feed", err.Error()) + return + } + + updateDataFromDockerContainerRegistryFeed(data, state.SpaceID.ValueString(), updatedFeed.(*feeds.DockerContainerRegistry)) + + tflog.Info(ctx, fmt.Sprintf("Docker Container Registry feed updated (%s)", data.ID)) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *dockerContainerRegistryFeedTypeResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data schemas.DockerContainerRegistryFeedTypeResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + if err := feeds.DeleteByID(r.Config.Client, data.SpaceID.ValueString(), data.ID.ValueString()); err != nil { + resp.Diagnostics.AddError("unable to delete docker container registry feed", err.Error()) + return + } +} + +func createDockerContainerRegistryFeedResourceFromData(data *schemas.DockerContainerRegistryFeedTypeResourceModel) (*feeds.DockerContainerRegistry, error) { + feed, err := feeds.NewDockerContainerRegistry(data.Name.ValueString()) + if err != nil { + return nil, err + } + + feed.ID = data.ID.ValueString() + feed.FeedURI = data.FeedUri.ValueString() + + var packageAcquisitionLocationOptions []string + for _, element := range data.PackageAcquisitionLocationOptions.Elements() { + packageAcquisitionLocationOptions = append(packageAcquisitionLocationOptions, element.(types.String).ValueString()) + } + + feed.PackageAcquisitionLocationOptions = packageAcquisitionLocationOptions + feed.Password = core.NewSensitiveValue(data.Password.ValueString()) + feed.SpaceID = data.SpaceID.ValueString() + feed.Username = data.Username.ValueString() + feed.APIVersion = data.APIVersion.ValueString() + feed.RegistryPath = data.RegistryPath.ValueString() + + return feed, nil +} + +func updateDataFromDockerContainerRegistryFeed(data *schemas.DockerContainerRegistryFeedTypeResourceModel, spaceId string, feed *feeds.DockerContainerRegistry) { + data.FeedUri = types.StringValue(feed.FeedURI) + data.Name = types.StringValue(feed.Name) + data.SpaceID = types.StringValue(spaceId) + if feed.APIVersion != "" { + data.APIVersion = types.StringValue(feed.APIVersion) + } + if feed.RegistryPath != "" { + data.RegistryPath = types.StringValue(feed.RegistryPath) + } + if feed.Username != "" { + data.Username = types.StringValue(feed.Username) + } + + packageAcquisitionLocationOptionsList := make([]attr.Value, len(feed.PackageAcquisitionLocationOptions)) + for i, option := range feed.PackageAcquisitionLocationOptions { + packageAcquisitionLocationOptionsList[i] = types.StringValue(option) + } + + var packageAcquisitionLocationOptionsListValue, _ = types.ListValue(types.StringType, packageAcquisitionLocationOptionsList) + data.PackageAcquisitionLocationOptions = packageAcquisitionLocationOptionsListValue + data.ID = types.StringValue(feed.ID) +} diff --git a/octopusdeploy/resource_docker_container_registry_test.go b/octopusdeploy_framework/resource_docker_container_registry_test.go similarity index 94% rename from octopusdeploy/resource_docker_container_registry_test.go rename to octopusdeploy_framework/resource_docker_container_registry_test.go index 377ced443..9e2c893fa 100644 --- a/octopusdeploy/resource_docker_container_registry_test.go +++ b/octopusdeploy_framework/resource_docker_container_registry_test.go @@ -1,16 +1,15 @@ -package octopusdeploy +package octopusdeploy_framework import ( "fmt" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/feeds" "github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework/octoclient" "github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework/test" + "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" "path/filepath" "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) func TestAccOctopusDeployDockerContainerRegistry(t *testing.T) { @@ -26,7 +25,7 @@ func TestAccOctopusDeployDockerContainerRegistry(t *testing.T) { resource.Test(t, resource.TestCase{ CheckDestroy: testDockerContainerRegistryCheckDestroy, - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { TestAccPreCheck(t) }, ProtoV6ProviderFactories: ProtoV6ProviderFactories(), Steps: []resource.TestStep{ { diff --git a/octopusdeploy_framework/resource_github_repository_feed.go b/octopusdeploy_framework/resource_github_repository_feed.go index 7a198daaa..30f7bdb28 100644 --- a/octopusdeploy_framework/resource_github_repository_feed.go +++ b/octopusdeploy_framework/resource_github_repository_feed.go @@ -28,7 +28,8 @@ func (r *githubRepositoryFeedTypeResource) Metadata(ctx context.Context, req res func (r *githubRepositoryFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: schemas.GetGitHubRepositoryFeedResourceSchema(), + Attributes: schemas.GetGitHubRepositoryFeedResourceSchema(), + Description: "This resource manages a GitHub repository feed in Octopus Deploy.", } } diff --git a/octopusdeploy_framework/resource_helm_feed.go b/octopusdeploy_framework/resource_helm_feed.go index 4fc1c9d3c..64ec52677 100644 --- a/octopusdeploy_framework/resource_helm_feed.go +++ b/octopusdeploy_framework/resource_helm_feed.go @@ -29,7 +29,8 @@ func (r *helmFeedTypeResource) Metadata(ctx context.Context, req resource.Metada func (r *helmFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: schemas.GetHelmFeedResourceSchema(), + Attributes: schemas.GetHelmFeedResourceSchema(), + Description: "This resource manages a Helm Feed in Octopus Deploy.", } } diff --git a/octopusdeploy_framework/resource_maven_feed.go b/octopusdeploy_framework/resource_maven_feed.go index c6f6ddd19..722081e81 100644 --- a/octopusdeploy_framework/resource_maven_feed.go +++ b/octopusdeploy_framework/resource_maven_feed.go @@ -28,7 +28,8 @@ func (r *mavenFeedTypeResource) Metadata(ctx context.Context, req resource.Metad func (r *mavenFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: schemas.GetMavenFeedResourceSchema(), + Attributes: schemas.GetMavenFeedResourceSchema(), + Description: "This resource manages a Maven feed in Octopus Deploy.", } } diff --git a/octopusdeploy_framework/resource_nuget_feed.go b/octopusdeploy_framework/resource_nuget_feed.go index 306e16f14..f053ea450 100644 --- a/octopusdeploy_framework/resource_nuget_feed.go +++ b/octopusdeploy_framework/resource_nuget_feed.go @@ -28,7 +28,8 @@ func (r *nugetFeedTypeResource) Metadata(ctx context.Context, req resource.Metad func (r *nugetFeedTypeResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: schemas.GetNugetFeedResourceSchema(), + Attributes: schemas.GetNugetFeedResourceSchema(), + Description: "This resource manages a Nuget feed in Octopus Deploy.", } } diff --git a/octopusdeploy_framework/schemas/docker_container_registry_feed.go b/octopusdeploy_framework/schemas/docker_container_registry_feed.go new file mode 100644 index 000000000..d7ff550c4 --- /dev/null +++ b/octopusdeploy_framework/schemas/docker_container_registry_feed.go @@ -0,0 +1,39 @@ +package schemas + +import ( + "github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util" + resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +const dockerContainerRegistryFeedDescription = "docker container registry feed" + +func GetDockerContainerRegistryFeedResourceSchema() map[string]resourceSchema.Attribute { + return map[string]resourceSchema.Attribute{ + "api_version": resourceSchema.StringAttribute{ + Optional: true, + }, + "feed_uri": util.GetFeedUriResourceSchema(), + "id": util.GetIdResourceSchema(), + "name": util.GetNameResourceSchema(true), + "package_acquisition_location_options": util.GetPackageAcquisitionLocationOptionsResourceSchema(), + "password": util.GetPasswordResourceSchema(false), + "space_id": util.GetSpaceIdResourceSchema(dockerContainerRegistryFeedDescription), + "username": util.GetUsernameResourceSchema(false), + "registry_path": resourceSchema.StringAttribute{ + Optional: true, + }, + } +} + +type DockerContainerRegistryFeedTypeResourceModel struct { + APIVersion types.String `tfsdk:"api_version"` + FeedUri types.String `tfsdk:"feed_uri"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + PackageAcquisitionLocationOptions types.List `tfsdk:"package_acquisition_location_options"` + Password types.String `tfsdk:"password"` + SpaceID types.String `tfsdk:"space_id"` + Username types.String `tfsdk:"username"` + RegistryPath types.String `tfsdk:"registry_path"` +} diff --git a/octopusdeploy_framework/schemas/library_variable_set.go b/octopusdeploy_framework/schemas/library_variable_set.go index f3355768f..5fab75d02 100644 --- a/octopusdeploy_framework/schemas/library_variable_set.go +++ b/octopusdeploy_framework/schemas/library_variable_set.go @@ -22,7 +22,8 @@ type LibraryVariableSetResourceModel struct { func GetLibraryVariableSetDataSourceSchema() datasourceSchema.Schema { return datasourceSchema.Schema{ - Attributes: getLibraryVariableSetDataSchema(), + Attributes: getLibraryVariableSetDataSchema(), + Description: "Provides information about existing library variable sets.", Blocks: map[string]datasourceSchema.Block{ "library_variable_sets": datasourceSchema.ListNestedBlock{ Description: "A list of library variable sets that match the filter(s).", @@ -97,6 +98,7 @@ func GetLibraryVariableSetResourceSchema() resourceSchema.Schema { Computed: true, }, }, + Description: "This resource manages library variable sets in Octopus Deploy.", Blocks: map[string]resourceSchema.Block{ "template": resourceSchema.ListNestedBlock{ NestedObject: resourceSchema.NestedBlockObject{ From 7c81ce944a04db0272c2a4aab8adac7d3b56a1b1 Mon Sep 17 00:00:00 2001 From: Huy Nguyen <162080607+HuyPhanNguyen@users.noreply.github.com> Date: Wed, 7 Aug 2024 18:37:14 +1000 Subject: [PATCH 2/3] Fix bug datasource spaces (#710) * Fix query.Ids convert and add basic test * Update the test * Fix the util method instead * just ignore if cant convert to string * try to fix flaky test * second try * Add lifecycle datasource test * Last try to avoid race condition * Test why not 7 variables create * switch the order --- octopusdeploy/testing_container_test.go | 5 ++ .../datasource_lifecycle_test.go | 63 +++++++++++++++++ .../datasource_spaces_test.go | 58 ++++++++++++++++ .../resource_variable_test.go | 15 +++- octopusdeploy_framework/schemas/schema.go | 7 +- terraform/49-variables/variables.tf | 68 ++++++++++++++++--- 6 files changed, 203 insertions(+), 13 deletions(-) create mode 100644 octopusdeploy_framework/datasource_lifecycle_test.go create mode 100644 octopusdeploy_framework/datasource_spaces_test.go diff --git a/octopusdeploy/testing_container_test.go b/octopusdeploy/testing_container_test.go index 8c1bd6397..6fd5dfba7 100644 --- a/octopusdeploy/testing_container_test.go +++ b/octopusdeploy/testing_container_test.go @@ -57,6 +57,11 @@ func TestMain(m *testing.M) { log.Printf("Failed to create client: (%s)", err.Error()) panic(m) } + + octoContainer = &test.OctopusContainer{ + Container: nil, + URI: url, + } } code := m.Run() os.Exit(code) diff --git a/octopusdeploy_framework/datasource_lifecycle_test.go b/octopusdeploy_framework/datasource_lifecycle_test.go new file mode 100644 index 000000000..c7febe404 --- /dev/null +++ b/octopusdeploy_framework/datasource_lifecycle_test.go @@ -0,0 +1,63 @@ +package octopusdeploy_framework + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDataSourceLifecycles(t *testing.T) { + spaceName := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha) + lifecycleName := "Default Lifecycle" + resourceName := "data.octopusdeploy_lifecycles.lifecycle_default_lifecycle" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { TestAccPreCheck(t) }, + ProtoV6ProviderFactories: ProtoV6ProviderFactories(), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceLifecyclesConfig(spaceName, lifecycleName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "space_id"), + resource.TestCheckResourceAttr(resourceName, "partial_name", lifecycleName), + resource.TestCheckResourceAttr(resourceName, "lifecycles.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "lifecycles.0.id"), + resource.TestCheckResourceAttr(resourceName, "lifecycles.0.name", lifecycleName), + testAccCheckOutputExists("octopus_space_id"), + testAccCheckOutputExists("octopus_lifecycle_id"), + ), + }, + }, + }) +} + +func testAccDataSourceLifecyclesConfig(spaceName, lifecycleName string) string { + return fmt.Sprintf(` +resource "octopusdeploy_space" "octopus_project_space_test" { + name = "%s" + is_default = false + is_task_queue_stopped = false + description = "Test space for lifecycles datasource" + space_managers_teams = ["teams-administrators"] +} + +data "octopusdeploy_lifecycles" "lifecycle_default_lifecycle" { + ids = null + partial_name = "%s" + space_id = octopusdeploy_space.octopus_project_space_test.id + skip = 0 + take = 1 + depends_on = [octopusdeploy_space.octopus_project_space_test] +} + +output "octopus_space_id" { + value = octopusdeploy_space.octopus_project_space_test.id +} + +output "octopus_lifecycle_id" { + value = data.octopusdeploy_lifecycles.lifecycle_default_lifecycle.lifecycles[0].id +} +`, spaceName, lifecycleName) +} diff --git a/octopusdeploy_framework/datasource_spaces_test.go b/octopusdeploy_framework/datasource_spaces_test.go new file mode 100644 index 000000000..dc48f1108 --- /dev/null +++ b/octopusdeploy_framework/datasource_spaces_test.go @@ -0,0 +1,58 @@ +package octopusdeploy_framework + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +func TestAccDataSourceSpaces(t *testing.T) { + spaceID := "Spaces-1" + resourceName := "data.octopusdeploy_spaces.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { TestAccPreCheck(t) }, + ProtoV6ProviderFactories: ProtoV6ProviderFactories(), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceSpacesConfig(spaceID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "ids.0", spaceID), + resource.TestCheckResourceAttr(resourceName, "skip", "0"), + resource.TestCheckResourceAttr(resourceName, "take", "1"), + resource.TestCheckResourceAttrSet(resourceName, "spaces.0.id"), + testAccCheckOutputExists("octopus_space_id"), + resource.TestCheckOutput("octopus_space_id", spaceID), + ), + }, + }, + }) +} + +func testAccDataSourceSpacesConfig(spaceID string) string { + tfConfig := fmt.Sprintf(` + data "octopusdeploy_spaces" "test" { + ids = ["%s"] + skip = 0 + take = 1 + } + + output "octopus_space_id" { + value = data.octopusdeploy_spaces.test.spaces[0].id + } + `, spaceID) + return tfConfig +} + +func testAccCheckOutputExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Outputs[name] + if !ok { + return fmt.Errorf("output %s not found", name) + } + return nil + } +} diff --git a/octopusdeploy_framework/resource_variable_test.go b/octopusdeploy_framework/resource_variable_test.go index 055d796d4..d71cc6dd8 100644 --- a/octopusdeploy_framework/resource_variable_test.go +++ b/octopusdeploy_framework/resource_variable_test.go @@ -3,7 +3,9 @@ package octopusdeploy_framework import ( "fmt" "path/filepath" + "strings" "testing" + "time" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" internalTest "github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal/test" @@ -320,6 +322,9 @@ func TestVariableResource(t *testing.T) { // Assert client, err := octoclient.CreateClient(octoContainer.URI, newSpaceId, test.ApiKey) project, err := client.Projects.GetByName("Test") + + // Add a short delay before querying the API + time.Sleep(5 * time.Second) variableSet, err := client.Variables.GetAll(project.ID) if err != nil { @@ -327,7 +332,15 @@ func TestVariableResource(t *testing.T) { } if len(variableSet.Variables) != 7 { - t.Fatalf("Expected 7 variables to be created.") + var report strings.Builder + report.WriteString(fmt.Sprintf("Expected 7 variables, but found %d.\nReturned variables:\n", len(variableSet.Variables))) + + for _, v := range variableSet.Variables { + report.WriteString(fmt.Sprintf("- Name: %s\n Type: %s\n Value: %s\n Scope: %+v\n\n", + v.Name, v.Type, v.Value, v.Scope)) + } + + t.Fatalf(report.String()) } for _, variable := range variableSet.Variables { diff --git a/octopusdeploy_framework/schemas/schema.go b/octopusdeploy_framework/schemas/schema.go index 5c786144b..395aefc7f 100644 --- a/octopusdeploy_framework/schemas/schema.go +++ b/octopusdeploy_framework/schemas/schema.go @@ -191,7 +191,12 @@ func GetBooleanResourceAttribute(description string, defaultValue bool, isOption func GetIds(ids types.List) []string { var result = make([]string, 0, len(ids.Elements())) for _, id := range ids.Elements() { - result = append(result, id.String()) + strVal, ok := id.(types.String) + + if !ok || strVal.IsNull() || strVal.IsUnknown() { + continue + } + result = append(result, strVal.ValueString()) } return result } diff --git a/terraform/49-variables/variables.tf b/terraform/49-variables/variables.tf index 9ebdc692c..0e2f15da7 100644 --- a/terraform/49-variables/variables.tf +++ b/terraform/49-variables/variables.tf @@ -1,21 +1,35 @@ + + +resource "octopusdeploy_variable" "scoped_project_variable_action" { + depends_on = [ + octopusdeploy_project.test_project, + ] + owner_id = octopusdeploy_project.test_project.id + type = "String" + name = "ActionScopedVariable" + value = "unscoped variable" + scope { + actions = [octopusdeploy_deployment_process.test_deployment_process.step[0].run_script_action[0].id] + } +} + resource "octopusdeploy_variable" "unscoped_project_variable" { + depends_on = [ + octopusdeploy_project.test_project, + octopusdeploy_variable.scoped_project_variable_action, + ] owner_id = octopusdeploy_project.test_project.id type = "String" name = "UnscopedVariable" value = "UnscopedVariable" } -resource "octopusdeploy_variable" "scoped_project_variable_action" { - owner_id = octopusdeploy_project.test_project.id - type = "String" - name = "ActionScopedVariable" - value = "unscoped variable" - scope { - actions = [octopusdeploy_deployment_process.test_deployment_process.step[0].run_script_action[0].id] - } -} - resource "octopusdeploy_variable" "scoped_project_variable_channel" { + depends_on = [ + octopusdeploy_project.test_project, + octopusdeploy_variable.unscoped_project_variable, + octopusdeploy_variable.scoped_project_variable_action, + ] owner_id = octopusdeploy_project.test_project.id type = "String" name = "ChannelScopedVariable" @@ -26,6 +40,12 @@ resource "octopusdeploy_variable" "scoped_project_variable_channel" { } resource "octopusdeploy_variable" "scoped_project_variable_environment" { + depends_on = [ + octopusdeploy_project.test_project, + octopusdeploy_variable.unscoped_project_variable, + octopusdeploy_variable.scoped_project_variable_action, + octopusdeploy_variable.scoped_project_variable_channel, + ] owner_id = octopusdeploy_project.test_project.id type = "String" name = "EnvironmentScopedVariable" @@ -36,6 +56,14 @@ resource "octopusdeploy_variable" "scoped_project_variable_environment" { } resource "octopusdeploy_variable" "scoped_project_variable_machine" { + depends_on = [ + octopusdeploy_project.test_project, + octopusdeploy_variable.unscoped_project_variable, + octopusdeploy_variable.scoped_project_variable_action, + octopusdeploy_variable.scoped_project_variable_channel, + octopusdeploy_variable.scoped_project_variable_environment + ] + owner_id = octopusdeploy_project.test_project.id type = "String" name = "MachineScopedVariable" @@ -46,6 +74,14 @@ resource "octopusdeploy_variable" "scoped_project_variable_machine" { } resource "octopusdeploy_variable" "scoped_project_variable_process" { + depends_on = [ + octopusdeploy_project.test_project, + octopusdeploy_variable.unscoped_project_variable, + octopusdeploy_variable.scoped_project_variable_action, + octopusdeploy_variable.scoped_project_variable_channel, + octopusdeploy_variable.scoped_project_variable_environment, + octopusdeploy_variable.scoped_project_variable_machine, + ] owner_id = octopusdeploy_project.test_project.id type = "String" name = "ProcessScopedVariable" @@ -56,6 +92,16 @@ resource "octopusdeploy_variable" "scoped_project_variable_process" { } resource "octopusdeploy_variable" "scoped_project_variable_role" { + depends_on = [ + octopusdeploy_project.test_project, + octopusdeploy_variable.unscoped_project_variable, + octopusdeploy_variable.scoped_project_variable_action, + octopusdeploy_variable.scoped_project_variable_channel, + octopusdeploy_variable.scoped_project_variable_environment, + octopusdeploy_variable.scoped_project_variable_machine, + octopusdeploy_variable.scoped_project_variable_process, + ] + owner_id = octopusdeploy_project.test_project.id type = "String" name = "RoleScopedVariable" @@ -63,4 +109,4 @@ resource "octopusdeploy_variable" "scoped_project_variable_role" { scope { roles = ["role"] } -} +} \ No newline at end of file From 3a8a027a764cda034b8840bbba6df254e5f0d6b4 Mon Sep 17 00:00:00 2001 From: Isaac Calligeros <101079287+IsaacCalligeros95@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:23:22 +0930 Subject: [PATCH 3/3] Isaac/mc schema fixes (#715) * propagate an error * The collection returned by data sources must not be optional * Add more optionals --------- Co-authored-by: Matthew Casperson --- octopusdeploy/data_source_tenants.go | 5 ++++- octopusdeploy/schema_account_resource.go | 1 + .../schema_azure_cloud_service_deployment_target.go | 2 +- .../schema_azure_service_fabric_cluster_deployment_target.go | 2 +- octopusdeploy/schema_azure_web_app_deployment_target.go | 2 +- octopusdeploy/schema_certificate.go | 2 +- octopusdeploy/schema_channel.go | 2 +- octopusdeploy/schema_cloud_region_deployment_target.go | 2 +- octopusdeploy/schema_deployment_target.go | 2 +- octopusdeploy/schema_kubernetes_agent_deployment_target.go | 2 +- octopusdeploy/schema_kubernetes_cluster_deployment_target.go | 2 +- octopusdeploy/schema_listening_tentacle_deployment_target.go | 2 +- octopusdeploy/schema_machine_policy.go | 2 +- .../schema_offline_package_drop_deployment_target.go | 2 +- octopusdeploy/schema_polling_tentacle_deployment_target.go | 2 +- octopusdeploy/schema_script_modules.go | 2 +- octopusdeploy/schema_ssh_connection_deployment_target.go | 2 +- octopusdeploy/schema_tag_set.go | 2 +- octopusdeploy/schema_team.go | 2 +- octopusdeploy/schema_tenant.go | 2 +- octopusdeploy/schema_user.go | 2 +- octopusdeploy/schema_user_role.go | 2 +- octopusdeploy/schema_worker_pool.go | 2 +- octopusdeploy_framework/schemas/gitCredential.go | 1 + octopusdeploy_framework/schemas/lifecycle.go | 1 + octopusdeploy_framework/schemas/project.go | 1 + 26 files changed, 29 insertions(+), 22 deletions(-) diff --git a/octopusdeploy/data_source_tenants.go b/octopusdeploy/data_source_tenants.go index fcbdceae8..4c9cfa569 100644 --- a/octopusdeploy/data_source_tenants.go +++ b/octopusdeploy/data_source_tenants.go @@ -44,7 +44,10 @@ func dataSourceTenantsRead(ctx context.Context, d *schema.ResourceData, meta int flattenedTenants = append(flattenedTenants, flattenTenant(tenant)) } - d.Set("tenants", flattenedTenants) + if err := d.Set("tenants", flattenedTenants); err != nil { + return diag.FromErr(err) + } + d.SetId("Tenants " + time.Now().UTC().String()) return nil diff --git a/octopusdeploy/schema_account_resource.go b/octopusdeploy/schema_account_resource.go index 5dbee9361..4a31f5017 100644 --- a/octopusdeploy/schema_account_resource.go +++ b/octopusdeploy/schema_account_resource.go @@ -50,6 +50,7 @@ func getAccountResourceDataSchema() map[string]*schema.Schema { Description: "A list of accounts that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, Type: schema.TypeList, + Optional: false, }, "id": getDataSchemaID(), "space_id": getQuerySpaceID(), diff --git a/octopusdeploy/schema_azure_cloud_service_deployment_target.go b/octopusdeploy/schema_azure_cloud_service_deployment_target.go index 46488a934..45e00de20 100644 --- a/octopusdeploy/schema_azure_cloud_service_deployment_target.go +++ b/octopusdeploy/schema_azure_cloud_service_deployment_target.go @@ -70,7 +70,7 @@ func getAzureCloudServiceDeploymentTargetDataSchema() map[string]*schema.Schema Computed: true, Description: "A list of Azure cloud service deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_azure_service_fabric_cluster_deployment_target.go b/octopusdeploy/schema_azure_service_fabric_cluster_deployment_target.go index 3f8af8905..639d08553 100644 --- a/octopusdeploy/schema_azure_service_fabric_cluster_deployment_target.go +++ b/octopusdeploy/schema_azure_service_fabric_cluster_deployment_target.go @@ -85,7 +85,7 @@ func getAzureServiceFabricClusterDeploymentTargetDataSchema() map[string]*schema Computed: true, Description: "A list of Azure service fabric cluster deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_azure_web_app_deployment_target.go b/octopusdeploy/schema_azure_web_app_deployment_target.go index 8478378b6..f8b2cfe25 100644 --- a/octopusdeploy/schema_azure_web_app_deployment_target.go +++ b/octopusdeploy/schema_azure_web_app_deployment_target.go @@ -55,7 +55,7 @@ func getAzureWebAppDeploymentTargetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of Azure web app deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_certificate.go b/octopusdeploy/schema_certificate.go index 4252f9899..2d35164c9 100644 --- a/octopusdeploy/schema_certificate.go +++ b/octopusdeploy/schema_certificate.go @@ -170,7 +170,7 @@ func getCertificateDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of certificates that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "first_result": getQueryFirstResult(), diff --git a/octopusdeploy/schema_channel.go b/octopusdeploy/schema_channel.go index 88aa0bda9..eed2eead6 100644 --- a/octopusdeploy/schema_channel.go +++ b/octopusdeploy/schema_channel.go @@ -73,7 +73,7 @@ func getChannelDataSchema() map[string]*schema.Schema { Computed: true, Description: "A channel that matches the specified filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "ids": getQueryIDs(), diff --git a/octopusdeploy/schema_cloud_region_deployment_target.go b/octopusdeploy/schema_cloud_region_deployment_target.go index bce3dd18e..8e2375e07 100644 --- a/octopusdeploy/schema_cloud_region_deployment_target.go +++ b/octopusdeploy/schema_cloud_region_deployment_target.go @@ -40,7 +40,7 @@ func getCloudRegionDeploymentTargetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of cloud region deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_deployment_target.go b/octopusdeploy/schema_deployment_target.go index 456265859..9649a7bec 100644 --- a/octopusdeploy/schema_deployment_target.go +++ b/octopusdeploy/schema_deployment_target.go @@ -90,7 +90,7 @@ func getDeploymentTargetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "environments": getQueryEnvironments(), diff --git a/octopusdeploy/schema_kubernetes_agent_deployment_target.go b/octopusdeploy/schema_kubernetes_agent_deployment_target.go index 822e7dce8..2323f311b 100644 --- a/octopusdeploy/schema_kubernetes_agent_deployment_target.go +++ b/octopusdeploy/schema_kubernetes_agent_deployment_target.go @@ -173,7 +173,7 @@ func getKubernetesAgentDeploymentTargetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of kubernetes agent deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_kubernetes_cluster_deployment_target.go b/octopusdeploy/schema_kubernetes_cluster_deployment_target.go index 6dcbd6a35..4704688ff 100644 --- a/octopusdeploy/schema_kubernetes_cluster_deployment_target.go +++ b/octopusdeploy/schema_kubernetes_cluster_deployment_target.go @@ -131,7 +131,7 @@ func getKubernetesClusterDeploymentTargetDataSchema() map[string]*schema.Schema Computed: true, Description: "A list of Kubernetes cluster deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_listening_tentacle_deployment_target.go b/octopusdeploy/schema_listening_tentacle_deployment_target.go index 32d2b3481..a35cdb8af 100644 --- a/octopusdeploy/schema_listening_tentacle_deployment_target.go +++ b/octopusdeploy/schema_listening_tentacle_deployment_target.go @@ -57,7 +57,7 @@ func getListeningTentacleDeploymentTargetDataSchema() map[string]*schema.Schema Computed: true, Description: "A list of listening tentacle deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_machine_policy.go b/octopusdeploy/schema_machine_policy.go index 537da34df..0d24b2f6c 100644 --- a/octopusdeploy/schema_machine_policy.go +++ b/octopusdeploy/schema_machine_policy.go @@ -112,7 +112,7 @@ func getMachinePolicyDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of machine policies that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "partial_name": getQueryPartialName(), diff --git a/octopusdeploy/schema_offline_package_drop_deployment_target.go b/octopusdeploy/schema_offline_package_drop_deployment_target.go index f8b88f704..371a08b01 100644 --- a/octopusdeploy/schema_offline_package_drop_deployment_target.go +++ b/octopusdeploy/schema_offline_package_drop_deployment_target.go @@ -51,7 +51,7 @@ func getOfflinePackageDropDeploymentTargetDataSchema() map[string]*schema.Schema Computed: true, Description: "A list of offline package drop deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_polling_tentacle_deployment_target.go b/octopusdeploy/schema_polling_tentacle_deployment_target.go index ab6472663..ee73b0cfb 100644 --- a/octopusdeploy/schema_polling_tentacle_deployment_target.go +++ b/octopusdeploy/schema_polling_tentacle_deployment_target.go @@ -51,7 +51,7 @@ func getPollingTentacleDeploymentTargetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of polling tentacle deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_script_modules.go b/octopusdeploy/schema_script_modules.go index c4a24d1f8..906d2ea54 100644 --- a/octopusdeploy/schema_script_modules.go +++ b/octopusdeploy/schema_script_modules.go @@ -86,7 +86,7 @@ func getScriptModuleDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of script modules that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "partial_name": getQueryPartialName(), diff --git a/octopusdeploy/schema_ssh_connection_deployment_target.go b/octopusdeploy/schema_ssh_connection_deployment_target.go index 90934132f..df977c19d 100644 --- a/octopusdeploy/schema_ssh_connection_deployment_target.go +++ b/octopusdeploy/schema_ssh_connection_deployment_target.go @@ -57,7 +57,7 @@ func getSSHConnectionDeploymentTargetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of SSH connection deployment targets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, } diff --git a/octopusdeploy/schema_tag_set.go b/octopusdeploy/schema_tag_set.go index db5c31a23..953b5c40c 100644 --- a/octopusdeploy/schema_tag_set.go +++ b/octopusdeploy/schema_tag_set.go @@ -54,7 +54,7 @@ func getTagSetDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of tag sets that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "take": getQueryTake(), diff --git a/octopusdeploy/schema_team.go b/octopusdeploy/schema_team.go index 3f782a1c9..d0656662e 100644 --- a/octopusdeploy/schema_team.go +++ b/octopusdeploy/schema_team.go @@ -85,7 +85,7 @@ func getTeamDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of teams that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, } diff --git a/octopusdeploy/schema_tenant.go b/octopusdeploy/schema_tenant.go index 6045f5981..260ba93f8 100644 --- a/octopusdeploy/schema_tenant.go +++ b/octopusdeploy/schema_tenant.go @@ -67,7 +67,7 @@ func getTenantDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of tenants that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, "take": getQueryTake(), diff --git a/octopusdeploy/schema_user.go b/octopusdeploy/schema_user.go index 5ef089c67..620c3db37 100644 --- a/octopusdeploy/schema_user.go +++ b/octopusdeploy/schema_user.go @@ -74,7 +74,7 @@ func getUserDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of users that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, } diff --git a/octopusdeploy/schema_user_role.go b/octopusdeploy/schema_user_role.go index 9258402e5..4487a9170 100644 --- a/octopusdeploy/schema_user_role.go +++ b/octopusdeploy/schema_user_role.go @@ -84,7 +84,7 @@ func getUserRoleDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of user roles that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, } diff --git a/octopusdeploy/schema_worker_pool.go b/octopusdeploy/schema_worker_pool.go index 9207124c2..036e2a04a 100644 --- a/octopusdeploy/schema_worker_pool.go +++ b/octopusdeploy/schema_worker_pool.go @@ -39,7 +39,7 @@ func getWorkerPoolDataSchema() map[string]*schema.Schema { Computed: true, Description: "A list of worker pools that match the filter(s).", Elem: &schema.Resource{Schema: dataSchema}, - Optional: true, + Optional: false, Type: schema.TypeList, }, } diff --git a/octopusdeploy_framework/schemas/gitCredential.go b/octopusdeploy_framework/schemas/gitCredential.go index 2a29f1b4d..594f927b1 100644 --- a/octopusdeploy_framework/schemas/gitCredential.go +++ b/octopusdeploy_framework/schemas/gitCredential.go @@ -54,6 +54,7 @@ func GetGitCredentialDataSourceSchema() map[string]datasourceSchema.Attribute { "take": util.GetQueryTakeDatasourceSchema(), "git_credentials": datasourceSchema.ListNestedAttribute{ Computed: true, + Optional: false, Description: "A list of Git Credentials that match the filter(s).", NestedObject: datasourceSchema.NestedAttributeObject{ Attributes: GetGitCredentialAttributes(), diff --git a/octopusdeploy_framework/schemas/lifecycle.go b/octopusdeploy_framework/schemas/lifecycle.go index 092d48ab6..04f7f493a 100644 --- a/octopusdeploy_framework/schemas/lifecycle.go +++ b/octopusdeploy_framework/schemas/lifecycle.go @@ -97,6 +97,7 @@ func GetDatasourceLifecycleSchema() datasourceSchema.Schema { "take": util.GetQueryTakeDatasourceSchema(), "lifecycles": datasourceSchema.ListNestedAttribute{ Computed: true, + Optional: false, NestedObject: datasourceSchema.NestedAttributeObject{ Attributes: map[string]datasourceSchema.Attribute{ "id": util.GetIdDatasourceSchema(), diff --git a/octopusdeploy_framework/schemas/project.go b/octopusdeploy_framework/schemas/project.go index fc4fee3b7..814710bda 100644 --- a/octopusdeploy_framework/schemas/project.go +++ b/octopusdeploy_framework/schemas/project.go @@ -193,6 +193,7 @@ func getProjectsDataSourceAttribute() datasourceSchema.ListNestedAttribute { return datasourceSchema.ListNestedAttribute{ Description: "A list of projects that match the filter(s).", Computed: true, + Optional: false, NestedObject: datasourceSchema.NestedAttributeObject{ Attributes: map[string]datasourceSchema.Attribute{ "allow_deployments_to_no_targets": util.DataSourceBool().Computed().Deprecated("Allow deployments to be created when there are no targets.").Build(),