internal/stack: Cleanup API
This commit cleans up the internal stack API to prepare it for an eventual move to using a native docker client.
This commit is contained in:
parent
7b38fdd801
commit
5d906169f4
15 changed files with 96 additions and 65 deletions
|
|
@ -3,6 +3,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
||||||
"github.com/FAU-CDI/wisski-distillery/env"
|
"github.com/FAU-CDI/wisski-distillery/env"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/execx"
|
||||||
"github.com/tkw1536/goprogram/exit"
|
"github.com/tkw1536/goprogram/exit"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -44,7 +45,10 @@ func (bu blindUpdate) Run(context wisski_distillery.Context) error {
|
||||||
}
|
}
|
||||||
context.EPrintf("Updating instance %s\n", instance.Slug)
|
context.EPrintf("Updating instance %s\n", instance.Slug)
|
||||||
|
|
||||||
code := instance.Shell(context.IOStream, "/utils/blind_update.sh")
|
code, err := instance.Shell(context.IOStream, "/utils/blind_update.sh")
|
||||||
|
if err != nil {
|
||||||
|
return errBlindUpdateFailed.WithMessageF(instance.Slug, execx.ExecCommandError)
|
||||||
|
}
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return errBlindUpdateFailed.WithMessageF(instance.Slug, code)
|
return errBlindUpdateFailed.WithMessageF(instance.Slug, code)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,10 @@ func (cr cron) Run(context wisski_distillery.Context) error {
|
||||||
// iterate over the instances and store the last value of error
|
// iterate over the instances and store the last value of error
|
||||||
for _, instance := range instances {
|
for _, instance := range instances {
|
||||||
logging.LogOperation(func() error {
|
logging.LogOperation(func() error {
|
||||||
code := instance.Shell(context.IOStream, "/utils/cron.sh")
|
code, err := instance.Shell(context.IOStream, "/utils/cron.sh")
|
||||||
|
if err != nil {
|
||||||
|
context.EPrintln(err)
|
||||||
|
}
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
// keep going, because we want to run as many crons as possible
|
// keep going, because we want to run as many crons as possible
|
||||||
err = errBlindUpdateFailed.WithMessageF(instance.Slug, code)
|
err = errBlindUpdateFailed.WithMessageF(instance.Slug, code)
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,10 @@ func (mma makeMysqlAccount) Run(context wisski_distillery.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
code := context.Environment.SQLShell(context.IOStream, "-e", query)
|
code, err := context.Environment.SQLShell(context.IOStream, "-e", query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return exit.Error{
|
return exit.Error{
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,10 @@ func (mysql) Description() wisski_distillery.Description {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms mysql) Run(context wisski_distillery.Context) error {
|
func (ms mysql) Run(context wisski_distillery.Context) error {
|
||||||
code := context.Environment.SQLShell(context.IOStream, ms.Positionals.Args...)
|
code, err := context.Environment.SQLShell(context.IOStream, ms.Positionals.Args...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return exit.Error{
|
return exit.Error{
|
||||||
ExitCode: exit.ExitCode(uint8(code)),
|
ExitCode: exit.ExitCode(uint8(code)),
|
||||||
|
|
|
||||||
10
cmd/shell.go
10
cmd/shell.go
|
|
@ -32,13 +32,21 @@ func (shell) Description() wisski_distillery.Description {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errShell = exit.Error{
|
||||||
|
Message: "Unable to start shell: %s",
|
||||||
|
ExitCode: exit.ExitGeneric,
|
||||||
|
}
|
||||||
|
|
||||||
func (sh shell) Run(context wisski_distillery.Context) error {
|
func (sh shell) Run(context wisski_distillery.Context) error {
|
||||||
instance, err := context.Environment.Instance(sh.Positionals.Slug)
|
instance, err := context.Environment.Instance(sh.Positionals.Slug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
code := instance.Shell(context.IOStream, sh.Positionals.Args...)
|
code, err := instance.Shell(context.IOStream, sh.Positionals.Args...)
|
||||||
|
if err != nil {
|
||||||
|
return errShell.WithMessageF(err)
|
||||||
|
}
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return exit.Error{
|
return exit.Error{
|
||||||
ExitCode: exit.ExitCode(uint8(code)),
|
ExitCode: exit.ExitCode(uint8(code)),
|
||||||
|
|
|
||||||
|
|
@ -114,13 +114,13 @@ func (si systemupdate) Run(context wisski_distillery.Context) error {
|
||||||
for _, stack := range dis.Stacks() {
|
for _, stack := range dis.Stacks() {
|
||||||
if err := logging.LogOperation(func() error {
|
if err := logging.LogOperation(func() error {
|
||||||
return stack.Install(context.IOStream, ctx)
|
return stack.Install(context.IOStream, ctx)
|
||||||
}, context.IOStream, "Installing docker stack %q", stack.Name); err != nil {
|
}, context.IOStream, "Installing docker stack %q", stack.Dir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := logging.LogOperation(func() error {
|
if err := logging.LogOperation(func() error {
|
||||||
return stack.Update(context.IOStream, true)
|
return stack.Update(context.IOStream, true)
|
||||||
}, context.IOStream, "Updating docker stack %q", stack.Name); err != nil {
|
}, context.IOStream, "Updating docker stack %q", stack.Dir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
env/instances.go
vendored
17
env/instances.go
vendored
|
|
@ -179,7 +179,7 @@ func (instance *Instance) Delete() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shell executes a shell command inside the
|
// Shell executes a shell command inside the
|
||||||
func (instance Instance) Shell(io stream.IOStream, argv ...string) int {
|
func (instance Instance) Shell(io stream.IOStream, argv ...string) (int, error) {
|
||||||
return instance.Stack().Exec(io, "barrel", "/user_shell.sh", argv...)
|
return instance.Stack().Exec(io, "barrel", "/user_shell.sh", argv...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,8 +219,7 @@ func (instance Instance) URL() *url.URL {
|
||||||
func (instance Instance) Stack() stack.Installable {
|
func (instance Instance) Stack() stack.Installable {
|
||||||
return stack.Installable{
|
return stack.Installable{
|
||||||
Stack: stack.Stack{
|
Stack: stack.Stack{
|
||||||
Name: "barrel",
|
Dir: instance.FilesystemBase,
|
||||||
Dir: instance.FilesystemBase,
|
|
||||||
},
|
},
|
||||||
ContextResource: filepath.Join("resources", "compose", "barrel"),
|
ContextResource: filepath.Join("resources", "compose", "barrel"),
|
||||||
|
|
||||||
|
|
@ -252,8 +251,7 @@ func (instance Instance) Stack() stack.Installable {
|
||||||
func (instance Instance) ReserveStack() stack.Installable {
|
func (instance Instance) ReserveStack() stack.Installable {
|
||||||
return stack.Installable{
|
return stack.Installable{
|
||||||
Stack: stack.Stack{
|
Stack: stack.Stack{
|
||||||
Name: "reserve",
|
Dir: instance.FilesystemBase,
|
||||||
Dir: instance.FilesystemBase,
|
|
||||||
},
|
},
|
||||||
ContextResource: filepath.Join("resources", "compose", "reserve"),
|
ContextResource: filepath.Join("resources", "compose", "reserve"),
|
||||||
|
|
||||||
|
|
@ -308,7 +306,11 @@ func (instance Instance) Provision(io stream.IOStream) error {
|
||||||
// TODO: Move the provision script into the control plane!
|
// TODO: Move the provision script into the control plane!
|
||||||
provisionScript := "sudo PATH=$PATH -u www-data /bin/bash /provision_container.sh " + strings.Join(provisionParams, " ")
|
provisionScript := "sudo PATH=$PATH -u www-data /bin/bash /provision_container.sh " + strings.Join(provisionParams, " ")
|
||||||
|
|
||||||
if st.Run(io, true, "barrel", "/bin/bash", "-c", provisionScript) != 0 {
|
code, err := st.Run(io, true, "barrel", "/bin/bash", "-c", provisionScript)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
return errors.New("Unable to run provision script")
|
return errors.New("Unable to run provision script")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,7 +338,8 @@ func (instance *Instance) PrefixConfig() (config string, err error) {
|
||||||
|
|
||||||
// default prefixes
|
// default prefixes
|
||||||
wu := stream.NewIOStream(&builder, nil, nil, 0)
|
wu := stream.NewIOStream(&builder, nil, nil, 0)
|
||||||
if instance.Stack().Exec(wu, "barrel", "/bin/bash", "/user_shell.sh", "-c", "drush php:script /wisskiutils/list_uri_prefixes.php") != 0 {
|
code, err := instance.Stack().Exec(wu, "barrel", "/bin/bash", "/user_shell.sh", "-c", "drush php:script /wisskiutils/list_uri_prefixes.php")
|
||||||
|
if err != nil || code != 0 {
|
||||||
return "", errPrefixExecFailed
|
return "", errPrefixExecFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
8
env/stack.go
vendored
8
env/stack.go
vendored
|
|
@ -20,11 +20,11 @@ func (dis *Distillery) Stacks() []stack.Installable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// asCoreStack treats the provided stack as a core component of this distillery.
|
// asCoreStack treats the provided stack as a core component of this distillery.
|
||||||
func (dis *Distillery) asCoreStack(stack stack.Installable) stack.Installable {
|
func (dis *Distillery) asCoreStack(name string, stack stack.Installable) stack.Installable {
|
||||||
stack.Dir = filepath.Join(dis.Config.DeployRoot, "core", stack.Name)
|
stack.Dir = filepath.Join(dis.Config.DeployRoot, "core", name)
|
||||||
|
|
||||||
stack.ContextResource = filepath.Join("resources", "compose", stack.Name)
|
stack.ContextResource = filepath.Join("resources", "compose", name)
|
||||||
stack.EnvFileResource = filepath.Join("resources", "templates", "docker-env", stack.Name)
|
stack.EnvFileResource = filepath.Join("resources", "templates", "docker-env", name)
|
||||||
|
|
||||||
return stack
|
return stack
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
env/stack_resolver.go
vendored
6
env/stack_resolver.go
vendored
|
|
@ -10,11 +10,7 @@ import (
|
||||||
const ResolverPrefixFile = "prefix.cfg"
|
const ResolverPrefixFile = "prefix.cfg"
|
||||||
|
|
||||||
func (dis *Distillery) ResolverStack() stack.Installable {
|
func (dis *Distillery) ResolverStack() stack.Installable {
|
||||||
stack := dis.asCoreStack(stack.Installable{
|
stack := dis.asCoreStack("resolver", stack.Installable{
|
||||||
Stack: stack.Stack{
|
|
||||||
Name: "resolver",
|
|
||||||
},
|
|
||||||
|
|
||||||
EnvFileContext: map[string]string{
|
EnvFileContext: map[string]string{
|
||||||
"VIRTUAL_HOST": dis.DefaultVirtualHost(),
|
"VIRTUAL_HOST": dis.DefaultVirtualHost(),
|
||||||
"LETSENCRYPT_HOST": dis.DefaultLetsencryptHost(),
|
"LETSENCRYPT_HOST": dis.DefaultLetsencryptHost(),
|
||||||
|
|
|
||||||
6
env/stack_self.go
vendored
6
env/stack_self.go
vendored
|
|
@ -8,11 +8,7 @@ func (dis *Distillery) SelfStack() stack.Installable {
|
||||||
TARGET = dis.Config.SelfRedirect.String()
|
TARGET = dis.Config.SelfRedirect.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
return dis.asCoreStack(stack.Installable{
|
return dis.asCoreStack("self", stack.Installable{
|
||||||
Stack: stack.Stack{
|
|
||||||
Name: "self",
|
|
||||||
},
|
|
||||||
|
|
||||||
EnvFileContext: map[string]string{
|
EnvFileContext: map[string]string{
|
||||||
"VIRTUAL_HOST": dis.DefaultVirtualHost(),
|
"VIRTUAL_HOST": dis.DefaultVirtualHost(),
|
||||||
"LETSENCRYPT_HOST": dis.DefaultLetsencryptHost(),
|
"LETSENCRYPT_HOST": dis.DefaultLetsencryptHost(),
|
||||||
|
|
|
||||||
14
env/stack_sql.go
vendored
14
env/stack_sql.go
vendored
|
|
@ -20,11 +20,7 @@ import (
|
||||||
|
|
||||||
// SQLStack returns the docker stack that handles the sql database.
|
// SQLStack returns the docker stack that handles the sql database.
|
||||||
func (dis *Distillery) SQLStack() stack.Installable {
|
func (dis *Distillery) SQLStack() stack.Installable {
|
||||||
return dis.asCoreStack(stack.Installable{
|
return dis.asCoreStack("sql", stack.Installable{
|
||||||
Stack: stack.Stack{
|
|
||||||
Name: "sql",
|
|
||||||
},
|
|
||||||
|
|
||||||
MakeDirsPerm: fs.ModeDir | fs.ModePerm,
|
MakeDirsPerm: fs.ModeDir | fs.ModePerm,
|
||||||
MakeDirs: []string{
|
MakeDirs: []string{
|
||||||
"data",
|
"data",
|
||||||
|
|
@ -87,7 +83,7 @@ func (dis *Distillery) sqlBkTable(silent bool) (*gorm.DB, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLShell executes a mysql shell inside the SQLStack.
|
// SQLShell executes a mysql shell inside the SQLStack.
|
||||||
func (dis *Distillery) SQLShell(io stream.IOStream, argv ...string) int {
|
func (dis *Distillery) SQLShell(io stream.IOStream, argv ...string) (int, error) {
|
||||||
return dis.SQLStack().Exec(io, "sql", "mysql", argv...)
|
return dis.SQLStack().Exec(io, "sql", "mysql", argv...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,7 +98,8 @@ const waitSQLInterval = 1 * time.Second
|
||||||
func (dis *Distillery) SQLWaitForShell() error {
|
func (dis *Distillery) SQLWaitForShell() error {
|
||||||
n := stream.FromNil()
|
n := stream.FromNil()
|
||||||
return wait.Wait(func() bool {
|
return wait.Wait(func() bool {
|
||||||
return dis.SQLShell(n, "-e", "show databases;") == 0
|
code, err := dis.SQLShell(n, "-e", "show databases;")
|
||||||
|
return err == nil && code == 0
|
||||||
}, waitSQLInterval, dis.Context())
|
}, waitSQLInterval, dis.Context())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +115,8 @@ var errInvalidDatabaseName = errors.New("SQLProvision: Invalid database name")
|
||||||
|
|
||||||
func (dis *Distillery) sqlRaw(query string, args ...interface{}) bool {
|
func (dis *Distillery) sqlRaw(query string, args ...interface{}) bool {
|
||||||
sql := sqle.Format(query, args...)
|
sql := sqle.Format(query, args...)
|
||||||
return dis.SQLShell(stream.FromNil(), "-e", sql) == 0
|
code, err := dis.SQLShell(stream.FromNil(), "-e", sql)
|
||||||
|
return err == nil && code == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLProvision provisions a new sql database and user
|
// SQLProvision provisions a new sql database and user
|
||||||
|
|
|
||||||
6
env/stack_ssh.go
vendored
6
env/stack_ssh.go
vendored
|
|
@ -4,11 +4,7 @@ import "github.com/FAU-CDI/wisski-distillery/internal/stack"
|
||||||
|
|
||||||
func (dis *Distillery) SSHStack() stack.Installable {
|
func (dis *Distillery) SSHStack() stack.Installable {
|
||||||
// TODO: Ensure that .env is copied if needed
|
// TODO: Ensure that .env is copied if needed
|
||||||
return dis.asCoreStack(stack.Installable{
|
return dis.asCoreStack("ssh", stack.Installable{})
|
||||||
Stack: stack.Stack{
|
|
||||||
Name: "sql",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dis *Distillery) SSHStackPath() string {
|
func (dis *Distillery) SSHStackPath() string {
|
||||||
|
|
|
||||||
6
env/stack_triplestore.go
vendored
6
env/stack_triplestore.go
vendored
|
|
@ -20,11 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (dis *Distillery) TriplestoreStack() stack.Installable {
|
func (dis *Distillery) TriplestoreStack() stack.Installable {
|
||||||
return dis.asCoreStack(stack.Installable{
|
return dis.asCoreStack("triplestore", stack.Installable{
|
||||||
Stack: stack.Stack{
|
|
||||||
Name: "triplestore",
|
|
||||||
},
|
|
||||||
|
|
||||||
CopyContextFiles: []string{"graphdb.zip"},
|
CopyContextFiles: []string{"graphdb.zip"},
|
||||||
|
|
||||||
MakeDirsPerm: fs.ModeDir | fs.ModePerm,
|
MakeDirsPerm: fs.ModeDir | fs.ModePerm,
|
||||||
|
|
|
||||||
6
env/stack_web.go
vendored
6
env/stack_web.go
vendored
|
|
@ -3,11 +3,7 @@ package env
|
||||||
import "github.com/FAU-CDI/wisski-distillery/internal/stack"
|
import "github.com/FAU-CDI/wisski-distillery/internal/stack"
|
||||||
|
|
||||||
func (dis *Distillery) WebStack() stack.Installable {
|
func (dis *Distillery) WebStack() stack.Installable {
|
||||||
return dis.asCoreStack(stack.Installable{
|
return dis.asCoreStack("web", stack.Installable{
|
||||||
Stack: stack.Stack{
|
|
||||||
Name: "web",
|
|
||||||
},
|
|
||||||
|
|
||||||
EnvFileContext: map[string]string{
|
EnvFileContext: map[string]string{
|
||||||
"DEFAULT_HOST": dis.Config.DefaultDomain,
|
"DEFAULT_HOST": dis.Config.DefaultDomain,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ import (
|
||||||
// This executable must be capable of the 'docker compose' command.
|
// This executable must be capable of the 'docker compose' command.
|
||||||
// In the future the idea is to replace this with a native docker compose client.
|
// In the future the idea is to replace this with a native docker compose client.
|
||||||
type Stack struct {
|
type Stack struct {
|
||||||
Name string // Name of this stack, TODO: Do we need this?
|
Dir string // Directory this Stack is located in
|
||||||
Dir string // Directory of this stack
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var errStackUpdatePull = errors.New("Stack.Update: Pull returned non-zero exit code")
|
var errStackUpdatePull = errors.New("Stack.Update: Pull returned non-zero exit code")
|
||||||
|
|
@ -26,11 +25,24 @@ var errStackUpdateBuild = errors.New("Stack.Update: Build returned non-zero exit
|
||||||
//
|
//
|
||||||
// See also Up.
|
// See also Up.
|
||||||
func (ds Stack) Update(io stream.IOStream, start bool) error {
|
func (ds Stack) Update(io stream.IOStream, start bool) error {
|
||||||
if ds.compose(io, "pull") != 0 {
|
{
|
||||||
return errStackUpdatePull
|
code, err := ds.compose(io, "pull")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
|
return errStackUpdatePull
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ds.compose(io, "build", "--pull") != 0 {
|
|
||||||
return errStackUpdateBuild
|
{
|
||||||
|
code, err := ds.compose(io, "build", "--pull")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
|
return errStackUpdateBuild
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if start {
|
if start {
|
||||||
return ds.Up(io)
|
return ds.Up(io)
|
||||||
|
|
@ -43,7 +55,11 @@ var errStackUp = errors.New("Stack.Up: Up returned non-zero exit code")
|
||||||
// Up creates and starts the containers in this Stack.
|
// Up creates and starts the containers in this Stack.
|
||||||
// It is equivalent to 'docker compose up -d' on the shell.
|
// It is equivalent to 'docker compose up -d' on the shell.
|
||||||
func (ds Stack) Up(io stream.IOStream) error {
|
func (ds Stack) Up(io stream.IOStream) error {
|
||||||
if ds.compose(io, "up", "-d") != 0 {
|
code, err := ds.compose(io, "up", "-d")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
return errStackUp
|
return errStackUp
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -53,7 +69,7 @@ func (ds Stack) Up(io stream.IOStream) error {
|
||||||
// It is equivalent to 'docker compose exec $service $executable $args...'.
|
// It is equivalent to 'docker compose exec $service $executable $args...'.
|
||||||
//
|
//
|
||||||
// It returns the exit code of the process.
|
// It returns the exit code of the process.
|
||||||
func (ds Stack) Exec(io stream.IOStream, service, executable string, args ...string) int {
|
func (ds Stack) Exec(io stream.IOStream, service, executable string, args ...string) (int, error) {
|
||||||
compose := []string{"exec"}
|
compose := []string{"exec"}
|
||||||
if io.StdinIsATerminal() {
|
if io.StdinIsATerminal() {
|
||||||
compose = append(compose, "-ti")
|
compose = append(compose, "-ti")
|
||||||
|
|
@ -67,7 +83,7 @@ func (ds Stack) Exec(io stream.IOStream, service, executable string, args ...str
|
||||||
// It is equivalent to 'docker compose run [--rm] $service $executable $args...'.
|
// It is equivalent to 'docker compose run [--rm] $service $executable $args...'.
|
||||||
//
|
//
|
||||||
// It returns the exit code of the process.
|
// It returns the exit code of the process.
|
||||||
func (ds Stack) Run(io stream.IOStream, autoRemove bool, service, command string, args ...string) int {
|
func (ds Stack) Run(io stream.IOStream, autoRemove bool, service, command string, args ...string) (int, error) {
|
||||||
compose := []string{"run"}
|
compose := []string{"run"}
|
||||||
if autoRemove {
|
if autoRemove {
|
||||||
compose = append(compose, "--rm")
|
compose = append(compose, "--rm")
|
||||||
|
|
@ -77,7 +93,12 @@ func (ds Stack) Run(io stream.IOStream, autoRemove bool, service, command string
|
||||||
}
|
}
|
||||||
compose = append(compose, command)
|
compose = append(compose, command)
|
||||||
compose = append(compose, args...)
|
compose = append(compose, args...)
|
||||||
return ds.compose(io, compose...)
|
|
||||||
|
code, err := ds.compose(io, compose...)
|
||||||
|
if err != nil {
|
||||||
|
return execx.ExecCommandError, nil
|
||||||
|
}
|
||||||
|
return code, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errStackRestart = errors.New("Stack.Restart: Restart returned non-zero exit code")
|
var errStackRestart = errors.New("Stack.Restart: Restart returned non-zero exit code")
|
||||||
|
|
@ -85,7 +106,11 @@ var errStackRestart = errors.New("Stack.Restart: Restart returned non-zero exit
|
||||||
// Restart restarts all containers in this Stack.
|
// Restart restarts all containers in this Stack.
|
||||||
// It is equivalent to 'docker compose restart' on the shell.
|
// It is equivalent to 'docker compose restart' on the shell.
|
||||||
func (ds Stack) Restart(io stream.IOStream) error {
|
func (ds Stack) Restart(io stream.IOStream) error {
|
||||||
if ds.compose(io, "restart") != 0 {
|
code, err := ds.compose(io, "restart")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
return errStackRestart
|
return errStackRestart
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -96,7 +121,11 @@ var errStackDown = errors.New("Stack.Down: Down returned non-zero exit code")
|
||||||
// Down stops and removes all containers in this Stack.
|
// Down stops and removes all containers in this Stack.
|
||||||
// It is equivalent to 'docker compose down -v' on the shell.
|
// It is equivalent to 'docker compose down -v' on the shell.
|
||||||
func (ds Stack) Down(io stream.IOStream) error {
|
func (ds Stack) Down(io stream.IOStream) error {
|
||||||
if ds.compose(io, "down", "-v") != 0 {
|
code, err := ds.compose(io, "down", "-v")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
return errStackDown
|
return errStackDown
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -104,7 +133,7 @@ func (ds Stack) Down(io stream.IOStream) error {
|
||||||
|
|
||||||
// Compose executes a 'docker compose' command on this stack.
|
// Compose executes a 'docker compose' command on this stack.
|
||||||
// TODO: This should be removed and replaced by an internal call directly to libcompose.
|
// TODO: This should be removed and replaced by an internal call directly to libcompose.
|
||||||
func (ds Stack) compose(io stream.IOStream, args ...string) int {
|
func (ds Stack) compose(io stream.IOStream, args ...string) (int, error) {
|
||||||
// TODO: can we migrate to a built-in version of this?
|
// TODO: can we migrate to a built-in version of this?
|
||||||
return execx.Compose(io, ds.Dir, args...)
|
return execx.Compose(io, ds.Dir, args...), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue