mirror of
https://github.com/gomods/athens
synced 2026-02-03 11:00:32 +00:00
* Changed mongo.go to use new driver * Modified mongo cataloger * More new driver related changes * Change lister.go * Change saver.go * Change imports * Remove unnecessary Count query * Use IndexView for indexing * Rename ModuleStore fields * Use map of key:sorting-order for creating the index * Minor changes * Use client options to configure mongo client * Use method chaining * gofmt changes * Change imports * Fix some build errors * Use new GridFS API * Fix more build errors * Add Go Mongo driver to dependency modules * Use multierror * Leave download stream open * Remove mgo error handling * Copy zip instead of loading all in memory * Use context.WithTimeout() wherever possible * Raise KindNotFound when mod@ver isn't found * NopCloser not needed * Fix IndexView error * Fix build errors * Remove another mgo error usage * Fix build error * Changes according to review * Formatting changes as per gofmt * Modify gofmt argument to show the expected formatting (diff) * Handle ErrNoDocument error and error arising from query execution * Fix kind of returned error * Minor changes * Bug fixes * gofmt related changes * Minor change * Use Insecure from MongoConfig, remove Insecure from global Config * Remove stray print statement
124 lines
3.1 KiB
Go
124 lines
3.1 KiB
Go
package mongo
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gomods/athens/pkg/config"
|
|
"github.com/gomods/athens/pkg/errors"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
// ModuleStore represents a mongo backed storage backend.
|
|
type ModuleStore struct {
|
|
client *mongo.Client
|
|
db string // database
|
|
coll string // collection
|
|
url string
|
|
certPath string
|
|
insecure bool // Only to be used for development instances
|
|
timeout time.Duration
|
|
}
|
|
|
|
// NewStorage returns a connected Mongo backed storage
|
|
// that satisfies the Backend interface.
|
|
func NewStorage(conf *config.MongoConfig, timeout time.Duration) (*ModuleStore, error) {
|
|
const op errors.Op = "mongo.NewStorage"
|
|
if conf == nil {
|
|
return nil, errors.E(op, "No Mongo Configuration provided")
|
|
}
|
|
ms := &ModuleStore{url: conf.URL, certPath: conf.CertPath, timeout: timeout, insecure: conf.InsecureConn}
|
|
client, err := ms.newClient(conf)
|
|
ms.client = client
|
|
|
|
if err != nil {
|
|
return nil, errors.E(op, err)
|
|
}
|
|
|
|
_, err = ms.connect(conf)
|
|
|
|
if err != nil {
|
|
return nil, errors.E(op, err)
|
|
}
|
|
|
|
return ms, nil
|
|
}
|
|
|
|
func (m *ModuleStore) connect(conf *config.MongoConfig) (*mongo.Collection, error) {
|
|
const op errors.Op = "mongo.connect"
|
|
|
|
var err error
|
|
err = m.client.Connect(context.Background())
|
|
|
|
if err != nil {
|
|
return nil, errors.E(op, err)
|
|
}
|
|
|
|
return m.initDatabase(), nil
|
|
}
|
|
|
|
func (m *ModuleStore) initDatabase() *mongo.Collection {
|
|
// TODO: database and collection as env vars, or params to New()? together with user/mongo
|
|
m.db = "athens"
|
|
m.coll = "modules"
|
|
|
|
c := m.client.Database(m.db).Collection(m.coll)
|
|
indexView := c.Indexes()
|
|
keys := make(map[string]int)
|
|
keys["base_url"] = 1
|
|
keys["module"] = 1
|
|
keys["version"] = 1
|
|
indexOptions := options.Index().SetBackground(true).SetSparse(true).SetUnique(true)
|
|
indexView.CreateOne(context.Background(), mongo.IndexModel{Keys: keys, Options: indexOptions}, options.CreateIndexes())
|
|
|
|
return c
|
|
}
|
|
|
|
func (m *ModuleStore) newClient(conf *config.MongoConfig) (*mongo.Client, error) {
|
|
tlsConfig := &tls.Config{}
|
|
clientOptions := options.Client()
|
|
// Maybe check for error using Validate()?
|
|
clientOptions = clientOptions.ApplyURI(m.url)
|
|
|
|
if m.certPath != "" {
|
|
// Sets only when the env var is setup in config.dev.toml
|
|
tlsConfig.InsecureSkipVerify = m.insecure
|
|
var roots *x509.CertPool
|
|
// See if there is a system cert pool
|
|
roots, err := x509.SystemCertPool()
|
|
if err != nil {
|
|
// If there is no system cert pool, create a new one
|
|
roots = x509.NewCertPool()
|
|
}
|
|
|
|
cert, err := ioutil.ReadFile(m.certPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if ok := roots.AppendCertsFromPEM(cert); !ok {
|
|
return nil, fmt.Errorf("failed to parse certificate from: %s", m.certPath)
|
|
}
|
|
|
|
tlsConfig.ClientCAs = roots
|
|
clientOptions = clientOptions.SetTLSConfig(tlsConfig)
|
|
}
|
|
clientOptions = clientOptions.SetConnectTimeout(m.timeout)
|
|
client, err := mongo.NewClient(clientOptions)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return client, nil
|
|
}
|
|
|
|
func (m *ModuleStore) gridFileName(mod, ver string) string {
|
|
return strings.Replace(mod, "/", "_", -1) + "_" + ver + ".zip"
|
|
}
|