Some checks failed
Docker image builds / build (push) Waiting to run
Asset Build Verification / asset_verification (push) Has been cancelled
Docs deploy / build (push) Has been cancelled
Go Mod Tidy Check / go_mod_tidy_check (push) Has been cancelled
Go / go_tests (push) Has been cancelled
Package builds (unstable) / package_builds (push) Has been cancelled
Smoke tests / smoke-test (default-config-macro) (push) Has been cancelled
Smoke tests / smoke-test (docker-registry) (push) Has been cancelled
Smoke tests / smoke-test (double_slash) (push) Has been cancelled
Smoke tests / smoke-test (forced-language) (push) Has been cancelled
Smoke tests / smoke-test (git-clone) (push) Has been cancelled
Smoke tests / smoke-test (git-push) (push) Has been cancelled
Smoke tests / smoke-test (healthcheck) (push) Has been cancelled
Smoke tests / smoke-test (i18n) (push) Has been cancelled
Smoke tests / smoke-test (log-file) (push) Has been cancelled
Smoke tests / smoke-test (nginx) (push) Has been cancelled
Smoke tests / smoke-test (palemoon/amd64) (push) Has been cancelled
Smoke tests / smoke-test (robots_txt) (push) Has been cancelled
Check Spelling / Check Spelling (push) Has been cancelled
SSH CI / ssh (aarch64-16k) (push) Has been cancelled
SSH CI / ssh (aarch64-4k) (push) Has been cancelled
SSH CI / ssh (ppc64le) (push) Has been cancelled
SSH CI / ssh (riscv64) (push) Has been cancelled
zizmor / zizmor latest via PyPI (push) Has been cancelled
94 lines
2.2 KiB
Go
94 lines
2.2 KiB
Go
package bbolt
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.sad.ovh/sophie/nuke/lib/store"
|
|
"go.etcd.io/bbolt"
|
|
)
|
|
|
|
var (
|
|
ErrMissingPath = errors.New("bbolt: path is missing from config")
|
|
ErrCantWriteToPath = errors.New("bbolt: can't write to path")
|
|
)
|
|
|
|
func init() {
|
|
store.Register("bbolt", Factory{})
|
|
}
|
|
|
|
// Factory builds new instances of the bbolt storage backend according to
|
|
// configuration passed via a json.RawMessage.
|
|
type Factory struct{}
|
|
|
|
// Build parses and validates the bbolt storage backend Config and creates
|
|
// a new instance of it.
|
|
func (Factory) Build(ctx context.Context, data json.RawMessage) (store.Interface, error) {
|
|
var config Config
|
|
if err := json.Unmarshal([]byte(data), &config); err != nil {
|
|
return nil, fmt.Errorf("%w: %w", store.ErrBadConfig, err)
|
|
}
|
|
|
|
if err := config.Valid(); err != nil {
|
|
return nil, fmt.Errorf("%w: %w", store.ErrBadConfig, err)
|
|
}
|
|
|
|
bdb, err := bbolt.Open(config.Path, 0600, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("can't open bbolt database %s: %w", config.Path, err)
|
|
}
|
|
|
|
result := &Store{
|
|
bdb: bdb,
|
|
}
|
|
|
|
go result.cleanupThread(ctx)
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// Valid parses and validates the bbolt store Config or returns
|
|
// an error.
|
|
func (Factory) Valid(data json.RawMessage) error {
|
|
var config Config
|
|
if err := json.Unmarshal([]byte(data), &config); err != nil {
|
|
return fmt.Errorf("%w: %w", store.ErrBadConfig, err)
|
|
}
|
|
|
|
if err := config.Valid(); err != nil {
|
|
return fmt.Errorf("%w: %w", store.ErrBadConfig, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Config is the bbolt storage backend configuration.
|
|
type Config struct {
|
|
// Path is the filesystem path of the database. The folder must be writable to Nuke.
|
|
Path string `json:"path"`
|
|
}
|
|
|
|
// Valid validates the configuration including checking if its containing folder is writable.
|
|
func (c Config) Valid() error {
|
|
var errs []error
|
|
|
|
if c.Path == "" {
|
|
errs = append(errs, ErrMissingPath)
|
|
} else {
|
|
dir := filepath.Dir(c.Path)
|
|
if err := os.WriteFile(filepath.Join(dir, ".test-file"), []byte(""), 0600); err != nil {
|
|
errs = append(errs, ErrCantWriteToPath)
|
|
}
|
|
os.Remove(filepath.Join(dir, ".test-file"))
|
|
}
|
|
|
|
if len(errs) != 0 {
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
return nil
|
|
}
|