From 4e3fb47d8bc0329e7f66a7dc2a425e9ca63fccd8 Mon Sep 17 00:00:00 2001 From: "warren.veerasingam@gmail.com" Date: Fri, 18 Oct 2019 16:18:28 -0500 Subject: [PATCH] add files to vendor directory --- Gopkg.lock | 9 + .../warrensbox/terraform-switcher/LICENSE | 21 ++ .../terraform-switcher/lib/command.go | 82 +++++++ .../terraform-switcher/lib/download.go | 47 ++++ .../terraform-switcher/lib/files.go | 225 ++++++++++++++++++ .../terraform-switcher/lib/install.go | 209 ++++++++++++++++ .../terraform-switcher/lib/list_versions.go | 115 +++++++++ .../terraform-switcher/lib/symlink.go | 65 +++++ 8 files changed, 773 insertions(+) create mode 100644 vendor/github.com/warrensbox/terraform-switcher/LICENSE create mode 100644 vendor/github.com/warrensbox/terraform-switcher/lib/command.go create mode 100644 vendor/github.com/warrensbox/terraform-switcher/lib/download.go create mode 100644 vendor/github.com/warrensbox/terraform-switcher/lib/files.go create mode 100644 vendor/github.com/warrensbox/terraform-switcher/lib/install.go create mode 100644 vendor/github.com/warrensbox/terraform-switcher/lib/list_versions.go create mode 100644 vendor/github.com/warrensbox/terraform-switcher/lib/symlink.go diff --git a/Gopkg.lock b/Gopkg.lock index af9498e..223f931 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -146,6 +146,14 @@ pruneopts = "UT" revision = "210d2dc333e90c7e3eedf4f2242507a8e83ed4ab" +[[projects]] + digest = "1:96185c606fc88fe06a33311957d4ebd7e85965363d40819cb78e4d8bf5b4bac8" + name = "github.com/warrensbox/terraform-switcher" + packages = ["lib"] + pruneopts = "UT" + revision = "6789a3f06dca991301d9fe5aef8dcae324b9560c" + version = "0.7.737" + [[projects]] branch = "master" digest = "1:969c44c96e9866e912a16e282a362cf045b64202107424983fe8abc3373d1eab" @@ -189,6 +197,7 @@ input-imports = [ "github.com/manifoldco/promptui", "github.com/pborman/getopt", + "github.com/warrensbox/terraform-switcher/lib", ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/warrensbox/terraform-switcher/LICENSE b/vendor/github.com/warrensbox/terraform-switcher/LICENSE new file mode 100644 index 0000000..7e9fc2e --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 warrensbox + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/warrensbox/terraform-switcher/lib/command.go b/vendor/github.com/warrensbox/terraform-switcher/lib/command.go new file mode 100644 index 0000000..fa00e5a --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/lib/command.go @@ -0,0 +1,82 @@ +package lib + +import ( + "io/ioutil" + "os" + "path/filepath" + "runtime" + "strings" +) + +// Command : type string +type Command struct { + name string +} + +// NewCommand : get command +func NewCommand(name string) *Command { + return &Command{name: name} +} + +// PathList : get bin path list +func (cmd *Command) PathList() []string { + path := os.Getenv("PATH") + return strings.Split(path, string(os.PathListSeparator)) +} + +func isDir(path string) bool { + fileInfo, err := os.Stat(path) + if err != nil || os.IsNotExist(err) { + return false + } + return fileInfo.IsDir() +} + +func isExecutable(path string) bool { + if isDir(path) { + return false + } + + fileInfo, err := os.Stat(path) + if err != nil || os.IsNotExist(err) { + return false + } + + if runtime.GOOS == "windows" { + return true + } + + if fileInfo.Mode()&0111 != 0 { + return true + } + + return false +} + +// Find : find all bin path +func (cmd *Command) Find() func() string { + pathChan := make(chan string) + go func() { + for _, p := range cmd.PathList() { + if !isDir(p) { + continue + } + fileList, err := ioutil.ReadDir(p) + if err != nil { + continue + } + + for _, f := range fileList { + path := filepath.Join(p, f.Name()) + if isExecutable(path) && f.Name() == cmd.name { + pathChan <- path + } + } + } + pathChan <- "" + }() + + return func() string { + return <-pathChan + } +} diff --git a/vendor/github.com/warrensbox/terraform-switcher/lib/download.go b/vendor/github.com/warrensbox/terraform-switcher/lib/download.go new file mode 100644 index 0000000..b2477b4 --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/lib/download.go @@ -0,0 +1,47 @@ +package lib + +import ( + "fmt" + "io" + "net/http" + "os" + "strings" +) + +// DownloadFromURL : Downloads the binary from the source url +func DownloadFromURL(installLocation string, url string) (string, error) { + tokens := strings.Split(url, "/") + fileName := tokens[len(tokens)-1] + fmt.Println("Downloading", url, "to", fileName) + fmt.Println("Downloading ...") + + response, err := http.Get(url) + + if err != nil { + fmt.Println("Error while downloading", url, "-", err) + return "", err + } + defer response.Body.Close() + + if response.StatusCode != 200 { + //Sometimes hashicorp terraform file names are not consistent + //For example 0.12.0-alpha4 naming convention in the release repo is not consistent + return "", fmt.Errorf("Unable to download from %s\nPlease download manually from https://releases.hashicorp.com/terraform/", url) + } + + output, err := os.Create(installLocation + fileName) + if err != nil { + fmt.Println("Error while creating", installLocation+fileName, "-", err) + return "", err + } + defer output.Close() + + n, err := io.Copy(output, response.Body) + if err != nil { + fmt.Println("Error while downloading", url, "-", err) + return "", err + } + + fmt.Println(n, "bytes downloaded.") + return installLocation + fileName, nil +} diff --git a/vendor/github.com/warrensbox/terraform-switcher/lib/files.go b/vendor/github.com/warrensbox/terraform-switcher/lib/files.go new file mode 100644 index 0000000..1ca70a4 --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/lib/files.go @@ -0,0 +1,225 @@ +package lib + +import ( + "archive/zip" + "bufio" + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +// RenameFile : rename file name +func RenameFile(src string, dest string) { + err := os.Rename(src, dest) + if err != nil { + fmt.Println(err) + return + } +} + +// RemoveFiles : remove file +func RemoveFiles(src string) { + files, err := filepath.Glob(src) + if err != nil { + + panic(err) + } + for _, f := range files { + if err := os.Remove(f); err != nil { + panic(err) + } + } +} + +// CheckFileExist : check if file exist in directory +func CheckFileExist(file string) bool { + _, err := os.Stat(file) + if err != nil { + return false + } + return true +} + +// 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) { + + var filenames []string + + r, err := zip.OpenReader(src) + if err != nil { + return filenames, err + } + defer r.Close() + + for _, f := range r.File { + + 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) + + } else { + + // 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 + } + + } + } + return filenames, nil +} + +//CreateDirIfNotExist : create directory if directory does not exist +func CreateDirIfNotExist(dir string) { + if _, err := os.Stat(dir); os.IsNotExist(err) { + log.Printf("Creating directory for terraform: %v", dir) + err = os.MkdirAll(dir, 0755) + if err != nil { + fmt.Printf("Unable to create directory for terraform: %v", dir) + panic(err) + } + } +} + +//WriteLines : writes into file +func WriteLines(lines []string, path string) (err error) { + var ( + file *os.File + ) + + if file, err = os.Create(path); err != nil { + return err + } + defer file.Close() + + for _, item := range lines { + _, err := file.WriteString(strings.TrimSpace(item) + "\n") + if err != nil { + fmt.Println(err) + break + } + } + + return nil +} + +// ReadLines : Read a whole file into the memory and store it as array of lines +func ReadLines(path string) (lines []string, err error) { + var ( + file *os.File + part []byte + prefix bool + ) + if file, err = os.Open(path); err != nil { + return + } + defer file.Close() + + reader := bufio.NewReader(file) + buffer := bytes.NewBuffer(make([]byte, 0)) + for { + if part, prefix, err = reader.ReadLine(); err != nil { + break + } + buffer.Write(part) + if !prefix { + lines = append(lines, buffer.String()) + buffer.Reset() + } + } + if err == io.EOF { + err = nil + } + return +} + +//IsDirEmpty : check if directory is empty (TODO UNIT TEST) +func IsDirEmpty(name string) bool { + + exist := false + + f, err := os.Open(name) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + _, err = f.Readdirnames(1) // Or f.Readdir(1) + if err == io.EOF { + exist = true + } + return exist // Either not empty or error, suits both cases +} + +//CheckDirHasTGBin : // check binary exist (TODO UNIT TEST) +func CheckDirHasTGBin(dir, prefix string) bool { + + exist := false + + files, err := ioutil.ReadDir(dir) + if err != nil { + log.Fatal(err) + //return exist, err + } + res := []string{} + for _, f := range files { + if !f.IsDir() && strings.HasPrefix(f.Name(), prefix) { + res = append(res, filepath.Join(dir, f.Name())) + exist = true + } + } + return exist +} + +//CheckDirExist : check if directory exist +//dir=path to file +//return path to directory +func CheckDirExist(dir string) bool { + if _, err := os.Stat(dir); os.IsNotExist(err) { + return false + } + return true +} + +// Path : returns path of directory +// value=path to file +func Path(value string) string { + return filepath.Dir(value) +} + +// GetFileName : remove file ext. .tfswitch.config returns .tfswitch +func GetFileName(configfile string) string { + + return strings.TrimSuffix(configfile, filepath.Ext(configfile)) +} diff --git a/vendor/github.com/warrensbox/terraform-switcher/lib/install.go b/vendor/github.com/warrensbox/terraform-switcher/lib/install.go new file mode 100644 index 0000000..6d416a4 --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/lib/install.go @@ -0,0 +1,209 @@ +package lib + +import ( + "fmt" + "log" + "os" + "os/user" + "runtime" +) + +const ( + hashiURL = "https://releases.hashicorp.com/terraform/" + installFile = "terraform" + installVersion = "terraform_" + //binLocation = "/usr/local/bin/terraform" + installPath = "/.terraform.versions/" + recentFile = "RECENT" +) + +var ( + installLocation = "/tmp" + //installedBinPath = "/tmp" +) + +func init() { + /* get current user */ + usr, errCurr := user.Current() + if errCurr != nil { + log.Fatal(errCurr) + } + + /* set installation location */ + installLocation = usr.HomeDir + installPath + + /* set default binary path for terraform */ + installedBinPath := "/usr/local/bin/terraform" + + /* find terraform binary location if terraform is already installed*/ + cmd := NewCommand("terraform") + next := cmd.Find() + + /* overrride installation default binary path if terraform is already installed */ + /* find the last bin path */ + for path := next(); len(path) > 0; path = next() { + installedBinPath = path + } + + /* remove current symlink if exist*/ + symlinkExist := CheckSymlink(installedBinPath) + + if symlinkExist { + RemoveSymlink(installedBinPath) + } + + /* Create local installation directory if it does not exist */ + CreateDirIfNotExist(installLocation) + +} + +//Install : Install the provided version in the argument +func Install(tfversion string, binPath string) { + + if !ValidVersionFormat(tfversion) { + fmt.Printf("The provided terraform version format does not exist - %s. Try `tfswitch -l` to see all available versions.\n", tfversion) + os.Exit(1) + } + + goarch := runtime.GOARCH + goos := runtime.GOOS + + /* check if selected version already downloaded */ + fileExist := CheckFileExist(installLocation + installVersion + tfversion) + + /* if selected version already exist, */ + if fileExist { + + /* remove current symlink if exist*/ + symlinkExist := CheckSymlink(binPath) + + if symlinkExist { + RemoveSymlink(binPath) + } + + /* set symlink to desired version */ + CreateSymlink(installLocation+installVersion+tfversion, binPath) + fmt.Printf("Switched terraform to version %q \n", tfversion) + AddRecent(tfversion) //add to recent file for faster lookup + os.Exit(0) + } + + /* if selected version already exist, */ + /* proceed to download it from the hashicorp release page */ + url := hashiURL + tfversion + "/" + installVersion + tfversion + "_" + goos + "_" + goarch + ".zip" + zipFile, errDownload := DownloadFromURL(installLocation, url) + + /* If unable to download file from url, exit(1) immediately */ + if errDownload != nil { + fmt.Println(errDownload) + os.Exit(1) + } + + /* unzip the downloaded zipfile */ + _, errUnzip := Unzip(zipFile, installLocation) + if errUnzip != nil { + fmt.Println("Unable to unzip downloaded zip file") + log.Fatal(errUnzip) + os.Exit(1) + } + + /* rename unzipped file to terraform version name - terraform_x.x.x */ + RenameFile(installLocation+installFile, installLocation+installVersion+tfversion) + + /* remove zipped file to clear clutter */ + RemoveFiles(installLocation + installVersion + tfversion + "_" + goos + "_" + goarch + ".zip") + + /* remove current symlink if exist*/ + symlinkExist := CheckSymlink(binPath) + + if symlinkExist { + RemoveSymlink(binPath) + } + + /* set symlink to desired version */ + CreateSymlink(installLocation+installVersion+tfversion, binPath) + fmt.Printf("Switched terraform to version %q \n", tfversion) + AddRecent(tfversion) //add to recent file for faster lookup + os.Exit(0) +} + +// AddRecent : add to recent file +func AddRecent(requestedVersion string) { + + fileExist := CheckFileExist(installLocation + recentFile) + if fileExist { + lines, errRead := ReadLines(installLocation + recentFile) + + if errRead != nil { + fmt.Printf("Error: %s\n", errRead) + return + } + + for _, line := range lines { + if !ValidVersionFormat(line) { + fmt.Println("File dirty. Recreating cache file.") + RemoveFiles(installLocation + recentFile) + CreateRecentFile(requestedVersion) + return + } + } + + versionExist := VersionExist(requestedVersion, lines) + + if !versionExist { + if len(lines) >= 3 { + _, lines = lines[len(lines)-1], lines[:len(lines)-1] + + lines = append([]string{requestedVersion}, lines...) + WriteLines(lines, installLocation+recentFile) + } else { + lines = append([]string{requestedVersion}, lines...) + WriteLines(lines, installLocation+recentFile) + } + } + + } else { + CreateRecentFile(requestedVersion) + } +} + +// GetRecentVersions : get recent version from file +func GetRecentVersions() ([]string, error) { + + fileExist := CheckFileExist(installLocation + recentFile) + if fileExist { + + lines, errRead := ReadLines(installLocation + recentFile) + outputRecent := []string{} + + if errRead != nil { + fmt.Printf("Error: %s\n", errRead) + return nil, errRead + } + + for _, line := range lines { + /* checks if versions in the recent file are valid. + If any version is invalid, it will be consider dirty + and the recent file will be removed + */ + if !ValidVersionFormat(line) { + RemoveFiles(installLocation + recentFile) + return nil, errRead + } + + /* output can be confusing since it displays the 3 most recent used terraform version + append the string *recent to the output to make it more user friendly + */ + outputRecent = append(outputRecent, fmt.Sprintf("%s *recent", line)) + } + + return outputRecent, nil + } + + return nil, nil +} + +//CreateRecentFile : create a recent file +func CreateRecentFile(requestedVersion string) { + WriteLines([]string{requestedVersion}, installLocation+recentFile) +} diff --git a/vendor/github.com/warrensbox/terraform-switcher/lib/list_versions.go b/vendor/github.com/warrensbox/terraform-switcher/lib/list_versions.go new file mode 100644 index 0000000..c7ca1fb --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/lib/list_versions.go @@ -0,0 +1,115 @@ +package lib + +import ( + "io/ioutil" + "log" + "net/http" + "reflect" + "regexp" + "strings" +) + +type tfVersionList struct { + tflist []string +} + +//GetTFList : Get the list of available terraform version given the hashicorp url +func GetTFList(hashiURL string, listAll bool) ([]string, error) { + + /* Get list of terraform versions from hashicorp releases */ + resp, errURL := http.Get(hashiURL) + if errURL != nil { + log.Printf("Error getting url: %v", errURL) + return nil, errURL + } + defer resp.Body.Close() + + body, errBody := ioutil.ReadAll(resp.Body) + if errBody != nil { + log.Printf("Error reading body: %v", errBody) + return nil, errBody + } + + bodyString := string(body) + result := strings.Split(bodyString, "\n") + + var tfVersionList tfVersionList + + for i := range result { + // Getting versions from body; should return match /X.X.X/ where X is a number + // Follow https://semver.org/spec/v2.0.0.html + r, _ := regexp.Compile(`\/(\d+\.\d+\.\d+)\/`) + if listAll { + // Getting versions from body; should return match /X.X.X-@/ where X is a number,@ is a word character between a-z or A-Z + // Follow https://semver.org/spec/v1.0.0-beta.html + // Check regular expression at https://rubular.com/r/ju3PxbaSBALpJB + r, _ = regexp.Compile(`\/(\d+\.\d+\.\d+)(-[a-zA-z]+\d*)?\/`) + } + + if r.MatchString(result[i]) { + str := r.FindString(result[i]) + trimstr := strings.Trim(str, "/") //remove "/" from /X.X.X/ + tfVersionList.tflist = append(tfVersionList.tflist, trimstr) + } + } + + return tfVersionList.tflist, nil + +} + +//VersionExist : check if requested version exist +func VersionExist(val interface{}, array interface{}) (exists bool) { + + exists = false + switch reflect.TypeOf(array).Kind() { + case reflect.Slice: + s := reflect.ValueOf(array) + + for i := 0; i < s.Len(); i++ { + if reflect.DeepEqual(val, s.Index(i).Interface()) == true { + exists = true + return exists + } + } + } + + return exists +} + +//RemoveDuplicateVersions : remove duplicate version +func RemoveDuplicateVersions(elements []string) []string { + // Use map to record duplicates as we find them. + encountered := map[string]bool{} + result := []string{} + + for _, val := range elements { + versionOnly := strings.Trim(val, " *recent") + if encountered[versionOnly] == true { + // Do not add duplicate. + } else { + // Record this element as an encountered element. + encountered[versionOnly] = true + // Append to result slice. + result = append(result, val) + } + } + // Return the new slice. + return result +} + +// ValidVersionFormat : returns valid version format +/* For example: 0.1.2 = valid +// For example: 0.1.2-beta1 = valid +// For example: 0.1.2-alpha = valid +// For example: a.1.2 = invalid +// For example: 0.1. 2 = invalid +*/ +func ValidVersionFormat(version string) bool { + + // Getting versions from body; should return match /X.X.X-@/ where X is a number,@ is a word character between a-z or A-Z + // Follow https://semver.org/spec/v1.0.0-beta.html + // Check regular expression at https://rubular.com/r/ju3PxbaSBALpJB + semverRegex := regexp.MustCompile(`^(\d+\.\d+\.\d+)(-[a-zA-z]+\d*)?$`) + + return semverRegex.MatchString(version) +} diff --git a/vendor/github.com/warrensbox/terraform-switcher/lib/symlink.go b/vendor/github.com/warrensbox/terraform-switcher/lib/symlink.go new file mode 100644 index 0000000..b64790c --- /dev/null +++ b/vendor/github.com/warrensbox/terraform-switcher/lib/symlink.go @@ -0,0 +1,65 @@ +package lib + +import ( + "log" + "os" +) + +//CreateSymlink : create symlink +func CreateSymlink(cwd string, dir string) { + + err := os.Symlink(cwd, dir) + if err != nil { + log.Fatalf(` + Unable to create new symlink. + Maybe symlink already exist. Try removing existing symlink manually. + Try running "unlink %s" to remove existing symlink. + If error persist, you may not have the permission to create a symlink at %s. + Error: %s + `, dir, dir, err) + os.Exit(1) + } +} + +//RemoveSymlink : remove symlink +func RemoveSymlink(symlinkPath string) { + + _, err := os.Lstat(symlinkPath) + if err != nil { + log.Fatalf(` + Unable to remove symlink. + Maybe symlink already exist. Try removing existing symlink manually. + Try running "unlink %s" to remove existing symlink. + If error persist, you may not have the permission to create a symlink at %s. + Error: %s + `, symlinkPath, symlinkPath, err) + os.Exit(1) + } else { + errRemove := os.Remove(symlinkPath) + if errRemove != nil { + log.Fatalf(` + Unable to remove symlink. + Maybe symlink already exist. Try removing existing symlink manually. + Try running "unlink %s" to remove existing symlink. + If error persist, you may not have the permission to create a symlink at %s. + Error: %s + `, symlinkPath, symlinkPath, errRemove) + os.Exit(1) + } + } +} + +// CheckSymlink : check file is symlink +func CheckSymlink(symlinkPath string) bool { + + fi, err := os.Lstat(symlinkPath) + if err != nil { + return false + } + + if fi.Mode()&os.ModeSymlink != 0 { + return true + } + + return false +}