forked from toolshed/abra
refactor: break up cli pkg into nice small chunks
This commit is contained in:
165
cli/recipe/recipe.go
Normal file
165
cli/recipe/recipe.go
Normal file
@ -0,0 +1,165 @@
|
||||
package recipe
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"text/template"
|
||||
|
||||
"coopcloud.tech/abra/catalogue"
|
||||
"coopcloud.tech/abra/cli/formatter"
|
||||
"coopcloud.tech/abra/config"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var recipeListCommand = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List all available recipes",
|
||||
Aliases: []string{"ls"},
|
||||
Action: func(c *cli.Context) error {
|
||||
catl, err := catalogue.ReadAppsCatalogue()
|
||||
if err != nil {
|
||||
logrus.Fatal(err.Error())
|
||||
}
|
||||
apps := catl.Flatten()
|
||||
sort.Sort(catalogue.ByAppName(apps))
|
||||
tableCol := []string{"Name", "Category", "Status"}
|
||||
table := formatter.CreateTable(tableCol)
|
||||
for _, app := range apps {
|
||||
status := fmt.Sprintf("%v", app.Features.Status)
|
||||
tableRow := []string{app.Name, app.Category, status}
|
||||
table.Append(tableRow)
|
||||
}
|
||||
table.Render()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var recipeVersionCommand = &cli.Command{
|
||||
Name: "versions",
|
||||
Usage: "List available versions for <recipe>",
|
||||
ArgsUsage: "<recipe>",
|
||||
Action: func(c *cli.Context) error {
|
||||
recipe := c.Args().First()
|
||||
if recipe == "" {
|
||||
cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
catalogue, err := catalogue.ReadAppsCatalogue()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if app, ok := catalogue[recipe]; ok {
|
||||
tableCol := []string{"Version", "Service", "Image", "Digest"}
|
||||
table := formatter.CreateTable(tableCol)
|
||||
for version := range app.Versions {
|
||||
for service := range app.Versions[version] {
|
||||
meta := app.Versions[version][service]
|
||||
table.Append([]string{version, service, meta.Image, meta.Digest})
|
||||
}
|
||||
}
|
||||
table.SetAutoMergeCells(true)
|
||||
table.Render()
|
||||
return nil
|
||||
}
|
||||
|
||||
logrus.Fatalf("'%s' recipe doesn't exist?", recipe)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var recipeCreateCommand = &cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create a new recipe",
|
||||
ArgsUsage: "<recipe>",
|
||||
Action: func(c *cli.Context) error {
|
||||
recipe := c.Args().First()
|
||||
if recipe == "" {
|
||||
cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
directory := path.Join(config.APPS_DIR, recipe)
|
||||
if _, err := os.Stat(directory); !os.IsNotExist(err) {
|
||||
logrus.Fatalf("'%s' recipe directory already exists?", directory)
|
||||
return nil
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/example.git", config.REPOS_BASE_URL)
|
||||
_, err := git.PlainClone(directory, false, &git.CloneOptions{URL: url, Tags: git.AllTags})
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
gitRepo := path.Join(config.APPS_DIR, recipe, ".git")
|
||||
if err := os.RemoveAll(gitRepo); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
toParse := []string{
|
||||
path.Join(config.APPS_DIR, recipe, "README.md"),
|
||||
path.Join(config.APPS_DIR, recipe, ".env.sample"),
|
||||
path.Join(config.APPS_DIR, recipe, ".drone.yml"),
|
||||
}
|
||||
for _, path := range toParse {
|
||||
file, err := os.OpenFile(path, os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
tpl, err := template.ParseFiles(path)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: ask for description and probably other things so that the
|
||||
// template repository is more "ready" to go than the current best-guess
|
||||
// mode of templating
|
||||
if err := tpl.Execute(file, struct {
|
||||
Name string
|
||||
Description string
|
||||
}{recipe, "TODO"}); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf(
|
||||
"New recipe '%s' created in %s, happy hacking!",
|
||||
recipe, path.Join(config.APPS_DIR, recipe),
|
||||
)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var RecipeCommand = &cli.Command{
|
||||
Name: "recipe",
|
||||
Usage: "Manage app recipes",
|
||||
Description: `
|
||||
A recipe is a blueprint for an app. It is made up of two things:
|
||||
|
||||
- A libre software app (e.g. Nextcloud, Wordpress, Mastodon)
|
||||
- A package configuration which describes how to deploy and maintain it
|
||||
|
||||
Recipes are developed, maintained and extended by the Co-op Cloud volunteer-run
|
||||
community. Each recipe has a "level" which is intended as a way to quickly show
|
||||
how reliable this app is to deploy and maintain in its current state.
|
||||
`,
|
||||
Subcommands: []*cli.Command{
|
||||
recipeListCommand,
|
||||
recipeVersionCommand,
|
||||
recipeCreateCommand,
|
||||
},
|
||||
}
|
Reference in New Issue
Block a user