From 552e0586b67962b5e342373eae77874b4ea68fe5 Mon Sep 17 00:00:00 2001 From: warren-veerasingam Date: Thu, 17 May 2018 00:19:36 -0500 Subject: [PATCH] added go convention go files --- .gitignore | 1 + lib/command.go | 78 +++++++++++++ main.go | 307 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 386 insertions(+) create mode 100644 .gitignore create mode 100644 lib/command.go create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..88d050b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +main \ No newline at end of file diff --git a/lib/command.go b/lib/command.go new file mode 100644 index 00000000..2584ffaa --- /dev/null +++ b/lib/command.go @@ -0,0 +1,78 @@ +package lib + +import ( + "io/ioutil" + "os" + "path/filepath" + "runtime" + "strings" +) + +type Command struct { + name string +} + +func NewCommand(name string) *Command { + return &Command{name: name} +} + +func (this *Command) PathList() []string { + path := os.Getenv("PATH") + return strings.Split(path, string(os.PathListSeparator)) +} + +func isDir(path string) bool { + file_info, err := os.Stat(path) + if err != nil || os.IsNotExist(err) { + return false + } + return file_info.IsDir() +} + +func isExecutable(path string) bool { + if isDir(path) { + return false + } + + file_info, err := os.Stat(path) + if err != nil || os.IsNotExist(err) { + return false + } + + if runtime.GOOS == "windows" { + return true + } + + if file_info.Mode()&0111 != 0 { + return true + } + + return false +} + +func (this *Command) Find() func() string { + path_chan := make(chan string) + go func() { + for _, p := range this.PathList() { + if !isDir(p) { + continue + } + file_list, err := ioutil.ReadDir(p) + if err != nil { + continue + } + + for _, f := range file_list { + path := filepath.Join(p, f.Name()) + if isExecutable(path) && f.Name() == this.name { + path_chan <- path + } + } + } + path_chan <- "" + }() + + return func() string { + return <-path_chan + } +} diff --git a/main.go b/main.go new file mode 100644 index 00000000..2e9e6130 --- /dev/null +++ b/main.go @@ -0,0 +1,307 @@ +package main + +/* +* Version 0.0.1 +* Compatible with Mac OS X ONLY + */ + +/*** WORKFLOW ***/ +/* +* 1- Check if user has sudo permission +* 2- Ask password to run sudo commands +* 3- Create /usr/local/terraform directory if does not exist +* 4- Download zip file from url to /usr/local/terraform +* 5- Unzip the file to /usr/local/terraform +* 6- Rename the file from `terraform` to `terraform_version` +* 7- Remove the downloaded zip file +* 8- Read the existing symlink for terraform (Check if it's a homebrew symlink) +* 9- Remove that symlink (Check if it's a homebrew symlink) +* 10- Create new symlink to binary `terraform_version` + */ + +import ( + "archive/zip" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "os/user" + "path/filepath" + "regexp" + "strings" + + "github.com/manifoldco/promptui" + cmd "github.com/warren-veerasingam/lib" +) + +type tfVersionList struct { + tflist []string +} + +const ( + hashiURL = "https://releases.hashicorp.com/terraform/" + installLocation = "/usr/local/terraform/" + installFile = "terraform" + installVersion = "terraform_" + binLocation = "/usr/local/bin/terraform" +) + +func main() { + + cmd := cmd.NewCommand("terraform") + next := cmd.Find() + + //log.Printf(next) + + existed := false + + for path := next(); len(path) > 0; path = next() { + fmt.Println(path) + existed = true + //if !argument.option_all { + // break + //} + } + if !existed { + //syscall.Exit(NotFoundStatus) + } + + resp, errURL := http.Get(hashiURL) + if errURL != nil { + log.Printf("Error getting url: %v", errURL) + } + defer resp.Body.Close() + + body, errBody := ioutil.ReadAll(resp.Body) + if errBody != nil { + log.Printf("Error reading body: %v", errBody) + return + } + + bodyString := string(body) + result := strings.Split(bodyString, "\n") + + var tfVersionList tfVersionList + + for i := range result { + //getting versions from body + r, _ := regexp.Compile(`\/(\d+)(\.)(\d+)(\.)(\d+)\/`) + + if r.MatchString(result[i]) { + str := r.FindString(result[i]) + trimstr := strings.Trim(str, "/") + tfVersionList.tflist = append(tfVersionList.tflist, trimstr) + } + } + + prompt := promptui.Select{ + Label: "Select Version", + Items: tfVersionList.tflist, + } + + _, version, errPrompt := prompt.Run() + + if errPrompt != nil { + log.Printf("Prompt failed %v\n", errPrompt) + return + } + + log.Printf("You picked %q\n", version) + + url := hashiURL + version + "/terraform_" + version + "_darwin_amd64.zip" + + zipFile, _ := DownloadFromURL(url) + + log.Printf("ZipFile: " + zipFile) + + files, errUnzip := Unzip(zipFile, installLocation) + if errUnzip != nil { + log.Fatal(errUnzip) + } + + log.Printf("Unzipped:\n" + strings.Join(files, "\n")) + + // RenameFile(installLocation+installFile, installLocation+installVersion+version) + // RemoveFiles(installLocation + installVersion + version + "_darwin_amd64.zip") + // ReadlinkI(binLocation) + // readLink(binLocation) + // removeSymlink(binLocation) + // CreateSymlink(installLocation+installVersion+version, binLocation) + +} + +// DownloadFromURL : Downloads the binary from the source url +func DownloadFromURL(url string) (string, error) { + tokens := strings.Split(url, "/") + fileName := tokens[len(tokens)-1] + fmt.Println("Downloading", url, "to", fileName) + + // TODO: check file existence first with io.IsExist + output, err := os.Create("/usr/local/terraform/" + fileName) + if err != nil { + fmt.Println("Error while creating", "/usr/local/terraform/"+fileName, "-", err) + return "", err + } + defer output.Close() + + response, err := http.Get(url) + if err != nil { + fmt.Println("Error while downloading", url, "-", err) + return "", err + } + defer response.Body.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 "/usr/local/terraform/" + fileName, nil +} + +//RenameFile : rename file name +func RenameFile(src string, dest string) { + + err := os.Rename(src, dest) + + if err != nil { + fmt.Println(err) + return + } + +} + +func getUser() { + user, err := user.Current() + if err != nil { + log.Fatal(err) + } + + fmt.Println("Hello " + user.Name) + fmt.Println("Hello GroupId" + user.Gid) + fmt.Println("====") + fmt.Println("Id: " + user.Uid) + fmt.Println("Username: " + user.Username) + fmt.Println("Home Dir: " + user.HomeDir) +} + +// 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) { + + fmt.Println("src: " + src) + + fmt.Println("dest: " + dest) + 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 +} + +// RemoveFiles : remove file +func RemoveFiles(src string) { + + fmt.Println(src) + + files, err := filepath.Glob(src) + if err != nil { + panic(err) + } + for _, f := range files { + if err := os.Remove(f); err != nil { + panic(err) + } + } +} + +func ReadlinkI(path string) { + fmt.Println("PATH") + // fmt.Println(path) + // exit_code := 0 + // defer os.Exit(exit_code) + ln, err := os.Readlink(path) + if err != nil { + fmt.Println("[ERR]", err) + //exit_code = 1 + return + } + fmt.Println("[FOUND]", ln) +} + +func readLink(path string) { + // exit_code := 0 + // defer os.Exit(exit_code) + ln, err := filepath.EvalSymlinks(path) + if err != nil { + fmt.Println("[ERR]", err) + //exit_code = 1 + return + } + fmt.Println("[FOUND]", ln) +} + +func CreateSymlink(cwd string, dir string) error { + + if err := os.Symlink(cwd, dir); err != nil { + return err + } + return nil +} + +func removeSymlink(symlinkPath string) error { + + if _, err := os.Lstat(symlinkPath); err != nil { + return err + } + os.Remove(symlinkPath) + return nil +}