Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ To run preview:
2. `pnpm install`
3. `cd ..`
4. `go run ./cmd/preview/main.go web --pnpm=site`
5. visit http://localhost:5173/?testcontrols=true
27 changes: 27 additions & 0 deletions preview_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (
"encoding/json"
"os"
"path/filepath"
"regexp"
"slices"
"testing"

"github.com/hashicorp/hcl/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -38,6 +41,7 @@ func Test_Extract(t *testing.T) {
expTags map[string]string
unknownTags []string
params map[string]assertParam
warnings []*regexp.Regexp
}{
{
name: "bad param values",
Expand Down Expand Up @@ -402,6 +406,19 @@ func Test_Extract(t *testing.T) {
"beta": ap().unknown(),
},
},
{
name: "missing_module",
dir: "missingmodule",
expTags: map[string]string{},
input: preview.Input{
ParameterValues: map[string]string{},
},
unknownTags: []string{},
params: map[string]assertParam{},
warnings: []*regexp.Regexp{
regexp.MustCompile("Module not loaded"),
},
},
{
skip: "skip until https://github.com/aquasecurity/trivy/pull/8479 is resolved",
name: "submodcount",
Expand Down Expand Up @@ -440,6 +457,16 @@ func Test_Extract(t *testing.T) {
}
require.False(t, diags.HasErrors())

if len(tc.warnings) > 0 {
for _, w := range tc.warnings {
idx := slices.IndexFunc(diags, func(diagnostic *hcl.Diagnostic) bool {
return w.MatchString(diagnostic.Error())

})
require.Greater(t, idx, -1, "expected warning %q to be present in diags", w.String())
}
}

// Assert tags
validTags := output.WorkspaceTags.Tags()

Expand Down
12 changes: 12 additions & 0 deletions testdata/missingmodule/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module "does-not-exist" {
source = "registry.coder.com/modules/does-not-exist/coder"
}

module "does-not-exist-2" {
count = 0
source = "registry.coder.com/modules/does-not-exist/coder"
}

module "one" {
source = "./one"
}
3 changes: 3 additions & 0 deletions testdata/missingmodule/one/one.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module "onea" {
source = "./onea"
}
14 changes: 14 additions & 0 deletions testdata/missingmodule/one/onea/onea.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
version = "2.4.0-pre0"
}
}
}

data "null_data_source" "values" {
inputs = {
foo = "bar"
}
}
1 change: 1 addition & 0 deletions testdata/missingmodule/skipe2e
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Not a real module
51 changes: 51 additions & 0 deletions warnings.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,57 @@ import (
func warnings(modules terraform.Modules) hcl.Diagnostics {
var diags hcl.Diagnostics
diags = diags.Extend(unexpandedCountBlocks(modules))
diags = diags.Extend(unresolvedModules(modules))

return diags
}

// unresolvedModules does a best effort to try and detect if some modules
// failed to resolve. This is usually because `terraform init` is not run.
func unresolvedModules(modules terraform.Modules) hcl.Diagnostics {
var diags hcl.Diagnostics
modulesUsed := make(map[string]bool)
modulesByID := make(map[string]*terraform.Block)

// There is no easy way to know if a `module` failed to resolve. The failure is
// only logged in the trivy package. No errors are returned to the caller. So
// instead this code will infer a failed resolution by checking if any blocks
// exist that reference each `module` block. This will work as long as the module
// has some content. If a module is completely empty, then it will be detected as
// "not loaded".
blocks := modules.GetBlocks()
for _, block := range blocks {
if block.InModule() && block.ModuleBlock() != nil {
modulesUsed[block.ModuleBlock().ID()] = true
}

if block.Type() == "module" {
modulesByID[block.ID()] = block
_, ok := modulesUsed[block.ID()]
if !ok {
modulesUsed[block.ID()] = false
}
}
}

for id, v := range modulesUsed {
if !v {
block, ok := modulesByID[id]
if ok {
label := block.Type()
for _, l := range block.Labels() {
label += " " + fmt.Sprintf("%q", l)
}

diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagWarning,
Summary: "Module not loaded, did you run `terraform init`? Or maybe the module is empty.",
Detail: fmt.Sprintf("Module '%s' in file %q cannot be resolved. This module will be ignored.", label, block.HCLBlock().DefRange),
Subject: &(block.HCLBlock().DefRange),
})
}
}
}

return diags
}
Expand Down
Loading