Compare commits
11 Commits
0.3.1-rc1
...
0.3.1-alph
Author | SHA1 | Date | |
---|---|---|---|
fcbf41ee95 | |||
5add4ccc1b
|
|||
9220a8c09b
|
|||
f78a04109c | |||
b67ad02f87 | |||
215431696e | |||
cd361237e7 | |||
db10c7b849 | |||
d38f82ebe7 | |||
59031595ea | |||
6f26b51f3e |
@ -18,6 +18,7 @@ to scaling apps up and spinning them down.
|
|||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
appNewCommand,
|
appNewCommand,
|
||||||
appConfigCommand,
|
appConfigCommand,
|
||||||
|
appRestartCommand,
|
||||||
appDeployCommand,
|
appDeployCommand,
|
||||||
appUpgradeCommand,
|
appUpgradeCommand,
|
||||||
appUndeployCommand,
|
appUndeployCommand,
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
abraFormatter "coopcloud.tech/abra/cli/formatter"
|
abraFormatter "coopcloud.tech/abra/cli/formatter"
|
||||||
"coopcloud.tech/abra/pkg/catalogue"
|
"coopcloud.tech/abra/pkg/catalogue"
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
|
"coopcloud.tech/abra/pkg/ssh"
|
||||||
"coopcloud.tech/tagcmp"
|
"coopcloud.tech/tagcmp"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
@ -69,6 +70,12 @@ can take some time.
|
|||||||
}
|
}
|
||||||
sort.Sort(config.ByServerAndType(apps))
|
sort.Sort(config.ByServerAndType(apps))
|
||||||
|
|
||||||
|
for _, app := range apps {
|
||||||
|
if err := ssh.EnsureHostKey(app.Server); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
statuses := make(map[string]map[string]string)
|
statuses := make(map[string]map[string]string)
|
||||||
tableCol := []string{"Server", "Type", "Domain"}
|
tableCol := []string{"Server", "Type", "Domain"}
|
||||||
if status {
|
if status {
|
||||||
|
72
cli/app/restart.go
Normal file
72
cli/app/restart.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"coopcloud.tech/abra/cli/internal"
|
||||||
|
"coopcloud.tech/abra/pkg/client"
|
||||||
|
"coopcloud.tech/abra/pkg/config"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var appRestartCommand = &cli.Command{
|
||||||
|
Name: "restart",
|
||||||
|
Usage: "Restart an app",
|
||||||
|
Aliases: []string{"R"},
|
||||||
|
ArgsUsage: "<service>",
|
||||||
|
Description: `This command restarts a service within a deployed app.`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
app := internal.ValidateApp(c)
|
||||||
|
|
||||||
|
serviceName := c.Args().Get(1)
|
||||||
|
if serviceName == "" {
|
||||||
|
err := errors.New("missing service?")
|
||||||
|
internal.ShowSubcommandHelpAndError(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cl, err := client.New(app.Server)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceFilter := fmt.Sprintf("%s_%s", app.StackName(), serviceName)
|
||||||
|
filters := filters.NewArgs()
|
||||||
|
filters.Add("name", serviceFilter)
|
||||||
|
containerOpts := types.ContainerListOptions{Filters: filters}
|
||||||
|
containers, err := cl.ContainerList(c.Context, containerOpts)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(containers) != 1 {
|
||||||
|
logrus.Fatalf("expected 1 service but got %v", len(containers))
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("attempting to restart %s", serviceFilter)
|
||||||
|
|
||||||
|
timeout := 30 * time.Second
|
||||||
|
if err := cl.ContainerRestart(c.Context, containers[0].ID, &timeout); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("%s service restarted", serviceFilter)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
BashComplete: func(c *cli.Context) {
|
||||||
|
appNames, err := config.GetAppNames()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warn(err)
|
||||||
|
}
|
||||||
|
if c.NArg() > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, a := range appNames {
|
||||||
|
fmt.Println(a)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
@ -8,6 +8,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"coopcloud.tech/abra/pkg/secret"
|
"coopcloud.tech/abra/pkg/secret"
|
||||||
|
"coopcloud.tech/abra/pkg/ssh"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
@ -163,6 +164,10 @@ func NewAction(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Secrets {
|
if Secrets {
|
||||||
|
if err := ssh.EnsureHostKey(NewAppServer); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
secrets, err := createSecrets(sanitisedAppName)
|
secrets, err := createSecrets(sanitisedAppName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/catalogue"
|
"coopcloud.tech/abra/pkg/catalogue"
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
|
"coopcloud.tech/abra/pkg/ssh"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
@ -98,6 +99,10 @@ func ValidateApp(c *cli.Context) config.App {
|
|||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ssh.EnsureHostKey(app.Server); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
logrus.Debugf("validated '%s' as app argument", appName)
|
logrus.Debugf("validated '%s' as app argument", appName)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
@ -39,7 +39,7 @@ system.
|
|||||||
|
|
||||||
You may invoke this command in "wizard" mode and be prompted for input:
|
You may invoke this command in "wizard" mode and be prompted for input:
|
||||||
|
|
||||||
abra recipe sync gitea
|
abra recipe sync
|
||||||
|
|
||||||
`,
|
`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
@ -36,6 +36,11 @@ update the relevant compose file tags on the local file system.
|
|||||||
Some image tags cannot be parsed because they do not follow some sort of
|
Some image tags cannot be parsed because they do not follow some sort of
|
||||||
semver-like convention. In this case, all possible tags will be listed and it
|
semver-like convention. In this case, all possible tags will be listed and it
|
||||||
is up to the end-user to decide.
|
is up to the end-user to decide.
|
||||||
|
|
||||||
|
You may invoke this command in "wizard" mode and be prompted for input:
|
||||||
|
|
||||||
|
abra recipe upgrade
|
||||||
|
|
||||||
`,
|
`,
|
||||||
ArgsUsage: "<recipe>",
|
ArgsUsage: "<recipe>",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
@ -44,7 +49,7 @@ is up to the end-user to decide.
|
|||||||
internal.MajorFlag,
|
internal.MajorFlag,
|
||||||
},
|
},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
recipe := internal.ValidateRecipe(c)
|
recipe := internal.ValidateRecipeWithPrompt(c)
|
||||||
|
|
||||||
bumpType := btoi(internal.Major)*4 + btoi(internal.Minor)*2 + btoi(internal.Patch)
|
bumpType := btoi(internal.Major)*4 + btoi(internal.Minor)*2 + btoi(internal.Patch)
|
||||||
if bumpType != 0 {
|
if bumpType != 0 {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/formatter"
|
"coopcloud.tech/abra/cli/formatter"
|
||||||
"coopcloud.tech/abra/pkg/ssh"
|
|
||||||
"coopcloud.tech/abra/pkg/upstream/convert"
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
loader "coopcloud.tech/abra/pkg/upstream/stack"
|
loader "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
@ -146,10 +145,6 @@ func LoadAppFiles(servers ...string) (AppFiles, error) {
|
|||||||
|
|
||||||
logrus.Debugf("collecting metadata from '%v' servers: '%s'", len(servers), strings.Join(servers, ", "))
|
logrus.Debugf("collecting metadata from '%v' servers: '%s'", len(servers), strings.Join(servers, ", "))
|
||||||
|
|
||||||
if err := EnsureHostKeysAllServers(servers...); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, server := range servers {
|
for _, server := range servers {
|
||||||
serverDir := path.Join(ABRA_SERVER_FOLDER, server)
|
serverDir := path.Join(ABRA_SERVER_FOLDER, server)
|
||||||
files, err := getAllFilesInDirectory(serverDir)
|
files, err := getAllFilesInDirectory(serverDir)
|
||||||
@ -373,15 +368,3 @@ func GetAppComposeConfig(recipe string, opts stack.Deploy, appEnv AppEnv) (*comp
|
|||||||
|
|
||||||
return compose, nil
|
return compose, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureHostKeysAllServers ensures all configured servers have server SSH host keys validated
|
|
||||||
func EnsureHostKeysAllServers(servers ...string) error {
|
|
||||||
for _, serverName := range servers {
|
|
||||||
logrus.Debugf("ensuring server SSH host key available for %s", serverName)
|
|
||||||
if err := ssh.EnsureHostKey(serverName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -427,6 +427,11 @@ func connectWithPasswordTimeout(host, username, port, pass string, timeout time.
|
|||||||
|
|
||||||
// EnsureHostKey ensures that a host key trusted and added to the ~/.ssh/known_hosts file
|
// EnsureHostKey ensures that a host key trusted and added to the ~/.ssh/known_hosts file
|
||||||
func EnsureHostKey(hostname string) error {
|
func EnsureHostKey(hostname string) error {
|
||||||
|
if hostname == "default" || hostname == "local" {
|
||||||
|
logrus.Debugf("not checking server SSH host key against local/default target")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
exists, _, err := GetHostKey(hostname)
|
exists, _, err := GetHostKey(hostname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -3,10 +3,13 @@ package stack // https://github.com/docker/cli/blob/master/cli/command/stack/swa
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
abraClient "coopcloud.tech/abra/pkg/client"
|
abraClient "coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/upstream/convert"
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
|
"github.com/docker/cli/cli/command/service/progress"
|
||||||
composetypes "github.com/docker/cli/cli/compose/types"
|
composetypes "github.com/docker/cli/cli/compose/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
@ -346,6 +349,7 @@ func deployServices(
|
|||||||
existingServiceMap[service.Spec.Name] = service
|
existingServiceMap[service.Spec.Name] = service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var serviceIDs []string
|
||||||
for internalName, serviceSpec := range services {
|
for internalName, serviceSpec := range services {
|
||||||
var (
|
var (
|
||||||
name = namespace.Scope(internalName)
|
name = namespace.Scope(internalName)
|
||||||
@ -405,6 +409,8 @@ func deployServices(
|
|||||||
return errors.Wrapf(err, "failed to update service %s", name)
|
return errors.Wrapf(err, "failed to update service %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serviceIDs = append(serviceIDs, service.ID)
|
||||||
|
|
||||||
for _, warning := range response.Warnings {
|
for _, warning := range response.Warnings {
|
||||||
logrus.Warn(warning)
|
logrus.Warn(warning)
|
||||||
}
|
}
|
||||||
@ -418,11 +424,35 @@ func deployServices(
|
|||||||
createOpts.QueryRegistry = true
|
createOpts.QueryRegistry = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := cl.ServiceCreate(ctx, serviceSpec, createOpts); err != nil {
|
serviceCreateResponse, err := cl.ServiceCreate(ctx, serviceSpec, createOpts)
|
||||||
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to create service %s", name)
|
return errors.Wrapf(err, "failed to create service %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serviceIDs = append(serviceIDs, serviceCreateResponse.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logrus.Infof("waiting for services to converge: %s", strings.Join(serviceIDs, ", "))
|
||||||
|
|
||||||
|
ch := make(chan error, len(serviceIDs))
|
||||||
|
for _, serviceID := range serviceIDs {
|
||||||
|
logrus.Debugf("waiting on %s to converge", serviceID)
|
||||||
|
go func(s string) {
|
||||||
|
ch <- waitOnService(ctx, cl, s)
|
||||||
|
}(serviceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, serviceID := range serviceIDs {
|
||||||
|
err := <-ch
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("assuming %s converged successfully", serviceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Info("services converged 👌")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,3 +467,17 @@ func getStackSecrets(ctx context.Context, dockerclient client.APIClient, namespa
|
|||||||
func getStackConfigs(ctx context.Context, dockerclient client.APIClient, namespace string) ([]swarm.Config, error) {
|
func getStackConfigs(ctx context.Context, dockerclient client.APIClient, namespace string) ([]swarm.Config, error) {
|
||||||
return dockerclient.ConfigList(ctx, types.ConfigListOptions{Filters: getStackFilter(namespace)})
|
return dockerclient.ConfigList(ctx, types.ConfigListOptions{Filters: getStackFilter(namespace)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/docker/cli/blob/master/cli/command/service/helpers.go
|
||||||
|
// https://github.com/docker/cli/blob/master/cli/command/service/progress/progress.go
|
||||||
|
func waitOnService(ctx context.Context, cl *dockerclient.Client, serviceID string) error {
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
pipeReader, pipeWriter := io.Pipe()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
errChan <- progress.ServiceProgress(ctx, cl, serviceID, pipeWriter)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go io.Copy(ioutil.Discard, pipeReader)
|
||||||
|
return <-errChan
|
||||||
|
}
|
||||||
|
@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
ABRA_VERSION="0.3.0-alpha"
|
ABRA_VERSION="0.3.0-alpha"
|
||||||
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$ABRA_VERSION"
|
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$ABRA_VERSION"
|
||||||
|
RC_VERSION="0.3.1-alpha-rc1"
|
||||||
|
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$RC_VERSION"
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
if [ "$arg" == "--rc" ]; then
|
||||||
|
ABRA_VERSION="$RC_VERSION"
|
||||||
|
ABRA_RELEASE_URL="$RC_VERSION_URL"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
function show_banner {
|
function show_banner {
|
||||||
echo ""
|
echo ""
|
||||||
@ -35,6 +44,7 @@ function install_abra_release {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# FIXME: support different architectures
|
# FIXME: support different architectures
|
||||||
PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m)
|
PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m)
|
||||||
FILENAME="abra_"$ABRA_VERSION"_"$PLATFORM""
|
FILENAME="abra_"$ABRA_VERSION"_"$PLATFORM""
|
||||||
@ -79,6 +89,7 @@ function install_abra_release {
|
|||||||
echo "abra installed to $HOME/.local/bin/abra"
|
echo "abra installed to $HOME/.local/bin/abra"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function run_installation {
|
function run_installation {
|
||||||
show_banner
|
show_banner
|
||||||
install_abra_release
|
install_abra_release
|
||||||
|
Reference in New Issue
Block a user