Skip to content

Commit

Permalink
Validate the module version as version instead of ID
Browse files Browse the repository at this point in the history
Without these changes a module version with prerelease or metadata will fail, while these are actually valid SemVer versions that are allowed by the module registry.
  • Loading branch information
svanharmelen committed Aug 12, 2022
1 parent ece2558 commit 7d61498
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 8 deletions.
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -9,6 +9,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.1
github.com/hashicorp/go-slug v0.10.0
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.5.0
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d
github.com/stretchr/testify v1.8.0
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -18,6 +18,8 @@ github.com/hashicorp/go-slug v0.10.0 h1:mh4DDkBJTh9BuEjY/cv8PTo7k9OjT4PcW8PgZnJ4
github.com/hashicorp/go-slug v0.10.0/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41RKLH301v4=
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=
github.com/hashicorp/go-version v1.5.0 h1:O293SZ2Eg+AAYijkVK3jR786Am1bhDEh2GHT0tIVE5E=
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d h1:9ARUJJ1VVynB176G1HCwleORqCaXm/Vx0uUi0dL26I0=
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
4 changes: 2 additions & 2 deletions registry_module.go
Expand Up @@ -407,7 +407,7 @@ func (r *registryModules) DeleteVersion(ctx context.Context, moduleID RegistryMo
if !validString(&version) {
return ErrRequiredVersion
}
if !validStringID(&version) {
if !validVersion(version) {
return ErrInvalidVersion
}

Expand Down Expand Up @@ -499,7 +499,7 @@ func (o RegistryModuleCreateVersionOptions) valid() error {
if !validString(o.Version) {
return ErrRequiredVersion
}
if !validStringID(o.Version) {
if !validVersion(*o.Version) {
return ErrInvalidVersion
}
return nil
Expand Down
55 changes: 55 additions & 0 deletions registry_module_integration_test.go
Expand Up @@ -266,6 +266,21 @@ func TestRegistryModulesCreateVersion(t *testing.T) {
})
})

t.Run("with prerelease and metadata version", func(t *testing.T) {
options := RegistryModuleCreateVersionOptions{
Version: String("1.2.3-alpha+feature"),
}

rmv, err := client.RegistryModules.CreateVersion(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
}, options)
require.NoError(t, err)
assert.NotEmpty(t, rmv.ID)
assert.Equal(t, *options.Version, rmv.Version)
})

t.Run("with invalid options", func(t *testing.T) {
t.Run("without version", func(t *testing.T) {
options := RegistryModuleCreateVersionOptions{}
Expand Down Expand Up @@ -809,6 +824,46 @@ func TestRegistryModulesDeleteVersion(t *testing.T) {
assert.Equal(t, registryModuleTest.VersionStatuses, rm.VersionStatuses)
})

t.Run("with prerelease and metadata version", func(t *testing.T) {
options := RegistryModuleCreateVersionOptions{
Version: String("1.2.3-alpha+feature"),
}
rmv, err := client.RegistryModules.CreateVersion(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
}, options)
require.NoError(t, err)
require.NotEmpty(t, rmv.Version)

rm, err := client.RegistryModules.Read(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
})
require.NoError(t, err)
require.NotEmpty(t, rm.VersionStatuses)
require.Equal(t, 2, len(rm.VersionStatuses))

err = client.RegistryModules.DeleteVersion(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
}, rmv.Version)
require.NoError(t, err)

rm, err = client.RegistryModules.Read(ctx, RegistryModuleID{
Organization: orgTest.Name,
Name: registryModuleTest.Name,
Provider: registryModuleTest.Provider,
})
require.NoError(t, err)
assert.NotEmpty(t, rm.VersionStatuses)
assert.Equal(t, 1, len(rm.VersionStatuses))
assert.NotEqual(t, registryModuleTest.VersionStatuses[0].Version, rmv.Version)
assert.Equal(t, registryModuleTest.VersionStatuses, rm.VersionStatuses)
})

t.Run("without a name", func(t *testing.T) {
err := client.RegistryModules.DeleteVersion(ctx, RegistryModuleID{
Organization: orgTest.Name,
Expand Down
17 changes: 11 additions & 6 deletions validations.go
Expand Up @@ -3,27 +3,32 @@ package tfe
import (
"net/mail"
"regexp"

version "github.com/hashicorp/go-version"
)

// A regular expression used to validate common string ID patterns.

var reStringID = regexp.MustCompile(`^[a-zA-Z0-9\-._]+$`)

// validString checks if the given input is present and non-empty.
// validEmail checks if the given input is a correct email
func validEmail(v string) bool {
_, err := mail.ParseAddress(v)
return err == nil
}

// validString checks if the given input is present and non-empty.
func validString(v *string) bool {
return v != nil && *v != ""
}

// validStringID checks if the given string pointer is non-nil and
// contains a typical string identifier.

func validStringID(v *string) bool {
return v != nil && reStringID.MatchString(*v)
}

// validEmail checks if the given input is a correct email
func validEmail(v string) bool {
_, err := mail.ParseAddress(v)
// validVersion checks if the given input is a valid version.
func validVersion(v string) bool {
_, err := version.NewVersion(v)
return err == nil
}

0 comments on commit 7d61498

Please sign in to comment.