2022-10-20 19:59:46 +00:00
|
|
|
package main
|
2021-04-20 21:31:37 +00:00
|
|
|
|
|
|
|
import (
|
2024-07-13 12:34:06 +00:00
|
|
|
"errors"
|
2021-04-20 21:31:37 +00:00
|
|
|
"fmt"
|
2024-09-09 14:34:00 +00:00
|
|
|
"isle/daemon/daecommon"
|
2021-04-20 21:31:37 +00:00
|
|
|
"os"
|
2022-11-08 13:54:31 +00:00
|
|
|
"path/filepath"
|
2021-04-20 21:31:37 +00:00
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
2023-09-04 19:38:28 +00:00
|
|
|
// minio-client keeps a configuration directory which contains various pieces of
|
|
|
|
// information which may or may not be useful. Unfortunately when it initializes
|
|
|
|
// this directory it likes to print some annoying logs, so we pre-initialize in
|
|
|
|
// order to prevent it from doing so.
|
2024-09-09 14:34:00 +00:00
|
|
|
func initMCConfigDir(envVars daecommon.EnvVars) (string, error) {
|
2023-09-04 19:38:28 +00:00
|
|
|
var (
|
2024-09-09 14:34:00 +00:00
|
|
|
path = filepath.Join(envVars.StateDir.Path, "mc")
|
2023-09-04 19:38:28 +00:00
|
|
|
sharePath = filepath.Join(path, "share")
|
|
|
|
configJSONPath = filepath.Join(path, "config.json")
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := os.MkdirAll(sharePath, 0700); err != nil {
|
|
|
|
return "", fmt.Errorf("creating %q: %w", sharePath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.WriteFile(configJSONPath, []byte(`{}`), 0600); err != nil {
|
|
|
|
return "", fmt.Errorf("writing %q: %w", configJSONPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return path, nil
|
|
|
|
}
|
|
|
|
|
2021-04-20 21:31:37 +00:00
|
|
|
var subCmdGarageMC = subCmd{
|
2024-12-10 21:07:25 +00:00
|
|
|
name: "mc",
|
|
|
|
descr: "Runs the mc (minio-client) binary. The isle garage can be accessed under the `garage` alias",
|
2024-09-04 20:35:29 +00:00
|
|
|
do: func(ctx subCmdCtx) error {
|
2024-09-23 18:50:45 +00:00
|
|
|
keyID := ctx.flags.StringP(
|
2021-04-20 21:31:37 +00:00
|
|
|
"key-id", "i", "",
|
2023-08-07 20:12:51 +00:00
|
|
|
"Optional key ID to use, defaults to that of the shared global key",
|
2021-04-20 21:31:37 +00:00
|
|
|
)
|
|
|
|
|
2024-09-23 18:50:45 +00:00
|
|
|
keySecret := ctx.flags.StringP(
|
2021-04-20 21:31:37 +00:00
|
|
|
"key-secret", "s", "",
|
2023-08-07 20:12:51 +00:00
|
|
|
"Optional key secret to use, defaults to that of the shared global key",
|
2021-04-20 21:31:37 +00:00
|
|
|
)
|
|
|
|
|
2024-12-10 21:07:25 +00:00
|
|
|
ctx, err := ctx.withParsedFlags(&withParsedFlagsOpts{
|
|
|
|
passthroughArgs: true,
|
|
|
|
})
|
2024-09-23 18:50:45 +00:00
|
|
|
if err != nil {
|
2021-04-20 21:31:37 +00:00
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-12-16 13:59:11 +00:00
|
|
|
daemonRPC, err := ctx.newDaemonRPC()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating daemon RPC client: %w", err)
|
|
|
|
}
|
|
|
|
defer daemonRPC.Close()
|
|
|
|
|
|
|
|
clientParams, err := daemonRPC.GetGarageClientParams(ctx)
|
2022-10-26 22:23:39 +00:00
|
|
|
if err != nil {
|
2024-07-12 14:03:37 +00:00
|
|
|
return fmt.Errorf("calling GetGarageClientParams: %w", err)
|
2022-10-26 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
2024-11-08 16:46:44 +00:00
|
|
|
s3APIAddr := clientParams.Node.S3APIAddr()
|
2021-04-20 21:31:37 +00:00
|
|
|
|
2022-11-13 19:14:16 +00:00
|
|
|
if *keyID == "" {
|
2024-07-12 14:03:37 +00:00
|
|
|
*keyID = clientParams.GlobalBucketS3APICredentials.ID
|
2022-11-13 19:14:16 +00:00
|
|
|
}
|
2021-04-20 21:31:37 +00:00
|
|
|
|
2022-11-13 19:14:16 +00:00
|
|
|
if *keySecret == "" {
|
2024-07-12 14:03:37 +00:00
|
|
|
*keySecret = clientParams.GlobalBucketS3APICredentials.Secret
|
2021-04-20 21:31:37 +00:00
|
|
|
}
|
|
|
|
|
2024-09-23 18:50:45 +00:00
|
|
|
args := ctx.flags.Args()
|
2021-04-20 21:31:37 +00:00
|
|
|
|
2024-09-23 18:50:45 +00:00
|
|
|
if i := ctx.flags.ArgsLenAtDash(); i >= 0 {
|
2021-04-20 21:31:37 +00:00
|
|
|
args = args[i:]
|
|
|
|
}
|
|
|
|
|
2024-09-09 14:34:00 +00:00
|
|
|
envVars := daecommon.GetEnvVars()
|
|
|
|
|
|
|
|
configDir, err := initMCConfigDir(envVars)
|
2023-09-04 19:38:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("initializing minio-client config directory: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
args = append([]string{
|
|
|
|
binPath("mc"),
|
|
|
|
"--config-dir", configDir,
|
|
|
|
}, args...)
|
2021-04-20 21:31:37 +00:00
|
|
|
|
|
|
|
var (
|
2022-11-13 19:14:16 +00:00
|
|
|
mcHostVar = fmt.Sprintf(
|
|
|
|
"MC_HOST_garage=http://%s:%s@%s",
|
|
|
|
*keyID, *keySecret, s3APIAddr,
|
|
|
|
)
|
|
|
|
|
2024-09-24 09:22:00 +00:00
|
|
|
binPath = binPath("mc")
|
2021-04-20 21:31:37 +00:00
|
|
|
cliEnv = append(
|
|
|
|
os.Environ(),
|
2022-11-13 19:14:16 +00:00
|
|
|
mcHostVar,
|
2021-04-20 21:31:37 +00:00
|
|
|
|
|
|
|
// The garage docs say this is necessary, though nothing bad
|
|
|
|
// seems to happen if we leave it out *shrug*
|
|
|
|
"MC_REGION=garage",
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := syscall.Exec(binPath, args, cliEnv); err != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"calling exec(%q, %#v, %#v): %w",
|
|
|
|
binPath, args, cliEnv, err,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var subCmdGarageCLI = subCmd{
|
2024-12-10 21:07:25 +00:00
|
|
|
name: "cli",
|
|
|
|
descr: "Runs the garage binary, automatically configured to point to the garage sub-process of a running isle daemon",
|
2024-09-04 20:35:29 +00:00
|
|
|
do: func(ctx subCmdCtx) error {
|
2024-12-10 21:07:25 +00:00
|
|
|
ctx, err := ctx.withParsedFlags(&withParsedFlagsOpts{
|
|
|
|
passthroughArgs: true,
|
|
|
|
})
|
2024-09-23 18:50:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
|
|
|
}
|
2021-04-20 21:31:37 +00:00
|
|
|
|
2024-12-16 13:59:11 +00:00
|
|
|
daemonRPC, err := ctx.newDaemonRPC()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating daemon RPC client: %w", err)
|
|
|
|
}
|
|
|
|
defer daemonRPC.Close()
|
|
|
|
|
|
|
|
clientParams, err := daemonRPC.GetGarageClientParams(ctx)
|
2022-10-26 22:23:39 +00:00
|
|
|
if err != nil {
|
2024-07-12 14:03:37 +00:00
|
|
|
return fmt.Errorf("calling GetGarageClientParams: %w", err)
|
2022-10-26 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
2024-07-13 12:34:06 +00:00
|
|
|
if clientParams.RPCSecret == "" {
|
|
|
|
return errors.New("this host does not have the garage RPC secret")
|
|
|
|
}
|
|
|
|
|
2021-04-20 21:31:37 +00:00
|
|
|
var (
|
2023-04-23 14:30:47 +00:00
|
|
|
binPath = binPath("garage")
|
2024-11-14 20:49:35 +00:00
|
|
|
args = append([]string{"garage"}, ctx.opts.args...)
|
2021-04-20 21:31:37 +00:00
|
|
|
cliEnv = append(
|
|
|
|
os.Environ(),
|
2024-11-08 16:46:44 +00:00
|
|
|
"GARAGE_RPC_HOST="+clientParams.Node.RPCNodeAddr(),
|
2024-07-12 14:03:37 +00:00
|
|
|
"GARAGE_RPC_SECRET="+clientParams.RPCSecret,
|
2021-04-20 21:31:37 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := syscall.Exec(binPath, args, cliEnv); err != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"calling exec(%q, %#v, %#v): %w",
|
|
|
|
binPath, args, cliEnv, err,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var subCmdGarage = subCmd{
|
|
|
|
name: "garage",
|
2023-08-05 21:53:17 +00:00
|
|
|
descr: "Runs the garage binary, automatically configured to point to the garage sub-process of a running isle daemon",
|
2024-09-04 20:35:29 +00:00
|
|
|
do: func(ctx subCmdCtx) error {
|
|
|
|
return ctx.doSubCmd(
|
2021-04-20 21:31:37 +00:00
|
|
|
subCmdGarageCLI,
|
|
|
|
subCmdGarageMC,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|