Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* implement command line interface Co-authored-by: Seth Hoenig <seth.a.hoenig@gmail.com> * cli: make `hc-install install` a subcommand * Apply suggestions from code review Co-authored-by: Radek Simko <radek.simko@gmail.com> * run go mod tidy * switch to use Install method * create the product on the fly * remove unused functions, return nicer success message * return installed path directly from Install method * fix bad return code Co-authored-by: kmoe <5575356+kmoe@users.noreply.github.com> * go fmt ./... Co-authored-by: Seth Hoenig <seth.a.hoenig@gmail.com> Co-authored-by: Radek Simko <radek.simko@gmail.com> Co-authored-by: kmoe <5575356+kmoe@users.noreply.github.com>
- Loading branch information
1 parent
eb7dc86
commit c241e27
Showing
4 changed files
with
221 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"runtime" | ||
"strings" | ||
|
||
"github.com/hashicorp/go-version" | ||
"github.com/mitchellh/cli" | ||
|
||
hci "github.com/hashicorp/hc-install" | ||
"github.com/hashicorp/hc-install/product" | ||
"github.com/hashicorp/hc-install/releases" | ||
"github.com/hashicorp/hc-install/src" | ||
) | ||
|
||
type InstallCommand struct { | ||
Ui cli.Ui | ||
} | ||
|
||
func (c *InstallCommand) Name() string { return "install" } | ||
|
||
func (c *InstallCommand) Synopsis() string { | ||
return "Install a HashiCorp product" | ||
} | ||
|
||
func (c *InstallCommand) Help() string { | ||
helpText := ` | ||
Usage: hc-install install [options] -version <version> <product> | ||
This command installs a HashiCorp product. | ||
Options: | ||
-version [REQUIRED] Version of product to install. | ||
-path Path to directory where the product will be installed. Defaults | ||
to current working directory. | ||
` | ||
return strings.TrimSpace(helpText) | ||
} | ||
|
||
func (c *InstallCommand) Run(args []string) int { | ||
var ( | ||
version string | ||
installDirPath string | ||
) | ||
|
||
fs := flag.NewFlagSet("install", flag.ExitOnError) | ||
fs.Usage = func() { c.Ui.Output(c.Help()) } | ||
fs.StringVar(&version, "version", "", "version of product to install") | ||
fs.StringVar(&installDirPath, "path", "", "path to directory where production will be installed") | ||
|
||
if err := fs.Parse(args); err != nil { | ||
return 1 | ||
} | ||
|
||
// golang's arg parser is Posix-compliant but doesn't match the | ||
// common GNU flag parsing argument, so force an error rather than | ||
// silently dropping the options | ||
args = fs.Args() | ||
if len(args) != 1 { | ||
c.Ui.Error(`This command requires one positional argument: <product> | ||
Option flags must be provided before the positional argument`) | ||
return 1 | ||
} | ||
product := fs.Args()[0] | ||
|
||
if version == "" { | ||
c.Ui.Error("-version flag is required") | ||
return 1 | ||
} | ||
|
||
if installDirPath == "" { | ||
cwd, err := os.Getwd() | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Could not get current working directory for default installation path: %v", err)) | ||
return 1 | ||
} | ||
installDirPath = cwd | ||
} | ||
|
||
installedPath, err := c.install(product, version, installDirPath) | ||
if err != nil { | ||
msg := fmt.Sprintf("failed to install %s@%s: %v", product, version, err) | ||
c.Ui.Error(msg) | ||
return 1 | ||
} | ||
|
||
c.Ui.Info(fmt.Sprintf("installed %s@%s to %s", product, version, installedPath)) | ||
return 0 | ||
} | ||
|
||
func (c *InstallCommand) install(project, tag, installDirPath string) (string, error) { | ||
msg := fmt.Sprintf("hc-install: will install %s@%s", project, tag) | ||
c.Ui.Info(msg) | ||
|
||
v, err := version.NewVersion(tag) | ||
if err != nil { | ||
return "", fmt.Errorf("invalid version: %w", err) | ||
} | ||
i := hci.NewInstaller() | ||
|
||
source := &releases.ExactVersion{ | ||
Product: product.Product{ | ||
Name: project, | ||
BinaryName: func() string { | ||
if runtime.GOOS == "windows" { | ||
return fmt.Sprintf("%s.exe", project) | ||
} | ||
return project | ||
}, | ||
}, | ||
Version: v, | ||
InstallDir: installDirPath, | ||
} | ||
|
||
ctx := context.Background() | ||
return i.Install(ctx, []src.Installable{source}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,131 +1,47 @@ | ||
package main | ||
|
||
// import ( | ||
// "context" | ||
// "flag" | ||
// "io/ioutil" | ||
// "log" | ||
// "os" | ||
// "strings" | ||
|
||
// "github.com/hashicorp/logutils" | ||
// "github.com/mitchellh/cli" | ||
|
||
// "github.com/hashicorp/hcinstall" | ||
// ) | ||
|
||
// // TODO: add versioning to this? | ||
// const userAgentAppend = "hcinstall-cli" | ||
|
||
// func main() { | ||
// filter := &logutils.LevelFilter{ | ||
// Levels: []logutils.LogLevel{"DEBUG", "WARN", "ERROR"}, | ||
// MinLevel: logutils.LogLevel("WARN"), | ||
// Writer: os.Stderr, | ||
// } | ||
// log.SetOutput(filter) | ||
|
||
// ui := &cli.ColoredUi{ | ||
// ErrorColor: cli.UiColorRed, | ||
// WarnColor: cli.UiColorYellow, | ||
// Ui: &cli.BasicUi{ | ||
// Reader: os.Stdin, | ||
// Writer: os.Stdout, | ||
// ErrorWriter: os.Stderr, | ||
// }, | ||
// } | ||
|
||
// exitStatus := run(ui, os.Args[1:]) | ||
|
||
// os.Exit(exitStatus) | ||
// } | ||
|
||
// func help() string { | ||
// return `Usage: hcinstall [--dir=DIR] VERSION-OR-REF | ||
|
||
// Downloads, verifies, and installs a official releases of a binary | ||
// from releases.hashicorp.com or downloads, compiles, and installs a version of | ||
// the the binary from the GitHub repository. | ||
|
||
// To download an official release, pass "latest" or a valid semantic versioning | ||
// version string. | ||
|
||
// To download and compile a version of the binary from the GitHub | ||
// repository pass a ref in the form "refs/...", some examples are shown below. | ||
|
||
// If a binary is successfully installed, its path will be printed to stdout. | ||
|
||
// Unless --dir is given, the default system temporary directory will be used. | ||
|
||
// Options: | ||
// --dir Directory into which to install the terraform binary. The | ||
// directory must exist. | ||
|
||
// Examples: | ||
// hcinstall terraform 0.12.28 | ||
// hcinstall consul latest | ||
// hcinstall terraform 0.13.0-beta3 | ||
// hcinstall --dir=/home/kmoe/bin 0.12.28 | ||
// hcinstall refs/heads/master | ||
// hcinstall refs/tags/v0.12.29 | ||
// hcinstall refs/pull/25633/head | ||
// ` | ||
// } | ||
|
||
// func run(ui cli.Ui, args []string) int { | ||
// ctx := context.Background() | ||
|
||
// args = os.Args[1:] | ||
// flags := flag.NewFlagSet("", flag.ExitOnError) | ||
// var tfDir string | ||
// flags.StringVar(&tfDir, "dir", "", "Local directory into which to install terraform") | ||
|
||
// err := flags.Parse(args) | ||
// if err != nil { | ||
// ui.Error(err.Error()) | ||
// return 1 | ||
// } | ||
|
||
// if flags.NArg() != 1 { | ||
// ui.Error("Please specify VERSION-OR-REF") | ||
// ui.Output(help()) | ||
// return 127 | ||
// } | ||
|
||
// tfVersion := flags.Args()[0] | ||
|
||
// if tfDir == "" { | ||
// tfDir, err = ioutil.TempDir("", "hcinstall") | ||
// if err != nil { | ||
// ui.Error(err.Error()) | ||
// return 1 | ||
// } | ||
// } | ||
|
||
// var findArgs []hcinstall.ExecPathFinder | ||
|
||
// switch { | ||
// case tfVersion == "latest": | ||
// finder := hcinstall.LatestVersion(tfDir, false) | ||
// finder.UserAgent = userAgentAppend | ||
// findArgs = append(findArgs, finder) | ||
// case strings.HasPrefix(tfVersion, "refs/"): | ||
// findArgs = append(findArgs, gitref.Install(tfVersion, "", tfDir)) | ||
// default: | ||
// if strings.HasPrefix(tfVersion, "v") { | ||
// tfVersion = tfVersion[1:] | ||
// } | ||
// finder := hcinstall.ExactVersion(tfVersion, tfDir) | ||
// finder.UserAgent = userAgentAppend | ||
// findArgs = append(findArgs, finder) | ||
// } | ||
|
||
// tfPath, err := hcinstall.Find(ctx, findArgs...) | ||
// if err != nil { | ||
// ui.Error(err.Error()) | ||
// return 1 | ||
// } | ||
|
||
// ui.Output(tfPath) | ||
// return 0 | ||
// } | ||
import ( | ||
"log" | ||
"os" | ||
|
||
"github.com/hashicorp/hc-install/internal/version" | ||
|
||
"github.com/hashicorp/logutils" | ||
"github.com/mitchellh/cli" | ||
) | ||
|
||
func main() { | ||
filter := &logutils.LevelFilter{ | ||
Levels: []logutils.LogLevel{"DEBUG", "WARN", "ERROR"}, | ||
MinLevel: logutils.LogLevel("WARN"), | ||
Writer: os.Stderr, | ||
} | ||
log.SetOutput(filter) | ||
|
||
ui := &cli.ColoredUi{ | ||
ErrorColor: cli.UiColorRed, | ||
WarnColor: cli.UiColorYellow, | ||
Ui: &cli.BasicUi{ | ||
Reader: os.Stdin, | ||
Writer: os.Stdout, | ||
ErrorWriter: os.Stderr, | ||
}, | ||
} | ||
|
||
c := cli.NewCLI("hc-install", version.ModuleVersion()) | ||
c.Args = os.Args[1:] | ||
c.Commands = map[string]cli.CommandFactory{ | ||
"install": func() (cli.Command, error) { | ||
return &InstallCommand{ | ||
Ui: ui, | ||
}, nil | ||
}, | ||
} | ||
|
||
exitStatus, err := c.Run() | ||
if err != nil { | ||
ui.Error(err.Error()) | ||
} | ||
|
||
os.Exit(exitStatus) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.