database.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var validators = require('utils/validator');
  19. var stringUtils = require('utils/string_utils');
  20. /**
  21. * Helper methods to process database values and properties
  22. * @module utils/configs/database
  23. */
  24. module.exports = {
  25. /**
  26. * Database type properties with <code>options</code> attribute usually displayed as radio-button.
  27. * <code>options</code> attribute contains mapping of database type to special properties name such as
  28. * database host and database name.
  29. * @type {object}
  30. */
  31. dbServicePropertyMap: {
  32. HIVE: {
  33. dbType: 'hive_database',
  34. databaseName: 'ambari.hive.db.schema.name',
  35. connectionUrl: 'javax.jdo.option.ConnectionURL',
  36. fallbackHostName: 'hive_ambari_host'
  37. },
  38. OOZIE: {
  39. dbType: 'oozie_database',
  40. connectionUrl: 'oozie.service.JPAService.jdbc.url',
  41. databaseName: 'oozie.db.schema.name',
  42. fallbackHostName: 'oozieserver_host'
  43. }
  44. },
  45. /**
  46. * Map of jdbc url patterns related to supported database types.
  47. *
  48. * @type {object}
  49. */
  50. DB_JDBC_PATTERNS: {
  51. mysql: 'jdbc:mysql://{0}/{1}',
  52. mssql: 'jdbc:sqlserver://{0};databaseName={1}',
  53. postgres: 'jdbc:postgresql://{0}:5432/{1}',
  54. derby: 'jdbc:derby:{0}/{1}',
  55. oracle: 'jdbc:oracle:thin:@(?:\/?\/?){0}:1521(\:|\/){1}'
  56. },
  57. /**
  58. * Setup database related properties.
  59. *
  60. * @method bootstrapDatabaseProperties
  61. * @param {App.ServiceConfigProperty[]} serviceConfigs
  62. * @param {string} [serviceName=false]
  63. */
  64. bootstrapDatabaseProperties: function(serviceConfigs, serviceName) {
  65. var self = this;
  66. var supportedServices = Em.keys(this.dbServicePropertyMap);
  67. if (serviceName && !supportedServices.contains(serviceName)) return;
  68. var serviceNames = serviceName ? [serviceName] : serviceConfigs.mapProperty('serviceName').uniq();
  69. serviceNames.forEach(function(serviceName) {
  70. if (!supportedServices.contains(serviceName)) return;
  71. var configs = serviceConfigs.filterProperty('serviceName', serviceName) || [];
  72. var connectionConfigs = self.dbServicePropertyMap[serviceName];
  73. var databaseTypeProperty = configs.findProperty('name', connectionConfigs.dbType);
  74. if (!databaseTypeProperty) return;
  75. var databaseTypePropertyIndex = configs.indexOf(databaseTypeProperty);
  76. var generatedProperties = self.getPropsByOptions(databaseTypeProperty, configs);
  77. var jdbcObject = self.parseJdbcUrl(Em.get(configs.findProperty('name', connectionConfigs.connectionUrl), 'value'));
  78. generatedProperties.forEach(function(property) {
  79. if (Em.get(property, 'name').endsWith('_host')) {
  80. // set UI host names for each database type with value parsed from jdbc connection url
  81. // if value is not ip or hostname (in case of New Derby Database) for Oozie set <code>fallbackUrl</code>
  82. // from <code>dbServicePropertyMap</code>
  83. Em.setProperties(property, {
  84. value: jdbcObject.location || ''
  85. });
  86. self.addPropertyToServiceConfigs(property, serviceConfigs, databaseTypePropertyIndex);
  87. }
  88. });
  89. });
  90. },
  91. isValidHostname: function(value) {
  92. return validators.isHostname(value) || validators.isIpAddress(value);
  93. },
  94. /**
  95. * Add UI specific property to serviceConfigObject if it does not exist, and update value for existed property.
  96. * This code affects properties related to `_host` and `_database` which are hardcoded on UI.
  97. *
  98. * @param {object} property - property to append/update
  99. * @param {App.ServiceConfigProperty[]} configs - loaded and processed service configs
  100. * @param {integer} index of first occurrence of database type in config
  101. */
  102. addPropertyToServiceConfigs: function(property, configs, index) {
  103. var configProperty = configs.findProperty('name', Em.get(property, 'name'));
  104. if (configProperty) {
  105. Em.set(configProperty, 'value', Em.get(property, 'value'));
  106. } else {
  107. if (index) {
  108. configs.insertAt(index, App.ServiceConfigProperty.create(property));
  109. } else {
  110. configs.pushObject(App.ServiceConfigProperty.create(property));
  111. }
  112. }
  113. },
  114. /**
  115. * Get hardcoded properties from site_properties.js which UI use to display host name and database name.
  116. *
  117. * @method getPropsByOptions
  118. * @param {object} databaseTypeProperty - hardcoded property from site_properties.js usualy used as radiobutton
  119. * @param {App.ServiceConfigProperty[]} configs - loaded and processed configs
  120. * @returns {object[]} - hardcoded properties from site_properties.js related to database name and location
  121. */
  122. getPropsByOptions: function(databaseTypeProperty) {
  123. Em.assert('Property related to database type should contains `options` attribute', databaseTypeProperty.get('options'));
  124. return databaseTypeProperty.options.mapProperty('foreignKeys').reduce(function(p,c) {
  125. return p.concat(c);
  126. }).uniq().map(function(name) {
  127. return App.config.get('preDefinedSiteProperties').findProperty('name', name) || null;
  128. }).compact();
  129. },
  130. /**
  131. * Get database location from jdbc url value.
  132. *
  133. * @method getDBLocationFromJDBC
  134. * @param {string} jdbcUrl - url to parse
  135. * @returns {string|null}
  136. */
  137. getDBLocationFromJDBC: function(jdbcUrl) {
  138. var self = this;
  139. var matches = Em.keys(this.DB_JDBC_PATTERNS).map(function(key) {
  140. var reg = new RegExp(self.DB_JDBC_PATTERNS[key].format('(.*)', '(.*)'));
  141. return jdbcUrl.match(reg);
  142. }).compact();
  143. if (matches.length) {
  144. var dbLocation = Em.get(matches, '0.1');
  145. if (dbLocation.startsWith('${')) {
  146. return Em.getWithDefault(matches, '0.0', '').match(/\${[^}]+}/)[0];
  147. }
  148. return dbLocation != '{0}' ? dbLocation : null;
  149. } else {
  150. return null;
  151. }
  152. },
  153. parseJdbcUrl: function(jdbcUrl) {
  154. var self = this;
  155. var result = {
  156. dbType: null,
  157. location: null,
  158. databaseName: null
  159. };
  160. var dbName;
  161. result.dbType = Em.keys(this.DB_JDBC_PATTERNS).filter(function(key) {
  162. var scheme = self.DB_JDBC_PATTERNS[key].match(/^jdbc:(\w+):/)[1];
  163. return new RegExp('jdbc:' + scheme).test(jdbcUrl);
  164. })[0];
  165. result.location = this.getDBLocationFromJDBC(jdbcUrl);
  166. if (!jdbcUrl.endsWith('{1}')) {
  167. dbName = jdbcUrl.replace(new RegExp(this.DB_JDBC_PATTERNS[result.dbType].format(stringUtils.escapeRegExp(result.location),'')), '');
  168. if (dbName) {
  169. result.databaseName = dbName.split(/[;|?]/)[0];
  170. }
  171. }
  172. return result;
  173. }
  174. };