forked from toolshed/abra
.gitea
cli
app
catalogue
internal
recipe
server
updater
cli.go
cmd
pkg
scripts
tests
.dockerignore
.drone.yml
.envrc.sample
.gitignore
.goreleaser.yml
AUTHORS.md
Dockerfile
LICENSE
Makefile
README.md
go.mod
go.sum
renovate.json
These were alpha prototypes and we'll reconsider once other layers of Abra are more stable.
211 lines
5.9 KiB
Go
211 lines
5.9 KiB
Go
// Package cli provides the interface for the command-line.
|
|
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
|
|
"coopcloud.tech/abra/cli/app"
|
|
"coopcloud.tech/abra/cli/catalogue"
|
|
"coopcloud.tech/abra/cli/internal"
|
|
"coopcloud.tech/abra/cli/recipe"
|
|
"coopcloud.tech/abra/cli/server"
|
|
"coopcloud.tech/abra/pkg/autocomplete"
|
|
"coopcloud.tech/abra/pkg/config"
|
|
"coopcloud.tech/abra/pkg/git"
|
|
"coopcloud.tech/abra/pkg/web"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
// AutoCompleteCommand helps people set up auto-complete in their shells
|
|
var AutoCompleteCommand = cli.Command{
|
|
Name: "autocomplete",
|
|
Aliases: []string{"ac"},
|
|
Usage: "Configure shell autocompletion (recommended)",
|
|
Description: `
|
|
Set up auto-completion in your shell by downloading the relevant files and
|
|
laying out what additional information must be loaded. Supported shells are as
|
|
follows: bash, fish, fizsh & zsh.
|
|
|
|
Example:
|
|
|
|
abra autocomplete bash
|
|
`,
|
|
ArgsUsage: "<shell>",
|
|
Flags: []cli.Flag{
|
|
internal.DebugFlag,
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
shellType := c.Args().First()
|
|
|
|
if shellType == "" {
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no shell provided"))
|
|
}
|
|
|
|
supportedShells := map[string]bool{
|
|
"bash": true,
|
|
"zsh": true,
|
|
"fizsh": true,
|
|
"fish": true,
|
|
}
|
|
|
|
if _, ok := supportedShells[shellType]; !ok {
|
|
logrus.Fatalf("%s is not a supported shell right now, sorry", shellType)
|
|
}
|
|
|
|
if shellType == "fizsh" {
|
|
shellType = "zsh" // handled the same on the autocompletion side
|
|
}
|
|
|
|
autocompletionDir := path.Join(config.ABRA_DIR, "autocompletion")
|
|
if err := os.Mkdir(autocompletionDir, 0764); err != nil {
|
|
if !os.IsExist(err) {
|
|
logrus.Fatal(err)
|
|
}
|
|
logrus.Debugf("%s already created", autocompletionDir)
|
|
}
|
|
|
|
autocompletionFile := path.Join(config.ABRA_DIR, "autocompletion", shellType)
|
|
if _, err := os.Stat(autocompletionFile); err != nil && os.IsNotExist(err) {
|
|
url := fmt.Sprintf("https://git.coopcloud.tech/coop-cloud/abra/raw/branch/main/scripts/autocomplete/%s", shellType)
|
|
logrus.Infof("fetching %s", url)
|
|
if err := web.GetFile(autocompletionFile, url); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
switch shellType {
|
|
case "bash":
|
|
fmt.Println(fmt.Sprintf(`
|
|
# Run the following commands to install auto-completion
|
|
sudo mkdir /etc/bash_completion.d/
|
|
sudo cp %s /etc/bash_completion.d/abra
|
|
echo "source /etc/bash_completion.d/abra" >> ~/.bashrc
|
|
# To test, run the following: "abra app <hit tab key>" - you should see command completion!
|
|
`, autocompletionFile))
|
|
case "zsh":
|
|
fmt.Println(fmt.Sprintf(`
|
|
# Run the following commands to install auto-completion
|
|
sudo mkdir /etc/zsh/completion.d/
|
|
sudo cp %s /etc/zsh/completion.d/abra
|
|
echo "PROG=abra\n_CLI_ZSH_AUTOCOMPLETE_HACK=1\nsource /etc/zsh/completion.d/abra" >> ~/.zshrc
|
|
# To test, run the following: "abra app <hit tab key>" - you should see command completion!
|
|
`, autocompletionFile))
|
|
case "fish":
|
|
fmt.Println(fmt.Sprintf(`
|
|
# Run the following commands to install auto-completion
|
|
sudo mkdir -p /etc/fish/completions
|
|
sudo cp %s /etc/fish/completions/abra
|
|
echo "source /etc/fish/completions/abra" >> ~/.config/fish/config.fish
|
|
# To test, run the following: "abra app <hit tab key>" - you should see command completion!
|
|
`, autocompletionFile))
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
// UpgradeCommand upgrades abra in-place.
|
|
var UpgradeCommand = cli.Command{
|
|
Name: "upgrade",
|
|
Aliases: []string{"u"},
|
|
Usage: "Upgrade Abra itself",
|
|
Description: `
|
|
Upgrade Abra in-place with the latest stable or release candidate.
|
|
|
|
Pass "-r/--rc" to install the latest release candidate. Please bear in mind
|
|
that it may contain catastrophic bugs. Thank you very much for the testing
|
|
efforts!
|
|
`,
|
|
Flags: []cli.Flag{internal.RCFlag},
|
|
Action: func(c *cli.Context) error {
|
|
mainURL := "https://install.abra.coopcloud.tech"
|
|
cmd := exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash", mainURL))
|
|
|
|
if internal.RC {
|
|
releaseCandidateURL := "https://git.coopcloud.tech/coop-cloud/abra/raw/branch/main/scripts/installer/installer"
|
|
cmd = exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash -s -- --rc", releaseCandidateURL))
|
|
}
|
|
|
|
logrus.Debugf("attempting to run %s", cmd)
|
|
|
|
if err := internal.RunCmd(cmd); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func newAbraApp(version, commit string) *cli.App {
|
|
app := &cli.App{
|
|
Name: "abra",
|
|
Usage: `The Co-op Cloud command-line utility belt 🎩🐇
|
|
____ ____ _ _
|
|
/ ___|___ ___ _ __ / ___| | ___ _ _ __| |
|
|
| | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' |
|
|
| |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |
|
|
\____\___/ \___/| .__/ \____|_|\___/ \__,_|\__,_|
|
|
|_|
|
|
`,
|
|
Version: fmt.Sprintf("%s-%s", version, commit[:7]),
|
|
Commands: []cli.Command{
|
|
app.AppCommand,
|
|
server.ServerCommand,
|
|
recipe.RecipeCommand,
|
|
catalogue.CatalogueCommand,
|
|
UpgradeCommand,
|
|
AutoCompleteCommand,
|
|
},
|
|
BashComplete: autocomplete.SubcommandComplete,
|
|
}
|
|
|
|
app.EnableBashCompletion = true
|
|
|
|
app.Before = func(c *cli.Context) error {
|
|
paths := []string{
|
|
config.ABRA_DIR,
|
|
config.SERVERS_DIR,
|
|
config.RECIPES_DIR,
|
|
config.VENDOR_DIR,
|
|
config.BACKUP_DIR,
|
|
}
|
|
|
|
for _, path := range paths {
|
|
if err := os.Mkdir(path, 0764); err != nil {
|
|
if !os.IsExist(err) {
|
|
logrus.Fatal(err)
|
|
}
|
|
continue
|
|
}
|
|
}
|
|
|
|
if _, err := os.Stat(config.CATALOGUE_DIR); os.IsNotExist(err) {
|
|
url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME)
|
|
logrus.Warnf("local recipe catalogue is missing, retrieving now")
|
|
if err := git.Clone(config.CATALOGUE_DIR, url); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
logrus.Debugf("abra version %s, commit %s", version, commit)
|
|
|
|
return nil
|
|
}
|
|
|
|
return app
|
|
}
|
|
|
|
// RunApp runs CLI abra app.
|
|
func RunApp(version, commit string) {
|
|
app := newAbraApp(version, commit)
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|