Skip to content

Commit 2038ca9

Browse files
committed
tighter public registry check, docstring on GetModuleSourceType, new test cases
1 parent 7d27b3e commit 2038ca9

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

coderd/telemetry/telemetry.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net/http"
1212
"net/url"
1313
"os"
14+
"regexp"
1415
"runtime"
1516
"slices"
1617
"strings"
@@ -700,6 +701,21 @@ const (
700701
ModuleSourceTypeUnknown ModuleSourceType = "unknown"
701702
)
702703

704+
// Terraform supports a variety of module source types, like:
705+
// - local paths (./ or ../)
706+
// - absolute local paths (/)
707+
// - git URLs (git:: or git@)
708+
// - http URLs
709+
// - s3 URLs
710+
//
711+
// and more!
712+
//
713+
// See https://developer.hashicorp.com/terraform/language/modules/sources for an overview.
714+
//
715+
// This function attempts to classify the source type of a module. It's imperfect,
716+
// as checks that terraform actually does are pretty complicated.
717+
// See e.g. https://github.com/hashicorp/go-getter/blob/842d6c379e5e70d23905b8f6b5a25a80290acb66/detect.go#L47
718+
// if you're interested in the complexity.
703719
func GetModuleSourceType(source string) ModuleSourceType {
704720
source = strings.TrimSpace(source)
705721
source = strings.ToLower(source)
@@ -709,6 +725,14 @@ func GetModuleSourceType(source string) ModuleSourceType {
709725
if strings.HasPrefix(source, "/") {
710726
return ModuleSourceTypeLocalAbs
711727
}
728+
// Match public registry modules in the format <NAMESPACE>/<NAME>/<PROVIDER>
729+
// Sources can have a `//...` suffix, which signifies a subdirectory.
730+
// The allowed characters are based on
731+
// https://developer.hashicorp.com/terraform/cloud-docs/api-docs/private-registry/modules#request-body-1
732+
// because Hashicorp's documentation about module sources doesn't mention it.
733+
if matched, _ := regexp.MatchString(`^[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+(//.*)?$`, source); matched {
734+
return ModuleSourceTypePublicRegistry
735+
}
712736
if strings.Contains(source, "github.com") {
713737
return ModuleSourceTypeGitHub
714738
}
@@ -739,9 +763,6 @@ func GetModuleSourceType(source string) ModuleSourceType {
739763
if strings.Contains(source, "registry.coder.com") {
740764
return ModuleSourceTypeCoderRegistry
741765
}
742-
if !strings.Contains(source, "://") && !strings.Contains(source, ".") && strings.Contains(source, "/") {
743-
return ModuleSourceTypePublicRegistry
744-
}
745766
return ModuleSourceTypeUnknown
746767
}
747768

coderd/telemetry/telemetry_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ func TestTelemetry(t *testing.T) {
169169
{source: "hashicorp/consul/aws", want: telemetry.ModuleSourceTypePublicRegistry},
170170
{source: "registry.terraform.io/hashicorp/aws", want: telemetry.ModuleSourceTypePublicRegistry},
171171
{source: "terraform-aws-modules/vpc/aws", want: telemetry.ModuleSourceTypePublicRegistry},
172+
{source: "hashicorp/consul/aws//modules/consul-cluster", want: telemetry.ModuleSourceTypePublicRegistry},
173+
{source: "hashicorp/co-nsul/aw_s//modules/consul-cluster", want: telemetry.ModuleSourceTypePublicRegistry},
172174

173175
// Private registry
174176
{source: "app.terraform.io/company/vpc/aws", want: telemetry.ModuleSourceTypePrivateRegistry},

0 commit comments

Comments
 (0)