Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

MongoURI support #8

Merged
merged 1 commit into from

2 participants

Juan M Uys Leon Radley
Leon Radley
Owner

Great, I'll have a look at merging this in the upcoming 1.0.4 release :)

Leon Radley leon merged commit ae278a7 into from
Leon Radley
Owner

I've implemented mongoURI now, I've pushed 1.0.4-SNAPSHOT
Give it a go and tell me if anything isn't working as expected.

Thanks to the specs, there should't be any surprises :)

Leon Radley
Owner

I've also added travis-ci

http://travis-ci.org/#!/leon/play-salat

Juan M Uys

Brilliant, thanks Leon :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 22, 2012
  1. Juan M Uys

    Add MongoURI support

    opyate authored
This page is out of date. Refresh to see the latest.
83 src/main/scala/se/radley/plugin/salat/SalatPlugin.scala
View
@@ -3,7 +3,7 @@ package se.radley.plugin.salat
import play.api._
import play.api.mvc._
import play.api.Play.current
-import com.mongodb.casbah.{WriteConcern, MongoCollection, MongoConnection}
+import com.mongodb.casbah.{WriteConcern, MongoCollection, MongoConnection, MongoURI}
import com.mongodb.ServerAddress
class SalatPlugin(app: Application) extends Plugin {
@@ -39,26 +39,71 @@ class SalatPlugin(app: Application) extends Plugin {
"/" + db
}
}
+
+ /**
+ * Extracts host as String and port as Int from host string
+ * and defaults port to 27017 if it doesn't exist.
+ *
+ * E.g. localhost:9999 returns (localhost, 9999)
+ * E.g. localhost returns (localhost, 27017)
+ */
+ def hostAndPort(host: String): (String, Int) = host.contains(':') match {
+ case true => {
+ val Array(h,p) = host.split(':')
+ (h,p.toInt)
+ }
+ case false => (host, 27017)
+ }
lazy val sources: Map[String, MongoSource] = configuration.subKeys.map { sourceKey =>
val source = configuration.getConfig(sourceKey).getOrElse(Configuration.empty)
- val db = source.getString("db").getOrElse(throw configuration.reportError("mongodb." + sourceKey + ".db", "db missing for source[" + sourceKey + "]"))
-
- // Simple config
- val host = source.getString("host").getOrElse("127.0.0.1")
- val port = source.getInt("port").getOrElse(27017)
- val user:Option[String] = source.getString("user")
- val password:Option[String] = source.getString("password")
-
- // Replica set config
- val hosts: List[ServerAddress] = source.getConfig("replicaset").map { replicaset =>
- replicaset.subKeys.map { hostKey =>
- val c = replicaset.getConfig(hostKey).get
- val host = c.getString("host").getOrElse(throw configuration.reportError("mongodb." + sourceKey + ".replicaset", "host missing for replicaset in source[" + sourceKey + "]"))
- val port = c.getInt("port").getOrElse(27017)
- new ServerAddress(host, port)
- }.toList
- }.getOrElse(List.empty)
+
+ // support MongoURI as per http://www.mongodb.org/display/DOCS/Connections
+ val (host, port, user, password, hosts, db) = source.getString("uri").map{ uri => {
+ val all = MongoURI(uri)
+ val (host,port) = hostAndPort(all.hosts(0))
+ val user = all.username match {
+ case "null" => None
+ case null => None
+ case s => Some(s)
+ }
+
+ val password = all.password match {
+ case null => None
+ case s => all.password.foldLeft("")(_ + _.toString) match {
+ case "" => None
+ case s => Some(s)
+ }
+ }
+
+ // to List[ServerAddress]
+ val hosts = all.hosts.map(host => {
+ val (h,p) = hostAndPort(host)
+ new ServerAddress(h, p)
+ })
+
+ (host, port, user, password, hosts.toList, all.database)
+ }}.getOrElse{
+ val db = source.getString("db").getOrElse(throw configuration.reportError("mongodb." + sourceKey + ".db", "db missing for source[" + sourceKey + "]"))
+
+ // Simple config
+ val host = source.getString("host").getOrElse("127.0.0.1")
+ val port = source.getInt("port").getOrElse(27017)
+ val user:Option[String] = source.getString("user")
+ val password:Option[String] = source.getString("password")
+
+ // Replica set config
+ val hosts: List[ServerAddress] = source.getConfig("replicaset").map { replicaset =>
+ replicaset.subKeys.map { hostKey =>
+ val c = replicaset.getConfig(hostKey).get
+ val host = c.getString("host").getOrElse(throw configuration.reportError("mongodb." + sourceKey + ".replicaset", "host missing for replicaset in source[" + sourceKey + "]"))
+ val port = c.getInt("port").getOrElse(27017)
+ new ServerAddress(host, port)
+ }.toList
+ }.getOrElse(List.empty)
+
+ (host, port, user, password, hosts, db)
+ }
val writeConcern = WriteConcern.valueOf(source.getString("writeconcern", Some(Set("fsyncsafe", "replicassafe", "safe", "normal"))).getOrElse("safe"))
@@ -66,7 +111,7 @@ class SalatPlugin(app: Application) extends Plugin {
if (hosts.isEmpty)
sourceKey -> MongoSource(List(new ServerAddress(host, port)), db, writeConcern, user, password)
else
- sourceKey -> MongoSource(hosts, db, writeConcern)
+ sourceKey -> MongoSource(hosts, db, writeConcern, user, password)
}.toMap
override def enabled = !configuration.subKeys.isEmpty
103 src/test/scala/se/radley/plugin/salat/SalatSpec.scala
View
@@ -29,6 +29,27 @@ object SalatSpec extends Specification {
("mongodb.default.replicaset.host2.host" -> "10.0.0.2")
)
)
+
+ lazy val fakeAppFromURI = FakeApplication(
+ additionalPlugins = Seq("se.radley.plugin.salat.SalatPlugin"),
+ additionalConfiguration = Map(
+ ("mongodb.default.uri" -> "mongodb://127.0.0.1:27017/salat-test")
+ )
+ )
+
+ lazy val fakeAppFromURIs = FakeApplication(
+ additionalPlugins = Seq("se.radley.plugin.salat.SalatPlugin"),
+ additionalConfiguration = Map(
+ ("mongodb.default.uri" -> "mongodb://127.0.0.1:27017,mongodb.org:1337/salat-test")
+ )
+ )
+
+ lazy val fakeAppFromURIsWithAuth = FakeApplication(
+ additionalPlugins = Seq("se.radley.plugin.salat.SalatPlugin"),
+ additionalConfiguration = Map(
+ ("mongodb.default.uri" -> "mongodb://nyancat:ILoveMyKittens@127.0.0.1:27017,mongodb.org:1337,192.168.88.99:27000/salat-test")
+ )
+ )
def salat = fakeApp.plugin[SalatPlugin].get
@@ -76,5 +97,87 @@ object SalatSpec extends Specification {
salat.collection("salat-collection", "sourcethatdoesntexist") must throwAn[PlayException]
}
}
+
+ // tests with a single URI defined
+ "start with URI only" in {
+ running(fakeAppFromURI) {
+ salat must beAnInstanceOf[SalatPlugin]
+ }
+ }
+
+ "return a MongoCollection with URI only" in {
+ running(fakeAppFromURI) {
+ val col = salat.collection("salat-collection")
+ col must beAnInstanceOf[MongoCollection]
+ }
+ }
+
+ "set replicasets with URI only" in {
+ running(fakeAppFromURI) {
+ def s = fakeAppFromURI.plugin[SalatPlugin].get
+ s must beAnInstanceOf[SalatPlugin]
+ val source = s.source("default")
+ source.hosts must equalTo(List(new ServerAddress("127.0.0.1", 27017)))
+ }
+ }
+
+ // tests with multiple URIs defined
+ "start with URIs only" in {
+ running(fakeAppFromURIs) {
+ salat must beAnInstanceOf[SalatPlugin]
+ }
+ }
+
+ "return a MongoCollection with URIs only" in {
+ running(fakeAppFromURIs) {
+ val col = salat.collection("salat-collection")
+ col must beAnInstanceOf[MongoCollection]
+ }
+ }
+
+ "set replicasets with URIs only" in {
+ running(fakeAppFromURIs) {
+ def s = fakeAppFromURIs.plugin[SalatPlugin].get
+ s must beAnInstanceOf[SalatPlugin]
+ val source = s.source("default")
+ source.hosts must equalTo(List(new ServerAddress("127.0.0.1", 27017), new ServerAddress("mongodb.org", 1337)))
+ }
+ }
+
+ // tests with multiple authenticated URIs defined
+ "start with authenticated URIs only" in {
+ running(fakeAppFromURIsWithAuth) {
+ salat must beAnInstanceOf[SalatPlugin]
+ }
+ }
+
+ "return a MongoCollection with authenticated URIs only" in {
+ running(fakeAppFromURIsWithAuth) {
+ val col = salat.collection("salat-collection")
+ col must beAnInstanceOf[MongoCollection]
+ }
+ }
+
+ "set replicasets with authenticated URIs only" in {
+ running(fakeAppFromURIsWithAuth) {
+ def s = fakeAppFromURIsWithAuth.plugin[SalatPlugin].get
+ s must beAnInstanceOf[SalatPlugin]
+ val source = s.source("default")
+ source.hosts must equalTo(List(new ServerAddress("127.0.0.1", 27017),
+ new ServerAddress("mongodb.org", 1337),
+ new ServerAddress("192.168.88.99", 27000)
+ ))
+ }
+ }
+
+ "should propagate authentication credentials" in {
+ running(fakeAppFromURIsWithAuth) {
+ def s = fakeAppFromURIsWithAuth.plugin[SalatPlugin].get
+ s must beAnInstanceOf[SalatPlugin]
+ val source = s.source("default")
+ source.user must equalTo(Some("nyancat"))
+ source.password must equalTo(Some("ILoveMyKittens"))
+ }
+ }
}
}
Something went wrong with that request. Please try again.