Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Development #79

Merged
merged 32 commits into from
Jan 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
de872a6
Merge branch 'master' into development
domodwyer Aug 8, 2017
1519fd3
Merge branch 'master' into development
domodwyer Aug 15, 2017
454da02
add DropAllIndexes() method (#25)
feliixx Aug 30, 2017
93aaa6e
readme: credit @feliixx for #25 (#26)
domodwyer Aug 30, 2017
165af68
send metadata during handshake (#28)
feliixx Sep 6, 2017
a76b1a0
Update README to add appName (#32)
domodwyer Sep 6, 2017
25200e4
add method CreateView() (#33)
feliixx Sep 11, 2017
1f4c10f
readme: credit @feliixx in the README (#36)
domodwyer Sep 11, 2017
934a190
Don't panic on indexed int64 fields (#23)
domodwyer Sep 11, 2017
b37e3c1
Add collation option to collection.Create() (#37)
feliixx Sep 13, 2017
aead58f
Test against MongoDB 3.4.x (#35)
feliixx Sep 15, 2017
950ed5a
Introduce constants for BSON element types (#41)
bozaro Sep 20, 2017
d21a525
bson.Unmarshal returns time in UTC (#42)
Sep 28, 2017
9d743b4
readme: add missing features / credit
domodwyer Sep 28, 2017
c86ed84
Merge pull request #45 from globalsign/feature/update-readme
Sep 28, 2017
97bd0cd
fix golint, go vet and gofmt warnings (#44)
feliixx Oct 6, 2017
fd79249
readme: credit @feliixx (#46)
domodwyer Oct 9, 2017
dba7b4c
Fix GetBSON() method usage (#40)
bozaro Oct 11, 2017
12fb1c2
readme: credit @bozaro (#47)
domodwyer Oct 11, 2017
199dc25
Improve cursorData struct unmarshaling speed (#49)
bozaro Oct 19, 2017
345ab0b
readme: credit @bozaro and @idy (#53)
domodwyer Oct 19, 2017
0454966
do not lock while writing to a socket (#52) (#54)
domodwyer Oct 19, 2017
663dfe5
Add proper DN construction (#55)
csucu Nov 2, 2017
7cd0b89
reduce memory allocation in bulk op (#56)
feliixx Nov 3, 2017
ea8e8e6
readme: credit @feliixx (#58)
domodwyer Nov 6, 2017
90c056c
MongoDB 3.6: implement the new wire protocol (#61)
feliixx Dec 12, 2017
1ac9b5d
Merge branch 'master' into development
domodwyer Dec 12, 2017
a104bfb
Recover from persistent "i/o timeout" or "Closed explicitly" pool err…
bachue Dec 27, 2017
f9be6c5
development: revert #61 (#73)
domodwyer Jan 9, 2018
138ba2f
readme: credit @bachue (#74)
domodwyer Jan 9, 2018
9acbd68
auth: add an example for x509 authentication (#75)
domodwyer Jan 9, 2018
eeedc17
session: add example concurrent usage (#78)
domodwyer Jan 15, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,23 @@ language: go

go_import_path: github.com/globalsign/mgo

go:
- 1.8.x
- 1.9.x

env:
global:
- BUCKET=https://s3.eu-west-2.amazonaws.com/globalsign-mgo
- FASTDL=https://fastdl.mongodb.org/linux
matrix:
- GO=1.7 MONGODB=x86_64-2.6.11
- GO=1.8.x MONGODB=x86_64-2.6.11
- GO=1.7 MONGODB=x86_64-3.0.9
- GO=1.8.x MONGODB=x86_64-3.0.9
- GO=1.7 MONGODB=x86_64-3.2.3-nojournal
- GO=1.8.x MONGODB=x86_64-3.2.3-nojournal
- GO=1.7 MONGODB=x86_64-3.2.12
- GO=1.8.x MONGODB=x86_64-3.2.12
- GO=1.7 MONGODB=x86_64-3.2.16
- GO=1.8.x MONGODB=x86_64-3.2.16
- GO=1.7 MONGODB=x86_64-3.4.8
- GO=1.8.x MONGODB=x86_64-3.4.8
- MONGODB=x86_64-ubuntu1404-3.0.15
- MONGODB=x86_64-ubuntu1404-3.2.17
- MONGODB=x86_64-ubuntu1404-3.4.10
- MONGODB=x86_64-ubuntu1404-3.6.0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we upgrade to 3.6.2 while we are at it ?


install:
- eval "$(gimme $GO)"

- wget $BUCKET/mongodb-linux-$MONGODB.tgz
- wget $FASTDL/mongodb-linux-$MONGODB.tgz
- tar xzvf mongodb-linux-$MONGODB.tgz
- export PATH=$PWD/mongodb-linux-$MONGODB/bin:$PATH

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Further PR's (with tests) are welcome, but please maintain backwards compatibili
* Fixes attempting to authenticate before every query ([details](https://github.com/go-mgo/mgo/issues/254))
* Removes bulk update / delete batch size limitations ([details](https://github.com/go-mgo/mgo/issues/288))
* Adds native support for `time.Duration` marshalling ([details](https://github.com/go-mgo/mgo/pull/373))
* Reduce memory footprint / garbage collection pressure by reusing buffers ([details](https://github.com/go-mgo/mgo/pull/229))
* Reduce memory footprint / garbage collection pressure by reusing buffers ([details](https://github.com/go-mgo/mgo/pull/229), [more](https://github.com/globalsign/mgo/pull/56))
* Support majority read concerns ([details](https://github.com/globalsign/mgo/pull/2))
* Improved connection handling ([details](https://github.com/globalsign/mgo/pull/5))
* Hides SASL warnings ([details](https://github.com/globalsign/mgo/pull/7))
Expand All @@ -32,10 +32,13 @@ Further PR's (with tests) are welcome, but please maintain backwards compatibili
* GetBSON correctly handles structs with both fields and pointers ([details](https://github.com/globalsign/mgo/pull/40))
* Improved bson.Raw unmarshalling performance ([details](https://github.com/globalsign/mgo/pull/49))
* Minimise socket connection timeouts due to excessive locking ([details](https://github.com/globalsign/mgo/pull/52))
* Natively support X509 client authentication ([details](https://github.com/globalsign/mgo/pull/55))
* Gracefully recover from a temporarily unreachable server ([details](https://github.com/globalsign/mgo/pull/69))

---

### Thanks to
* @bachue
* @bozaro
* @BenLubar
* @carter2000
Expand Down
70 changes: 69 additions & 1 deletion auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ package mgo_test

import (
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"io/ioutil"
Expand All @@ -38,7 +39,7 @@ import (
"sync"
"time"

mgo "github.com/globalsign/mgo"
"github.com/globalsign/mgo"
. "gopkg.in/check.v1"
)

Expand Down Expand Up @@ -963,6 +964,73 @@ func (s *S) TestAuthX509Cred(c *C) {
c.Assert(len(names) > 0, Equals, true)
}

func (s *S) TestAuthX509CredRDNConstruction(c *C) {
session, err := mgo.Dial("localhost:40001")
c.Assert(err, IsNil)
defer session.Close()
binfo, err := session.BuildInfo()
c.Assert(err, IsNil)
if binfo.OpenSSLVersion == "" {
c.Skip("server does not support SSL")
}

clientCertPEM, err := ioutil.ReadFile("harness/certs/client.pem")
c.Assert(err, IsNil)

clientCert, err := tls.X509KeyPair(clientCertPEM, clientCertPEM)
c.Assert(err, IsNil)

clientCert.Leaf, err = x509.ParseCertificate(clientCert.Certificate[0])
c.Assert(err, IsNil)

tlsConfig := &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{clientCert},
}

var host = "localhost:40003"
c.Logf("Connecting to %s...", host)
session, err = mgo.DialWithInfo(&mgo.DialInfo{
Addrs: []string{host},
DialServer: func(addr *mgo.ServerAddr) (net.Conn, error) {
return tls.Dial("tcp", addr.String(), tlsConfig)
},
})
c.Assert(err, IsNil)
defer session.Close()

cred := &mgo.Credential{
Username: "root",
Mechanism: "MONGODB-X509",
Source: "$external",
Certificate: tlsConfig.Certificates[0].Leaf,
}
err = session.Login(cred)
c.Assert(err, NotNil)

err = session.Login(&mgo.Credential{Username: "root", Password: "rapadura"})
c.Assert(err, IsNil)

// This needs to be kept in sync with client.pem
x509Subject := "CN=localhost,OU=Client,O=MGO,L=MGO,ST=MGO,C=GO"

externalDB := session.DB("$external")
var x509User = mgo.User{
Username: x509Subject,
OtherDBRoles: map[string][]mgo.Role{"admin": {mgo.RoleRoot}},
}
err = externalDB.UpsertUser(&x509User)
c.Assert(err, IsNil)

session.LogoutAll()

cred.Username = ""
c.Logf("Authenticating...")
err = session.Login(cred)
c.Assert(err, IsNil)
c.Logf("Authenticated!")
}

var (
plainFlag = flag.String("plain", "", "Host to test PLAIN authentication against (depends on custom environment)")
plainUser = "einstein"
Expand Down
17 changes: 16 additions & 1 deletion bulk.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package mgo
import (
"bytes"
"sort"
"sync"

"github.com/globalsign/mgo/bson"
)
Expand Down Expand Up @@ -118,6 +119,15 @@ func (e *BulkError) Cases() []BulkErrorCase {
return e.ecases
}

var actionPool = sync.Pool{
New: func() interface{} {
return &bulkAction{
docs: make([]interface{}, 0),
idxs: make([]int, 0),
}
},
}

// Bulk returns a value to prepare the execution of a bulk operation.
func (c *Collection) Bulk() *Bulk {
return &Bulk{c: c, ordered: true}
Expand Down Expand Up @@ -145,7 +155,9 @@ func (b *Bulk) action(op bulkOp, opcount int) *bulkAction {
}
}
if action == nil {
b.actions = append(b.actions, bulkAction{op: op})
a := actionPool.Get().(*bulkAction)
a.op = op
b.actions = append(b.actions, *a)
action = &b.actions[len(b.actions)-1]
}
for i := 0; i < opcount; i++ {
Expand Down Expand Up @@ -288,6 +300,9 @@ func (b *Bulk) Run() (*BulkResult, error) {
default:
panic("unknown bulk operation")
}
action.idxs = action.idxs[0:0]
action.docs = action.docs[0:0]
actionPool.Put(action)
if !ok {
failed = true
if b.ordered {
Expand Down
4 changes: 2 additions & 2 deletions cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2083,8 +2083,8 @@ func (s *S) TestDoNotFallbackToMonotonic(c *C) {
if !s.versionAtLeast(3, 0) {
c.Skip("command-counting logic depends on 3.0+")
}
if s.versionAtLeast(3, 4) {
c.Skip("failing on 3.4+")
if s.versionAtLeast(3, 2, 17) {
c.Skip("failing on 3.2.17+")
}

session, err := mgo.Dial("localhost:40012")
Expand Down
136 changes: 136 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package mgo

import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"net"
"sync"
)

func ExampleCredential_x509Authentication() {
// MongoDB follows RFC2253 for the ordering of the DN - if the order is
// incorrect when creating the user in Mongo, the client will not be able to
// connect.
//
// The best way to generate the DN with the correct ordering is with
// openssl:
//
// openssl x509 -in client.crt -inform PEM -noout -subject -nameopt RFC2253
// subject= CN=Example App,OU=MongoDB Client Authentication,O=GlobalSign,C=GB
//
//
// And then create the user in MongoDB with the above DN:
//
// db.getSiblingDB("$external").runCommand({
// createUser: "CN=Example App,OU=MongoDB Client Authentication,O=GlobalSign,C=GB",
// roles: [
// { role: 'readWrite', db: 'bananas' },
// { role: 'userAdminAnyDatabase', db: 'admin' }
// ],
// writeConcern: { w: "majority" , wtimeout: 5000 }
// })
//
//
// References:
// - https://docs.mongodb.com/manual/tutorial/configure-x509-client-authentication/
// - https://docs.mongodb.com/manual/core/security-x.509/
//

// Read in the PEM encoded X509 certificate.
//
// See the client.pem file at the path below.
clientCertPEM, err := ioutil.ReadFile("harness/certs/client.pem")

// Read in the PEM encoded private key.
clientKeyPEM, err := ioutil.ReadFile("harness/certs/client.key")

// Parse the private key, and the public key contained within the
// certificate.
clientCert, err := tls.X509KeyPair(clientCertPEM, clientKeyPEM)

// Parse the actual certificate data
clientCert.Leaf, err = x509.ParseCertificate(clientCert.Certificate[0])

// Use the cert to set up a TLS connection to Mongo
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{clientCert},

// This is set to true so the example works within the test
// environment.
//
// DO NOT set InsecureSkipVerify to true in a production
// environment - if you use an untrusted CA/have your own, load
// its certificate into the RootCAs value instead.
//
// RootCAs: myCAChain,
InsecureSkipVerify: true,
}

// Connect to Mongo using TLS
host := "localhost:40003"
session, err := DialWithInfo(&DialInfo{
Addrs: []string{host},
DialServer: func(addr *ServerAddr) (net.Conn, error) {
return tls.Dial("tcp", host, tlsConfig)
},
})

// Authenticate using the certificate
cred := &Credential{Certificate: tlsConfig.Certificates[0].Leaf}
if err := session.Login(cred); err != nil {
panic(err)
}

// Done! Use mgo as normal from here.
//
// You should actually check the error code at each step.
_ = err
}

func ExampleSession_concurrency() {
// This example shows the best practise for concurrent use of a mgo session.
//
// Internally mgo maintains a connection pool, dialling new connections as
// required.
//
// Some general suggestions:
// - Define a struct holding the original session, database name and
// collection name instead of passing them explicitly.
// - Define an interface abstracting your data access instead of exposing
// mgo to your application code directly.
// - Limit concurrency at the application level, not with SetPoolLimit().

// This will be our concurrent worker
var doStuff = func(wg *sync.WaitGroup, session *Session) {
defer wg.Done()

// Copy the session - if needed this will dial a new connection which
// can later be reused.
//
// Calling close returns the connection to the pool.
conn := session.Copy()
defer conn.Close()

// Do something(s) with the connection
_, _ = conn.DB("").C("my_data").Count()
}

///////////////////////////////////////////////

// Dial a connection to Mongo - this creates the connection pool
session, err := Dial("localhost:40003/my_database")
if err != nil {
panic(err)
}

// Concurrently do things, passing the session to the worker
wg := &sync.WaitGroup{}
for i := 0; i < 10; i++ {
wg.Add(1)
go doStuff(wg, session)
}
wg.Wait()

session.Close()
}
10 changes: 0 additions & 10 deletions harness/daemons/.env
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ versionAtLeast() {

COMMONDOPTSNOIP="
--nohttpinterface
--noprealloc
--nojournal
--smallfiles
--nssize=1
--oplogSize=1
--dbpath ./db
"
Expand Down Expand Up @@ -55,14 +53,12 @@ if versionAtLeast 3 2; then
# 3.2 doesn't like --nojournal on config servers.
COMMONCOPTS="$(echo "$COMMONCOPTS" | sed '/--nojournal/d')"


if versionAtLeast 3 4; then
# http interface is disabled by default, this option does not exist anymore
COMMONDOPTSNOIP="$(echo "$COMMONDOPTSNOIP" | sed '/--nohttpinterface/d')"
COMMONDOPTS="$(echo "$COMMONDOPTS" | sed '/--nohttpinterface/d')"
COMMONCOPTS="$(echo "$COMMONCOPTS" | sed '/--nohttpinterface/d')"


# config server need to be started as replica set
CFG1OPTS="--replSet conf1"
CFG2OPTS="--replSet conf2"
Expand All @@ -71,12 +67,6 @@ if versionAtLeast 3 2; then
MONGOS1OPTS="--configdb conf1/127.0.0.1:40101"
MONGOS2OPTS="--configdb conf2/127.0.0.1:40102"
MONGOS3OPTS="--configdb conf3/127.0.0.1:40103"
else

# Go back to MMAPv1 so it's not super sluggish. :-(
COMMONDOPTSNOIP="--storageEngine=mmapv1 $COMMONDOPTSNOIP"
COMMONDOPTS="--storageEngine=mmapv1 $COMMONDOPTS"
COMMONCOPTS="--storageEngine=mmapv1 $COMMONCOPTS"
fi
fi

Expand Down
1 change: 0 additions & 1 deletion harness/daemons/db2/run
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
. ../.env

exec mongod $COMMONDOPTS \
--shardsvr \
--port 40002 \
--auth
1 change: 0 additions & 1 deletion harness/daemons/db3/run
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
. ../.env

exec mongod $COMMONDOPTS \
--shardsvr \
--port 40003 \
--auth \
--sslMode preferSSL \
Expand Down
Loading