These changes address the following warning showing up on `go get`
operations:
go: module github.com/golang/protobuf is deprecated: Use the
"google.golang.org/protobuf" module instead.
All changes are made using the recommendations in the per-function
deprecation notices from the docs at
https://pkg.go.dev/github.com/golang/protobuf/ptypes
306 lines
6.7 KiB
Go
306 lines
6.7 KiB
Go
package state
|
|
|
|
import (
|
|
"google.golang.org/protobuf/proto"
|
|
"github.com/hashicorp/go-memdb"
|
|
"github.com/hashicorp/go-version"
|
|
"github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk"
|
|
"github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
|
|
bolt "go.etcd.io/bbolt"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
var boxBucket = []byte("box")
|
|
|
|
func init() {
|
|
dbBuckets = append(dbBuckets, boxBucket)
|
|
dbIndexers = append(dbIndexers, (*State).boxIndexInit)
|
|
schemas = append(schemas, boxIndexSchema)
|
|
}
|
|
|
|
func (s *State) BoxList() ([]*vagrant_plugin_sdk.Ref_Box, error) {
|
|
memTxn := s.inmem.Txn(false)
|
|
defer memTxn.Abort()
|
|
|
|
return s.boxList(memTxn)
|
|
}
|
|
|
|
func (s *State) BoxDelete(ref *vagrant_plugin_sdk.Ref_Box) error {
|
|
memTxn := s.inmem.Txn(true)
|
|
defer memTxn.Abort()
|
|
|
|
err := s.db.Update(func(dbTxn *bolt.Tx) error {
|
|
return s.boxDelete(dbTxn, memTxn, ref)
|
|
})
|
|
if err == nil {
|
|
memTxn.Commit()
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (s *State) BoxGet(ref *vagrant_plugin_sdk.Ref_Box) (*vagrant_server.Box, error) {
|
|
memTxn := s.inmem.Txn(false)
|
|
defer memTxn.Abort()
|
|
|
|
var result *vagrant_server.Box
|
|
err := s.db.View(func(dbTxn *bolt.Tx) error {
|
|
var err error
|
|
result, err = s.boxGet(dbTxn, memTxn, ref)
|
|
return err
|
|
})
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (s *State) BoxPut(box *vagrant_server.Box) error {
|
|
memTxn := s.inmem.Txn(true)
|
|
defer memTxn.Abort()
|
|
|
|
err := s.db.Update(func(dbTxn *bolt.Tx) error {
|
|
return s.boxPut(dbTxn, memTxn, box)
|
|
})
|
|
if err == nil {
|
|
memTxn.Commit()
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (s *State) BoxFind(b *vagrant_plugin_sdk.Ref_Box) (*vagrant_server.Box, error) {
|
|
memTxn := s.inmem.Txn(false)
|
|
defer memTxn.Abort()
|
|
|
|
var result *vagrant_server.Box
|
|
err := s.db.View(func(dbTxn *bolt.Tx) error {
|
|
var err error
|
|
result, err = s.boxFind(dbTxn, memTxn, b)
|
|
return err
|
|
})
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (s *State) boxList(
|
|
memTxn *memdb.Txn,
|
|
) (r []*vagrant_plugin_sdk.Ref_Box, err error) {
|
|
iter, err := memTxn.Get(boxIndexTableName, boxIndexIdIndexName+"_prefix", "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result []*vagrant_plugin_sdk.Ref_Box
|
|
for {
|
|
next := iter.Next()
|
|
if next == nil {
|
|
break
|
|
}
|
|
result = append(result, &vagrant_plugin_sdk.Ref_Box{
|
|
ResourceId: next.(*boxIndexRecord).Id,
|
|
Name: next.(*boxIndexRecord).Name,
|
|
Version: next.(*boxIndexRecord).Version,
|
|
Provider: next.(*boxIndexRecord).Provider,
|
|
})
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (s *State) boxDelete(
|
|
dbTxn *bolt.Tx,
|
|
memTxn *memdb.Txn,
|
|
ref *vagrant_plugin_sdk.Ref_Box,
|
|
) (err error) {
|
|
b, err := s.boxGet(dbTxn, memTxn, ref)
|
|
if err != nil {
|
|
if status.Code(err) == codes.NotFound {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
// Delete the box
|
|
if err = dbTxn.Bucket(boxBucket).Delete(s.boxId(b)); err != nil {
|
|
return
|
|
}
|
|
if err = memTxn.Delete(boxIndexTableName, s.newBoxIndexRecord(b)); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *State) boxGet(
|
|
dbTxn *bolt.Tx,
|
|
memTxn *memdb.Txn,
|
|
ref *vagrant_plugin_sdk.Ref_Box,
|
|
) (r *vagrant_server.Box, err error) {
|
|
var result vagrant_server.Box
|
|
b := dbTxn.Bucket(boxBucket)
|
|
return &result, dbGet(b, s.boxIdByRef(ref), &result)
|
|
}
|
|
|
|
func (s *State) boxPut(
|
|
dbTxn *bolt.Tx,
|
|
memTxn *memdb.Txn,
|
|
value *vagrant_server.Box,
|
|
) (err error) {
|
|
id := s.boxId(value)
|
|
b := dbTxn.Bucket(boxBucket)
|
|
if err = dbPut(b, id, value); err != nil {
|
|
s.log.Error("failed to store box in db", "box", value, "error", err)
|
|
return
|
|
}
|
|
|
|
s.log.Trace("indexing box", "box", value)
|
|
if err = s.boxIndexSet(memTxn, id, value); err != nil {
|
|
s.log.Error("failed to index box", "box", value, "error", err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *State) boxFind(
|
|
dbTxn *bolt.Tx,
|
|
memTxn *memdb.Txn,
|
|
ref *vagrant_plugin_sdk.Ref_Box,
|
|
) (r *vagrant_server.Box, err error) {
|
|
var match *boxIndexRecord
|
|
highestVersion, _ := version.NewVersion("0.0.0")
|
|
req := s.newBoxIndexRecordByRef(ref)
|
|
// Get the name first
|
|
if req.Name != "" {
|
|
raw, err := memTxn.Get(
|
|
boxIndexTableName,
|
|
boxIndexNameIndexName,
|
|
req.Name,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if req.Version == "" {
|
|
req.Version = ">= 0"
|
|
}
|
|
versionConstraint, err := version.NewConstraint(req.Version)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for e := raw.Next(); e != nil; e = raw.Next() {
|
|
boxIndexEntry := e.(*boxIndexRecord)
|
|
if req.Version != "" {
|
|
boxVersion, _ := version.NewVersion(boxIndexEntry.Version)
|
|
if !versionConstraint.Check(boxVersion) {
|
|
continue
|
|
}
|
|
}
|
|
if req.Provider != "" {
|
|
if boxIndexEntry.Provider != req.Provider {
|
|
continue
|
|
}
|
|
}
|
|
// Set first match
|
|
if match == nil {
|
|
match = boxIndexEntry
|
|
}
|
|
v, _ := version.NewVersion(boxIndexEntry.Version)
|
|
if v.GreaterThan(highestVersion) {
|
|
highestVersion = v
|
|
match = boxIndexEntry
|
|
}
|
|
}
|
|
|
|
if match != nil {
|
|
return s.boxGet(dbTxn, memTxn, &vagrant_plugin_sdk.Ref_Box{
|
|
ResourceId: match.Id,
|
|
})
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
const (
|
|
boxIndexIdIndexName = "id"
|
|
boxIndexNameIndexName = "name"
|
|
boxIndexTableName = "box-index"
|
|
)
|
|
|
|
type boxIndexRecord struct {
|
|
Id string // Resource ID
|
|
Name string // Box Name
|
|
Version string // Box Version
|
|
Provider string // Box Provider
|
|
}
|
|
|
|
func (s *State) newBoxIndexRecord(b *vagrant_server.Box) *boxIndexRecord {
|
|
id := b.Name + "-" + b.Version + "-" + b.Provider
|
|
return &boxIndexRecord{
|
|
Id: id,
|
|
Name: b.Name,
|
|
Version: b.Version,
|
|
Provider: b.Provider,
|
|
}
|
|
}
|
|
|
|
func (s *State) boxIndexSet(txn *memdb.Txn, id []byte, value *vagrant_server.Box) error {
|
|
return txn.Insert(boxIndexTableName, s.newBoxIndexRecord(value))
|
|
}
|
|
|
|
func (s *State) boxIndexInit(dbTxn *bolt.Tx, memTxn *memdb.Txn) error {
|
|
bucket := dbTxn.Bucket(boxBucket)
|
|
return bucket.ForEach(func(k, v []byte) error {
|
|
var value vagrant_server.Box
|
|
if err := proto.Unmarshal(v, &value); err != nil {
|
|
return err
|
|
}
|
|
if err := s.boxIndexSet(memTxn, k, &value); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func boxIndexSchema() *memdb.TableSchema {
|
|
return &memdb.TableSchema{
|
|
Name: boxIndexTableName,
|
|
Indexes: map[string]*memdb.IndexSchema{
|
|
boxIndexIdIndexName: {
|
|
Name: boxIndexIdIndexName,
|
|
AllowMissing: false,
|
|
Unique: true,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "Id",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
boxIndexNameIndexName: {
|
|
Name: boxIndexNameIndexName,
|
|
AllowMissing: false,
|
|
Unique: false,
|
|
Indexer: &memdb.StringFieldIndex{
|
|
Field: "Name",
|
|
Lowercase: true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func (s *State) newBoxIndexRecordByRef(ref *vagrant_plugin_sdk.Ref_Box) *boxIndexRecord {
|
|
return &boxIndexRecord{
|
|
Id: ref.ResourceId,
|
|
Name: ref.Name,
|
|
Version: ref.Version,
|
|
Provider: ref.Provider,
|
|
}
|
|
}
|
|
|
|
func (s *State) boxId(b *vagrant_server.Box) []byte {
|
|
return []byte(b.Id)
|
|
}
|
|
|
|
func (s *State) boxIdByRef(b *vagrant_plugin_sdk.Ref_Box) []byte {
|
|
return []byte(b.ResourceId)
|
|
}
|