Skip to content

Commit

Permalink
fix for error - remote source address with subdir
Browse files Browse the repository at this point in the history
  • Loading branch information
patilpankaj212 committed Apr 6, 2021
1 parent dfc0d08 commit 2a1e33e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 60 deletions.
44 changes: 12 additions & 32 deletions pkg/iac-providers/terraform/commons/load-dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/accurics/terrascan/pkg/downloader"
"github.com/accurics/terrascan/pkg/iac-providers/output"
Expand Down Expand Up @@ -52,9 +51,6 @@ type ModuleConfig struct {
// resources present in rootDir and descendant modules
func LoadIacDir(absRootDir string) (allResourcesConfig output.AllResourceConfigs, err error) {

// map to hold the download paths of remote modules
remoteModPaths := make(map[string]string)

// create a new config parser
parser := hclConfigs.NewParser(afero.NewOsFs())

Expand Down Expand Up @@ -89,13 +85,13 @@ func LoadIacDir(absRootDir string) (allResourcesConfig output.AllResourceConfigs
var pathToModule string
if downloader.IsLocalSourceAddr(req.SourceAddr) {

pathToModule = processLocalSource(req, remoteModPaths, absRootDir)
pathToModule = processLocalSource(req)
zap.S().Debugf("processing local module %q", pathToModule)
} else if downloader.IsRegistrySourceAddr(req.SourceAddr) {
// temp dir to download the remote repo
tempDir := generateTempDir()

pathToModule, err = processTerraformRegistrySource(req, remoteModPaths, tempDir, r)
pathToModule, err = processTerraformRegistrySource(req, tempDir, r)
if err != nil {
zap.S().Errorf("failed to download remote module %q. error: '%v'", req.SourceAddr, err)
}
Expand Down Expand Up @@ -194,35 +190,21 @@ func generateTempDir() string {
return filepath.Join(os.TempDir(), utils.GenRandomString(6))
}

func processLocalSource(req *hclConfigs.ModuleRequest, remoteModPaths map[string]string, absRootDir string) string {
func processLocalSource(req *hclConfigs.ModuleRequest) string {
// determine the absolute path from root module to the sub module
// since we start at the end of the path, we need to assemble
// the parts in reverse order

pathToModule := req.SourceAddr
for p := req.Parent; p != nil; p = p.Parent {
pathToModule = filepath.Join(p.SourceAddr, pathToModule)
}
// while building the unified config, recursive calls are made for all the paths resolved,
// the source address in a tf file is relative while this func is called, hence, we get the
// path of caller dir, and join the source address of current module request to get the path to module

// check if pathToModule consists of a remote module downloaded
// if yes, then update the module path, with the remote module
// download path
keyFound := false
for remoteSourceAddr, downloadPath := range remoteModPaths {
if strings.Contains(pathToModule, remoteSourceAddr) {
pathToModule = strings.Replace(pathToModule, remoteSourceAddr, "", 1)
pathToModule = filepath.Join(downloadPath, pathToModule)
keyFound = true
break
}
}
if !keyFound {
pathToModule = filepath.Join(absRootDir, pathToModule)
}
return pathToModule
// get the caller dir path
callDirPath := filepath.Join(req.CallRange.Filename, "..")

// join source address to the caller dir
return filepath.Join(callDirPath, req.SourceAddr)
}

func processTerraformRegistrySource(req *hclConfigs.ModuleRequest, remoteModPaths map[string]string, tempDir string, m downloader.ModuleDownloader) (string, error) {
func processTerraformRegistrySource(req *hclConfigs.ModuleRequest, tempDir string, m downloader.ModuleDownloader) (string, error) {
// regsrc.ParseModuleSource func returns a terraform registry module source
// error check is not required as the source address is already validated
module, _ := regsrc.ParseModuleSource(req.SourceAddr)
Expand All @@ -232,7 +214,5 @@ func processTerraformRegistrySource(req *hclConfigs.ModuleRequest, remoteModPath
return pathToModule, err
}

// add the entry of remote module's source address to the map
remoteModPaths[req.SourceAddr] = pathToModule
return pathToModule, nil
}
38 changes: 10 additions & 28 deletions pkg/iac-providers/terraform/commons/load-dir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,31 @@ package commons

import (
"os"
"path/filepath"
"testing"

"github.com/accurics/terrascan/pkg/downloader"
"github.com/hashicorp/hcl/v2"
hclConfigs "github.com/hashicorp/terraform/configs"
)

// test data
var (
testLocalSourceAddr = "./someModule"
testRemoteSourceAddr = "terraform-aws-modules/eks/aws"
testDirPath = filepath.Join("root", "test")
testFileNamePath = filepath.Join(testDirPath, "main.tf")

testModuleReqA = &hclConfigs.ModuleRequest{
SourceAddr: testLocalSourceAddr,
Parent: &hclConfigs.Config{
SourceAddr: "./eks/aws",
},
}

testModuleReqB = &hclConfigs.ModuleRequest{
SourceAddr: testLocalSourceAddr,
Parent: &hclConfigs.Config{
SourceAddr: testRemoteSourceAddr,
},
CallRange: hcl.Range{Filename: testFileNamePath},
}
)

func TestProcessLocalSource(t *testing.T) {

type args struct {
req *hclConfigs.ModuleRequest
remoteModPaths map[string]string
absRootDir string
req *hclConfigs.ModuleRequest
}
tests := []struct {
name string
Expand All @@ -59,25 +52,14 @@ func TestProcessLocalSource(t *testing.T) {
{
name: "no remote module",
args: args{
req: testModuleReqA,
absRootDir: "/home/somedir",
},
want: "/home/somedir/eks/aws/someModule",
},
{
name: "with remote module",
args: args{
req: testModuleReqB,
remoteModPaths: map[string]string{
testRemoteSourceAddr: "/var/temp/testDir",
},
req: testModuleReqA,
},
want: "/var/temp/testDir/someModule",
want: filepath.Join(testDirPath, "someModule"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := processLocalSource(tt.args.req, tt.args.remoteModPaths, tt.args.absRootDir); got != tt.want {
if got := processLocalSource(tt.args.req); got != tt.want {
t.Errorf("processLocalSource() got = %v, want = %v", got, tt.want)
}
})
Expand Down Expand Up @@ -127,7 +109,7 @@ func TestProcessTerraformRegistrySource(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer os.RemoveAll(tt.args.tempDir)
got, err := processTerraformRegistrySource(tt.args.req, tt.args.remoteModPaths, tt.args.tempDir, tt.args.m)
got, err := processTerraformRegistrySource(tt.args.req, tt.args.tempDir, tt.args.m)
if (err != nil) != tt.wantErr {
t.Errorf("processTerraformRegistrySource() got error = %v, wantErr = %v", err, tt.wantErr)
return
Expand Down

0 comments on commit 2a1e33e

Please sign in to comment.