Skip to content

Commit

Permalink
Merge pull request #356 from MatrixCrawler/refactor-params
Browse files Browse the repository at this point in the history
Refactor parameter parsing
  • Loading branch information
MatrixCrawler authored Apr 21, 2024
2 parents c0bc923 + a316885 commit 9059ac6
Show file tree
Hide file tree
Showing 52 changed files with 1,085 additions and 840 deletions.
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_"
)
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())
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

0 comments on commit 9059ac6

Please sign in to comment.