Permalink
Browse files

added tag to autologin to dbconsole

  • Loading branch information...
1 parent aac11c7 commit 10fda78ca279ea0a277601d07758df78bef3c02a @burtbeckwith burtbeckwith committed Sep 27, 2011
View
@@ -4,7 +4,9 @@
<classpathentry kind="src" path="src/groovy"/>
<classpathentry kind="src" path="src/docs"/>
<classpathentry kind="src" path="grails-app/conf"/>
+ <classpathentry kind="src" path="grails-app/taglib"/>
<classpathentry kind="src" path="scripts"/>
+ <classpathentry kind="src" path="test/integration"/>
<classpathentry kind="src" path="test/unit"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="com.springsource.sts.grails.core.CLASSPATH_CONTAINER"/>
View
@@ -60,7 +60,6 @@
<delete dir='grails-app/domain'/>
<delete dir='grails-app/i18n'/>
<delete dir='grails-app/services'/>
- <delete dir='grails-app/taglib'/>
<delete dir='grails-app/utils'/>
<delete dir='grails-app/views'/>
<delete dir='web-app'/>
@@ -0,0 +1,128 @@
+/* Copyright 2011 SpringSource.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package grails.plugin.cloudfoundry
+
+import grails.converters.JSON
+
+import java.util.Map
+
+/**
+ * @author Burt Beckwith
+ */
+class CloudFoundryTagLib {
+
+ static namespace = 'cf'
+
+ def grailsApplication
+ def pluginManager
+
+ /**
+ * Creates a link that opens the H2 database console using connect information from VCAP_SERVICES.
+ *
+ * @attr name if specified the link will be for that service, otherwise the first JDBC service will be used
+ * @attr consolePath optional - the root of the uri to the console; usually not necessary but useful if you have a url mapping
+ */
+ def dbconsoleLink = { attrs, body ->
+
+ String name = attrs.name ?: null
+ def connectInfo = findDbConnectInfo(name)
+ if (!connectInfo) {
+ if (name) {
+ log.warn "No service found with name '$name'"
+ }
+ else {
+ log.warn "No MySQL or PostgreSQL service found"
+ }
+ return
+ }
+
+ String dbDriver = URLEncoder.encode(connectInfo.driver, 'UTF-8')
+ String dbUrl = URLEncoder.encode(connectInfo.url, 'UTF-8')
+ String dbUser = URLEncoder.encode(connectInfo.user, 'UTF-8')
+ String dbPassword = URLEncoder.encode(connectInfo.password, 'UTF-8')
+
+ String consolePath
+ if (attrs.consolePath) {
+ consolePath = attrs.consolePath
+ }
+ else {
+ if (pluginManager.hasGrailsPlugin('dbconsole')) {
+ // not configurable in the plugin
+ consolePath = '/dbconsole'
+ }
+ else {
+ consolePath = grailsApplication.config.grails.dbconsole.urlRoot ?: '/dbconsole'
+ }
+ }
+
+ out << """<a href='javascript:void(0)' onclick='openDbConsole()'>${body()}</a>
+<script>
+function openDbConsole() {
+ \$.get('${request.contextPath}$consolePath/login.do', function(html) {
+ var start = html.indexOf('login.jsp?jsessionid=');
+ var end = html.indexOf("'", start + 1);
+ var jsessionid = html.substring(start + 21, end);
+ location.href = '${request.contextPath}$consolePath/login.do?driver=${dbDriver}&url=${dbUrl}&user=${dbUser}&password=${dbPassword}&jsessionid=' + jsessionid;
+ });
+}
+</script>
+"""
+ }
+
+ private Map findDbConnectInfo(String name, boolean multiple = false) {
+ // put in TreeMap to make order predictable for testing
+ def servicesMap = new TreeMap(JSON.parse(System.getenv('VCAP_SERVICES')))
+
+ for (entry in servicesMap) {
+ String key = entry.key
+ def services = entry.value
+ String type
+ String driver
+ if (key.startsWith('mysql')) {
+ type = 'mysql'
+ driver = 'com.mysql.jdbc.Driver'
+ }
+ else if (key.startsWith('postgresql')) {
+ type = 'postgresql'
+ driver = 'org.postgresql.Driver'
+ }
+ else {
+ continue
+ }
+
+ def maps = []
+ for (service in services) {
+ if (name == null || name.equals(service.name)) {
+ def data = [
+ url: "jdbc:$type://$service.credentials.hostname:$service.credentials.port/$service.credentials.name",
+ user: service.credentials.user,
+ password: service.credentials.password,
+ driver: driver]
+
+ if (multiple) {
+ maps << data
+ }
+ else {
+ return data
+ }
+ }
+ }
+
+ if (multiple) {
+ return maps
+ }
+ }
+ }
+}
@@ -0,0 +1,114 @@
+package grails.plugin.cloudfoundry
+
+import grails.test.GroovyPagesTestCase
+
+class CloudFoundryTagLibTests extends GroovyPagesTestCase {
+
+ static transactional = false
+
+ private realSystemMetaclass
+
+ private static final String JSON = '''
+{"redis-2.2":
+ [{"name":"redis-1d8e28a",
+ "label":"redis-2.2",
+ "plan":"free",
+ "credentials":{
+ "node_id":"redis_node_3",
+ "hostname":"172.30.48.42",
+ "port":5004,
+ "password":"1463d9d0-4e35-4f2e-be2f-01dc5536f183",
+ "name":"redis-1a69a915-6522-496c-93d5-1271d2b3118e"}
+ }],
+ "mongodb-1.8":
+ [{"name":"mongodb-3854dbe",
+ "label":"mongodb-1.8",
+ "plan":"free",
+ "credentials":{
+ "hostname":"172.30.48.63",
+ "port":25003,
+ "username":"b6877670-da98-4124-85ca-84357f042797",
+ "password":"f53e6a4b-f4b8-497d-ac81-43cb22cf1e88",
+ "name":"mongodb-9dda2cfb-9672-4d58-8786-98c3abcb21ec",
+ "db":"db"}
+ }],
+ "mysql-5.1":
+ [{"name":"mysql-service",
+ "label":"mysql-5.1",
+ "plan":"free",
+ "credentials":{
+ "node_id":"mysql_node_8",
+ "hostname":"mysql_server",
+ "port":4321,
+ "password":"mysql_password",
+ "name":"mysql_database",
+ "user":"mysql_user"}
+ }],
+ "postgresql-9":
+ [{"name":"postgres-service",
+ "label":"postgres-9",
+ "plan":"free",
+ "credentials":{
+ "node_id":"postgres_node_8",
+ "hostname":"postgresql_server",
+ "port":1234,
+ "password":"postgresql_password",
+ "name":"postgresql_database",
+ "user":"postgresql_user"}
+ }]
+}
+'''
+
+ @Override
+ protected void setUp() {
+ super.setUp()
+
+ //registerMetaClass isn't available
+ realSystemMetaclass = System.metaClass
+ def emc = new ExpandoMetaClass(System, true, true)
+ emc.initialize()
+ GroovySystem.metaClassRegistry.setMetaClass(System, emc)
+
+ System.getenv('VCAP_SERVICES')
+ System.metaClass.static.getenv = { String name -> JSON }
+ }
+
+ @Override
+ protected void tearDown() {
+ super.tearDown()
+ GroovySystem.metaClassRegistry.removeMetaClass(System)
+ GroovySystem.metaClassRegistry.setMetaClass(System, realSystemMetaclass)
+ }
+
+ void testNoName() {
+ String output = applyTemplate('<cf:dbconsoleLink>MySQL DbConsole</cf:dbconsoleLink>')
+
+ assertTrue output.contains("<a href='javascript:void(0)' onclick='openDbConsole()'>MySQL DbConsole</a>")
+
+ assertTrue output.contains(
+ "location.href = '/dbconsole/login.do" +
+ "?driver=com.mysql.jdbc.Driver" +
+ "&url=jdbc%3Amysql%3A%2F%2Fmysql_server%3A4321%2Fmysql_database" +
+ "&user=mysql_user" +
+ "&password=mysql_password" +
+ "&jsessionid=' + jsessionid;")
+ }
+
+ void testBadName() {
+ assertOutputEquals('', '<cf:dbconsoleLink name="flongle">Foo</cf:dbconsoleLink>')
+ }
+
+ void testGoodName() {
+ String output = applyTemplate('<cf:dbconsoleLink name="postgres-service">PostgreSQL DbConsole</cf:dbconsoleLink>')
+
+ assertTrue output.contains("<a href='javascript:void(0)' onclick='openDbConsole()'>PostgreSQL DbConsole</a>")
+
+ assertTrue output.contains(
+ "location.href = '/dbconsole/login.do" +
+ "?driver=org.postgresql.Driver" +
+ "&url=jdbc%3Apostgresql%3A%2F%2Fpostgresql_server%3A1234%2Fpostgresql_database" +
+ "&user=postgresql_user" +
+ "&password=postgresql_password" +
+ "&jsessionid=' + jsessionid;")
+ }
+}

0 comments on commit 10fda78

Please sign in to comment.