This commit adds and passes context around to (almost) every function. This allows cancelling (almost) every function call globally.
201 lines
5.5 KiB
Go
201 lines
5.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"io/fs"
|
|
"path/filepath"
|
|
|
|
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
|
"github.com/FAU-CDI/wisski-distillery/internal/bootstrap"
|
|
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
|
"github.com/FAU-CDI/wisski-distillery/internal/config"
|
|
|
|
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
|
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
|
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
|
"github.com/tkw1536/goprogram/exit"
|
|
)
|
|
|
|
// Bootstrap is the 'bootstrap' command
|
|
var Bootstrap wisski_distillery.Command = cBootstrap{}
|
|
|
|
type cBootstrap struct {
|
|
Directory string `short:"r" long:"root-directory" description:"path to the root deployment directory" default:"/var/www/deploy"`
|
|
Hostname string `short:"h" long:"hostname" description:"default hostname of the distillery (default: system hostname)"`
|
|
}
|
|
|
|
func (cBootstrap) Description() wisski_distillery.Description {
|
|
return wisski_distillery.Description{
|
|
Requirements: cli.Requirements{
|
|
NeedsDistillery: false,
|
|
},
|
|
Command: "bootstrap",
|
|
Description: "Bootstraps the installation of a Distillery System",
|
|
}
|
|
}
|
|
|
|
var errBootstrapDifferent = exit.Error{
|
|
Message: "refusing to bootstrap: base directory is already set to %s.",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
var errBootstrapFailedToCreateDirectory = exit.Error{
|
|
Message: "failed to create directory %s",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
var errBootstrapFailedToSaveDirectory = exit.Error{
|
|
Message: "failed to register base directory: %s",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
var errBoostrapFailedToCopyExe = exit.Error{
|
|
Message: "failed to copy wdcli executable: %s",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
var errBootstrapWriteConfig = exit.Error{
|
|
Message: "failed to write configuration file: %s",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
var errBootstrapOpenConfig = exit.Error{
|
|
Message: "failed to open configuration file: %s",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
var errBootstrapCreateFile = exit.Error{
|
|
Message: "failed to touch configuration file: %s",
|
|
ExitCode: exit.ExitGeneric,
|
|
}
|
|
|
|
func (bs cBootstrap) Run(context wisski_distillery.Context) error {
|
|
// installation environment is the native environment!
|
|
// TODO: Should this be configurable?
|
|
env := new(environment.Native)
|
|
|
|
root := bs.Directory
|
|
|
|
// check that we didn't get a different base directory
|
|
{
|
|
got, err := cli.ReadBaseDirectory(env)
|
|
if err == nil && got != "" && got != root {
|
|
return errBootstrapDifferent.WithMessageF(got)
|
|
}
|
|
}
|
|
|
|
{
|
|
logging.LogMessage(context.IOStream, "Creating root deployment directory")
|
|
if err := env.MkdirAll(root, environment.DefaultDirPerm); err != nil {
|
|
return errBootstrapFailedToCreateDirectory.WithMessageF(root)
|
|
}
|
|
if err := cli.WriteBaseDirectory(env, root); err != nil {
|
|
return errBootstrapFailedToSaveDirectory.WithMessageF(root)
|
|
}
|
|
context.Println(root)
|
|
}
|
|
|
|
// TODO: Should we read an existing configuration file?
|
|
wdcliPath := filepath.Join(root, bootstrap.Executable)
|
|
envPath := filepath.Join(root, bootstrap.ConfigFile)
|
|
|
|
// setup a new template for the configuration file!
|
|
var tpl config.Template
|
|
tpl.DeployRoot = bs.Directory
|
|
tpl.DefaultDomain = bs.Hostname
|
|
|
|
// and use thge defaults
|
|
if err := tpl.SetDefaults(env); err != nil {
|
|
return errBootstrapWriteConfig.WithMessageF(err)
|
|
}
|
|
|
|
{
|
|
logging.LogMessage(context.IOStream, "Copying over wdcli executable")
|
|
exe, err := env.Executable()
|
|
if err != nil {
|
|
return errBoostrapFailedToCopyExe.WithMessageF(err)
|
|
}
|
|
|
|
err = fsx.CopyFile(context.Context, env, wdcliPath, exe)
|
|
if err != nil && err != fsx.ErrCopySameFile {
|
|
return errBoostrapFailedToCopyExe.WithMessageF(err)
|
|
}
|
|
context.Println(wdcliPath)
|
|
}
|
|
|
|
{
|
|
if !fsx.IsFile(env, envPath) {
|
|
if err := logging.LogOperation(func() error {
|
|
env, err := env.Create(envPath, environment.DefaultFilePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer env.Close()
|
|
|
|
return tpl.MarshalTo(env)
|
|
}, context.IOStream, "Installing configuration file"); err != nil {
|
|
return errBootstrapWriteConfig.WithMessageF(err)
|
|
}
|
|
|
|
if err := logging.LogOperation(func() error {
|
|
|
|
context.Println(tpl.SelfOverridesFile)
|
|
if err := environment.WriteFile(
|
|
env,
|
|
tpl.SelfOverridesFile,
|
|
bootstrap.DefaultOverridesJSON,
|
|
fs.ModePerm,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
|
|
context.Println(tpl.AuthorizedKeys)
|
|
if err := environment.WriteFile(
|
|
env,
|
|
tpl.AuthorizedKeys,
|
|
bootstrap.DefaultAuthorizedKeys,
|
|
fs.ModePerm,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
|
|
context.Println(tpl.SelfResolverBlockFile)
|
|
if err := environment.WriteFile(
|
|
env,
|
|
tpl.SelfResolverBlockFile,
|
|
bootstrap.DefaultResolverBlockedTXT,
|
|
fs.ModePerm,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}, context.IOStream, "Creating additional config files"); err != nil {
|
|
return errBootstrapCreateFile.WithMessageF(err)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// re-read the configuration and print it!
|
|
logging.LogMessage(context.IOStream, "Configuration is now complete")
|
|
f, err := env.Open(envPath)
|
|
if err != nil {
|
|
return errBootstrapOpenConfig.WithMessageF(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
var cfg config.Config
|
|
if err := cfg.Unmarshal(env, f); err != nil {
|
|
return errBootstrapOpenConfig.WithMessageF(err)
|
|
}
|
|
context.Println(cfg)
|
|
|
|
// Tell the user how to proceed
|
|
logging.LogMessage(context.IOStream, "Bootstrap is complete")
|
|
context.Printf("Adjust the configuration file at %s\n", envPath)
|
|
context.Printf("Then make sure 'docker compose' is installed.\n")
|
|
context.Printf("Finally grab a GraphDB zipped source file and run:\n")
|
|
context.Printf("%s system_update /path/to/graphdb.zip\n", wdcliPath)
|
|
|
|
return nil
|
|
}
|