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

Refactor parameter parsing #356

Merged
merged 49 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c5a54ad
- extract params into own struct for better usability
MatrixCrawler Apr 2, 2024
0462a64
Apply suggestions from code review
MatrixCrawler Apr 3, 2024
67b96c9
- implement suggestions from review
MatrixCrawler Apr 3, 2024
007dd1b
- explicitly create viper parser
MatrixCrawler Apr 3, 2024
04fa46b
- update test files
MatrixCrawler Apr 3, 2024
c9f8028
Apply suggestions from code review
MatrixCrawler Apr 4, 2024
f2faf5f
- try to use terragrunt parser
MatrixCrawler Apr 4, 2024
9e61257
Revert "- try to use terragrunt parser"
MatrixCrawler Apr 4, 2024
b248c9e
- rebase
MatrixCrawler Apr 5, 2024
4339565
- adapt to logging
MatrixCrawler Apr 5, 2024
f79fa5b
- move defaults
MatrixCrawler Apr 5, 2024
3eb7618
Apply suggestions from code review
MatrixCrawler Apr 5, 2024
687b9ec
Apply suggestions from code review
MatrixCrawler Apr 5, 2024
9d5d479
- apply suggested changes
MatrixCrawler Apr 5, 2024
763c30a
- apply suggested changes
MatrixCrawler Apr 5, 2024
ec776ab
- remove unnecessary logging
MatrixCrawler Apr 5, 2024
32f7185
- rebased and updated vulnerable dependencies
MatrixCrawler Apr 5, 2024
2af831f
- update dependencies
MatrixCrawler Apr 5, 2024
02b03ff
- fix parameters for DownloadFromURL
MatrixCrawler Apr 5, 2024
c5c1cd9
- remove fatal loggings from tests. Relates to #363
MatrixCrawler Apr 7, 2024
64ee48c
- make logger exit on fatal
MatrixCrawler Apr 7, 2024
c3659d8
- rebasing
MatrixCrawler Apr 8, 2024
06e7817
- fix logging
MatrixCrawler Apr 8, 2024
8210443
- don't rely on the terraform module file
MatrixCrawler Apr 8, 2024
0f20b3b
- exit on version or usage print
MatrixCrawler Apr 8, 2024
9fd3ecb
Apply suggestions from code review
MatrixCrawler Apr 8, 2024
ef6418e
- fix imports and fix cancellation of prompt
MatrixCrawler Apr 8, 2024
05bd380
- fix race condition with waiting for deferred file closes and renami…
MatrixCrawler Apr 9, 2024
cf1e230
- update to hcl/v2 package
MatrixCrawler Apr 9, 2024
09fed37
Apply suggestions from code review
MatrixCrawler Apr 11, 2024
778ffcc
Apply suggestions from code review
MatrixCrawler Apr 11, 2024
753cb53
- added log-level parameter
MatrixCrawler Apr 11, 2024
ef175f6
- moved all utility functions out of main.
MatrixCrawler Apr 11, 2024
dee1bd6
- added log-level to toml file
MatrixCrawler Apr 11, 2024
3c75651
- sort if block alphabetically
MatrixCrawler Apr 11, 2024
8286b20
- added test for defect terragrunt decalaration
MatrixCrawler Apr 16, 2024
cb39011
- added test for non existing file for .tfswitchrc file
MatrixCrawler Apr 16, 2024
bc11354
- added test for non existing and erroneous file for tfswitch.toml file
MatrixCrawler Apr 16, 2024
5f7b627
- added test for non existing, erroneous terraform module file
MatrixCrawler Apr 16, 2024
7dfa3c9
- fixed comment counter
MatrixCrawler Apr 16, 2024
f3ba257
- added an exception for integration tests as an empty or an erroneou…
MatrixCrawler Apr 16, 2024
d039a67
- added integration tests for windows
MatrixCrawler Apr 16, 2024
30710fc
Revert "- added integration tests for windows"
MatrixCrawler Apr 16, 2024
12ef46d
- use filepath.Join instead of concatenating strings
MatrixCrawler Apr 19, 2024
34e13d8
- use filepath.Join instead of concatenating strings
MatrixCrawler Apr 19, 2024
48b744b
- use filepath.Join instead of concatenating strings
MatrixCrawler Apr 19, 2024
7d4d411
- replaced if else with switch statement
MatrixCrawler Apr 19, 2024
a08c5ee
- remove commented lines
MatrixCrawler Apr 21, 2024
a316885
- show caller only if not info logging level
MatrixCrawler Apr 21, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
mkdir -p build
go build -v -o build/tfswitch
mkdir `pwd`/bin/
find ./test-data/* -type d -print0 | while read -r -d $'\0' TEST_PATH; do
find ./test-data/integration-tests/* -type d -print0 | while read -r -d $'\0' TEST_PATH; do
./build/tfswitch -c "${TEST_PATH}" -b `pwd`/bin/terraform || exit 1
done
Expand Down
31 changes: 16 additions & 15 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.22
require (
github.com/gookit/slog v0.5.5
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80
github.com/hashicorp/hcl/v2 v2.20.1
github.com/hashicorp/terraform-config-inspect v0.0.0-20231204233900-a34142ec2a72
github.com/manifoldco/promptui v0.9.0
github.com/mitchellh/go-homedir v1.1.0
Expand All @@ -16,36 +16,37 @@ require (
)

require (
github.com/agext/levenshtein v1.2.2 // indirect
github.com/apparentlymart/go-textseg v1.0.0 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gookit/goutil v0.6.15 // indirect
github.com/gookit/gsr v0.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/hcl/v2 v2.0.0 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/zclconf/go-cty v1.1.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/sync v0.5.0 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.20.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
122 changes: 41 additions & 81 deletions go.sum

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions lib/checksum.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,27 @@ func getChecksumFromHashFile(signatureFilePath string, terraformFileName string)

// checkChecksumMatches This will calculate and compare the check sum of the downloaded zip file
func checkChecksumMatches(hashFile string, targetFile *os.File) bool {
logger.Debugf("Checksum comparison for %q", targetFile.Name())
var fileHandlersToClose []*os.File
fileHandlersToClose = append(fileHandlersToClose, targetFile)
defer closeFileHandlers(fileHandlersToClose)

_, fileName := filepath.Split(targetFile.Name())
expectedChecksum, err := getChecksumFromHashFile(hashFile, fileName)
if err != nil {
closeFileHandlers(fileHandlersToClose)
logger.Errorf("Could not get checksum from file %q: %v", hashFile, err)
return false
}
hash := sha256.New()
if _, err := io.Copy(hash, targetFile); err != nil {
closeFileHandlers(fileHandlersToClose)
logger.Errorf("Checksum calculation failed for %q: %v", fileName, err)
return false
}
checksum := hex.EncodeToString(hash.Sum(nil))
if expectedChecksum != checksum {
closeFileHandlers(fileHandlersToClose)
logger.Errorf("Checksum mismatch for %q. Expected: %q, calculated: %v", fileName, expectedChecksum, checksum)
return false
}
closeFileHandlers(fileHandlersToClose)
return true
}

Expand Down
1 change: 1 addition & 0 deletions lib/checksum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func Test_getChecksumFromHashFile(t *testing.T) {
}

func Test_checkChecksumMatches(t *testing.T) {
InitLogger("TRACE")
targetFile, err := os.Open("../test-data/checksum-check-file")
if err != nil {
t.Errorf("[Error]: Could not open testfile for signature verification.")
Expand Down
10 changes: 0 additions & 10 deletions lib/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,6 @@ func createFile(path string) {
logger.Infof("==> done creating %q file", path)
}

func createDirIfNotExist(dir string) {
if _, err := os.Stat(dir); os.IsNotExist(err) {
logger.Infof("Creating directory for terraform: %v", dir)
err = os.MkdirAll(dir, 0755)
if err != nil {
logger.Panic("Unable to create %q directory for terraform: %v", dir, err)
}
}
}

func cleanUp(path string) {
removeContents(path)
removeFiles(path)
Expand Down
10 changes: 10 additions & 0 deletions lib/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@ func GetDefaultBin() string {
}
return defaultBin
}

const (
DefaultMirror = "https://releases.hashicorp.com/terraform"
DefaultLatest = ""
installFile = "terraform"
installPath = ".terraform.versions"
recentFile = "RECENT"
tfDarwinArm64StartVersion = "1.0.2"
VersionPrefix = "terraform_"
MatrixCrawler marked this conversation as resolved.
Show resolved Hide resolved
)
2 changes: 1 addition & 1 deletion lib/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func downloadFromURL(installLocation string, url string) (string, error) {

func downloadPublicKey(installLocation string, targetFileName string) error {
logger.Debugf("Looking up public key file at %q", targetFileName)
publicKeyFileExists := FileExists(targetFileName)
publicKeyFileExists := FileExistsAndIsNotDir(targetFileName)
if !publicKeyFileExists {
// Public key does not exist. Let's grab it from hashicorp
pubKeyFile, errDl := downloadFromURL(installLocation, PubKeyUri)
Expand Down
6 changes: 3 additions & 3 deletions lib/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {
logger.Fatalf("Could not detect home directory")
}

logger.Infof("Current home directory: %q", home)
t.Logf("Current home directory: %q", home)
var installLocation = ""
if runtime.GOOS != "windows" {
installLocation = filepath.Join(home, installPath)
} else {
installLocation = installPath
}
logger.Infof("Install Location: %v", installLocation)
t.Logf("install Location: %v", installLocation)

// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
Expand Down Expand Up @@ -74,7 +74,7 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {

t.Cleanup(func() {
defer os.Remove(tempDir)
logger.Infof("Cleanup temporary directory %q", tempDir)
t.Logf("Cleanup temporary directory %q", tempDir)
})
}

Expand Down
124 changes: 72 additions & 52 deletions lib/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import (
"archive/zip"
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
)

// RenameFile : rename file name
func RenameFile(src string, dest string) {
logger.Debugf("Renaming file %q to %q", src, dest)
err := os.Rename(src, dest)
if err != nil {
logger.Error(err)
return
logger.Fatal(err)
}
}

Expand Down Expand Up @@ -46,68 +47,39 @@ func CheckFileExist(file string) bool {
// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, dest string) ([]string, error) {
logger.Debugf("Unzipping file %q", src)

var filenames []string

r, err := zip.OpenReader(src)
reader, err := zip.OpenReader(src)
if err != nil {
return filenames, err
}
defer r.Close()

for _, f := range r.File {

filePath, _ := filepath.Abs(f.Name)
rc, err := f.Open()
if err != nil {
return filenames, err
}
defer rc.Close()

// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
filenames = append(filenames, fpath)

if f.FileInfo().IsDir() {

// Make Folder
_ = os.MkdirAll(fpath, os.ModePerm)

defer reader.Close()
destination, err := filepath.Abs(dest)
if err != nil {
logger.Fatalf("Could not open destination: %v", err)
}
var wg sync.WaitGroup
for _, f := range reader.File {
wg.Add(1)
unzipErr := unzipFile(f, destination, &wg)
if unzipErr != nil {
logger.Fatalf("Error unzipping %v", unzipErr)
} else {
if !strings.Contains(filePath, "..") {
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}

outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return filenames, err
}

_, err = io.Copy(outFile, rc)

// Close the file without defer to close before next iteration of loop
_ = outFile.Close()

if err != nil {
return filenames, err
}
}

filenames = append(filenames, filepath.Join(destination, f.Name))
}
}
return filenames, nil
}

// CreateDirIfNotExist : create directory if directory does not exist
func CreateDirIfNotExist(dir string) {
// createDirIfNotExist : create directory if directory does not exist
func createDirIfNotExist(dir string) {
if _, err := os.Stat(dir); os.IsNotExist(err) {
logger.Infof("Creating directory for terraform binary at %q", dir)
err = os.MkdirAll(dir, 0755)
if err != nil {
logger.Error(err)
logger.Panicf("Unable to create directory for terraform binary at: %v", dir)
logger.Panicf("Unable to create %q directory for terraform: %v", dir, err)
}
}
}
Expand Down Expand Up @@ -188,10 +160,9 @@ func CheckDirHasTGBin(dir, prefix string) bool {

exist := false

files, err := ioutil.ReadDir(dir)
files, err := os.ReadDir(dir)
if err != nil {
logger.Fatal(err)
os.Exit(1)
}
res := []string{}
for _, f := range files {
Expand Down Expand Up @@ -230,7 +201,56 @@ func GetCurrentDirectory() string {
dir, err := os.Getwd() //get current directory
if err != nil {
logger.Fatalf("Failed to get current directory %v", err)
os.Exit(1)
}
return dir
}

func unzipFile(f *zip.File, destination string, wg *sync.WaitGroup) error {
defer wg.Done()
// 1. Check if file paths are not vulnerable to Zip Slip
filePath := filepath.Join(destination, f.Name)
if !strings.HasPrefix(filePath, filepath.Clean(destination)+string(os.PathSeparator)) {
return fmt.Errorf("Invalid file path: %q", filePath)
}

// 2. Create directory tree
if f.FileInfo().IsDir() {
logger.Debugf("Extracting directory %q", filePath)
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
return err
}
return nil
}

if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return err
}

// 3. Create a destination file for unzipped content
destinationFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
MatrixCrawler marked this conversation as resolved.
Show resolved Hide resolved
defer func(destinationFile *os.File) {
_ = destinationFile.Close()
}(destinationFile)
if err != nil {
return err
}

// 4. Unzip the content of a file and copy it to the destination file
zippedFile, err := f.Open()
defer func(zippedFile io.ReadCloser) {
_ = zippedFile.Close()
}(zippedFile)
if err != nil {
return err
}

logger.Debugf("Extracting File %q", destinationFile.Name())
if _, err := io.Copy(destinationFile, zippedFile); err != nil {
return err
}
logger.Debugf("Closing destination file handler %q", destinationFile.Name())
_ = destinationFile.Close()
logger.Debugf("Closing zipped file handler %q", f.Name)
_ = zippedFile.Close()
return nil
}
Loading