Skip to content

Commit

Permalink
Add ls command to tvm (#37)
Browse files Browse the repository at this point in the history
* Add ls command to tvm

This allows you to list the locally-downloaded versions of Terraform in
the tvm repo/cache.
  • Loading branch information
dansimau authored and btromanova committed Oct 2, 2019
1 parent 2aec9b3 commit c972a31
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 2 deletions.
3 changes: 1 addition & 2 deletions astro/tvm/cli/tvm/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import (
"fmt"
"log"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/uber/astro/astro/tvm"

"github.com/spf13/cobra"
)

// defaultInstallPath is the path that the Terraform binary will be
Expand Down
95 changes: 95 additions & 0 deletions astro/tvm/cli/tvm/cmd/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2019 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cmd

import (
"fmt"
"log"
"os"
"os/exec"
"sort"

version "github.com/burl/go-version"
"github.com/spf13/cobra"

"github.com/uber/astro/astro/tvm"
)

var listCmd = &cobra.Command{
Use: "ls",
Short: "List locally downloaded versions of Terraform",
Run: func(cmd *cobra.Command, args []string) {
tvm, err := tvm.NewVersionRepoForCurrentSystem(repoPath)
if err != nil {
log.Fatal(err)
}

// Get list of downloaded versions and path to binaries
versionsPaths, err := tvm.List()
if err != nil {
log.Fatal(err)
}

// Extract just the version strings
versions := []string{}
for v := range versionsPaths {
versions = append(versions, v)
}

// Get the path to the current Terraform binary, according to $PATH
terraformPath, _ := exec.LookPath("terraform")

// Get path that Terraform binary links to
terraformLinkPath, _ := os.Readlink(terraformPath)

// List the versions
for _, v := range sortedVersions(versions) {
s := v.String()
print(s)

// If the current Terraform binary is linked to a particular
// path from tvm, then it's active and has been installed by tvm
if versionsPaths[s] == terraformLinkPath {
fmt.Printf(" (current, installed at: %s)", terraformPath)
}

println()
}
},
}

// sortedVersions takes a list of version strings and returns them sorted in
// reverse order.
func sortedVersions(versions []string) (sortedVersions version.Collection) {
for _, v := range versions {
semver, err := version.NewVersion(v)
if err != nil {
log.Println(err)
continue
}

sortedVersions = append(sortedVersions, semver)
}

sort.Sort(sort.Reverse(sortedVersions))

return
}

func init() {
rootCmd.AddCommand(listCmd)
}
31 changes: 31 additions & 0 deletions astro/tvm/versionrepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"sync"

Expand All @@ -40,6 +41,10 @@ const terraformBinaryFile = "terraform"
// files from the Hashicorp website.
var terraformZipFileDownloadURL = "https://releases.hashicorp.com/terraform/%s/terraform_%s_%s_%s.zip"

// versionDirectoryFormat is a regexp that matches Terraform semver,
// e.g. "1.2.30"
var versionDirectoryFormat = regexp.MustCompile(`\d+\.\d+\.\d+`)

// VersionRepo is a directory on the filesystem that keeps
// Terraform binaries.
type VersionRepo struct {
Expand Down Expand Up @@ -191,6 +196,32 @@ func (r *VersionRepo) Link(version string, targetPath string, overwrite bool) er
return os.Symlink(terraformPath, targetPath)
}

// List returns all locally downloaded Terraform versions and their paths.
func (r *VersionRepo) List() (map[string]string, error) {
dirs := map[string]string{}

repoBaseDir := r.dir("")
f, err := os.Open(repoBaseDir)
defer f.Close()
if err != nil {
return nil, err
}

files, err := f.Readdir(-1)
if err != nil {
return nil, err
}

for _, file := range files {
terraformVersion := file.Name()
if file.IsDir() && versionDirectoryFormat.MatchString(terraformVersion) {
dirs[terraformVersion] = r.terraformPath(terraformVersion)
}
}

return dirs, nil
}

// terraformPath returns the path to the Terraform binary file with the
// specified version.
func (r *VersionRepo) terraformPath(version string) string {
Expand Down

0 comments on commit c972a31

Please sign in to comment.