Skip to content

Commit

Permalink
add support for both public and private module creation without VCS
Browse files Browse the repository at this point in the history
  • Loading branch information
Uk1288 committed Jul 11, 2022
1 parent 2a4cc50 commit bf74088
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 17 deletions.
4 changes: 4 additions & 0 deletions errors.go
Expand Up @@ -29,6 +29,8 @@ var (
ErrUnsupportedRunTriggerType = errors.New(`"RunTriggerType" must be "inbound" when requesting "include" query params`)

ErrUnsupportedBothTriggerPatternsAndPrefixes = errors.New(`"TriggerPatterns" and "TriggerPrefixes" cannot be populated at the same time`)

ErrUnsupportedBothNamespaceAndPrivateRegistryName = errors.New(`"Namespace" cannot be populated when "RegistryName" is "private"`)
)

// Library errors that usually indicate a bug in the implementation of go-tfe
Expand Down Expand Up @@ -294,4 +296,6 @@ var (
ErrRequiredFilename = errors.New("filename is required")

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

ErrRequiredNamespace = errors.New("namespace is required for public registry")
)
23 changes: 23 additions & 0 deletions registry_module.go
Expand Up @@ -95,6 +95,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 @@ -150,6 +152,11 @@ type RegistryModuleCreateOptions struct {
Name *string `jsonapi:"attr,name"`
// Required:
Provider *string `jsonapi:"attr,provider"`
// Optional: Whether this is a publicly maintained module or private. Must be either public or private.
// Defaults to private if not specified
RegistryName RegistryName `jsonapi:"attr,registry-name,omitempty"`
// Optional: The namespace of this module. Required for public modules only.
Namespace string `jsonapi:"attr,namespace,omitempty"`
}

// RegistryModuleCreateVersionOptions is used when creating a registry module version
Expand Down Expand Up @@ -436,6 +443,22 @@ func (o RegistryModuleCreateOptions) valid() error {
if !validStringID(o.Provider) {
return ErrInvalidProvider
}

// RegistryName is optional, only validate if specified
if validString((*string)(&o.RegistryName)) {
registryNamesMap := map[RegistryName]RegistryName{PublicRegistry: PublicRegistry, PrivateRegistry: PrivateRegistry}
if _, ok := registryNamesMap[o.RegistryName]; !ok {
return ErrInvalidRegistryName
}

if o.RegistryName == PublicRegistry && !validString(&o.Namespace) {
return ErrRequiredNamespace
}

if o.RegistryName == PrivateRegistry && validString(&o.Namespace) {
return ErrUnsupportedBothNamespaceAndPrivateRegistryName
}
}
return nil
}

Expand Down
111 changes: 94 additions & 17 deletions registry_module_integration_test.go
Expand Up @@ -71,29 +71,72 @@ func TestRegistryModulesCreate(t *testing.T) {
defer orgTestCleanup()

t.Run("with valid options", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("name"),
Provider: String("provider"),
assertRegistryModuleAttributes := func(t *testing.T, registryModule *RegistryModule) {
t.Run("permissions are properly decoded", func(t *testing.T) {
assert.True(t, registryModule.Permissions.CanDelete)
assert.True(t, registryModule.Permissions.CanResync)
assert.True(t, registryModule.Permissions.CanRetry)
})

t.Run("relationships are properly decoded", func(t *testing.T) {
assert.Equal(t, orgTest.Name, registryModule.Organization.Name)
})

t.Run("timestamps are properly decoded", func(t *testing.T) {
assert.NotEmpty(t, registryModule.CreatedAt)
assert.NotEmpty(t, registryModule.UpdatedAt)
})
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, *options.Name, rm.Name)
assert.Equal(t, *options.Provider, rm.Provider)

t.Run("permissions are properly decoded", func(t *testing.T) {
assert.True(t, rm.Permissions.CanDelete)
assert.True(t, rm.Permissions.CanResync)
assert.True(t, rm.Permissions.CanRetry)
t.Run("without RegistryName", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("name"),
Provider: String("provider"),
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, *options.Name, rm.Name)
assert.Equal(t, *options.Provider, rm.Provider)
assert.Equal(t, PrivateRegistry, rm.RegistryName)
assert.Equal(t, orgTest.Name, rm.Namespace)

assertRegistryModuleAttributes(t, rm)
})

t.Run("relationships are properly decoded", func(t *testing.T) {
assert.Equal(t, orgTest.Name, rm.Organization.Name)
t.Run("with private RegistryName", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("another_name"),
Provider: String("provider"),
RegistryName: PrivateRegistry,
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, *options.Name, rm.Name)
assert.Equal(t, *options.Provider, rm.Provider)
assert.Equal(t, options.RegistryName, rm.RegistryName)
assert.Equal(t, orgTest.Name, rm.Namespace)

assertRegistryModuleAttributes(t, rm)
})

t.Run("timestamps are properly decoded", func(t *testing.T) {
assert.NotEmpty(t, rm.CreatedAt)
assert.NotEmpty(t, rm.UpdatedAt)
t.Run("with public RegistryName", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("vpc"),
Provider: String("aws"),
RegistryName: PublicRegistry,
Namespace: "terraform-aws-modules",
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)
assert.Equal(t, *options.Name, rm.Name)
assert.Equal(t, *options.Provider, rm.Provider)
assert.Equal(t, options.RegistryName, rm.RegistryName)
assert.Equal(t, options.Namespace, rm.Namespace)

assertRegistryModuleAttributes(t, rm)
})
})

Expand Down Expand Up @@ -135,6 +178,40 @@ func TestRegistryModulesCreate(t *testing.T) {
assert.Nil(t, rm)
assert.Equal(t, err, ErrInvalidProvider)
})

t.Run("with an invalid registry name", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("name"),
Provider: String("provider"),
RegistryName: "PRIVATE",
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
assert.Nil(t, rm)
assert.Equal(t, err, ErrInvalidRegistryName)
})

t.Run("without a namespace for public registry name", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("name"),
Provider: String("provider"),
RegistryName: PublicRegistry,
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
assert.Nil(t, rm)
assert.Equal(t, err, ErrRequiredNamespace)
})

t.Run("with a namespace for private registry name", func(t *testing.T) {
options := RegistryModuleCreateOptions{
Name: String("name"),
Provider: String("provider"),
RegistryName: PrivateRegistry,
Namespace: "namespace",
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
assert.Nil(t, rm)
assert.Equal(t, err, ErrUnsupportedBothNamespaceAndPrivateRegistryName)
})
})

t.Run("without a valid organization", func(t *testing.T) {
Expand Down

0 comments on commit bf74088

Please sign in to comment.