Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no code provisioning in registry modules #562

Merged
merged 13 commits into from Nov 15, 2022
Merged
15 changes: 15 additions & 0 deletions mocks/registry_module_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 56 additions & 0 deletions registry_module.go
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"strings"
)
Expand Down Expand Up @@ -40,6 +41,9 @@ type RegistryModules interface {
// Delete a specific registry module version
DeleteVersion(ctx context.Context, moduleID RegistryModuleID, version string) error

// Update properties of a registry module
Update(ctx context.Context, moduleID RegistryModuleID, options RegistryModuleUpdateOptions) (*RegistryModule, error)

// Upload Terraform configuration files for the provided registry module version. It
// requires a path to the configuration files on disk, which will be packaged by
// hashicorp/go-slug before being uploaded.
Expand Down Expand Up @@ -104,6 +108,7 @@ type RegistryModule struct {
Provider string `jsonapi:"attr,provider"`
RegistryName RegistryName `jsonapi:"attr,registry-name"`
Namespace string `jsonapi:"attr,namespace"`
NoCode bool `jsonapi:"attr,no-code"`
Permissions *RegistryModulePermissions `jsonapi:"attr,permissions"`
Status RegistryModuleStatus `jsonapi:"attr,status"`
VCSRepo *VCSRepo `jsonapi:"attr,vcs-repo"`
Expand Down Expand Up @@ -164,6 +169,9 @@ type RegistryModuleCreateOptions struct {
RegistryName RegistryName `jsonapi:"attr,registry-name,omitempty"`
// Optional: The namespace of this module. Required for public modules only.
Namespace string `jsonapi:"attr,namespace,omitempty"`
// Optional: If set to true the module is enabled for no-code provisioning.
// **Note: This field is still in BETA and subject to change.**
NoCode bool `jsonapi:"attr,no-code,omitempty"`
miguelhrocha marked this conversation as resolved.
Show resolved Hide resolved
}

// RegistryModuleCreateVersionOptions is used when creating a registry module version
Expand All @@ -189,6 +197,19 @@ type RegistryModuleCreateWithVCSConnectionOptions struct {
VCSRepo *RegistryModuleVCSRepoOptions `jsonapi:"attr,vcs-repo"`
}

// RegistryModuleCreateVersionOptions is used when updating a registry module
type RegistryModuleUpdateOptions struct {
// Type is a public field utilized by JSON:API to
// set the resource type via the field tag.
// It is not a user-defined value and does not need to be set.
// https://jsonapi.org/format/#crud-updating
Type string `jsonapi:"primary,registry-modules"`

// Optional: Flag to enable no-code provisioning for the whole module.
// **Note: This field is still in BETA and subject to change.**
NoCode *bool `jsonapi:"attr,no-code,omitempty"`
}

type RegistryModuleVCSRepoOptions struct {
Identifier *string `json:"identifier"` // Required
OAuthTokenID *string `json:"oauth-token-id"` // Required
Expand Down Expand Up @@ -265,6 +286,41 @@ func (r *registryModules) Create(ctx context.Context, organization string, optio
return rm, nil
}

func (r *registryModules) Update(ctx context.Context, moduleID RegistryModuleID, options RegistryModuleUpdateOptions) (*RegistryModule, error) {
if err := moduleID.valid(); err != nil {
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
}

org := url.QueryEscape(moduleID.Organization)
registryName := url.QueryEscape(string(moduleID.RegistryName))
namespace := url.QueryEscape(moduleID.Namespace)
name := url.QueryEscape(moduleID.Name)
provider := url.QueryEscape(moduleID.Provider)
url := fmt.Sprintf("organizations/%s/registry-modules/%s/%s/%s/%s", org, registryName, namespace, name, provider)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💅 A small style suggestion - in this file (& the rest of the code), we generally avoid creating variables for each URL element like on this line.


req, err := r.client.NewRequest(http.MethodPatch, url, &options)
if err != nil {
return nil, err
}

rm := &RegistryModule{}
if err := req.Do(ctx, rm); err != nil {
return nil, err
}

return rm, nil
}

// CreateVersion creates a new registry module version
func (r *registryModules) CreateVersion(ctx context.Context, moduleID RegistryModuleID, options RegistryModuleCreateVersionOptions) (*RegistryModuleVersion, error) {
if err := moduleID.valid(); err != nil {
Expand Down
73 changes: 73 additions & 0 deletions registry_module_integration_test.go
Expand Up @@ -106,6 +106,7 @@ func TestRegistryModulesCreate(t *testing.T) {
assert.Equal(t, *options.Provider, rm.Provider)
assert.Equal(t, PrivateRegistry, rm.RegistryName)
assert.Equal(t, orgTest.Name, rm.Namespace)
assert.False(t, rm.NoCode, "no-code module attribute should be false by default")

assertRegistryModuleAttributes(t, rm)
})
Expand All @@ -123,6 +124,7 @@ func TestRegistryModulesCreate(t *testing.T) {
assert.Equal(t, *options.Provider, rm.Provider)
assert.Equal(t, options.RegistryName, rm.RegistryName)
assert.Equal(t, orgTest.Name, rm.Namespace)
assert.False(t, rm.NoCode, "no-code module attribute should be false by default")

assertRegistryModuleAttributes(t, rm)
})
Expand All @@ -141,6 +143,27 @@ func TestRegistryModulesCreate(t *testing.T) {
assert.Equal(t, *options.Provider, rm.Provider)
assert.Equal(t, options.RegistryName, rm.RegistryName)
assert.Equal(t, options.Namespace, rm.Namespace)
assert.False(t, rm.NoCode, "no-code module attribute should be false by default")

assertRegistryModuleAttributes(t, rm)
})

t.Run("with no-code attribute", func(t *testing.T) {
skipIfBeta(t)
options := RegistryModuleCreateOptions{
Name: String("iam"),
Provider: String("aws"),
NoCode: true,
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)
assert.Equal(t, options.NoCode, rm.NoCode)
miguelhrocha marked this conversation as resolved.
Show resolved Hide resolved

assertRegistryModuleAttributes(t, rm)
})
Expand Down Expand Up @@ -231,6 +254,56 @@ func TestRegistryModulesCreate(t *testing.T) {
})
}

func TestRegistryModuleUpdate(t *testing.T) {
skipIfBeta(t)
client := testClient(t)
ctx := context.Background()

orgTest, orgTestCleanup := createOrganization(t, client)
defer orgTestCleanup()

options := RegistryModuleCreateOptions{
Name: String("vault"),
Provider: String("aws"),
RegistryName: PublicRegistry,
Namespace: "hashicorp",
}
rm, err := client.RegistryModules.Create(ctx, orgTest.Name, options)
require.NoError(t, err)
assert.NotEmpty(t, rm.ID)

t.Run("enable no-code", func(t *testing.T) {
options := RegistryModuleUpdateOptions{
NoCode: Bool(true),
}
rm, err := client.RegistryModules.Update(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: "vault",
Provider: "aws",
Namespace: "hashicorp",
RegistryName: PublicRegistry,
}, options)
require.NoError(t, err)
assert.True(t, rm.NoCode)
})

t.Run("disable no-code", func(t *testing.T) {
options := RegistryModuleUpdateOptions{
NoCode: Bool(false),
}
rm, err := client.RegistryModules.Update(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: "vault",
Provider: "aws",
Namespace: "hashicorp",
RegistryName: PublicRegistry,
}, options)
require.NoError(t, err)
assert.False(t, rm.NoCode)
})

}

func TestRegistryModulesCreateVersion(t *testing.T) {
skipIfNotCINode(t)

Expand Down