internal/rosa: mirror service via external cache
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m43s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m43s
Test / Flake checks (push) Successful in 1m18s
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m43s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m43s
Test / Flake checks (push) Successful in 1m18s
This provides an authenticated implementation of the external cache. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -14,6 +14,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -47,6 +48,19 @@ import (
|
||||
"hakurei.app/cmd/mbf/internal/pkgserver/ui"
|
||||
)
|
||||
|
||||
// writeFileExcl is like [os.WriteFile], but sets [os.O_EXCL] instead.
|
||||
func writeFileExcl(name string, data []byte, perm os.FileMode) error {
|
||||
f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.Write(data)
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
container.TryArgv0(nil)
|
||||
|
||||
@@ -186,6 +200,10 @@ func main() {
|
||||
&cm.base,
|
||||
"d", command.StringFlag("$MBF_CACHE_DIR"),
|
||||
"Directory to store cured artifacts",
|
||||
).Flag(
|
||||
&cm.mirror,
|
||||
"r", command.StringFlag("$MBF_REMOTE"),
|
||||
"URL of mirror service",
|
||||
).Flag(
|
||||
&cm.idle,
|
||||
"sched-idle", command.BoolFlag(false),
|
||||
@@ -462,6 +480,70 @@ func main() {
|
||||
},
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
"keygen",
|
||||
"Create keypair for local cache",
|
||||
func([]string) error {
|
||||
pub, priv, err := ed25519.GenerateKey(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return errors.Join(writeFileExcl(filepath.Join(
|
||||
cm.base,
|
||||
"ed25519.pub",
|
||||
), pub, 0444), writeFileExcl(filepath.Join(
|
||||
cm.base,
|
||||
"ed25519",
|
||||
), priv, 0400))
|
||||
},
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
"serve",
|
||||
"Export local cache as mirror",
|
||||
func(args []string) error {
|
||||
const shutdownTimeout = 15 * time.Second
|
||||
|
||||
if len(args) != 1 {
|
||||
return errors.New("serve requires 1 argument")
|
||||
}
|
||||
|
||||
var key ed25519.PrivateKey
|
||||
if p, err := os.ReadFile(filepath.Join(cm.base, "ed25519")); err != nil {
|
||||
return err
|
||||
} else if len(p) != ed25519.PrivateKeySize {
|
||||
return errors.New("invalid private key")
|
||||
} else {
|
||||
key = p
|
||||
}
|
||||
|
||||
var h http.Handler
|
||||
if base, err := os.OpenRoot(cm.base); err != nil {
|
||||
return err
|
||||
} else {
|
||||
h = rosa.NewMirror(msg, base, key)
|
||||
}
|
||||
|
||||
server := http.Server{Addr: args[0], Handler: h}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
cc, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
||||
defer cancel()
|
||||
if err := server.Shutdown(cc); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
msg.Verbosef("listening on %q", args[0])
|
||||
err := server.ListenAndServe()
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
},
|
||||
)
|
||||
|
||||
{
|
||||
var (
|
||||
flagGentoo string
|
||||
|
||||
Reference in New Issue
Block a user