105 lines
3.9 KiB
Go
105 lines
3.9 KiB
Go
package wisski_distillery
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/signal"
|
|
"os/user"
|
|
|
|
"github.com/FAU-CDI/wisski-distillery/internal/bootstrap"
|
|
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
|
"github.com/FAU-CDI/wisski-distillery/internal/dis"
|
|
"github.com/rs/zerolog"
|
|
"github.com/tkw1536/goprogram"
|
|
"github.com/tkw1536/goprogram/exit"
|
|
)
|
|
|
|
// these define the ggman-specific program types
|
|
// none of these are strictly needed, they're just around for convenience
|
|
type wdcliEnv = *dis.Distillery
|
|
type wdcliParameters = cli.Params
|
|
type wdcliRequirements = cli.Requirements
|
|
type wdCliFlags = cli.Flags
|
|
|
|
type Program = goprogram.Program[wdcliEnv, wdcliParameters, wdCliFlags, wdcliRequirements]
|
|
type Command = goprogram.Command[wdcliEnv, wdcliParameters, wdCliFlags, wdcliRequirements]
|
|
|
|
// Context holds the context passed to any wdcli command.
|
|
//
|
|
// The context contains a reference to a "context.Context" as well as an IOStream.
|
|
//
|
|
// The context.Context holds a global context.
|
|
// It is initialized in the NewContext function below.
|
|
//
|
|
// It is cancelled if the user sends SIGINT or SIGKILL.
|
|
// Despite the context being a pseudo-global, it is passed to (almost) every function using the variable name "ctx".
|
|
//
|
|
// The IOStream is typically used in three ways:
|
|
//
|
|
// - Standard output is used to log events
|
|
// - Standard error is used to interactively display progress
|
|
// - Standard input is passed to a (few) interactive programs
|
|
//
|
|
// The standard output writer is passed directly into the context, see the "pkg/logging" package for conventions.
|
|
// Other parts are passed around (standard error using the variable name "progress") as required.
|
|
//
|
|
// The IOStream as a whole is only passed to functions that exist directly under cmd/.
|
|
//
|
|
// TODO(twiesing): The logging on the standard logger is still to be done.
|
|
type Context = goprogram.Context[wdcliEnv, wdcliParameters, wdCliFlags, wdcliRequirements]
|
|
type Arguments = goprogram.Arguments[wdCliFlags]
|
|
type ContextCleanupFunc = goprogram.ContextCleanupFunc[wdcliEnv, wdcliParameters, wdCliFlags, wdcliRequirements]
|
|
type Description = goprogram.Description[wdCliFlags, wdcliRequirements]
|
|
|
|
var GetContext = goprogram.GetContext[wdcliEnv, wdcliParameters, wdCliFlags, wdcliRequirements]
|
|
|
|
// an error when nor arguments are provided.
|
|
var errUserIsNotRoot = exit.Error{
|
|
ExitCode: exit.ExitGeneralArguments,
|
|
Message: "this command has to be executed as root. the current user is not root",
|
|
}
|
|
|
|
const warnNoDeployWdcli = "Warning: Not using %q executable at %q. This might leave the distillery in an inconsistent state. \n"
|
|
|
|
func NewProgram() Program {
|
|
return Program{
|
|
BeforeCommand: func(context Context, command Command) error {
|
|
// make sure that we are root!
|
|
usr, err := user.Current()
|
|
if err != nil || usr.Uid != "0" || usr.Gid != "0" {
|
|
return errUserIsNotRoot
|
|
}
|
|
|
|
// when not running inside docker and we need a distillery
|
|
// then we should warn if we are not using the distillery executable.
|
|
if dis := context.Environment; !context.Args.Flags.InternalInDocker && context.Description.Requirements.NeedsDistillery && !dis.Config.Paths.UsingDistilleryExecutable() {
|
|
context.EPrintf(warnNoDeployWdcli, bootstrap.Executable, dis.Config.Paths.ExecutablePath())
|
|
}
|
|
|
|
return nil
|
|
},
|
|
|
|
NewContext: func(params *wdcliParameters, parent context.Context) (context.Context, ContextCleanupFunc, error) {
|
|
if params == nil {
|
|
return parent, nil, nil
|
|
}
|
|
|
|
{
|
|
context := GetContext(parent)
|
|
writer := zerolog.NewConsoleWriter()
|
|
writer.Out = context.Stdout
|
|
|
|
logger := zerolog.New(writer).Level(context.Args.Flags.LogLevel.Level())
|
|
|
|
parent = logger.WithContext(parent)
|
|
}
|
|
|
|
ctx, stop := signal.NotifyContext(parent, os.Interrupt, os.Kill)
|
|
return ctx, func(context *Context) { stop() }, nil
|
|
},
|
|
|
|
NewEnvironment: func(params wdcliParameters, context Context) (e wdcliEnv, err error) {
|
|
return dis.NewDistillery(params, context.Args.Flags, context.Description.Requirements)
|
|
},
|
|
}
|
|
}
|