Catalogue package had to be merged into the recipe package due to too many circular import errors. Also, use https url for cloning, assume folks don't have ssh setup by default (the whole reason for the refactor).
233 lines
5.4 KiB
Go
233 lines
5.4 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
abraFormatter "coopcloud.tech/abra/cli/formatter"
|
|
"coopcloud.tech/abra/pkg/client"
|
|
"coopcloud.tech/abra/pkg/config"
|
|
"coopcloud.tech/abra/pkg/dns"
|
|
"coopcloud.tech/abra/pkg/git"
|
|
"coopcloud.tech/abra/pkg/lint"
|
|
"coopcloud.tech/abra/pkg/recipe"
|
|
"coopcloud.tech/abra/pkg/upstream/stack"
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
// DeployAction is the main command-line action for this package
|
|
func DeployAction(c *cli.Context) error {
|
|
app := ValidateApp(c)
|
|
stackName := app.StackName()
|
|
|
|
if err := recipe.EnsureUpToDate(app.Type); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
r, err := recipe.Get(app.Type)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if err := lint.LintForErrors(r); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
cl, err := client.New(app.Server)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
logrus.Debugf("checking whether %s is already deployed", stackName)
|
|
|
|
isDeployed, deployedVersion, err := stack.IsDeployed(c.Context, cl, stackName)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if isDeployed {
|
|
if Force || Chaos {
|
|
logrus.Warnf("%s is already deployed but continuing (--force/--chaos)", stackName)
|
|
} else {
|
|
logrus.Fatalf("%s is already deployed", stackName)
|
|
}
|
|
}
|
|
|
|
version := deployedVersion
|
|
if version == "" && !Chaos {
|
|
catl, err := recipe.ReadRecipeCatalogue()
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
versions, err := recipe.GetRecipeCatalogueVersions(app.Type, catl)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
if len(versions) > 0 {
|
|
version = versions[len(versions)-1]
|
|
logrus.Debugf("choosing %s as version to deploy", version)
|
|
if err := recipe.EnsureVersion(app.Type, version); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
} else {
|
|
head, err := git.GetRecipeHead(app.Type)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
version = head.String()[:8]
|
|
logrus.Warn("no versions detected, using latest commit")
|
|
if err := recipe.EnsureLatest(app.Type); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
if version == "" && !Chaos {
|
|
logrus.Debugf("choosing %s as version to deploy", version)
|
|
if err := recipe.EnsureVersion(app.Type, version); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
if version != "" && !Chaos {
|
|
if err := recipe.EnsureVersion(app.Type, version); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
if Chaos {
|
|
logrus.Warnf("chaos mode engaged")
|
|
var err error
|
|
version, err = recipe.ChaosVersion(app.Type)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Type, "abra.sh")
|
|
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
for k, v := range abraShEnv {
|
|
app.Env[k] = v
|
|
}
|
|
|
|
composeFiles, err := config.GetAppComposeFiles(app.Type, app.Env)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
deployOpts := stack.Deploy{
|
|
Composefiles: composeFiles,
|
|
Namespace: stackName,
|
|
Prune: false,
|
|
ResolveImage: stack.ResolveImageAlways,
|
|
}
|
|
compose, err := config.GetAppComposeConfig(app.Name, deployOpts, app.Env)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if err := DeployOverview(app, version, "continue with deployment?"); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if !NoDomainChecks {
|
|
domainName := app.Env["DOMAIN"]
|
|
ipv4, err := dns.EnsureIPv4(domainName)
|
|
if err != nil || ipv4 == "" {
|
|
logrus.Fatalf("could not find an IP address assigned to %s?", domainName)
|
|
}
|
|
|
|
if _, err = dns.EnsureDomainsResolveSameIPv4(domainName, app.Server); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
} else {
|
|
logrus.Warn("skipping domain checks as requested")
|
|
}
|
|
|
|
if err := stack.RunDeploy(cl, deployOpts, compose, app.Env["TYPE"], DontWaitConverge); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeployOverview shows a deployment overview
|
|
func DeployOverview(app config.App, version, message string) error {
|
|
tableCol := []string{"server", "compose", "domain", "app name", "version"}
|
|
table := abraFormatter.CreateTable(tableCol)
|
|
|
|
deployConfig := "compose.yml"
|
|
if composeFiles, ok := app.Env["COMPOSE_FILE"]; ok {
|
|
deployConfig = strings.Join(strings.Split(composeFiles, ":"), "\n")
|
|
}
|
|
|
|
server := app.Server
|
|
if app.Server == "default" {
|
|
server = "local"
|
|
}
|
|
|
|
table.Append([]string{server, deployConfig, app.Domain, app.StackName(), version})
|
|
table.Render()
|
|
|
|
if NoInput {
|
|
return nil
|
|
}
|
|
|
|
response := false
|
|
prompt := &survey.Confirm{
|
|
Message: message,
|
|
}
|
|
|
|
if err := survey.AskOne(prompt, &response); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !response {
|
|
logrus.Fatal("exiting as requested")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// NewVersionOverview shows an upgrade or downgrade overview
|
|
func NewVersionOverview(app config.App, currentVersion, newVersion string) error {
|
|
tableCol := []string{"server", "compose", "domain", "app name", "current version", "to be deployed"}
|
|
table := abraFormatter.CreateTable(tableCol)
|
|
|
|
deployConfig := "compose.yml"
|
|
if composeFiles, ok := app.Env["COMPOSE_FILE"]; ok {
|
|
deployConfig = strings.Join(strings.Split(composeFiles, ":"), "\n")
|
|
}
|
|
|
|
server := app.Server
|
|
if app.Server == "default" {
|
|
server = "local"
|
|
}
|
|
|
|
table.Append([]string{server, deployConfig, app.Domain, app.StackName(), currentVersion, newVersion})
|
|
table.Render()
|
|
|
|
if NoInput {
|
|
return nil
|
|
}
|
|
|
|
response := false
|
|
prompt := &survey.Confirm{
|
|
Message: "continue with deployment?",
|
|
}
|
|
|
|
if err := survey.AskOne(prompt, &response); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !response {
|
|
logrus.Fatal("exiting as requested")
|
|
}
|
|
|
|
return nil
|
|
}
|