Repository: getporter/porter
Pull request #1745 (2021-08-27 19:46:46)

Use official mongodb driver 
# What does this change
I used the mgo driver (because it's easier to use) but it doesn't support the newer version of mongodb (4+) and also doesn't support the newer connection string format used exclusively by mongodb atlas (mongo's cloud offering for mongodb, its freee 💸 soooooooooo, we are totes gonna support it).

# What issue does it fix
Now I can do my kubecon demo using a cloud database that I don't have to pay for or keep updated myself. Huzzah!

# Notes for the reviewer
Sorry for not biting the bullet and just using the official driver when I first implemented this. The driver honestly isn't as easy to use but luckily most of the changes necessary are in just a few spots.

# Checklist
- [x] Unit Tests
- [ ] Documentation
- [ ] Schema (porter.yaml)



Patch:
diff --git a/docs/content/plugins/mongodb.md b/docs/content/plugins/mongodb.md
index f9335e22..82afe3d7 100644
--- a/docs/content/plugins/mongodb.md
+++ b/docs/content/plugins/mongodb.md
@@ -20,6 +20,7 @@ default-secrets = "mymongo"
 
   [storage.config]
     url = "conn_str"
+    timeout = 10 # time in seconds
 ```
 
 [config file]: /configuration/#config-file
@@ -47,3 +48,8 @@ localhost at the default port 27017, using the database name "mydb".
 ```
 "mongodb://localhost:27017/mydb"
 ```
+
+### timeout
+
+Sets the timeout (in seconds) used for database queries.
+The default timeout is 2 seconds.
diff --git a/go.mod b/go.mod
index 1de024cd..32e7cfca 100644
--- a/go.mod
+++ b/go.mod
@@ -41,7 +41,6 @@ require (
 	github.com/docker/docker v20.10.6+incompatible
 	github.com/dustin/go-humanize v1.0.0
 	github.com/ghodss/yaml v1.0.0
-	github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
 	github.com/gobuffalo/logger v1.0.4 // indirect
 	github.com/gobuffalo/packr/v2 v2.8.1 // indirect
 	github.com/google/go-containerregistry v0.1.2
@@ -69,6 +68,7 @@ require (
 	github.com/stretchr/testify v1.7.0
 	github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
 	github.com/xeipuuv/gojsonschema v1.2.0
+	go.mongodb.org/mongo-driver v1.7.1
 	golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 	golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
diff --git a/go.sum b/go.sum
index 4015ede0..9601318e 100644
--- a/go.sum
+++ b/go.sum
@@ -479,8 +479,6 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
-github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=
-github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g=
 github.com/go-critic/go-critic v0.4.3/go.mod h1:j4O3D4RoIwRqlZw5jJpx0BNfXWWbpcJoKu5cYSe4YmQ=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -516,6 +514,7 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
@@ -533,14 +532,38 @@ github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslW
 github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
 github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
 github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
+github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
+github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
+github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
+github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
+github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
+github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
+github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
+github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
+github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
+github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
+github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
+github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
+github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
 github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM=
 github.com/gobuffalo/logger v1.0.4 h1:HFJRqL7AmL4QNvQb9Grss9sDz+3u02VBgAoR03A7q4o=
 github.com/gobuffalo/logger v1.0.4/go.mod h1:/GRUdWb+gM3shxj0P5jiV6ecVS3X0aboJvl+hBu0HeE=
+github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
 github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM=
 github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI=
+github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
+github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
 github.com/gobuffalo/packr/v2 v2.8.0/go.mod h1:PDk2k3vGevNE3SwVyVRgQCCXETC9SaONCNSXT1Q8M1g=
 github.com/gobuffalo/packr/v2 v2.8.1 h1:tkQpju6i3EtMXJ9uoF5GT6kB+LMTimDWD8Xvbz6zDVA=
 github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5OeMf+NnJpg=
+github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
 github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
 github.com/goccy/go-yaml v1.8.1 h1:JuZRFlqLM5cWF6A+waL8AKVuCcqvKOuhJtUQI+L3ez0=
 github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y=
@@ -816,6 +839,8 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
 github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
+github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
+github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
 github.com/karrick/godirwalk v1.15.3/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
 github.com/karrick/godirwalk v1.15.8/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
 github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
@@ -830,6 +855,7 @@ github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49/go.mod h1:yyMNCy
 github.com/kisom/goutils v1.1.0/go.mod h1:+UBTfd78habUYWFbNWTJNG+jNG/i/lGURakr4A/yNRw=
 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
 github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
@@ -875,6 +901,7 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
 github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU=
 github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
 github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
+github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
 github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=
 github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=
 github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
@@ -974,6 +1001,7 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
 github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
 github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
@@ -1074,6 +1102,7 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
 github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
 github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
@@ -1150,6 +1179,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uY
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.5.2 h1:qLvObTrvO/XRCqmkKxUlOBc48bI3efyDuAZe25QiF0w=
 github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -1186,6 +1217,7 @@ github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvH
 github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -1259,6 +1291,8 @@ github.com/tetafro/godot v0.3.7/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQx
 github.com/tetafro/godot v0.4.2/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0=
 github.com/theupdateframework/notary v0.6.1 h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz+cjWoom6l0=
 github.com/theupdateframework/notary v0.6.1/go.mod h1:MOfgIfmox8s7/7fduvB2xyPPMJCrjRLRizA8OFwpnKY=
+github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
 github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
 github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
@@ -1307,6 +1341,12 @@ github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
 github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
 github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
 github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
+github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
+github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
+github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -1319,6 +1359,8 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofm
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1339,6 +1381,8 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
 go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
+go.mongodb.org/mongo-driver v1.7.1 h1:jwqTeEM3x6L9xDXrCxN0Hbg7vdGfPBOTIkr0+/LYZDA=
+go.mongodb.org/mongo-driver v1.7.1/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8=
 go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
 go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
 go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A=
@@ -1370,6 +1414,7 @@ golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1381,6 +1426,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
@@ -1489,6 +1535,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1513,13 +1560,16 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1625,11 +1675,15 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
diff --git a/pkg/claims/claimstore.go b/pkg/claims/claimstore.go
index 48e0f0ae..5a9a6d28 100644
--- a/pkg/claims/claimstore.go
+++ b/pkg/claims/claimstore.go
@@ -2,10 +2,9 @@ package claims
 
 import (
 	"get.porter.sh/porter/pkg/storage"
-	"github.com/globalsign/mgo"
-	"github.com/globalsign/mgo/bson"
 	"github.com/hashicorp/go-multierror"
 	"github.com/pkg/errors"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 const (
@@ -39,11 +38,8 @@ func (s ClaimStore) Initialize() error {
 
 	// query installations by a namespace (list) or namespace + name (get)
 	err := s.store.EnsureIndex(CollectionInstallations, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "name"},
-			Unique:     true,
-			Background: true,
-		},
+		Keys:   []string{"namespace", "name"},
+		Unique: true,
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
@@ -51,10 +47,7 @@ func (s ClaimStore) Initialize() error {
 
 	// query runs by installation (list)
 	err = s.store.EnsureIndex(CollectionRuns, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "installation"},
-			Background: true,
-		},
+		Keys: []string{"namespace", "installation"},
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
@@ -62,10 +55,7 @@ func (s ClaimStore) Initialize() error {
 
 	// query results by installation (delete or batch get)
 	err = s.store.EnsureIndex(CollectionResults, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "installation"},
-			Background: true,
-		},
+		Keys: []string{"namespace", "installation"},
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
@@ -73,10 +63,7 @@ func (s ClaimStore) Initialize() error {
 
 	// query results by run (list)
 	err = s.store.EnsureIndex(CollectionResults, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"runId"},
-			Background: true,
-		},
+		Keys: []string{"runId"},
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
@@ -84,10 +71,7 @@ func (s ClaimStore) Initialize() error {
 
 	// query most recent outputs by run (porter installation run show, when we list outputs)
 	err = s.store.EnsureIndex(CollectionOutputs, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "installation", "-resultId"},
-			Background: true,
-		},
+		Keys: []string{"namespace", "installation", "-resultId"},
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
@@ -95,11 +79,8 @@ func (s ClaimStore) Initialize() error {
 
 	// query outputs by result (list)
 	err = s.store.EnsureIndex(CollectionOutputs, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"resultId", "name"},
-			Unique:     true,
-			Background: true,
-		},
+		Keys:   []string{"resultId", "name"},
+		Unique: true,
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
@@ -107,10 +88,7 @@ func (s ClaimStore) Initialize() error {
 
 	// query most recent outputs by name for an installation
 	err = s.store.EnsureIndex(CollectionOutputs, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "installation", "name", "-resultId"},
-			Background: true,
-		},
+		Keys: []string{"namespace", "installation", "name", "-resultId"},
 	})
 	if err != nil {
 		bigErr = multierror.Append(bigErr, err)
diff --git a/pkg/cnab/parameter_sources.go b/pkg/cnab/parameter_sources.go
index 2a1b8549..21834ac3 100644
--- a/pkg/cnab/parameter_sources.go
+++ b/pkg/cnab/parameter_sources.go
@@ -2,7 +2,6 @@ package cnab
 
 import (
 	"encoding/json"
-	"fmt"
 
 	"github.com/pkg/errors"
 )
@@ -209,7 +208,6 @@ func (b ExtendedBundle) SupportsParameterSources() bool {
 // GetParameterSources checks if the parameter sources extension is present and returns its
 // extension configuration.
 func (e ProcessedExtensions) GetParameterSources() (ParameterSources, bool, error) {
-	fmt.Printf("Processed bundle extensions:\n%#v\n", e)
 	rawExt, required := e[ParameterSourcesExtensionKey]
 
 	ext, ok := rawExt.(ParameterSources)
diff --git a/pkg/cnab/provider/credentials.go b/pkg/cnab/provider/credentials.go
index 717026bb..3f204246 100644
--- a/pkg/cnab/provider/credentials.go
+++ b/pkg/cnab/provider/credentials.go
@@ -9,8 +9,8 @@ import (
 	"get.porter.sh/porter/pkg/encoding"
 	"get.porter.sh/porter/pkg/secrets"
 	"get.porter.sh/porter/pkg/storage"
-	"github.com/globalsign/mgo/bson"
 	"github.com/pkg/errors"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 func (r *Runtime) loadCredentials(b cnab.ExtendedBundle, args ActionArguments) (secrets.Set, error) {
diff --git a/pkg/credentials/credential_store.go b/pkg/credentials/credential_store.go
index be81e635..a1e1ce77 100644
--- a/pkg/credentials/credential_store.go
+++ b/pkg/credentials/credential_store.go
@@ -7,7 +7,6 @@ import (
 	"get.porter.sh/porter/pkg/secrets"
 	"get.porter.sh/porter/pkg/storage"
 	"github.com/cnabio/cnab-go/secrets/host"
-	"github.com/globalsign/mgo"
 	"github.com/hashicorp/go-multierror"
 	"github.com/pkg/errors"
 )
@@ -36,11 +35,8 @@ func NewCredentialStore(storage storage.Store, secrets secrets.Store) *Credentia
 func (s CredentialStore) Initialize() error {
 	// query credentials by namespace + name
 	err := s.Documents.EnsureIndex(CollectionCredentials, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "name"},
-			Unique:     true,
-			Background: true,
-		},
+		Keys:   []string{"namespace", "name"},
+		Unique: true,
 	})
 	return err
 }
diff --git a/pkg/parameters/parameter_store.go b/pkg/parameters/parameter_store.go
index 050451dc..ffa02e43 100644
--- a/pkg/parameters/parameter_store.go
+++ b/pkg/parameters/parameter_store.go
@@ -7,7 +7,6 @@ import (
 	"get.porter.sh/porter/pkg/secrets"
 	"get.porter.sh/porter/pkg/storage"
 	"github.com/cnabio/cnab-go/secrets/host"
-	"github.com/globalsign/mgo"
 	"github.com/hashicorp/go-multierror"
 	"github.com/pkg/errors"
 )
@@ -36,11 +35,8 @@ func NewParameterStore(storage storage.Store, secrets secrets.Store) *ParameterS
 func (s ParameterStore) Initialize() error {
 	// query parameters by namespace + name
 	err := s.Documents.EnsureIndex(CollectionParameters, storage.EnsureIndexOptions{
-		Index: mgo.Index{
-			Key:        []string{"namespace", "name"},
-			Unique:     true,
-			Background: true,
-		},
+		Keys:   []string{"namespace", "name"},
+		Unique: true,
 	})
 	return err
 }
diff --git a/pkg/porter/parameters.go b/pkg/porter/parameters.go
index 83ffa03c..74906091 100644
--- a/pkg/porter/parameters.go
+++ b/pkg/porter/parameters.go
@@ -14,7 +14,7 @@ import (
 	"get.porter.sh/porter/pkg/printer"
 	"get.porter.sh/porter/pkg/secrets"
 	"get.porter.sh/porter/pkg/storage"
-	"github.com/globalsign/mgo/bson"
+	"go.mongodb.org/mongo-driver/bson"
 
 	dtprinter "github.com/carolynvs/datetime-printer"
 	tablewriter "github.com/olekukonko/tablewriter"
diff --git a/pkg/storage/migrations/manager.go b/pkg/storage/migrations/manager.go
index 18f41165..335edef0 100644
--- a/pkg/storage/migrations/manager.go
+++ b/pkg/storage/migrations/manager.go
@@ -118,7 +118,7 @@ func (m *Manager) Aggregate(collection string, opts storage.AggregateOptions, ou
 	return m.store.Aggregate(collection, opts, out)
 }
 
-func (m *Manager) Count(collection string, opts storage.CountOptions) (int, error) {
+func (m *Manager) Count(collection string, opts storage.CountOptions) (int64, error) {
 	if err := m.Connect(); err != nil {
 		return 0, err
 	}
diff --git a/pkg/storage/plugin_adapter.go b/pkg/storage/plugin_adapter.go
index 67946200..871d678a 100644
--- a/pkg/storage/plugin_adapter.go
+++ b/pkg/storage/plugin_adapter.go
@@ -6,8 +6,8 @@ import (
 	"strings"
 
 	"get.porter.sh/porter/pkg/storage/plugins"
-	"github.com/globalsign/mgo/bson"
 	"github.com/pkg/errors"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 var _ Store = PluginAdapter{}
@@ -59,7 +59,7 @@ func (a PluginAdapter) EnsureIndex(collection string, opts EnsureIndexOptions) e
 	return a.plugin.EnsureIndex(opts.ToPluginOptions(collection))
 }
 
-func (a PluginAdapter) Count(collection string, opts CountOptions) (int, error) {
+func (a PluginAdapter) Count(collection string, opts CountOptions) (int64, error) {
 	err := a.Connect()
 	if err != nil {
 		return 0, err
@@ -115,7 +115,7 @@ func (a PluginAdapter) unmarshalSlice(bsonResults []bson.Raw, out interface{}) e
 	tmpResults := make([]bson.M, len(bsonResults))
 	for i, bsonResult := range bsonResults {
 		var result bson.M
-		err := bson.Unmarshal(bsonResult.Data, &result)
+		err := bson.Unmarshal(bsonResult, &result)
 		if err != nil {
 			return err
 		}
@@ -141,7 +141,7 @@ func (a PluginAdapter) unmarshal(bsonResult bson.Raw, out interface{}) error {
 	// We want to go from bson.Raw -> bson.M -> json -> out (typed struct)
 
 	var tmpResult bson.M
-	err := bson.Unmarshal(bsonResult.Data, &tmpResult)
+	err := bson.Unmarshal(bsonResult, &tmpResult)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/storage/plugins/mongodb/mongodb.go b/pkg/storage/plugins/mongodb/mongodb.go
index 45c5a365..0ed6eb20 100644
--- a/pkg/storage/plugins/mongodb/mongodb.go
+++ b/pkg/storage/plugins/mongodb/mongodb.go
@@ -1,15 +1,19 @@
 package mongodb
 
 import (
+	"context"
 	"fmt"
-	"net/url"
 	"strings"
+	"time"
 
-	"get.porter.sh/porter/pkg/context"
+	portercontext "get.porter.sh/porter/pkg/context"
 	"get.porter.sh/porter/pkg/storage/plugins"
-	"github.com/globalsign/mgo"
-	"github.com/globalsign/mgo/bson"
 	"github.com/pkg/errors"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"go.mongodb.org/mongo-driver/mongo/readpref"
+	"go.mongodb.org/mongo-driver/x/mongo/driver/connstring"
 )
 
 var (
@@ -19,235 +23,208 @@ var (
 
 // Store implements the Porter plugin.StoragePlugin interface for mongodb.
 type Store struct {
-	*context.Context
+	*portercontext.Context
 
 	url      string
 	database string
-	session  *mgo.Session
+	client   *mongo.Client
+	timeout  time.Duration
 }
 
 // NewStore creates a new storage engine that uses MongoDB.
-func NewStore(c *context.Context, cfg PluginConfig) *Store {
+func NewStore(c *portercontext.Context, cfg PluginConfig) *Store {
 	return &Store{
 		Context: c,
 		url:     cfg.URL,
+		timeout: time.Duration(cfg.Timeout) * time.Second,
 	}
 }
 
 func (s *Store) Connect() error {
-	if s.session != nil {
+	if s.client != nil {
 		return nil
 	}
 
-	host, port, db, err := parseConnectionString(s.url)
+	connStr, err := connstring.ParseAndValidate(s.url)
 	if err != nil {
-		return err
+		return errors.Wrapf(err, "invalid mongodb connection string %s", s.url)
 	}
-	if db == "" {
-		db = "porter"
+
+	if connStr.Database == "" {
+		s.database = "porter"
+	} else {
+		s.database = strings.TrimSuffix(connStr.Database, "/")
 	}
-	s.database = db
 
 	if s.Debug {
-		fmt.Fprintf(s.Err, "Connecting to mongo database %s at %s on %s\n", s.database, host, port)
+		fmt.Fprintf(s.Err, "Connecting to mongo database %s at %s\n", s.database, connStr.Hosts)
 	}
-	session, err := mgo.Dial(s.url)
+
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
+
+	client, err := mongo.Connect(cxt, options.Client().ApplyURI(s.url))
 	if err != nil {
 		return err
 	}
-	s.session = session
-	return nil
+
+	s.client = client
+	return s.Ping()
 }
 
 func (s *Store) Close() error {
-	if s.session != nil {
-		s.session.Close()
-		s.session = nil
+	if s.client != nil {
+		cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+		defer cancel()
+
+		s.client.Disconnect(cxt)
+		s.client = nil
 	}
 	return nil
 }
 
 // Ping the connected session to check if everything is okay.
 func (s *Store) Ping() error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
-	return session.Ping()
+	return s.client.Ping(cxt, readpref.Primary())
 }
 
 func (s *Store) Aggregate(opts plugins.AggregateOptions) ([]bson.Raw, error) {
-	session, err := s.copySession()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
+
+	// TODO(carolynvs): wrap each call with session.refresh  on error and a single retry
+	c := s.getCollection(opts.Collection)
+	cur, err := c.Aggregate(cxt, opts.Pipeline)
 	if err != nil {
 		return nil, err
 	}
-	defer session.Close()
 
-	// TODO(carolynvs): wrap each call with session.refresh  on error and a single retry
-	c := s.getCollection(session, opts.Collection)
 	var results []bson.Raw
-	err = c.Pipe(opts.Pipeline).All(&results)
+	for cur.Next(cxt) {
+		results = append(results, cur.Current)
+	}
 	return results, err
 }
 
 // EnsureIndexes makes sure that the specified indexes exist and are
 // defined appropriately.
 func (s *Store) EnsureIndex(opts plugins.EnsureIndexOptions) error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
+
+	c := s.getCollection(opts.Collection)
+	indexOpts := mongo.IndexModel{
+		Keys:    opts.Keys,
+		Options: options.Index(),
 	}
-	defer session.Close()
+	indexOpts.Options.SetUnique(opts.Unique)
+	indexOpts.Options.SetBackground(true)
 
-	c := s.getCollection(session, opts.Collection)
-	return c.EnsureIndex(opts.Index)
+	_, err := c.Indexes().CreateOne(cxt, indexOpts)
+	return err
 }
 
-func (s *Store) Count(opts plugins.CountOptions) (int, error) {
-	session, err := s.copySession()
-	if err != nil {
-		return 0, err
-	}
-	defer session.Close()
+func (s *Store) Count(opts plugins.CountOptions) (int64, error) {
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
-	c := s.getCollection(session, opts.Collection)
-	return c.Find(opts.Filter).Count()
+	c := s.getCollection(opts.Collection)
+	return c.CountDocuments(cxt, opts.Filter)
 }
 
 func (s *Store) Find(opts plugins.FindOptions) ([]bson.Raw, error) {
-	session, err := s.copySession()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
+
+	c := s.getCollection(opts.Collection)
+	findOpts := s.buildFindOptions(opts)
+	cur, err := c.Find(cxt, opts.Filter, findOpts)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrapf(err, "find failed:\n%#v\n%#v", opts.Filter, findOpts)
 	}
-	defer session.Close()
-
-	query := s.buildQuery(session, opts)
 
 	var results []bson.Raw
-	err = query.All(&results)
-	if err != nil {
-		return nil, errors.Wrapf(err, "find failed:\n%#v", opts)
+	for cur.Next(cxt) {
+		results = append(results, cur.Current)
 	}
 
 	return results, nil
 }
 
-func (s *Store) buildQuery(session *mgo.Session, opts plugins.FindOptions) *mgo.Query {
-	c := s.getCollection(session, opts.Collection)
-
-	var query *mgo.Query
-	if opts.Filter != nil {
-		query = c.Find(opts.Filter)
-	} else {
-		query = c.Find(bson.M{})
-	}
+func (s *Store) buildFindOptions(opts plugins.FindOptions) *options.FindOptions {
+	query := options.Find()
 
 	if opts.Select != nil {
-		query = query.Select(opts.Select)
+		query.SetProjection(opts.Select)
 	}
 
 	if opts.Limit > 0 {
-		query = query.Limit(opts.Limit)
+		query.SetLimit(opts.Limit)
 	}
 
 	if opts.Skip > 0 {
-		query = query.Skip(opts.Skip)
+		query.SetSkip(opts.Skip)
 	}
 
-	if len(opts.Sort) > 0 {
-		query = query.Sort(opts.Sort...)
+	if opts.Sort != nil {
+		query.SetSort(opts.Sort)
 	}
+
 	return query
 }
 
 func (s *Store) Insert(opts plugins.InsertOptions) error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
-	c := s.getCollection(session, opts.Collection)
-	return c.Insert(opts.Documents...)
+	c := s.getCollection(opts.Collection)
+	_, err := c.InsertMany(cxt, opts.Documents)
+	return err
 }
 
 func (s *Store) Patch(opts plugins.PatchOptions) error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
-	c := s.getCollection(session, opts.Collection)
-	return c.Update(opts.QueryDocument, opts.Transformation)
+	c := s.getCollection(opts.Collection)
+	_, err := c.UpdateOne(cxt, opts.QueryDocument, opts.Transformation)
+	return err
 }
 
 func (s *Store) Remove(opts plugins.RemoveOptions) error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
-	c := s.getCollection(session, opts.Collection)
+	c := s.getCollection(opts.Collection)
 	if opts.All {
-		_, err := c.RemoveAll(opts.Filter)
+		_, err := c.DeleteMany(cxt, opts.Filter)
 		return err
 	}
-	return c.Remove(opts.Filter)
+	_, err := c.DeleteOne(cxt, opts.Filter)
+	return err
 }
 
 func (s *Store) Update(opts plugins.UpdateOptions) error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
-	c := s.getCollection(session, opts.Collection)
-	if opts.Upsert {
-		_, err := c.Upsert(opts.Filter, opts.Document)
-		return err
-	}
-	return c.Update(opts.Filter, opts.Document)
+	c := s.getCollection(opts.Collection)
+	_, err := c.ReplaceOne(cxt, opts.Filter, opts.Document, &options.ReplaceOptions{Upsert: &opts.Upsert})
+	return err
 }
 
-func (s *Store) copySession() (*mgo.Session, error) {
-	if s.session == nil {
-		return nil, ErrNotConnected
-	}
-
-	return s.session.Copy(), nil
-}
-
-func (s *Store) getCollection(session *mgo.Session, collection string) *mgo.Collection {
-	return session.DB(s.database).C(collection)
+func (s *Store) getCollection(collection string) *mongo.Collection {
+	return s.client.Database(s.database).Collection(collection)
 }
 
 // RemoveDatabase removes the current database.
 func (s *Store) RemoveDatabase() error {
-	session, err := s.copySession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
+	cxt, cancel := context.WithTimeout(context.Background(), s.timeout)
+	defer cancel()
 
 	fmt.Fprintf(s.Err, "Dropping database %s!\n", s.database)
-	return session.DB(s.database).DropDatabase()
-}
-
-func parseConnectionString(dialStr string) (host string, port string, database string, err error) {
-	u, err := url.Parse(dialStr)
-	if err != nil {
-		return "", "", "", err
-	}
-
-	if u.Path != "" {
-		return u.Host, u.Port(), strings.Trim(u.Path, "/"), nil
-	}
-	// If this returns empty, then the driver is supposed to substitute in the
-	// default database.
-	return "", "", "", nil
+	return s.client.Database(s.database).Drop(cxt)
 }
diff --git a/pkg/storage/plugins/mongodb/plugin.go b/pkg/storage/plugins/mongodb/plugin.go
index 1a426303..c2aaf235 100644
--- a/pkg/storage/plugins/mongodb/plugin.go
+++ b/pkg/storage/plugins/mongodb/plugin.go
@@ -12,11 +12,14 @@ const PluginKey = plugins.PluginInterface + ".porter.mongodb"
 // PluginConfig are the configuration settings that can be defined for the
 // mongodb plugin in porter.yaml
 type PluginConfig struct {
-	URL string `mapstructure:"url"`
+	URL     string `mapstructure:"url"`
+	Timeout int    `mapstructure:"timeout,omitempty"`
 }
 
 func NewPlugin(cxt *context.Context, pluginConfig interface{}) (plugins.StoragePlugin, error) {
-	cfg := PluginConfig{}
+	cfg := PluginConfig{
+		Timeout: 2,
+	}
 	if err := mapstructure.Decode(pluginConfig, &cfg); err != nil {
 		return nil, errors.Wrapf(err, "error decoding %s plugin config from %#v", PluginKey, pluginConfig)
 	}
diff --git a/pkg/storage/plugins/mongodb_docker/plugin.go b/pkg/storage/plugins/mongodb_docker/plugin.go
index 4eb49f16..a784b9e6 100644
--- a/pkg/storage/plugins/mongodb_docker/plugin.go
+++ b/pkg/storage/plugins/mongodb_docker/plugin.go
@@ -12,8 +12,11 @@ const PluginKey = plugins.PluginInterface + ".porter.mongodb-docker"
 
 // PluginConfig supported by the mongodb-docker plugin as defined in porter.yaml
 type PluginConfig struct {
-	Port     string `mapstructure:"port"`
-	Database string `mapstructure:"database"`
+	Port     string `mapstructure:"port,omitempty"`
+	Database string `mapstructure:"database,omitempty"`
+
+	// Timeout in seconds
+	Timeout int `mapstructure:"timeout,omitempty"`
 }
 
 // NewPlugin creates an instance of the storage.porter.mongodb-docker plugin
@@ -21,6 +24,7 @@ func NewPlugin(cxt *context.Context, pluginConfig interface{}) (plugins.StorageP
 	cfg := PluginConfig{
 		Port:     "27018",
 		Database: "porter",
+		Timeout:  2,
 	}
 	if err := mapstructure.Decode(pluginConfig, &cfg); err != nil {
 		return nil, errors.Wrapf(err, "error decoding %s plugin config from %#v", PluginKey, pluginConfig)
diff --git a/pkg/storage/plugins/mongodb_docker/store.go b/pkg/storage/plugins/mongodb_docker/store.go
index dbd51fb3..6a8e50b0 100644
--- a/pkg/storage/plugins/mongodb_docker/store.go
+++ b/pkg/storage/plugins/mongodb_docker/store.go
@@ -41,7 +41,7 @@ func (s *Store) Connect() error {
 	container := "porter-mongodb-docker-plugin"
 	dataVol := container + "-data"
 
-	conn, err := EnsureMongoIsRunning(s.context, container, s.config.Port, dataVol, s.config.Database)
+	conn, err := EnsureMongoIsRunning(s.context, container, s.config.Port, dataVol, s.config.Database, s.config.Timeout)
 	if err != nil {
 		return err
 	}
@@ -53,10 +53,18 @@ func (s *Store) Connect() error {
 func (s *Store) Close() error {
 	// leave the container running for performance purposes
 	//exec.Command("docker", "rm", "-f", "porter-mongodb-docker-plugin")
+
+	// close the connection to the mongodb running in the container
+	if conn, ok := s.StorageProtocol.(*mongodb.Store); ok {
+		return conn.Close()
+	}
+
+	s.StorageProtocol = nil
+
 	return nil
 }
 
-func EnsureMongoIsRunning(c *portercontext.Context, container string, port string, dataVol string, dbName string) (*mongodb.Store, error) {
+func EnsureMongoIsRunning(c *portercontext.Context, container string, port string, dataVol string, dbName string, timeoutSeconds int) (*mongodb.Store, error) {
 	if dataVol != "" {
 		err := exec.Command("docker", "volume", "inspect", dataVol).Run()
 		if err != nil {
@@ -136,7 +144,8 @@ func EnsureMongoIsRunning(c *portercontext.Context, container string, port strin
 		fmt.Fprintln(c.Err, "waiting for the mongo service to be ready")
 	}
 	mongoPluginCfg := mongodb.PluginConfig{
-		URL: fmt.Sprintf("mongodb://localhost:%s/%s", port, dbName),
+		URL:     fmt.Sprintf("mongodb://localhost:%s/%s?connect=direct", port, dbName),
+		Timeout: timeoutSeconds,
 	}
 	timeout, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 	defer cancel()
@@ -148,10 +157,9 @@ func EnsureMongoIsRunning(c *portercontext.Context, container string, port strin
 			conn := mongodb.NewStore(c, mongoPluginCfg)
 			err := conn.Connect()
 			if err == nil {
-				_, err = conn.Find(plugins.FindOptions{Collection: "config"})
-				if err == nil {
-					return conn, nil
-				}
+				return conn, nil
+			} else if c.Debug {
+				fmt.Fprintln(c.Err, errors.Wrapf(err, "mongodb isn't ready yet"))
 			}
 		}
 	}
diff --git a/pkg/storage/plugins/storage_protocol.go b/pkg/storage/plugins/storage_protocol.go
index dde17e64..01288d2e 100644
--- a/pkg/storage/plugins/storage_protocol.go
+++ b/pkg/storage/plugins/storage_protocol.go
@@ -1,8 +1,7 @@
 package plugins
 
 import (
-	"github.com/globalsign/mgo"
-	"github.com/globalsign/mgo/bson"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 // StorageProtocol is the interface that storage plugins must implement.
@@ -17,7 +16,7 @@ type StorageProtocol interface {
 
 	// Count the number of results that match an optional query.
 	// When the query is omitted, the entire collection is counted.
-	Count(opts CountOptions) (int, error)
+	Count(opts CountOptions) (int64, error)
 
 	// Find queries a collection, optionally projecting a subset of fields, and
 	// then returns the results as a list of bson documents.
@@ -39,8 +38,9 @@ type StorageProtocol interface {
 // EnsureIndexOptions is the set of options available to the
 // StorageProtocol.EnsureIndex operation.
 type EnsureIndexOptions struct {
-	Collection string `bson:"collection"`
-	mgo.Index  `bson:",inline"`
+	Collection string      `bson:"collection"`
+	Keys       interface{} `json:"keys"`
+	Unique     bool        `json:"unique"`
 }
 
 // AggregateOptions is the set of options available to the
@@ -72,14 +72,13 @@ type FindOptions struct {
 	Collection string
 
 	// Sort is a list of field names by which the results should be sorted.
-	// Prefix a field with "-" to sort in reverse order.
-	Sort []string
+	Sort interface{}
 
 	// Skip is the number of results to skip past and exclude from the results.
-	Skip int
+	Skip int64
 
 	// Limit is the number of results to return.
-	Limit int
+	Limit int64
 
 	// Select is a projection document
 	// See https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
diff --git a/pkg/storage/pluginstore/rpc.go b/pkg/storage/pluginstore/rpc.go
index b1413963..5b4fda4f 100644
--- a/pkg/storage/pluginstore/rpc.go
+++ b/pkg/storage/pluginstore/rpc.go
@@ -4,7 +4,7 @@ import (
 	"net/rpc"
 
 	"get.porter.sh/porter/pkg/storage/plugins"
-	"github.com/globalsign/mgo/bson"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 var _ plugins.StorageProtocol = &Client{}
@@ -22,8 +22,8 @@ func (g *Client) Aggregate(opts plugins.AggregateOptions) ([]bson.Raw, error) {
 	return results, err
 }
 
-func (g *Client) Count(opts plugins.CountOptions) (int, error) {
-	var count int
+func (g *Client) Count(opts plugins.CountOptions) (int64, error) {
+	var count int64
 	args := map[string]interface{}{
 		"opts": opts,
 	}
@@ -90,7 +90,7 @@ func (s *Server) Aggregate(args map[string]interface{}, resp *[]bson.Raw) error
 	return err
 }
 
-func (s *Server) Count(args map[string]interface{}, resp *int) error {
+func (s *Server) Count(args map[string]interface{}, resp *int64) error {
 	var err error
 	*resp, err = s.Impl.Count(args["opts"].(plugins.CountOptions))
 	return err
diff --git a/pkg/storage/pluginstore/store.go b/pkg/storage/pluginstore/store.go
index a1439339..c978eb66 100644
--- a/pkg/storage/pluginstore/store.go
+++ b/pkg/storage/pluginstore/store.go
@@ -7,8 +7,8 @@ import (
 	"get.porter.sh/porter/pkg/storage/plugins"
 	"get.porter.sh/porter/pkg/storage/plugins/mongodb"
 	"get.porter.sh/porter/pkg/storage/plugins/mongodb_docker"
-	"github.com/globalsign/mgo/bson"
 	"github.com/pkg/errors"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 var _ plugins.StoragePlugin = &Store{}
@@ -107,7 +107,7 @@ func (s *Store) Aggregate(opts plugins.AggregateOptions) ([]bson.Raw, error) {
 	return s.plugin.Aggregate(opts)
 }
 
-func (s *Store) Count(opts plugins.CountOptions) (int, error) {
+func (s *Store) Count(opts plugins.CountOptions) (int64, error) {
 	if err := s.Connect(); err != nil {
 		return 0, err
 	}
diff --git a/pkg/storage/query.go b/pkg/storage/query.go
index 61ff5e3c..d64e9121 100644
--- a/pkg/storage/query.go
+++ b/pkg/storage/query.go
@@ -2,10 +2,10 @@ package storage
 
 import (
 	"encoding/json"
+	"strings"
 
 	"get.porter.sh/porter/pkg/storage/plugins"
-	"github.com/globalsign/mgo"
-	"github.com/globalsign/mgo/bson"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 // AggregateOptions is the set of options available to the Aggregate operation on any
@@ -25,13 +25,38 @@ func (o AggregateOptions) ToPluginOptions(collection string) plugins.AggregateOp
 
 // EnsureIndexOptions is the set of options available to the EnsureIndex operation.
 type EnsureIndexOptions struct {
-	mgo.Index
+	Keys   []string `json:"keys"`
+	Unique bool     `json:"unique"`
+}
+
+// Convert from a simplified sort specifier like []{"-key"}
+// to a mongodb sort document like []{{Key: "key", Value: -1}}
+func convertSortKeys(values []string) interface{} {
+	if len(values) == 0 {
+		return nil
+	}
+
+	keys := make(bson.D, len(values))
+	for i, key := range values {
+		sortKey := key
+		sortOrder := 1
+		if strings.HasPrefix(key, "-") {
+			sortKey = strings.Trim(key, "-")
+			sortOrder = -1
+		}
+		keys[i] = bson.E{
+			Key:   sortKey,
+			Value: sortOrder,
+		}
+	}
+	return keys
 }
 
 func (o EnsureIndexOptions) ToPluginOptions(collection string) plugins.EnsureIndexOptions {
 	return plugins.EnsureIndexOptions{
 		Collection: collection,
-		Index:      o.Index,
+		Keys:       convertSortKeys(o.Keys),
+		Unique:     o.Unique,
 	}
 }
 
@@ -44,6 +69,9 @@ type CountOptions struct {
 }
 
 func (o CountOptions) ToPluginOptions(collection string) plugins.CountOptions {
+	if o.Filter == nil {
+		o.Filter = bson.M{}
+	}
 	return plugins.CountOptions{
 		Collection: collection,
 		Filter:     o.Filter,
@@ -58,10 +86,10 @@ type FindOptions struct {
 	Sort []string
 
 	// Skip is the number of results to skip past and exclude from the results.
-	Skip int
+	Skip int64
 
 	// Limit is the number of results to return.
-	Limit int
+	Limit int64
 
 	// Filter specifies a filter the results.
 	// See https://docs.mongodb.com/manual/core/document/#std-label-document-query-filter
@@ -73,9 +101,12 @@ type FindOptions struct {
 }
 
 func (o FindOptions) ToPluginOptions(collection string) plugins.FindOptions {
+	if o.Filter == nil {
+		o.Filter = bson.M{}
+	}
 	return plugins.FindOptions{
 		Collection: collection,
-		Sort:       o.Sort,
+		Sort:       convertSortKeys(o.Sort),
 		Skip:       o.Skip,
 		Limit:      o.Limit,
 		Filter:     o.Filter,
diff --git a/pkg/storage/store.go b/pkg/storage/store.go
index 72b98c44..46c87221 100644
--- a/pkg/storage/store.go
+++ b/pkg/storage/store.go
@@ -14,7 +14,7 @@ type Store interface {
 
 	// Count the number of results that match an optional query.
 	// When the query is omitted, the entire collection is counted.
-	Count(collection string, opts CountOptions) (int, error)
+	Count(collection string, opts CountOptions) (int64, error)
 
 	// EnsureIndex makes sure that the specified index exists as specified.
 	// If it does exist with a different definition, the index is recreated.


Test patch:
diff --git a/pkg/claims/claimstore_test.go b/pkg/claims/claimstore_test.go
index 55d5211a..68b1670f 100644
--- a/pkg/claims/claimstore_test.go
+++ b/pkg/claims/claimstore_test.go
@@ -259,6 +259,7 @@ func TestClaimStore_Run(t *testing.T) {
 
 func TestClaimStore_Results(t *testing.T) {
 	cp := generateClaimData(t)
+	defer cp.Teardown()
 
 	barRuns, err := cp.ListRuns("dev", "bar")
 	require.NoError(t, err, "ListRuns failed")
@@ -291,6 +292,7 @@ func TestClaimStore_Results(t *testing.T) {
 
 func TestClaimStore_Outputs(t *testing.T) {
 	cp := generateClaimData(t)
+	defer cp.Teardown()
 
 	fooRuns, err := cp.ListRuns("dev", "foo")
 	require.NoError(t, err, "ListRuns failed")
diff --git a/pkg/storage/plugins/testplugin/plugin.go b/pkg/storage/plugins/testplugin/plugin.go
index 91fe28de..100d9b8c 100644
--- a/pkg/storage/plugins/testplugin/plugin.go
+++ b/pkg/storage/plugins/testplugin/plugin.go
@@ -58,7 +58,7 @@ func (s *TestStoragePlugin) Setup() error {
 
 func (s *TestStoragePlugin) useDevDatabase() error {
 	cfg := mongodb.PluginConfig{
-		URL: fmt.Sprintf("mongodb://localhost:27017/%s", s.database),
+		URL: fmt.Sprintf("mongodb://localhost:27017/%s?connect=direct", s.database),
 	}
 	devMongo := mongodb.NewStore(s.tc.Context, cfg)
 	err := devMongo.Connect()
@@ -76,7 +76,7 @@ func (s *TestStoragePlugin) useDevDatabase() error {
 }
 
 func (s *TestStoragePlugin) runTestDatabase() error {
-	testMongo, err := mongodb_docker.EnsureMongoIsRunning(s.tc.Context, "porter-test-mongodb-plugin", "27017", "", s.database)
+	testMongo, err := mongodb_docker.EnsureMongoIsRunning(s.tc.Context, "porter-test-mongodb-plugin", "27017", "", s.database, 10)
 	if err != nil {
 		return err
 	}
@@ -86,10 +86,9 @@ func (s *TestStoragePlugin) runTestDatabase() error {
 
 // Teardown stops the test mongo instance and cleans up any temporary files.
 func (s *TestStoragePlugin) Teardown() error {
-	s.Close()
-
 	if s.Store != nil {
-		return s.Store.RemoveDatabase()
+		s.Store.RemoveDatabase()
+		return s.Close()
 	}
 	return nil
 }
@@ -99,11 +98,11 @@ func (s *TestStoragePlugin) Connect() error {
 	return s.Setup()
 }
 
-// Close does nothing, keep an open connection to the test database until the
-// test is torn down.
+// Close the connection to the database.
 func (s *TestStoragePlugin) Close() error {
-	// do nothing
-	return nil
+	err := s.Store.Close()
+	s.Store = nil
+	return err
 }
 
 func generateDatabaseName(testName string) string {
diff --git a/pkg/storage/query_test.go b/pkg/storage/query_test.go
index 9611bacc..5950596f 100644
--- a/pkg/storage/query_test.go
+++ b/pkg/storage/query_test.go
@@ -4,7 +4,9 @@ import (
 	"encoding/json"
 	"testing"
 
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 var _ Document = TestDocument{}
@@ -59,3 +61,14 @@ func TestUpdateOptions_ToPluginOptions(t *testing.T) {
 	wantRawDoc := map[string]interface{}{"_id": "aid", "name": "a"}
 	require.Equal(t, wantRawDoc, gotOpts.Document)
 }
+
+func TestFindOptions_ToPluginOptions(t *testing.T) {
+	so := FindOptions{
+		Sort: []string{"-_id", "name"},
+	}
+	po := so.ToPluginOptions("mythings")
+	wantSortDoc := bson.D{
+		bson.E{Key: "_id", Value: -1},
+		bson.E{Key: "name", Value: 1}}
+	assert.Equal(t, wantSortDoc, po.Sort)
+}
diff --git a/tests/smoke/main_test.go b/tests/smoke/main_test.go
index e6b6a9e4..abe274c1 100644
--- a/tests/smoke/main_test.go
+++ b/tests/smoke/main_test.go
@@ -75,7 +75,7 @@ func NewTest(t *testing.T) (Test, error) {
 
 func (t Test) startMongo() error {
 	c := context.NewTestContext(t.T)
-	conn, err := mongodb_docker.EnsureMongoIsRunning(c.Context, "porter-smoke-test-mongodb-plugin", "27017", "", "porter-smoke-test")
+	conn, err := mongodb_docker.EnsureMongoIsRunning(c.Context, "porter-smoke-test-mongodb-plugin", "27017", "", "porter-smoke-test", 2)
 	defer conn.Close()
 	if err != nil {
 		return err
diff --git a/tests/smoke/testdata/config.toml b/tests/smoke/testdata/config.toml
index 6847e684..9b35ac8e 100644
--- a/tests/smoke/testdata/config.toml
+++ b/tests/smoke/testdata/config.toml
@@ -10,4 +10,4 @@ build-driver = "buildkit"
   plugin = "mongodb"
 
 [storage.config]
-  url = "mongodb://localhost:27017/porter-smoke-test"
+  url = "mongodb://localhost:27017/porter-smoke-test?connect=direct"