forked from toolshed/abra
parent
bfed51a69c
commit
5975be6870
@ -206,10 +206,15 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`,
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toDeployChaosVersionLabel := toDeployChaosVersion
|
||||||
|
if app.Recipe.Dirty {
|
||||||
|
toDeployChaosVersionLabel = fmt.Sprintf("%s%s", toDeployChaosVersion, config.DIRTY_DEFAULT)
|
||||||
|
}
|
||||||
|
|
||||||
appPkg.ExposeAllEnv(stackName, compose, app.Env)
|
appPkg.ExposeAllEnv(stackName, compose, app.Env)
|
||||||
appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name)
|
appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name)
|
||||||
appPkg.SetChaosLabel(compose, stackName, internal.Chaos)
|
appPkg.SetChaosLabel(compose, stackName, internal.Chaos)
|
||||||
appPkg.SetChaosVersionLabel(compose, stackName, toDeployChaosVersion)
|
appPkg.SetChaosVersionLabel(compose, stackName, toDeployChaosVersionLabel)
|
||||||
appPkg.SetUpdateLabel(compose, stackName, app.Env)
|
appPkg.SetUpdateLabel(compose, stackName, app.Env)
|
||||||
|
|
||||||
envVars, err := appPkg.CheckEnv(app)
|
envVars, err := appPkg.CheckEnv(app)
|
||||||
@ -275,7 +280,6 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`,
|
|||||||
if toDeployChaosVersion != config.CHAOS_DEFAULT {
|
if toDeployChaosVersion != config.CHAOS_DEFAULT {
|
||||||
app.Recipe.Version = toDeployChaosVersion
|
app.Recipe.Version = toDeployChaosVersion
|
||||||
}
|
}
|
||||||
log.Debugf("choosing %s as version to save to env file", app.Recipe.Version)
|
|
||||||
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
|
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
|
||||||
log.Fatalf("writing new recipe version in env file: %s", err)
|
log.Fatalf("writing new recipe version in env file: %s", err)
|
||||||
}
|
}
|
||||||
|
139
cli/app/labels.go
Normal file
139
cli/app/labels.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"coopcloud.tech/abra/cli/internal"
|
||||||
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
|
"coopcloud.tech/abra/pkg/client"
|
||||||
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
|
"coopcloud.tech/abra/pkg/log"
|
||||||
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
|
composetypes "github.com/docker/cli/cli/compose/types"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
dockerClient "github.com/docker/docker/client"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AppLabelsCommand = &cobra.Command{
|
||||||
|
Use: "labels <app> [flags]",
|
||||||
|
Aliases: []string{"lb"},
|
||||||
|
Short: "Show deployment labels",
|
||||||
|
Long: "Both local recipe and live deployment labels are shown.",
|
||||||
|
Example: " abra app labels 1312.net",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
ValidArgsFunction: func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return autocomplete.AppNameComplete()
|
||||||
|
},
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
app := internal.ValidateApp(args)
|
||||||
|
|
||||||
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cl, err := client.New(app.Server)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteLabels, err := getLabels(cl, app.StackName())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := [][]string{
|
||||||
|
{"DEPLOYED LABELS", "---"},
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteLabelKeys := make([]string, 0, len(remoteLabels))
|
||||||
|
for k := range remoteLabels {
|
||||||
|
remoteLabelKeys = append(remoteLabelKeys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(remoteLabelKeys)
|
||||||
|
|
||||||
|
for _, k := range remoteLabelKeys {
|
||||||
|
rows = append(rows, []string{
|
||||||
|
k,
|
||||||
|
remoteLabels[k],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(remoteLabelKeys) == 0 {
|
||||||
|
rows = append(rows, []string{"unknown"})
|
||||||
|
}
|
||||||
|
|
||||||
|
rows = append(rows, []string{"RECIPE LABELS", "---"})
|
||||||
|
|
||||||
|
config, err := app.Recipe.GetComposeConfig(app.Env)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var localLabelKeys []string
|
||||||
|
var appServiceConfig composetypes.ServiceConfig
|
||||||
|
for _, service := range config.Services {
|
||||||
|
if service.Name == "app" {
|
||||||
|
appServiceConfig = service
|
||||||
|
|
||||||
|
for k := range service.Deploy.Labels {
|
||||||
|
localLabelKeys = append(localLabelKeys, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(localLabelKeys)
|
||||||
|
|
||||||
|
for _, k := range localLabelKeys {
|
||||||
|
rows = append(rows, []string{
|
||||||
|
k,
|
||||||
|
appServiceConfig.Deploy.Labels[k],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
overview := formatter.CreateOverview("LABELS OVERVIEW", rows)
|
||||||
|
fmt.Println(overview)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLabels reads docker labels from running services in the format of "coop-cloud.${STACK_NAME}.${LABEL}".
|
||||||
|
func getLabels(cl *dockerClient.Client, stackName string) (map[string]string, error) {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
|
||||||
|
filter := filters.NewArgs()
|
||||||
|
filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName))
|
||||||
|
|
||||||
|
services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: filter})
|
||||||
|
if err != nil {
|
||||||
|
return labels, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, service := range services {
|
||||||
|
if service.Spec.Name != fmt.Sprintf("%s_app", stackName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range service.Spec.Labels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AppLabelsCommand.Flags().BoolVarP(
|
||||||
|
&internal.Chaos,
|
||||||
|
"chaos",
|
||||||
|
"C",
|
||||||
|
false,
|
||||||
|
"ignore uncommitted recipes changes",
|
||||||
|
)
|
||||||
|
}
|
@ -201,8 +201,8 @@ var AppNewCommand = &cobra.Command{
|
|||||||
|
|
||||||
log.Warnf(
|
log.Warnf(
|
||||||
"secrets are %s shown again, please save them %s",
|
"secrets are %s shown again, please save them %s",
|
||||||
formatter.BoldStyle.Render("NOT"),
|
formatter.BoldUnderlineStyle.Render("NOT"),
|
||||||
formatter.BoldStyle.Render("NOW"),
|
formatter.BoldUnderlineStyle.Render("NOW"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,6 @@ var AppNewCommand = &cobra.Command{
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("choosing %s as version to save to env file", recipeVersion)
|
|
||||||
if err := app.WriteRecipeVersion(recipeVersion, false); err != nil {
|
if err := app.WriteRecipeVersion(recipeVersion, false); err != nil {
|
||||||
log.Fatalf("writing new recipe version in env file: %s", err)
|
log.Fatalf("writing new recipe version in env file: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
appPkg "coopcloud.tech/abra/pkg/app"
|
appPkg "coopcloud.tech/abra/pkg/app"
|
||||||
@ -24,7 +25,7 @@ import (
|
|||||||
var AppPsCommand = &cobra.Command{
|
var AppPsCommand = &cobra.Command{
|
||||||
Use: "ps <app> [flags]",
|
Use: "ps <app> [flags]",
|
||||||
Aliases: []string{"p"},
|
Aliases: []string{"p"},
|
||||||
Short: "Check app status",
|
Short: "Check app deployment status",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
ValidArgsFunction: func(
|
ValidArgsFunction: func(
|
||||||
cmd *cobra.Command,
|
cmd *cobra.Command,
|
||||||
@ -57,9 +58,11 @@ var AppPsCommand = &cobra.Command{
|
|||||||
statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true)
|
statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true)
|
||||||
if statusMeta, ok := statuses[app.StackName()]; ok {
|
if statusMeta, ok := statuses[app.StackName()]; ok {
|
||||||
if isChaos, exists := statusMeta["chaos"]; exists && isChaos == "true" {
|
if isChaos, exists := statusMeta["chaos"]; exists && isChaos == "true" {
|
||||||
chaosVersion, err = app.Recipe.ChaosVersion()
|
if cVersion, exists := statusMeta["chaosVersion"]; exists {
|
||||||
if err != nil {
|
chaosVersion = cVersion
|
||||||
log.Fatal(err)
|
if strings.HasSuffix(chaosVersion, config.DIRTY_DEFAULT) {
|
||||||
|
chaosVersion = formatter.BoldDirtyDefault(chaosVersion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,6 @@ beforehand.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.Recipe.Version = chosenDowngrade
|
app.Recipe.Version = chosenDowngrade
|
||||||
log.Debugf("choosing %s as version to save to env file", app.Recipe.Version)
|
|
||||||
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
|
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
|
||||||
log.Fatalf("writing new recipe version in env file: %s", err)
|
log.Fatalf("writing new recipe version in env file: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,6 @@ Passing "--prune/-p" does not remove those volumes.`,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("choosing %s as version to save to env file", deployMeta.Version)
|
|
||||||
if err := app.WriteRecipeVersion(deployMeta.Version, false); err != nil {
|
if err := app.WriteRecipeVersion(deployMeta.Version, false); err != nil {
|
||||||
log.Fatalf("writing undeployed recipe version in env file: %s", err)
|
log.Fatalf("writing undeployed recipe version in env file: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ beforehand.`,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
for _, version := range versions {
|
for _, version := range internal.SortVersionsDesc(versions) {
|
||||||
parsedVersion, err := tagcmp.Parse(version)
|
parsedVersion, err := tagcmp.Parse(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -289,7 +289,6 @@ beforehand.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.Recipe.Version = chosenUpgrade
|
app.Recipe.Version = chosenUpgrade
|
||||||
log.Debugf("choosing %s as version to save to env file", app.Recipe.Version)
|
|
||||||
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
|
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
|
||||||
log.Fatalf("writing new recipe version in env file: %s", err)
|
log.Fatalf("writing new recipe version in env file: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -61,18 +61,22 @@ func NewVersionOverview(
|
|||||||
domain = config.NO_DOMAIN_DEFAULT
|
domain = config.NO_DOMAIN_DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upperKind := strings.ToUpper(kind)
|
||||||
|
|
||||||
rows := [][]string{
|
rows := [][]string{
|
||||||
{"APP", domain},
|
{"APP", domain},
|
||||||
{"RECIPE", app.Recipe.Name},
|
{"RECIPE", app.Recipe.Name},
|
||||||
{"SERVER", server},
|
{"SERVER", server},
|
||||||
{"DEPLOYED", deployedVersion},
|
|
||||||
{"CURRENT CHAOS ", deployedChaosVersion},
|
|
||||||
{fmt.Sprintf("TO %s", strings.ToUpper(kind)), toDeployVersion},
|
|
||||||
{"CONFIG", deployConfig},
|
{"CONFIG", deployConfig},
|
||||||
|
{"CURRENT DEPLOYMENT", "---"},
|
||||||
|
{"VERSION", deployedVersion},
|
||||||
|
{"CHAOS ", deployedChaosVersion},
|
||||||
|
{upperKind, "---"},
|
||||||
|
{"VERSION", toDeployVersion},
|
||||||
}
|
}
|
||||||
|
|
||||||
overview := formatter.CreateOverview(
|
overview := formatter.CreateOverview(
|
||||||
fmt.Sprintf("%s OVERVIEW", strings.ToUpper(kind)),
|
fmt.Sprintf("%s OVERVIEW", upperKind),
|
||||||
rows,
|
rows,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -131,15 +135,25 @@ func DeployOverview(
|
|||||||
domain = config.NO_DOMAIN_DEFAULT
|
domain = config.NO_DOMAIN_DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deployedChaosVersion = formatter.BoldDirtyDefault(deployedChaosVersion)
|
||||||
|
|
||||||
|
if app.Recipe.Dirty {
|
||||||
|
toDeployChaosVersion = formatter.BoldDirtyDefault(toDeployChaosVersion)
|
||||||
|
}
|
||||||
|
|
||||||
rows := [][]string{
|
rows := [][]string{
|
||||||
{"APP", domain},
|
{"APP", domain},
|
||||||
{"RECIPE", app.Recipe.Name},
|
{"RECIPE", app.Recipe.Name},
|
||||||
{"SERVER", server},
|
{"SERVER", server},
|
||||||
{"DEPLOYED", deployedVersion},
|
|
||||||
{"CURRENT CHAOS ", deployedChaosVersion},
|
|
||||||
{"TO DEPLOY", toDeployVersion},
|
|
||||||
{"NEW CHAOS", toDeployChaosVersion},
|
|
||||||
{"CONFIG", deployConfig},
|
{"CONFIG", deployConfig},
|
||||||
|
|
||||||
|
{"CURRENT DEPLOYMENT", "---"},
|
||||||
|
{"VERSION", deployedVersion},
|
||||||
|
{"CHAOS", deployedChaosVersion},
|
||||||
|
|
||||||
|
{"NEW DEPLOYMENT", "---"},
|
||||||
|
{"VERSION", toDeployVersion},
|
||||||
|
{"CHAOS", toDeployChaosVersion},
|
||||||
}
|
}
|
||||||
|
|
||||||
overview := formatter.CreateOverview("DEPLOY OVERVIEW", rows)
|
overview := formatter.CreateOverview("DEPLOY OVERVIEW", rows)
|
||||||
@ -187,13 +201,18 @@ func UndeployOverview(
|
|||||||
domain = config.NO_DOMAIN_DEFAULT
|
domain = config.NO_DOMAIN_DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if app.Recipe.Dirty {
|
||||||
|
chaosVersion = formatter.BoldDirtyDefault(chaosVersion)
|
||||||
|
}
|
||||||
|
|
||||||
rows := [][]string{
|
rows := [][]string{
|
||||||
{"APP", domain},
|
{"APP", domain},
|
||||||
{"RECIPE", app.Recipe.Name},
|
{"RECIPE", app.Recipe.Name},
|
||||||
{"SERVER", server},
|
{"SERVER", server},
|
||||||
|
{"CONFIG", deployConfig},
|
||||||
|
{"CURRENT DEPLOYMENT", "---"},
|
||||||
{"DEPLOYED", version},
|
{"DEPLOYED", version},
|
||||||
{"CHAOS", chaosVersion},
|
{"CHAOS", chaosVersion},
|
||||||
{"CONFIG", deployConfig},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
overview := formatter.CreateOverview("UNDEPLOY OVERVIEW", rows)
|
overview := formatter.CreateOverview("UNDEPLOY OVERVIEW", rows)
|
||||||
|
17
cli/internal/deploy_test.go
Normal file
17
cli/internal/deploy_test.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSortVersionsDesc(t *testing.T) {
|
||||||
|
versions := SortVersionsDesc([]string{
|
||||||
|
"0.2.3+1.2.2",
|
||||||
|
"1.0.0+2.2.2",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, "1.0.0+2.2.2", versions[0])
|
||||||
|
assert.Equal(t, "0.2.3+1.2.2", versions[1])
|
||||||
|
}
|
@ -187,6 +187,7 @@ func Run(version, commit string) {
|
|||||||
app.AppUndeployCommand,
|
app.AppUndeployCommand,
|
||||||
app.AppUpgradeCommand,
|
app.AppUpgradeCommand,
|
||||||
app.AppVolumeCommand,
|
app.AppVolumeCommand,
|
||||||
|
app.AppLabelsCommand,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
@ -91,6 +91,17 @@ type App struct {
|
|||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String outputs a human-friendly string representation.
|
||||||
|
func (a App) String() string {
|
||||||
|
out := fmt.Sprintf("{name: %s, ", a.Name)
|
||||||
|
out += fmt.Sprintf("recipe: %s, ", a.Recipe)
|
||||||
|
out += fmt.Sprintf("domain: %s, ", a.Domain)
|
||||||
|
out += fmt.Sprintf("env %s, ", a.Env)
|
||||||
|
out += fmt.Sprintf("server %s, ", a.Server)
|
||||||
|
out += fmt.Sprintf("path %s}", a.Path)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// Type aliases to make code hints easier to understand
|
// Type aliases to make code hints easier to understand
|
||||||
|
|
||||||
// AppName is AppName
|
// AppName is AppName
|
||||||
@ -492,13 +503,13 @@ func GetAppComposeConfig(recipe string, opts stack.Deploy, appEnv envfile.AppEnv
|
|||||||
func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv envfile.AppEnv) {
|
func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv envfile.AppEnv) {
|
||||||
for _, service := range compose.Services {
|
for _, service := range compose.Services {
|
||||||
if service.Name == "app" {
|
if service.Name == "app" {
|
||||||
log.Debugf("add the following environment to the app service config of %s:", stackName)
|
log.Debugf("adding env vars to %s service config", stackName)
|
||||||
for k, v := range appEnv {
|
for k, v := range appEnv {
|
||||||
_, exists := service.Environment[k]
|
_, exists := service.Environment[k]
|
||||||
if !exists {
|
if !exists {
|
||||||
value := v
|
value := v
|
||||||
service.Environment[k] = &value
|
service.Environment[k] = &value
|
||||||
log.Debugf("add env var: %s value: %s to %s", k, value, stackName)
|
log.Debugf("%s: %s: %s", stackName, k, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,16 +578,19 @@ func ReadAbraShCmdNames(abraSh string) ([]string, error) {
|
|||||||
return cmdNames, nil
|
return cmdNames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a App) WriteRecipeVersion(version string, dryRun bool) error {
|
// Wipe removes the version from the app .env file.
|
||||||
|
func (a App) WipeRecipeVersion() error {
|
||||||
file, err := os.Open(a.Path)
|
file, err := os.Open(a.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
skipped := false
|
var (
|
||||||
scanner := bufio.NewScanner(file)
|
lines []string
|
||||||
lines := []string{}
|
scanner = bufio.NewScanner(file)
|
||||||
|
)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
if !strings.HasPrefix(line, "RECIPE=") && !strings.HasPrefix(line, "TYPE=") {
|
if !strings.HasPrefix(line, "RECIPE=") && !strings.HasPrefix(line, "TYPE=") {
|
||||||
@ -589,13 +603,71 @@ func (a App) WriteRecipeVersion(version string, dryRun bool) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(line, version) {
|
splitted := strings.Split(line, ":")
|
||||||
|
lines = append(lines, splitted[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(a.Path, []byte(strings.Join(lines, "\n")), os.ModePerm); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("version wiped from %s.env", a.Domain)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteRecipeVersion writes the recipe version to the app .env file.
|
||||||
|
func (a App) WriteRecipeVersion(version string, dryRun bool) error {
|
||||||
|
file, err := os.Open(a.Path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
dirtyVersion string
|
||||||
|
skipped bool
|
||||||
|
lines []string
|
||||||
|
scanner = bufio.NewScanner(file)
|
||||||
|
)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if !strings.HasPrefix(line, "RECIPE=") && !strings.HasPrefix(line, "TYPE=") {
|
||||||
|
lines = append(lines, line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "#") {
|
||||||
|
lines = append(lines, line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(line, version) && !a.Recipe.Dirty && !strings.HasSuffix(line, config.DIRTY_DEFAULT) {
|
||||||
skipped = true
|
skipped = true
|
||||||
lines = append(lines, line)
|
lines = append(lines, line)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
splitted := strings.Split(line, ":")
|
splitted := strings.Split(line, ":")
|
||||||
|
|
||||||
|
if a.Recipe.Dirty {
|
||||||
|
dirtyVersion = fmt.Sprintf("%s%s", version, config.DIRTY_DEFAULT)
|
||||||
|
if strings.Contains(line, dirtyVersion) {
|
||||||
|
skipped = true
|
||||||
|
lines = append(lines, line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
line = fmt.Sprintf("%s:%s", splitted[0], dirtyVersion)
|
||||||
|
lines = append(lines, line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
line = fmt.Sprintf("%s:%s", splitted[0], version)
|
line = fmt.Sprintf("%s:%s", splitted[0], version)
|
||||||
lines = append(lines, line)
|
lines = append(lines, line)
|
||||||
}
|
}
|
||||||
@ -604,6 +676,10 @@ func (a App) WriteRecipeVersion(version string, dryRun bool) error {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.Recipe.Dirty && dirtyVersion != "" {
|
||||||
|
version = dirtyVersion
|
||||||
|
}
|
||||||
|
|
||||||
if !dryRun {
|
if !dryRun {
|
||||||
if err := os.WriteFile(a.Path, []byte(strings.Join(lines, "\n")), os.ModePerm); err != nil {
|
if err := os.WriteFile(a.Path, []byte(strings.Join(lines, "\n")), os.ModePerm); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -198,3 +198,41 @@ func compareFilter(t *testing.T, f1 filters.Args, f2 map[string]map[string]bool)
|
|||||||
t.Errorf("filters mismatch (-want +got):\n%s", diff)
|
t.Errorf("filters mismatch (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteRecipeVersionOverwrite(t *testing.T) {
|
||||||
|
app, err := appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer t.Cleanup(func() {
|
||||||
|
if err := app.WipeRecipeVersion(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, "", app.Recipe.Version)
|
||||||
|
|
||||||
|
if err := app.WriteRecipeVersion("foo", false); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
app, err = appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, "foo", app.Recipe.Version)
|
||||||
|
|
||||||
|
app.Recipe.Dirty = true
|
||||||
|
if err := app.WriteRecipeVersion("foo+U", false); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
app, err = appPkg.GetApp(testPkg.ExpectedAppFiles, testPkg.AppName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, "foo+U", app.Recipe.Version)
|
||||||
|
}
|
||||||
|
@ -114,6 +114,8 @@ var (
|
|||||||
// complained yet!
|
// complained yet!
|
||||||
CHAOS_DEFAULT = "false"
|
CHAOS_DEFAULT = "false"
|
||||||
|
|
||||||
|
DIRTY_DEFAULT = "+U"
|
||||||
|
|
||||||
NO_DOMAIN_DEFAULT = "N/A"
|
NO_DOMAIN_DEFAULT = "N/A"
|
||||||
NO_VERSION_DEFAULT = "N/A"
|
NO_VERSION_DEFAULT = "N/A"
|
||||||
)
|
)
|
||||||
|
@ -13,11 +13,15 @@ import (
|
|||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/schollz/progressbar/v3"
|
"github.com/schollz/progressbar/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var BoldStyle = lipgloss.NewStyle().
|
var BoldStyle = lipgloss.NewStyle().
|
||||||
|
Bold(true)
|
||||||
|
|
||||||
|
var BoldUnderlineStyle = lipgloss.NewStyle().
|
||||||
Bold(true).
|
Bold(true).
|
||||||
Underline(true)
|
Underline(true)
|
||||||
|
|
||||||
@ -102,7 +106,6 @@ func CreateOverview(header string, rows [][]string) string {
|
|||||||
var borderStyle = lipgloss.NewStyle().
|
var borderStyle = lipgloss.NewStyle().
|
||||||
BorderStyle(lipgloss.ThickBorder()).
|
BorderStyle(lipgloss.ThickBorder()).
|
||||||
Padding(0, 1, 0, 1).
|
Padding(0, 1, 0, 1).
|
||||||
MaxWidth(79).
|
|
||||||
BorderForeground(lipgloss.Color("63"))
|
BorderForeground(lipgloss.Color("63"))
|
||||||
|
|
||||||
var headerStyle = lipgloss.NewStyle().
|
var headerStyle = lipgloss.NewStyle().
|
||||||
@ -110,9 +113,7 @@ func CreateOverview(header string, rows [][]string) string {
|
|||||||
Bold(true).
|
Bold(true).
|
||||||
PaddingBottom(1)
|
PaddingBottom(1)
|
||||||
|
|
||||||
var leftStyle = lipgloss.NewStyle().
|
var leftStyle = lipgloss.NewStyle()
|
||||||
Bold(true)
|
|
||||||
|
|
||||||
var rightStyle = lipgloss.NewStyle()
|
var rightStyle = lipgloss.NewStyle()
|
||||||
|
|
||||||
var longest int
|
var longest int
|
||||||
@ -138,10 +139,20 @@ func CreateOverview(header string, rows [][]string) string {
|
|||||||
offset = offset + " "
|
offset = offset + " "
|
||||||
}
|
}
|
||||||
|
|
||||||
renderedRows = append(
|
rendered := horizontal(leftStyle.Render(row[0]), offset, rightStyle.Render(row[1]))
|
||||||
renderedRows,
|
if row[1] == "---" {
|
||||||
horizontal(leftStyle.Render(row[0]), offset, rightStyle.Render(row[1])),
|
rendered = horizontal(
|
||||||
)
|
leftStyle.
|
||||||
|
Bold(true).
|
||||||
|
Underline(true).
|
||||||
|
PaddingTop(1).
|
||||||
|
Render(row[0]),
|
||||||
|
offset,
|
||||||
|
rightStyle.Render(""),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderedRows = append(renderedRows, rendered)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := strings.Builder{}
|
body := strings.Builder{}
|
||||||
@ -242,3 +253,13 @@ func ByteCountSI(b uint64) string {
|
|||||||
|
|
||||||
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
|
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoldDirtyDefault ensures a dirty modifier is rendered in bold.
|
||||||
|
func BoldDirtyDefault(v string) string {
|
||||||
|
if strings.HasSuffix(v, config.DIRTY_DEFAULT) {
|
||||||
|
vBold := BoldStyle.Render(config.DIRTY_DEFAULT)
|
||||||
|
v = strings.Replace(v, config.DIRTY_DEFAULT, vBold, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
11
pkg/formatter/formatter_test.go
Normal file
11
pkg/formatter/formatter_test.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package formatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBoldDirtyDefault(t *testing.T) {
|
||||||
|
assert.Equal(t, "foo", BoldDirtyDefault("foo"))
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
@ -17,12 +19,16 @@ import (
|
|||||||
func IsClean(repoPath string) (bool, error) {
|
func IsClean(repoPath string) (bool, error) {
|
||||||
repo, err := git.PlainOpen(repoPath)
|
repo, err := git.PlainOpen(repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
if errors.Is(err, git.ErrRepositoryNotExists) {
|
||||||
|
return false, git.ErrRepositoryNotExists
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("unable to open %s: %s", repoPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
worktree, err := repo.Worktree()
|
worktree, err := repo.Worktree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, fmt.Errorf("unable to open worktree of %s: %s", repoPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
patterns, err := GetExcludesFiles()
|
patterns, err := GetExcludesFiles()
|
||||||
@ -36,14 +42,14 @@ func IsClean(repoPath string) (bool, error) {
|
|||||||
|
|
||||||
status, err := worktree.Status()
|
status, err := worktree.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, fmt.Errorf("unable to query status of %s: %s", repoPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.String() != "" {
|
if status.String() != "" {
|
||||||
noNewline := strings.TrimSuffix(status.String(), "\n")
|
noNewline := strings.TrimSuffix(status.String(), "\n")
|
||||||
log.Debugf("discovered git status in %s: %s", repoPath, noNewline)
|
log.Debugf("git status: %s: %s", repoPath, noNewline)
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("discovered clean git status in %s", repoPath)
|
log.Debugf("git status: %s: clean", repoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return status.IsClean(), nil
|
return status.IsClean(), nil
|
||||||
|
15
pkg/git/read_test.go
Normal file
15
pkg/git/read_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsClean(t *testing.T) {
|
||||||
|
isClean, err := IsClean("/tmp")
|
||||||
|
assert.Equal(t, isClean, false)
|
||||||
|
assert.True(t, errors.Is(err, git.ErrRepositoryNotExists))
|
||||||
|
}
|
@ -137,8 +137,7 @@ func (r Recipe) EnsureIsClean() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isClean {
|
if !isClean {
|
||||||
msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding"
|
return fmt.Errorf("%s (%s) has locally unstaged changes?", r.Name, r.Dir)
|
||||||
return fmt.Errorf(msg, r.Name, r.Dir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -230,8 +229,23 @@ func (r Recipe) EnsureUpToDate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDirty checks whether a recipe is dirty or not. N.B., if you call IsDirty
|
||||||
|
// from another Recipe method, you should propagate the pointer reference (*).
|
||||||
|
func (r *Recipe) IsDirty() error {
|
||||||
|
isClean, err := gitPkg.IsClean(r.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isClean {
|
||||||
|
r.Dirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ChaosVersion constructs a chaos mode recipe version.
|
// ChaosVersion constructs a chaos mode recipe version.
|
||||||
func (r Recipe) ChaosVersion() (string, error) {
|
func (r *Recipe) ChaosVersion() (string, error) {
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
head, err := r.Head()
|
head, err := r.Head()
|
||||||
@ -241,15 +255,10 @@ func (r Recipe) ChaosVersion() (string, error) {
|
|||||||
|
|
||||||
version = formatter.SmallSHA(head.String())
|
version = formatter.SmallSHA(head.String())
|
||||||
|
|
||||||
isClean, err := gitPkg.IsClean(r.Dir)
|
if err := r.IsDirty(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return version, err
|
return version, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isClean {
|
|
||||||
version = fmt.Sprintf("%s+U", version)
|
|
||||||
}
|
|
||||||
|
|
||||||
return version, nil
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
pkg/recipe/git_test.go
Normal file
39
pkg/recipe/git_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package recipe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsDirty(t *testing.T) {
|
||||||
|
r := Get("abra-test-recipe")
|
||||||
|
|
||||||
|
if err := r.EnsureExists(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.IsDirty(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.False(t, r.Dirty)
|
||||||
|
|
||||||
|
fpath := filepath.Join(r.Dir, "foo.txt")
|
||||||
|
f, err := os.Create(fpath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
defer t.Cleanup(func() {
|
||||||
|
os.Remove(fpath)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := r.IsDirty(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, r.Dirty)
|
||||||
|
}
|
@ -2,6 +2,7 @@ package recipe
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -20,6 +21,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/web"
|
"coopcloud.tech/abra/pkg/web"
|
||||||
"coopcloud.tech/tagcmp"
|
"coopcloud.tech/tagcmp"
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RecipeCatalogueURL is the only current recipe catalogue available.
|
// RecipeCatalogueURL is the only current recipe catalogue available.
|
||||||
@ -131,7 +133,12 @@ func Get(name string) Recipe {
|
|||||||
log.Fatalf("version seems invalid: %s", name)
|
log.Fatalf("version seems invalid: %s", name)
|
||||||
}
|
}
|
||||||
name = split[0]
|
name = split[0]
|
||||||
|
|
||||||
version = split[1]
|
version = split[1]
|
||||||
|
if strings.HasSuffix(version, config.DIRTY_DEFAULT) {
|
||||||
|
version = strings.Replace(split[1], config.DIRTY_DEFAULT, "", 1)
|
||||||
|
log.Debugf("removed dirty suffix from .env version: %s -> %s", split[1], version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gitURL := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, name)
|
gitURL := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, name)
|
||||||
@ -151,7 +158,7 @@ func Get(name string) Recipe {
|
|||||||
|
|
||||||
dir := path.Join(config.RECIPES_DIR, escapeRecipeName(name))
|
dir := path.Join(config.RECIPES_DIR, escapeRecipeName(name))
|
||||||
|
|
||||||
return Recipe{
|
r := Recipe{
|
||||||
Name: name,
|
Name: name,
|
||||||
Version: version,
|
Version: version,
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
@ -163,11 +170,18 @@ func Get(name string) Recipe {
|
|||||||
SampleEnvPath: path.Join(dir, ".env.sample"),
|
SampleEnvPath: path.Join(dir, ".env.sample"),
|
||||||
AbraShPath: path.Join(dir, "abra.sh"),
|
AbraShPath: path.Join(dir, "abra.sh"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := r.IsDirty(); err != nil && !errors.Is(err, git.ErrRepositoryNotExists) {
|
||||||
|
log.Fatalf("failed to check git status of %s: %s", r.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
type Recipe struct {
|
type Recipe struct {
|
||||||
Name string
|
Name string
|
||||||
Version string
|
Version string
|
||||||
|
Dirty bool // NOTE(d1): git terminology for unstaged changes
|
||||||
Dir string
|
Dir string
|
||||||
GitURL string
|
GitURL string
|
||||||
SSHURL string
|
SSHURL string
|
||||||
@ -178,6 +192,21 @@ type Recipe struct {
|
|||||||
AbraShPath string
|
AbraShPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String outputs a human-friendly string representation.
|
||||||
|
func (r Recipe) String() string {
|
||||||
|
out := fmt.Sprintf("{name: %s, ", r.Name)
|
||||||
|
out += fmt.Sprintf("version : %s, ", r.Version)
|
||||||
|
out += fmt.Sprintf("dirty: %v, ", r.Dirty)
|
||||||
|
out += fmt.Sprintf("dir: %s, ", r.Dir)
|
||||||
|
out += fmt.Sprintf("git url: %s, ", r.GitURL)
|
||||||
|
out += fmt.Sprintf("ssh url: %s, ", r.SSHURL)
|
||||||
|
out += fmt.Sprintf("compose: %s, ", r.ComposePath)
|
||||||
|
out += fmt.Sprintf("readme: %s, ", r.ReadmePath)
|
||||||
|
out += fmt.Sprintf("sample env: %s, ", r.SampleEnvPath)
|
||||||
|
out += fmt.Sprintf("abra.sh: %s}", r.AbraShPath)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func escapeRecipeName(recipeName string) string {
|
func escapeRecipeName(recipeName string) string {
|
||||||
recipeName = strings.ReplaceAll(recipeName, "/", "_")
|
recipeName = strings.ReplaceAll(recipeName, "/", "_")
|
||||||
recipeName = strings.ReplaceAll(recipeName, ".", "_")
|
recipeName = strings.ReplaceAll(recipeName, ".", "_")
|
||||||
|
@ -105,3 +105,8 @@ func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) {
|
|||||||
assert.NotEqual(t, label, defaultTimeoutLabel)
|
assert.NotEqual(t, label, defaultTimeoutLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDirtyMarkerRemoved(t *testing.T) {
|
||||||
|
r := Get("abra-test-recipe:1e83340e+U")
|
||||||
|
assert.Equal(t, "1e83340e", r.Version)
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
stdlibErr "errors"
|
stdlibErr "errors"
|
||||||
|
|
||||||
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/upstream/convert"
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
"github.com/docker/cli/cli/command/service/progress"
|
"github.com/docker/cli/cli/command/service/progress"
|
||||||
@ -112,7 +113,7 @@ func IsDeployed(ctx context.Context, cl *dockerClient.Client, stackName string)
|
|||||||
IsDeployed: false,
|
IsDeployed: false,
|
||||||
Version: "unknown",
|
Version: "unknown",
|
||||||
IsChaos: false,
|
IsChaos: false,
|
||||||
ChaosVersion: "false", // NOTE(d1): match string type used on label
|
ChaosVersion: config.CHAOS_DEFAULT,
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := filters.NewArgs()
|
filter := filters.NewArgs()
|
||||||
|
@ -65,7 +65,6 @@ teardown(){
|
|||||||
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
||||||
--chaos --no-input --no-converge-checks
|
--chaos --no-input --no-converge-checks
|
||||||
assert_success
|
assert_success
|
||||||
assert_output --partial 'NEW CHAOS'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@ -128,7 +127,6 @@ teardown(){
|
|||||||
--no-input --no-converge-checks --chaos
|
--no-input --no-converge-checks --chaos
|
||||||
assert_success
|
assert_success
|
||||||
assert_output --partial "${wantHash:0:8}"
|
assert_output --partial "${wantHash:0:8}"
|
||||||
assert_output --partial 'NEW CHAOS'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@ -347,3 +345,18 @@ teardown(){
|
|||||||
run $ABRA app secret rm "$TEST_APP_DOMAIN" --all
|
run $ABRA app secret rm "$TEST_APP_DOMAIN" --all
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# bats test_tags=slow
|
||||||
|
@test "chaos version label includes dirty marker" {
|
||||||
|
run bash -c "echo foo >> $ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
|
||||||
|
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
||||||
|
--no-input --no-converge-checks --chaos
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN" --chaos
|
||||||
|
assert_success
|
||||||
|
assert_output --regexp 'chaos-version.*+U'
|
||||||
|
}
|
||||||
|
109
tests/integration/app_labels.bats
Normal file
109
tests/integration/app_labels.bats
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
setup_file(){
|
||||||
|
load "$PWD/tests/integration/helpers/common"
|
||||||
|
_common_setup
|
||||||
|
_add_server
|
||||||
|
_new_app
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown_file(){
|
||||||
|
_rm_app
|
||||||
|
_rm_server
|
||||||
|
_reset_recipe
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(){
|
||||||
|
load "$PWD/tests/integration/helpers/common"
|
||||||
|
_common_setup
|
||||||
|
_ensure_catalogue
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown(){
|
||||||
|
_reset_recipe
|
||||||
|
_reset_app
|
||||||
|
_undeploy_app
|
||||||
|
_reset_tags
|
||||||
|
|
||||||
|
run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "validate app argument" {
|
||||||
|
run $ABRA app labels
|
||||||
|
assert_failure
|
||||||
|
|
||||||
|
run $ABRA app labels DOESNTEXIST
|
||||||
|
assert_failure
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "bail if unstaged changes and no --chaos" {
|
||||||
|
run bash -c "echo foo >> $ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" status
|
||||||
|
assert_success
|
||||||
|
assert_output --partial 'foo'
|
||||||
|
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN" --no-input
|
||||||
|
assert_failure
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "do not bail if unstaged changes and --chaos" {
|
||||||
|
run bash -c 'echo "unstaged changes" >> "$ABRA_DIR/recipes/$TEST_RECIPE/foo"'
|
||||||
|
assert_success
|
||||||
|
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" status
|
||||||
|
assert_success
|
||||||
|
assert_output --partial 'foo'
|
||||||
|
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN" --chaos
|
||||||
|
assert_success
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "ensure recipe up to date if no --offline" {
|
||||||
|
wantHash=$(_get_n_hash 3)
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" reset --hard HEAD~3
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
assert_equal $(_get_current_hash) "$wantHash"
|
||||||
|
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN"
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
assert_equal $(_get_head_hash) $(_get_current_hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "ensure recipe not up to date if --offline" {
|
||||||
|
_ensure_env_version "0.1.0+1.20.0"
|
||||||
|
latestRelease=$(_latest_release)
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag -d "$latestRelease"
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN" --offline
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag -l
|
||||||
|
refute_output --partial "$latestRelease"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "show unknown if no deloyment" {
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN"
|
||||||
|
assert_success
|
||||||
|
assert_output --partial 'unknown'
|
||||||
|
}
|
||||||
|
|
||||||
|
# bats test_tags=slow
|
||||||
|
@test "show deploy labels when deployed" {
|
||||||
|
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
||||||
|
--no-input --no-converge-checks
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA app labels "$TEST_APP_DOMAIN"
|
||||||
|
assert_success
|
||||||
|
assert_output --partial 'com.docker.stack.image'
|
||||||
|
}
|
@ -137,3 +137,16 @@ teardown(){
|
|||||||
assert_output --partial "$latestRelease"
|
assert_output --partial "$latestRelease"
|
||||||
assert_output --partial "${headHash:0:8}" # is a chaos deploy
|
assert_output --partial "${headHash:0:8}" # is a chaos deploy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# bats test_tags=slow
|
||||||
|
@test "ensure live chaos commit is shown" {
|
||||||
|
headHash=$(_get_head_hash)
|
||||||
|
|
||||||
|
run $ABRA app deploy "$TEST_APP_DOMAIN" "0f5a0570" --no-input
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA app ps "$TEST_APP_DOMAIN"
|
||||||
|
assert_success
|
||||||
|
assert_output --partial "0f5a0570" # is not latest HEAD
|
||||||
|
refute_output --partial "${headHash:0:8}"
|
||||||
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
RECIPE=ecloud
|
RECIPE=ecloud
|
||||||
DOMAIN=ecloud.evil.corp
|
DOMAIN=ecloud.evil.corp
|
||||||
SMTP_AUTHTYPE=login
|
SMTP_AUTHTYPE=login
|
Loading…
x
Reference in New Issue
Block a user