diff --git a/lib/liberty_buildpack/services/compose_mysql.rb b/lib/liberty_buildpack/services/compose_mysql.rb new file mode 100644 index 000000000..1a1f3710d --- /dev/null +++ b/lib/liberty_buildpack/services/compose_mysql.rb @@ -0,0 +1,102 @@ +# Encoding: utf-8 +# IBM WebSphere Application Server Liberty Buildpack +# Copyright 2014 the original author or authors. +# +# 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. + +require 'base64' +require 'rexml/document' +require 'liberty_buildpack/services/client_jar_utils' +require 'liberty_buildpack/services/mysql' + +module LibertyBuildpack::Services + + #------------------------------------------------------------------------------------ + # The ComposeMySQL class is the class for Compose for MySQL relational database resources. + #------------------------------------------------------------------------------------ + class ComposeMySQL < MySQL + + #------------------------------------------------------------------------------------ + # Initialize + # + # @param type - the vcap_services type + # @param config - a hash containing the configuration data from the yml file. + #------------------------------------------------------------------------------------ + def initialize(type, config, context) + super(type, config) + @config_type = 'compose-mysql' + @app_dir = context[:app_dir] + end + + #----------------------------------------------------------------------------------------- + # parse the vcap services and create cloud properties + # + # @param element - the root element of the REXML document for runtime-vars.xml + # @param instance - the hash containing the vcap_services data for this instance + #------------------------------------------------------------------------------------------ + def parse_vcap_services(element, instance) + super + + credentials = instance['credentials'] || {} + + # fix the database name as the relational_db uses 'name' from vcap_services + # which does not match the actual database name in compose + service_uri = credentials['uri'] + uri = URI.parse(service_uri) + db_var_name = "cloud.services.#{@service_name}.connection.db" + new_element = REXML::Element.new('variable', element) + new_element.add_attribute('name', db_var_name) + new_element.add_attribute('value', uri.path[1..-1]) + @db_name = "${#{db_var_name}}" + + @mysql_url = 'jdbc:' + URI::Generic.build( + scheme: 'mysql', + host: uri.host, + path: uri.path, + port: uri.port, + query: "useSSL=true&serverSslCert=/home/vcap/app/#{CRT_DIRECTORY}/#{CRT_FILE}" + ).to_s + + @service_cert = credentials['ca_certificate_base64'] + raise "Resource #{@service_name} does not contain a #{conn_prefix}uri property" if @service_cert.nil? + end + + protected + + #------------------------------------------------------------------------------------ + # Method to customize properties - called on create or update. + # + # @param properties_element - the properties element + #------------------------------------------------------------------------------------ + def modify_properties(properties_element) + save_cert + + properties_element.add_attribute('url', @mysql_url) + end + + private + + CRT_DIRECTORY = '.compose_mysql'.freeze + + CRT_FILE = 'cacert.pem'.freeze + + def save_cert + cert_dir = File.join(@app_dir, CRT_DIRECTORY) + FileUtils.mkdir_p(cert_dir) + cert_file = File.join(cert_dir, CRT_FILE) + File.open(cert_file, 'w+') { |f| f.write(Base64.decode64(@service_cert)) } + end + + end + +end diff --git a/lib/liberty_buildpack/services/config/compose_mysql.yml b/lib/liberty_buildpack/services/config/compose_mysql.yml new file mode 100644 index 000000000..b4c9d3766 --- /dev/null +++ b/lib/liberty_buildpack/services/config/compose_mysql.yml @@ -0,0 +1,35 @@ +# IBM WebSphere Application Server Liberty Buildpack +# Copyright 2014 the original author or authors. +# +# 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. + +# Service configuration +--- +# attributes required by all service plugins +class_name : LibertyBuildpack::Services::ComposeMySQL +class_file : compose_mysql.rb +server_xml_stanza : dataSource +service_filter : 'compose-for-mysql' + +# plugin specific attributes +features: + if: ['jdbc-4.0'] + then: [] + else: ['jdbc-4.1'] + +client_jars : 'mariadb-java-client*.jar|mysql-connector-java*.jar' +connection_pool_size : -1 + +driver: + version: 1.+ + repository_root: "https://download.run.pivotal.io/mariadb-jdbc" diff --git a/lib/liberty_buildpack/services/config/mysql.yml b/lib/liberty_buildpack/services/config/mysql.yml index 386e8e2dc..b21d2a512 100644 --- a/lib/liberty_buildpack/services/config/mysql.yml +++ b/lib/liberty_buildpack/services/config/mysql.yml @@ -19,10 +19,10 @@ class_name : LibertyBuildpack::Services::MySQL class_file : mysql.rb server_xml_stanza : dataSource -service_filter : 'mysql|cleardb' +service_filter : '(?' + expected_vars << '' + expected_vars << '' + expected_vars << '' + expected_vars << '' + expected_vars << '' + expected_vars << '' + + runtime_vars = File.join(root, 'runtime-vars.xml') + validate_xml(runtime_vars, expected_vars) + end + + def check_server_xml_create(root, sm) + server_xml = File.join(root, 'server.xml') + server_xml_doc = REXML::Document.new('') + sm.update_configuration(server_xml_doc, true, root) + File.open(server_xml, 'w') { |file| server_xml_doc.write(file) } + + expected_config = [] + expected_config << 'jdbc-4.1' + t1 = "" + t2 = "" + t3 = '' + expected_config << t1 + t2 + t3 + driver_info = "javax.sql.ConnectionPoolDataSource='org.mariadb.jdbc.MySQLDataSource' javax.sql.XADataSource='org.mariadb.jdbc.MySQLDataSource'" + expected_config << "" + expected_config << "" + + validate_xml(server_xml, expected_config) + end + + def check_server_xml_update(root, sm) + driver_info = "javax.sql.ConnectionPoolDataSource='org.mariadb.jdbc.MySQLDataSource' javax.sql.XADataSource='org.mariadb.jdbc.MySQLDataSource'" + + contents = [] + contents << '' + contents << 'jsp-2.2' + t1 = "" + t2 = "" + t3 = '' + contents << t1 + t2 + t3 + contents << "" + contents << "" + contents << '' + + server_xml_doc = REXML::Document.new(contents.join) + server_xml = File.join(root, 'server.xml') + sm.update_configuration(server_xml_doc, false, root) + + File.open(server_xml, 'w') { |file| server_xml_doc.write(file) } + + # check if dataSource properties and library were updated. Other elements should not be updated. + expected_config = [] + expected_config << 'jsp-2.2' + expected_config << 'jdbc-4.1' + t1 = "" + t2 = "" + t3 = '' + expected_config << t1 + t2 + t3 + expected_config << "" + expected_config << "" + validate_xml(server_xml, expected_config) + end + + def run_test(vcap_services) + Dir.mktmpdir do |root| + context = { app_dir: root } + sm = LibertyBuildpack::Container::ServicesManager.new(vcap_services, root, nil, context) + check_variables(root, vcap_services) + check_server_xml_create(root, sm) + check_server_xml_update(root, sm) + end + end + + it 'on Bluemix (compose for mysql)' do + vcap_services = {} + mysql = {} + mysql['name'] = 'myDatabase' + mysql['label'] = 'compose-for-mysql' + mysql_credentials = {} + mysql_credentials['name'] = 'foobar' + mysql_credentials['uri'] = 'mysql://myUser:myPassword@myHost.com:5432/myDb' + mysql_credentials['ca_certificate_base64'] = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNDVENDQVkrZ0F3SUJBZ0lRYUVwWWNJQnI4SThDK3ZiZTZMQ1FrREFLQmdncWhrak9QUVFEQXpCR01Rc3dDUVlEVlFRR0V3SkQKVGpFYU1CZ0dBMVVFQ2hNUlYyOVRhV2R1SUVOQklFeHBiV2wwWldReEd6QVpCZ05WQkFNVEVrTkJJRmR2VTJsbmJpQkZRME1nVW05dgpkREFlRncweE5ERXhNRGd3TURVNE5UaGFGdzAwTkRFeE1EZ3dNRFU0TlRoYU1FWXhDekFKQmdOVkJBWVRBa05PTVJvd0dBWURWUVFLCkV4RlhiMU5wWjI0Z1EwRWdUR2x0YVhSbFpERWJNQmtHQTFVRUF4TVNRMEVnVjI5VGFXZHVJRVZEUXlCU2IyOTBNSFl3RUFZSEtvWkkKemowQ0FRWUZLNEVFQUNJRFlnQUU0ZjJPdUVNa3E1WjdoY0s2QzYyTjREcmpKTG5Tc2I2SU9zcS9Tcmo1N3l3dnIxRlFQRWQxYlBpVQp0NXY4S0I3RlZNeGpuUlpMVThIbklLdk5yQ1hTZjQvQ3dWcUNYakNMZWxUT0E3V1JmNnFVME5HS1NNeUNCU2FoMVZFUzFuczJvMEl3ClFEQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXF2M1ZXcVAyaDRzeWhmM1IKTWx1QVJaUHpBN2d3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl4QU9Ta2hMQ0IxVDJ3ZEt5VXBPZ09QUUIwVEtHWGEva05VVHloMlR2MApEYXVwbjc1T2NzcUYxTm5zdFRKRkdHK3JyUUl3ZmNmM2FXTXZvZUdZN3hNUTBYay8wZjdxTzMvZVZ2U1FzUlVSMkxJaUZkQXZ3eVl1CmEvR1JzcEJsOUpybWtPNUsKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=' + mysql['credentials'] = mysql_credentials + vcap_services['compose-for-mysql'] = [mysql] + + run_test(vcap_services) + end + + end + + end + +end