package entrypoint import ( "fmt" "io/fs" "log" "os" "strings" "syscall" crypticnet "cryptic-net" "cryptic-net/garage" ) func getGaragePeer(env *crypticnet.Env) (string, error) { if allocs := env.ThisDaemon().Storage.Allocations; len(allocs) > 0 { return garage.GeneratePeerAddr(env.ThisHost().Nebula.IP, allocs[0].RPCPort) } bootstrapPeers, err := garage.BootstrapPeerAddrs(env.Hosts) if err != nil { return "", err } return bootstrapPeers[0], nil } var subCmdGarageMC = subCmd{ name: "mc", descr: "Runs the mc (minio-client) binary. The cryptic-net garage can be accessed under the `garage` alias", checkLock: true, do: func(subCmdCtx subCmdCtx) error { flags := subCmdCtx.flagSet(true) keyID := flags.StringP( "key-id", "i", "", "Optional key ID to use, defaults to that of the shared cryptic-net-global key", ) keySecret := flags.StringP( "key-secret", "s", "", "Optional key secret to use, defaults to that of the shared cryptic-net-global key", ) if err := flags.Parse(subCmdCtx.args); err != nil { return fmt.Errorf("parsing flags: %w", err) } env := subCmdCtx.env apiAddr := garage.APIAddr(env) if *keyID == "" || *keySecret == "" { globalBucketCreds, err := garage.GlobalBucketAPICredentials(env) if err != nil { return fmt.Errorf("loading global bucket credentials: %w", err) } if *keyID == "" { *keyID = globalBucketCreds.ID } if *keySecret == "" { *keySecret = globalBucketCreds.Secret } } args := flags.Args() if i := flags.ArgsLenAtDash(); i >= 0 { args = args[i:] } args = append([]string{"mc"}, args...) var ( binPath = env.BinPath("mc") cliEnv = append( os.Environ(), fmt.Sprintf( "MC_HOST_garage=http://%s:%s@%s", *keyID, *keySecret, apiAddr, ), // 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{ name: "cli", descr: "Runs the garage binary, automatically configured to point to the garage sub-process of a running cryptic-net daemon", checkLock: true, do: func(subCmdCtx subCmdCtx) error { env := subCmdCtx.env peerAddr, err := getGaragePeer(env) if err != nil { return fmt.Errorf("picking peer to communicate with: %w", err) } rpcSecretB, err := fs.ReadFile(env.BootstrapFS, "garage/rpc-secret.txt") if err != nil { log.Fatalf("reading garage rpc secret bootstrap fs: %v", err) } rpcSecret := strings.TrimSpace(string(rpcSecretB)) var ( binPath = env.BinPath("garage") args = append([]string{"garage"}, subCmdCtx.args...) cliEnv = append( os.Environ(), "GARAGE_RPC_HOST="+peerAddr, "GARAGE_RPC_SECRET="+rpcSecret, ) ) 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", descr: "Runs the garage binary, automatically configured to point to the garage sub-process of a running cryptic-net daemon", do: func(subCmdCtx subCmdCtx) error { return subCmdCtx.doSubCmd( subCmdGarageCLI, subCmdGarageMC, ) }, }