Skip to content

Commit

Permalink
Merge pull request #464 from hashicorp/uk1288-replace-deprecated-api
Browse files Browse the repository at this point in the history
Replace deprecated GET api for registry modules
  • Loading branch information
Uk1288 committed Jul 14, 2022
2 parents 833ec49 + 1138e10 commit 0f7b645
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1,8 +1,10 @@
# Unreleased

## Enhancements
* [beta] Add support for triggering Workspace runs through matching Git tags [#434](https://github.com/hashicorp/go-tfe/pull/434)
* Add `Query` param field to `AgentPoolListOptions` to allow searching based on agent pool name, by @JarrettSpiker [#417](https://github.com/hashicorp/go-tfe/pull/417)
* Add organization scope and allowed workspaces field for scope agents by @Netra2104 [#453](https://github.com/hashicorp/go-tfe/pull/453)
* Adds `Namespace` and `RegistryName` fields to `RegistryModuleID` to allow reading of Public Registry Modules by @Uk1288 [#464](https://github.com/hashicorp/go-tfe/pull/464)

## Bug fixes
* Fixed JSON mapping for Configuration Versions failing to properly set the `speculative` property [#459](https://github.com/hashicorp/go-tfe/pull/459)
Expand Down
4 changes: 3 additions & 1 deletion errors.go
Expand Up @@ -174,7 +174,7 @@ var (

ErrInvalidArch = errors.New("invalid value for arch")

ErrInvalidRegistryName = errors.New("invalid value for registry-name")
ErrInvalidRegistryName = errors.New(`invalid value for registry-name. It must be either "private" or "public"`)
)

// Missing values for required field/option
Expand Down Expand Up @@ -300,4 +300,6 @@ var (
ErrRequiredFilename = errors.New("filename is required")

ErrInvalidAsciiArmor = errors.New("ascii armor is invalid")

ErrRequiredNamespace = errors.New("namespace is required for public registry")
)
37 changes: 36 additions & 1 deletion registry_module.go
Expand Up @@ -3,7 +3,9 @@ package tfe
import (
"context"
"fmt"
"log"
"net/url"
"strings"
)

// Compile-time proof of interface implementation.
Expand Down Expand Up @@ -82,6 +84,11 @@ type RegistryModuleID struct {
Name string
// The module's provider, see RegistryModule.Provider
Provider string
// The namespace of the module. For private modules this is the name of the organization that owns the module
// Required for public modules
Namespace string
// Either public or private. If not provided, defaults to private
RegistryName RegistryName
}

// RegistryModuleList represents a list of registry modules.
Expand All @@ -95,6 +102,8 @@ type RegistryModule struct {
ID string `jsonapi:"primary,registry-modules"`
Name string `jsonapi:"attr,name"`
Provider string `jsonapi:"attr,provider"`
RegistryName RegistryName `jsonapi:"attr,registry-name"`
Namespace string `jsonapi:"attr,namespace"`
Permissions *RegistryModulePermissions `jsonapi:"attr,permissions"`
Status RegistryModuleStatus `jsonapi:"attr,status"`
VCSRepo *VCSRepo `jsonapi:"attr,vcs-repo"`
Expand Down Expand Up @@ -307,12 +316,25 @@ func (r *registryModules) Read(ctx context.Context, moduleID RegistryModuleID) (
return nil, err
}

if moduleID.RegistryName == "" {
log.Println("[WARN] Support for using the RegistryModuleID without RegistryName is deprecated as of release 1.5.0 and may be removed in a future version. The preferred method is to include the RegistryName in RegistryModuleID.")
moduleID.RegistryName = PrivateRegistry
}

if moduleID.RegistryName == PrivateRegistry && strings.TrimSpace(moduleID.Namespace) == "" {
log.Println("[WARN] Support for using the RegistryModuleID without Namespace is deprecated as of release 1.5.0 and may be removed in a future version. The preferred method is to include the Namespace in RegistryModuleID.")
moduleID.Namespace = moduleID.Organization
}

u := fmt.Sprintf(
"registry-modules/show/%s/%s/%s",
"organizations/%s/registry-modules/%s/%s/%s/%s",
url.QueryEscape(moduleID.Organization),
url.QueryEscape(string(moduleID.RegistryName)),
url.QueryEscape(moduleID.Namespace),
url.QueryEscape(moduleID.Name),
url.QueryEscape(moduleID.Provider),
)

req, err := r.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -420,6 +442,19 @@ func (o RegistryModuleID) valid() error {
return ErrInvalidProvider
}

switch o.RegistryName {
case PublicRegistry:
if !validString(&o.Namespace) {
return ErrRequiredNamespace
}
case PrivateRegistry:
case "":
// no-op: RegistryName is optional
// for all other string
default:
return ErrInvalidRegistryName
}

return nil
}

Expand Down
45 changes: 43 additions & 2 deletions registry_module_integration_test.go
Expand Up @@ -417,6 +417,31 @@ func TestRegistryModulesRead(t *testing.T) {
})
})

t.Run("with complete registry module ID fields", func(t *testing.T) {
rm, err := client.RegistryModules.Read(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
Namespace: orgTest.Name,
RegistryName: PrivateRegistry,
})
require.NoError(t, err)
require.NotEmpty(t, rm)
assert.Equal(t, registryModuleTest.ID, rm.ID)

t.Run("permissions are properly decoded", func(t *testing.T) {
require.NotEmpty(t, rm.Permissions)
assert.True(t, rm.Permissions.CanDelete)
assert.True(t, rm.Permissions.CanResync)
assert.True(t, rm.Permissions.CanRetry)
})

t.Run("timestamps are properly decoded", func(t *testing.T) {
assert.NotEmpty(t, rm.CreatedAt)
assert.NotEmpty(t, rm.UpdatedAt)
})
})

t.Run("without a name", func(t *testing.T) {
rm, err := client.RegistryModules.Read(ctx, RegistryModuleID{
Organization: orgTest.Name,
Expand Down Expand Up @@ -457,6 +482,18 @@ func TestRegistryModulesRead(t *testing.T) {
assert.Equal(t, err, ErrInvalidProvider)
})

t.Run("with an invalid registry name", func(t *testing.T) {
rm, err := client.RegistryModules.Read(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
Namespace: orgTest.Name,
RegistryName: "PRIVATE",
})
assert.Nil(t, rm)
assert.Equal(t, err, ErrInvalidRegistryName)
})

t.Run("without a valid organization", func(t *testing.T) {
rm, err := client.RegistryModules.Read(ctx, RegistryModuleID{
Organization: badIdentifier,
Expand Down Expand Up @@ -775,8 +812,10 @@ func TestRegistryModule_Unmarshal(t *testing.T) {
"type": "registry-modules",
"id": "1",
"attributes": map[string]interface{}{
"name": "module",
"provider": "tfe",
"name": "module",
"provider": "tfe",
"namespace": "org-abc",
"registry-name": "private",
"permissions": map[string]interface{}{
"can-delete": true,
"can-resync": true,
Expand Down Expand Up @@ -815,6 +854,8 @@ func TestRegistryModule_Unmarshal(t *testing.T) {
assert.Equal(t, rm.ID, "1")
assert.Equal(t, rm.Name, "module")
assert.Equal(t, rm.Provider, "tfe")
assert.Equal(t, rm.Namespace, "org-abc")
assert.Equal(t, rm.RegistryName, PrivateRegistry)
assert.Equal(t, rm.Permissions.CanDelete, true)
assert.Equal(t, rm.Permissions.CanRetry, true)
assert.Equal(t, rm.Status, RegistryModuleStatusPending)
Expand Down

0 comments on commit 0f7b645

Please sign in to comment.