refactor: vertical deploy overview
This commit is contained in:
parent
d3ede0f0f6
commit
f28cffe6d8
@ -2,6 +2,7 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
@ -47,6 +48,8 @@ EXAMPLE:
|
|||||||
abra app deploy foo.example.com 1e83340e`,
|
abra app deploy foo.example.com 1e83340e`,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
BashComplete: autocomplete.AppNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
var warnMessages []string
|
||||||
|
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(c)
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
@ -115,7 +118,7 @@ EXAMPLE:
|
|||||||
|
|
||||||
if deployMeta.IsDeployed {
|
if deployMeta.IsDeployed {
|
||||||
if internal.Force || internal.Chaos {
|
if internal.Force || internal.Chaos {
|
||||||
log.Warnf("%s is already deployed but continuing (--force/--chaos)", app.Name)
|
warnMessages = append(warnMessages, fmt.Sprintf("%s is already deployed", app.Name))
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("%s is already deployed", app.Name)
|
log.Fatalf("%s is already deployed", app.Name)
|
||||||
}
|
}
|
||||||
@ -139,13 +142,13 @@ EXAMPLE:
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
version = formatter.SmallSHA(head.String())
|
version = formatter.SmallSHA(head.String())
|
||||||
log.Warn("no versions detected, using latest commit")
|
warnMessages = append(warnMessages, fmt.Sprintf("no versions detected, using latest commit"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chaosVersion := "false"
|
chaosVersion := "false"
|
||||||
if internal.Chaos {
|
if internal.Chaos {
|
||||||
log.Warnf("chaos mode engaged")
|
warnMessages = append(warnMessages, "chaos mode engaged")
|
||||||
|
|
||||||
if isChaosCommit {
|
if isChaosCommit {
|
||||||
chaosVersion = specificVersion
|
chaosVersion = specificVersion
|
||||||
@ -201,14 +204,12 @@ EXAMPLE:
|
|||||||
|
|
||||||
for _, envVar := range envVars {
|
for _, envVar := range envVars {
|
||||||
if !envVar.Present {
|
if !envVar.Present {
|
||||||
log.Warnf("env var %s missing from %s.env, present in recipe .env.sample", envVar.Name, app.Domain)
|
warnMessages = append(warnMessages,
|
||||||
|
fmt.Sprintf("env var %s missing from %s.env, present in recipe .env.sample", envVar.Name, app.Domain),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := internal.DeployOverview(app, version, chaosVersion, "continue with deployment?"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !internal.NoDomainChecks {
|
if !internal.NoDomainChecks {
|
||||||
domainName, ok := app.Env["DOMAIN"]
|
domainName, ok := app.Env["DOMAIN"]
|
||||||
if ok {
|
if ok {
|
||||||
@ -216,10 +217,14 @@ EXAMPLE:
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Warn("skipping domain checks as no DOMAIN=... configured for app")
|
warnMessages = append(warnMessages, "skipping domain checks as no DOMAIN=... configured for app")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Warn("skipping domain checks as requested")
|
warnMessages = append(warnMessages, "skipping domain checks as requested")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := internal.DeployOverview(app, warnMessages, version, chaosVersion); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.WaitTimeout, err = appPkg.GetTimeoutFromLabel(compose, stackName)
|
stack.WaitTimeout, err = appPkg.GetTimeoutFromLabel(compose, stackName)
|
||||||
|
@ -47,6 +47,8 @@ EXAMPLE:
|
|||||||
abra app rollback foo.example.com 1.2.3+3.2.1`,
|
abra app rollback foo.example.com 1.2.3+3.2.1`,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
BashComplete: autocomplete.AppNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
var warnMessages []string
|
||||||
|
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(c)
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ EXAMPLE:
|
|||||||
var availableDowngrades []string
|
var availableDowngrades []string
|
||||||
if deployMeta.Version == "unknown" {
|
if deployMeta.Version == "unknown" {
|
||||||
availableDowngrades = versions
|
availableDowngrades = versions
|
||||||
log.Warnf("failed to determine deployed version of %s", app.Name)
|
warnMessages = append(warnMessages, fmt.Sprintf("failed to determine deployed version of %s", app.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
specificVersion := c.Args().Get(1)
|
specificVersion := c.Args().Get(1)
|
||||||
@ -113,7 +115,7 @@ EXAMPLE:
|
|||||||
|
|
||||||
if deployMeta.Version != "unknown" && specificVersion == "" {
|
if deployMeta.Version != "unknown" && specificVersion == "" {
|
||||||
if deployMeta.IsChaos {
|
if deployMeta.IsChaos {
|
||||||
log.Warn("attempting to rollback a chaos deployment")
|
warnMessages = append(warnMessages, fmt.Sprintf("attempting to rollback a chaos deployment"))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, version := range versions {
|
for _, version := range versions {
|
||||||
@ -203,7 +205,14 @@ EXAMPLE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(d1): no release notes implemeneted for rolling back
|
// NOTE(d1): no release notes implemeneted for rolling back
|
||||||
if err := internal.NewVersionOverview(app, deployMeta.Version, chaosVersion, chosenDowngrade, ""); err != nil {
|
if err := internal.NewVersionOverview(
|
||||||
|
app,
|
||||||
|
warnMessages,
|
||||||
|
"rollback",
|
||||||
|
deployMeta.Version,
|
||||||
|
chaosVersion,
|
||||||
|
chosenDowngrade,
|
||||||
|
""); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ Passing "-p/--prune" does not remove those volumes.`,
|
|||||||
chaosVersion = deployMeta.ChaosVersion
|
chaosVersion = deployMeta.ChaosVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := internal.DeployOverview(app, deployMeta.Version, chaosVersion, "continue with undeploy?"); err != nil {
|
if err := internal.DeployOverview(app, []string{}, deployMeta.Version, chaosVersion); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@ EXAMPLE:
|
|||||||
abra app upgrade foo.example.com 1.2.3+3.2.1`,
|
abra app upgrade foo.example.com 1.2.3+3.2.1`,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
BashComplete: autocomplete.AppNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
var warnMessages []string
|
||||||
|
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(c)
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ EXAMPLE:
|
|||||||
var availableUpgrades []string
|
var availableUpgrades []string
|
||||||
if deployMeta.Version == "unknown" {
|
if deployMeta.Version == "unknown" {
|
||||||
availableUpgrades = versions
|
availableUpgrades = versions
|
||||||
log.Warnf("failed to determine deployed version of %s", app.Name)
|
warnMessages = append(warnMessages, fmt.Sprintf("failed to determine deployed version of %s", app.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
specificVersion := c.Args().Get(1)
|
specificVersion := c.Args().Get(1)
|
||||||
@ -114,7 +116,7 @@ EXAMPLE:
|
|||||||
|
|
||||||
if deployMeta.Version != "unknown" && specificVersion == "" {
|
if deployMeta.Version != "unknown" && specificVersion == "" {
|
||||||
if deployMeta.IsChaos {
|
if deployMeta.IsChaos {
|
||||||
log.Warn("attempting to upgrade a chaos deployment")
|
warnMessages = append(warnMessages, fmt.Sprintf("attempting to upgrade a chaos deployment"))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, version := range versions {
|
for _, version := range versions {
|
||||||
@ -156,7 +158,7 @@ EXAMPLE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if internal.Force && chosenUpgrade == "" {
|
if internal.Force && chosenUpgrade == "" {
|
||||||
log.Warnf("%s is already upgraded to latest but continuing (--force)", app.Name)
|
warnMessages = append(warnMessages, fmt.Sprintf("%s is already upgraded to latest", app.Name))
|
||||||
chosenUpgrade = deployMeta.Version
|
chosenUpgrade = deployMeta.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +232,9 @@ EXAMPLE:
|
|||||||
|
|
||||||
for _, envVar := range envVars {
|
for _, envVar := range envVars {
|
||||||
if !envVar.Present {
|
if !envVar.Present {
|
||||||
log.Warnf("env var %s missing from %s.env, present in recipe .env.sample", envVar.Name, app.Domain)
|
warnMessages = append(warnMessages,
|
||||||
|
fmt.Sprintf("env var %s missing from %s.env, present in recipe .env.sample", envVar.Name, app.Domain),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +249,14 @@ EXAMPLE:
|
|||||||
chaosVersion = deployMeta.ChaosVersion
|
chaosVersion = deployMeta.ChaosVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := internal.NewVersionOverview(app, deployMeta.Version, chaosVersion, chosenUpgrade, releaseNotes); err != nil {
|
if err := internal.NewVersionOverview(
|
||||||
|
app,
|
||||||
|
warnMessages,
|
||||||
|
"upgrade",
|
||||||
|
deployMeta.Version,
|
||||||
|
chaosVersion,
|
||||||
|
chosenUpgrade,
|
||||||
|
releaseNotes); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,17 +6,41 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
appPkg "coopcloud.tech/abra/pkg/app"
|
appPkg "coopcloud.tech/abra/pkg/app"
|
||||||
"coopcloud.tech/abra/pkg/formatter"
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewVersionOverview shows an upgrade or downgrade overview
|
var borderStyle = lipgloss.NewStyle().
|
||||||
func NewVersionOverview(app appPkg.App, currentVersion, chaosVersion, newVersion, releaseNotes string) error {
|
BorderStyle(lipgloss.ThickBorder()).
|
||||||
tableCol := []string{"server", "recipe", "config", "domain", "version", "chaos", "to deploy"}
|
Padding(0, 1, 0, 1).
|
||||||
table := formatter.CreateTable(tableCol)
|
MaxWidth(79).
|
||||||
|
BorderForeground(lipgloss.Color("63"))
|
||||||
|
|
||||||
|
var headerStyle = lipgloss.NewStyle().
|
||||||
|
Underline(true).
|
||||||
|
Bold(true)
|
||||||
|
|
||||||
|
var leftStyle = lipgloss.NewStyle().
|
||||||
|
Bold(true)
|
||||||
|
|
||||||
|
var rightStyle = lipgloss.NewStyle()
|
||||||
|
|
||||||
|
// horizontal is a JoinHorizontal helper function.
|
||||||
|
func horizontal(left, mid, right string) string {
|
||||||
|
return lipgloss.JoinHorizontal(lipgloss.Left, left, mid, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVersionOverview shows an upgrade or downgrade overview
|
||||||
|
func NewVersionOverview(
|
||||||
|
app appPkg.App,
|
||||||
|
warnMessages []string,
|
||||||
|
kind,
|
||||||
|
currentVersion,
|
||||||
|
chaosVersion,
|
||||||
|
newVersion,
|
||||||
|
releaseNotes string) error {
|
||||||
deployConfig := "compose.yml"
|
deployConfig := "compose.yml"
|
||||||
if composeFiles, ok := app.Env["COMPOSE_FILE"]; ok {
|
if composeFiles, ok := app.Env["COMPOSE_FILE"]; ok {
|
||||||
deployConfig = strings.Join(strings.Split(composeFiles, ":"), "\n")
|
deployConfig = strings.Join(strings.Split(composeFiles, ":"), "\n")
|
||||||
@ -27,22 +51,36 @@ func NewVersionOverview(app appPkg.App, currentVersion, chaosVersion, newVersion
|
|||||||
server = "local"
|
server = "local"
|
||||||
}
|
}
|
||||||
|
|
||||||
table.Append([]string{
|
body := strings.Builder{}
|
||||||
server,
|
body.WriteString(
|
||||||
app.Recipe.Name,
|
borderStyle.Render(
|
||||||
deployConfig,
|
lipgloss.JoinVertical(
|
||||||
app.Domain,
|
lipgloss.Center,
|
||||||
currentVersion,
|
headerStyle.Render(fmt.Sprintf("%s OVERVIEW", strings.ToUpper(kind))),
|
||||||
chaosVersion,
|
lipgloss.JoinVertical(
|
||||||
newVersion,
|
lipgloss.Left,
|
||||||
})
|
horizontal(leftStyle.Render("SERVER"), " ", rightStyle.Render(server)),
|
||||||
table.Render()
|
horizontal(leftStyle.Render("DOMAIN"), " ", rightStyle.Render(app.Domain)),
|
||||||
|
horizontal(leftStyle.Render("RECIPE"), " ", rightStyle.Render(app.Recipe.Name)),
|
||||||
|
horizontal(leftStyle.Render("CONFIG"), " ", rightStyle.Render(deployConfig)),
|
||||||
|
horizontal(leftStyle.Render("VERSION"), " ", rightStyle.Render(currentVersion)),
|
||||||
|
horizontal(leftStyle.Render("CHAOS"), " ", rightStyle.Render(chaosVersion)),
|
||||||
|
horizontal(leftStyle.Render("DEPLOY"), " ", rightStyle.Padding(0).Render(newVersion)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
fmt.Println(body.String())
|
||||||
|
|
||||||
if releaseNotes != "" && newVersion != "" {
|
if releaseNotes != "" && newVersion != "" {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Print(releaseNotes)
|
fmt.Print(releaseNotes)
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("no release notes available for %s", newVersion)
|
warnMessages = append(warnMessages, fmt.Sprintf("no release notes available for %s", newVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, msg := range warnMessages {
|
||||||
|
log.Warn(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if NoInput {
|
if NoInput {
|
||||||
@ -50,16 +88,66 @@ func NewVersionOverview(app appPkg.App, currentVersion, chaosVersion, newVersion
|
|||||||
}
|
}
|
||||||
|
|
||||||
response := false
|
response := false
|
||||||
prompt := &survey.Confirm{
|
prompt := &survey.Confirm{Message: "proceed?"}
|
||||||
Message: "continue with deployment?",
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := survey.AskOne(prompt, &response); err != nil {
|
if err := survey.AskOne(prompt, &response); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !response {
|
if !response {
|
||||||
log.Fatal("exiting as requested")
|
log.Fatal("deployment cancelled")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeployOverview shows a deployment overview
|
||||||
|
func DeployOverview(app appPkg.App, warnMessages []string, version, chaosVersion string) error {
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
body := strings.Builder{}
|
||||||
|
body.WriteString(
|
||||||
|
borderStyle.Render(
|
||||||
|
lipgloss.JoinVertical(
|
||||||
|
lipgloss.Center,
|
||||||
|
headerStyle.Render("DEPLOY OVERVIEW"),
|
||||||
|
lipgloss.JoinVertical(
|
||||||
|
lipgloss.Left,
|
||||||
|
horizontal(leftStyle.Render("SERVER"), " ", rightStyle.Render(server)),
|
||||||
|
horizontal(leftStyle.Render("DOMAIN"), " ", rightStyle.Render(app.Domain)),
|
||||||
|
horizontal(leftStyle.Render("RECIPE"), " ", rightStyle.Render(app.Recipe.Name)),
|
||||||
|
horizontal(leftStyle.Render("CONFIG"), " ", rightStyle.Render(deployConfig)),
|
||||||
|
horizontal(leftStyle.Render("VERSION"), " ", rightStyle.Render(version)),
|
||||||
|
horizontal(leftStyle.Render("CHAOS"), " ", rightStyle.Padding(0).Render(chaosVersion)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
fmt.Println(body.String())
|
||||||
|
|
||||||
|
for _, msg := range warnMessages {
|
||||||
|
log.Warn(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if NoInput {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
response := false
|
||||||
|
prompt := &survey.Confirm{Message: "proceed?"}
|
||||||
|
if err := survey.AskOne(prompt, &response); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !response {
|
||||||
|
log.Fatal("deployment cancelled")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -118,48 +206,3 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeployOverview shows a deployment overview
|
|
||||||
func DeployOverview(app appPkg.App, version, chaosVersion, message string) error {
|
|
||||||
tableCol := []string{"server", "recipe", "config", "domain", "version", "chaos"}
|
|
||||||
table := formatter.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,
|
|
||||||
app.Recipe.Name,
|
|
||||||
deployConfig,
|
|
||||||
app.Domain,
|
|
||||||
version,
|
|
||||||
chaosVersion,
|
|
||||||
})
|
|
||||||
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 {
|
|
||||||
log.Fatal("exiting as requested")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user