diff --git a/CHANGELOG.md b/CHANGELOG.md index b74267e0f..8637f1a59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Unreleased FEATURES: +* r/registry_module: Adds `no_code` field. ([#673](https://github.com/hashicorp/terraform-provider-tfe/pull/673)) * r/tfe_organization: Add `allow_force_delete_workspaces` attribute to set whether admins are permitted to delete workspaces with resource under management. ([#661](https://github.com/hashicorp/terraform-provider-tfe/pull/661)) ## v0.38.0 (October 24, 2022) diff --git a/go.mod b/go.mod index f2f6cd2ed..686c7e55a 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.1 // indirect github.com/hashicorp/go-slug v0.10.0 - github.com/hashicorp/go-tfe v1.12.0 + github.com/hashicorp/go-tfe v1.13.0 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce github.com/hashicorp/hcl/v2 v2.15.0 // indirect diff --git a/go.sum b/go.sum index f16d31ba1..380b30b4d 100644 --- a/go.sum +++ b/go.sum @@ -163,8 +163,8 @@ github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1 github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-slug v0.10.0 h1:mh4DDkBJTh9BuEjY/cv8PTo7k9OjT4PcW8PgZnJ4jTY= github.com/hashicorp/go-slug v0.10.0/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41RKLH301v4= -github.com/hashicorp/go-tfe v1.12.0 h1:2l7emKW8rNTTbnxYHNVj6b46iJzOEp2G/3xIHfGSDnc= -github.com/hashicorp/go-tfe v1.12.0/go.mod h1:thYtIxtgBpDDNdf/2yYPdBJ94Fz5yT5XCNZvGtTGHAU= +github.com/hashicorp/go-tfe v1.13.0 h1:Z8pJrmN9BV5EncnFRmQmLjhP7pHMNXkC2VkCQXWxKjM= +github.com/hashicorp/go-tfe v1.13.0/go.mod h1:thYtIxtgBpDDNdf/2yYPdBJ94Fz5yT5XCNZvGtTGHAU= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= diff --git a/tfe/resource_tfe_registry_module.go b/tfe/resource_tfe_registry_module.go index adb3e8687..5e663ad52 100644 --- a/tfe/resource_tfe_registry_module.go +++ b/tfe/resource_tfe_registry_module.go @@ -17,6 +17,7 @@ func resourceTFERegistryModule() *schema.Resource { return &schema.Resource{ Create: resourceTFERegistryModuleCreate, Read: resourceTFERegistryModuleRead, + Update: resourceTFERegistryModuleUpdate, Delete: resourceTFERegistryModuleDelete, Importer: &schema.ResourceImporter{ StateContext: resourceTFERegistryModuleImporter, @@ -76,6 +77,11 @@ func resourceTFERegistryModule() *schema.Resource { ForceNew: true, RequiredWith: []string{"registry_name"}, }, + "no_code": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, "registry_name": { Type: schema.TypeString, Optional: true, @@ -118,6 +124,7 @@ func resourceTFERegistryModuleCreateWithoutVCS(meta interface{}, d *schema.Resou options := tfe.RegistryModuleCreateOptions{ Name: tfe.String(d.Get("name").(string)), Provider: tfe.String(d.Get("module_provider").(string)), + NoCode: d.Get("no_code").(bool), } if registryName, ok := d.GetOk("registry_name"); ok { @@ -190,6 +197,40 @@ func resourceTFERegistryModuleCreate(d *schema.ResourceData, meta interface{}) e return resourceTFERegistryModuleRead(d, meta) } +func resourceTFERegistryModuleUpdate(d *schema.ResourceData, meta interface{}) error { + tfeClient := meta.(*tfe.Client) + + options := tfe.RegistryModuleUpdateOptions{ + NoCode: tfe.Bool(d.Get("no_code").(bool)), + } + var registryModule *tfe.RegistryModule + var err error + + rmID := tfe.RegistryModuleID{ + Organization: d.Get("organization").(string), + Name: d.Get("name").(string), + Provider: d.Get("module_provider").(string), + Namespace: d.Get("namespace").(string), + RegistryName: tfe.RegistryName(d.Get("registry_name").(string)), + } + + err = resource.Retry(time.Duration(5)*time.Minute, func() *resource.RetryError { + registryModule, err = tfeClient.RegistryModules.Update(ctx, rmID, options) + if err != nil { + return resource.RetryableError(err) + } + return nil + }) + + if err != nil { + return fmt.Errorf("Error while waiting for module %s/%s to be updated: %w", registryModule.Organization.Name, registryModule.Name, err) + } + + d.SetId(registryModule.ID) + + return resourceTFERegistryModuleRead(d, meta) +} + func resourceTFERegistryModuleRead(d *schema.ResourceData, meta interface{}) error { tfeClient := meta.(*tfe.Client) @@ -221,6 +262,7 @@ func resourceTFERegistryModuleRead(d *schema.ResourceData, meta interface{}) err d.Set("organization", registryModule.Organization.Name) d.Set("namespace", registryModule.Namespace) d.Set("registry_name", registryModule.RegistryName) + d.Set("no_code", registryModule.NoCode) // Set VCS repo options. var vcsRepo []interface{} diff --git a/tfe/resource_tfe_registry_module_test.go b/tfe/resource_tfe_registry_module_test.go index 2453da3b4..2eb042209 100644 --- a/tfe/resource_tfe_registry_module_test.go +++ b/tfe/resource_tfe_registry_module_test.go @@ -236,6 +236,59 @@ func TestAccTFERegistryModule_publicRegistryModule(t *testing.T) { }) } +func TestAccTFERegistryModule_noCodeModule(t *testing.T) { + registryModule := &tfe.RegistryModule{} + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + orgName := fmt.Sprintf("tst-terraform-%d", rInt) + + expectedRegistryModuleAttributes := &tfe.RegistryModule{ + Name: "vpc", + Provider: "aws", + RegistryName: tfe.PublicRegistry, + Namespace: "terraform-aws-modules", + Organization: &tfe.Organization{Name: orgName}, + NoCode: true, + } + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckTFERegistryModuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFERegistryModule_NoCode(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFERegistryModuleExists( + "tfe_registry_module.foobar", + tfe.RegistryModuleID{ + Organization: orgName, + Name: expectedRegistryModuleAttributes.Name, + Provider: expectedRegistryModuleAttributes.Provider, + RegistryName: expectedRegistryModuleAttributes.RegistryName, + Namespace: expectedRegistryModuleAttributes.Namespace, + }, registryModule), + testAccCheckTFERegistryModuleAttributes(registryModule, expectedRegistryModuleAttributes), + resource.TestCheckResourceAttr( + "tfe_registry_module.foobar", "organization", orgName), + resource.TestCheckResourceAttr( + "tfe_registry_module.foobar", "name", expectedRegistryModuleAttributes.Name), + resource.TestCheckResourceAttr( + "tfe_registry_module.foobar", "module_provider", expectedRegistryModuleAttributes.Provider), + resource.TestCheckResourceAttr( + "tfe_registry_module.foobar", "namespace", expectedRegistryModuleAttributes.Namespace), + resource.TestCheckResourceAttr( + "tfe_registry_module.foobar", "registry_name", string(expectedRegistryModuleAttributes.RegistryName)), + resource.TestCheckResourceAttr( + "tfe_registry_module.foobar", "no_code", fmt.Sprint(expectedRegistryModuleAttributes.NoCode)), + ), + }, + }, + }) +} + func TestAccTFERegistryModuleImport_vcsPrivateRMDeprecatedFormat(t *testing.T) { rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() @@ -674,6 +727,24 @@ resource "tfe_registry_module" "foobar" { rInt) } +func testAccTFERegistryModule_NoCode(rInt int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_registry_module" "foobar" { + organization = tfe_organization.foobar.id + namespace = "terraform-aws-modules" + module_provider = "aws" + name = "vpc" + registry_name = "public" + no_code = true + }`, + rInt) +} + func testAccTFERegistryModule_invalidWithBothVCSRepoAndModuleProvider() string { return ` resource "tfe_registry_module" "foobar" { diff --git a/website/docs/r/registry_module.html.markdown b/website/docs/r/registry_module.html.markdown index c9dfed58d..58e65b92a 100644 --- a/website/docs/r/registry_module.html.markdown +++ b/website/docs/r/registry_module.html.markdown @@ -70,6 +70,24 @@ resource "tfe_registry_module" "test-public-registry-module" { } ``` +Create no-code provisioning registry module: + +```hcl +resource "tfe_organization" "test-organization" { + name = "my-org-name" + email = "admin@company.com" +} + +resource "tfe_registry_module" "test-no-code-provisioning-registry-module" { + organization = tfe_organization.test-organization.name + namespace = "terraform-aws-modules" + module_provider = "aws" + name = "vpc" + registry_name = "public" + no_code = true +} +``` + ## Argument Reference The following arguments are supported: @@ -81,6 +99,7 @@ The following arguments are supported: * `organization` - (Optional) The name of the organization associated with the registry module. It must be set if `module_provider` is used. * `namespace` - (Optional) The namespace of a public registry module. It can be used if `module_provider` is set and `registry_name` is public. * `registry_name` - (Optional) Whether the registry module is private or public. It can be used if `module_provider` is set. +* `no_code` - (Optional) Whether the registry module is enabled for [no-code provisioning](https://learn.hashicorp.com/tutorials/terraform/no-code-provisioning). Defaults to `false`. The `vcs_repo` block supports: @@ -101,6 +120,7 @@ The `vcs_repo` block supports: * `organization` - The name of the organization associated with the registry module. * `namespace` - The namespace of the module. For private modules this is the name of the organization that owns the module. * `registry_name` - The registry name of the registry module depicting whether the registry module is private or public. +* `no_code` - The property that will enable or disable a module as no-code provisioning ready. ## Import