hosts_based_initializer_mixin.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  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 App = require('app');
  19. /**
  20. * Regexp for host with port ('hostName:1234')
  21. *
  22. * @type {string}
  23. */
  24. var hostWithPort = "([\\w|\\.]*)(?=:)";
  25. /**
  26. * Regexp for host with port and protocol ('://hostName:1234')
  27. *
  28. * @type {string}
  29. */
  30. var hostWithPrefix = ":\/\/" + hostWithPort;
  31. /**
  32. * Mixin describes host name computations initializers and handlers.
  33. *
  34. * @mixin App.HostsBasedInitializerMixin
  35. */
  36. App.HostsBasedInitializerMixin = Em.Mixin.create({
  37. initializerTypes: [
  38. {name: 'host_with_component', method: '_initAsHostWithComponent'},
  39. {name: 'hosts_with_components', method: '_initAsHostsWithComponents'},
  40. {name: 'hosts_list_with_component', method: '_initAsHostsListWithComponent'}
  41. ],
  42. /**
  43. * Initializer for configs with value equal to hostName with needed component
  44. * Value example: 'hostName'
  45. *
  46. * @param {configProperty} configProperty
  47. * @param {topologyLocalDB} localDB
  48. * @param {object} dependencies
  49. * @param {object} initializer
  50. * @returns {Object}
  51. * @private
  52. */
  53. _initAsHostWithComponent: function (configProperty, localDB, dependencies, initializer) {
  54. var component = localDB.masterComponentHosts.findProperty('component', initializer.component);
  55. if (!component) {
  56. return configProperty;
  57. }
  58. if (initializer.modifier) {
  59. var replaceWith = Em.getWithDefault(initializer.modifier, 'prefix', '')
  60. + component.hostName
  61. + Em.getWithDefault(initializer.modifier, 'suffix', '');
  62. this.setRecommendedValue(configProperty, initializer.modifier.regex, replaceWith);
  63. }
  64. else {
  65. Em.setProperties(configProperty, {
  66. recommendedValue: component.hostName,
  67. value: component.hostName
  68. });
  69. }
  70. return configProperty;
  71. },
  72. /**
  73. * Settings for <code>hosts_with_components</code>-initializer
  74. * Used for configs with value equal to the hosts list
  75. * May set value as array (if <code>asArray</code> is true) or as comma-sepratated string (if <code>asArray</code> is false)
  76. *
  77. * @see _initAsHostsWithComponents
  78. * @param {string|string[]} components
  79. * @param {boolean} [asArray=false]
  80. * @param {boolean|undefined} [isInstalled=undefined]
  81. * @returns {{type: string, components: string[], asArray: boolean}}
  82. */
  83. getComponentsHostsConfig: function(components, asArray, isInstalled) {
  84. if (1 === arguments.length) {
  85. asArray = false;
  86. }
  87. return {
  88. type: 'hosts_with_components',
  89. components: Em.makeArray(components),
  90. asArray: asArray,
  91. isInstalled: isInstalled
  92. };
  93. },
  94. /**
  95. * Initializer for configs with value equal to hostNames with needed components
  96. * May be array or comma-separated list
  97. * Depends on <code>initializer.asArray</code> (true - array, false - string)
  98. * Value example: 'hostName1,hostName2,hostName3' or ['hostName1', 'hostName2', 'hostName3']
  99. *
  100. * @param {configProperty} configProperty
  101. * @param {topologyLocalDB} localDB
  102. * @param {object} dependencies
  103. * @param {object} initializer
  104. * @return {Object}
  105. * @private
  106. */
  107. _initAsHostsWithComponents: function (configProperty, localDB, dependencies, initializer) {
  108. var hostNames = localDB.masterComponentHosts.filter(function (masterComponent) {
  109. var hasFound = initializer.components.contains(masterComponent.component);
  110. if (Em.isNone(initializer.isInstalled)) {
  111. return hasFound;
  112. } else {
  113. return hasFound && masterComponent.isInstalled === initializer.isInstalled;
  114. }
  115. }).sortProperty('hostName').mapProperty('hostName');
  116. if (!initializer.asArray) {
  117. hostNames = hostNames.uniq().join(',');
  118. }
  119. Em.setProperties(configProperty, {
  120. value: hostNames,
  121. recommendedValue: hostNames
  122. });
  123. return configProperty;
  124. },
  125. /**
  126. * Settings for <code>host_with_component</code>-initializer
  127. * Used for configs with value equal to hostName that has <code>component</code>
  128. * Value may be modified with if <code>withModifier</code> is true (it is by default)
  129. * <code>hostWithPort</code>-regexp will be used in this case
  130. *
  131. * @see _initAsHostWithComponent
  132. * @param {string} component
  133. * @param {boolean} [withModifier=true]
  134. * @return {object}
  135. */
  136. getSimpleComponentConfig: function(component, withModifier) {
  137. if (arguments.length === 1) {
  138. withModifier = true;
  139. }
  140. var config = {
  141. type: 'host_with_component',
  142. component: component
  143. };
  144. if (withModifier) {
  145. config.modifier = {
  146. type: 'regexp',
  147. regex: hostWithPort
  148. };
  149. }
  150. return config;
  151. },
  152. /**
  153. * Almost the same to <code>getSimpleComponentConfig</code>, but with possibility to modify <code>replaceWith</code>-value
  154. * <code>prefix</code> is added before it
  155. * <code>suffix</code> is added after it
  156. * <code>hostWithPrefix</code>-regexp is used
  157. *
  158. * @see _initAsHostWithComponent
  159. * @param {string} component
  160. * @param {string} [prefix]
  161. * @param {string} [suffix]
  162. * @returns {object}
  163. */
  164. getComponentConfigWithAffixes: function(component, prefix, suffix) {
  165. prefix = prefix || '';
  166. suffix = suffix || '';
  167. return {
  168. type: 'host_with_component',
  169. component: component,
  170. modifier: {
  171. type: 'regexp',
  172. regex: hostWithPrefix,
  173. prefix: prefix,
  174. suffix: suffix
  175. }
  176. };
  177. },
  178. /**
  179. * Settings for <code>host_with_port</code>-initializer
  180. * Used for configs with value equal to hostName where some component exists concatenated with port-value
  181. * Port-value is calculated according to <code>port</code> and <code>portFromDependencies</code> values
  182. * If <code>portFromDependencies</code> is <code>true</code>, <code>port</code>-value is used as key of the <code>dependencies</code> (where real port-value is)
  183. * Otherwise - <code>port</code>-value used as is
  184. * If calculated port-value is empty, it will be skipped (and ':' too)
  185. * Value also may be customized with prefix and suffix
  186. *
  187. * @param {string} component needed component
  188. * @param {boolean} componentExists component already exists or just going to be installed
  189. * @param {string} prefix=''
  190. * @param {string} suffix=''
  191. * @param {string} port
  192. * @param {boolean} [portFromDependencies=false]
  193. * @returns {{type: string, component: string, componentExists: boolean, modifier: {prefix: (string), suffix: (string)}}}
  194. * @method getHostWithPortConfig
  195. * @static
  196. */
  197. getHostWithPortConfig: function (component, componentExists, prefix, suffix, port, portFromDependencies) {
  198. if (arguments.length < 6) {
  199. portFromDependencies = false;
  200. }
  201. prefix = prefix || '';
  202. suffix = suffix || '';
  203. var ret = {
  204. type: 'host_with_port',
  205. component: component,
  206. componentExists: componentExists,
  207. modifier: {
  208. prefix: prefix,
  209. suffix: suffix
  210. }
  211. };
  212. if (portFromDependencies) {
  213. ret.portKey = port;
  214. }
  215. else {
  216. ret.port = port;
  217. }
  218. return ret;
  219. },
  220. /**
  221. * Initializer for configs with value equal to the hostName where some component exists
  222. * Value may be customized with prefix and suffix (see <code>initializer.modifier</code>)
  223. * Port-value is calculated according to <code>initializer.portKey</code> or <code>initializer.port</code> values
  224. * If calculated port-value is empty, it will be skipped (and ':' too)
  225. * Value-examples: 'SOME_COOL_PREFIXhost1:port1SOME_COOL_SUFFIX', 'host1:port2'
  226. *
  227. * @param {configProperty} configProperty
  228. * @param {extendedTopologyLocalDB} localDB
  229. * @param {object} dependencies
  230. * @param {object} initializer
  231. * @returns {object}
  232. * @private
  233. * @method _initAsHostWithPort
  234. */
  235. _initAsHostWithPort: function (configProperty, localDB, dependencies, initializer) {
  236. var hostName = localDB.masterComponentHosts.filterProperty('component', initializer.component).findProperty('isInstalled', initializer.componentExists).hostName;
  237. var port = this.__getPort(dependencies, initializer);
  238. var value = initializer.modifier.prefix + hostName + (port ? ':' + port : '') + initializer.modifier.suffix;
  239. Em.setProperties(configProperty, {
  240. value: value,
  241. recommendedValue: value
  242. });
  243. return configProperty;
  244. },
  245. /**
  246. * Settings for <code>hosts_with_port</code>-initializer
  247. * Used for configs with value equal to the list of hostNames with port
  248. * Value also may be customized with prefix, suffix and delimiter between host:port elements
  249. * Port-value is calculated according to <code>port</code> and <code>portFromDependencies</code> values
  250. * If <code>portFromDependencies</code> is <code>true</code>, <code>port</code>-value is used as key of the <code>dependencies</code> (where real port-value is)
  251. * Otherwise - <code>port</code>-value used as is
  252. * If calculated port-value is empty, it will be skipped (and ':' too)
  253. *
  254. * @param {string|string[]} component hosts where this component(s) exists are used as config-value
  255. * @param {string} prefix='' substring added before hosts-list
  256. * @param {string} suffix='' substring added after hosts-list
  257. * @param {string} delimiter=',' delimiter between hosts in the value
  258. * @param {string} port if <code>portFromDependencies</code> is <code>false</code> this value is used as port for hosts
  259. * if <code>portFromDependencies</code> is <code>true</code> `port` is used as key in the <code>dependencies</code> to get real port-value
  260. * @param {boolean} portFromDependencies=false true - use <code>port</code> as key for <code>dependencies</code> to get real port-value,
  261. * false - use <code>port</code> as port-value
  262. * @returns {{type: string, component: string, modifier: {prefix: (string), suffix: (string), delimiter: (string)}}}
  263. * @method getHostsWithPortConfig
  264. * @static
  265. */
  266. getHostsWithPortConfig: function (component, prefix, suffix, delimiter, port, portFromDependencies) {
  267. if (arguments.length < 6) {
  268. portFromDependencies = false;
  269. }
  270. prefix = prefix || '';
  271. suffix = suffix || '';
  272. delimiter = delimiter || ',';
  273. var ret = {
  274. type: 'hosts_with_port',
  275. component: component,
  276. modifier: {
  277. prefix: prefix,
  278. suffix: suffix,
  279. delimiter: delimiter
  280. }
  281. };
  282. if (portFromDependencies) {
  283. ret.portKey = port;
  284. }
  285. else {
  286. ret.port = port;
  287. }
  288. return ret;
  289. },
  290. /**
  291. * Initializer for configs with value equal to the list of hosts where some component exists
  292. * Value may be customized with prefix and suffix (see <code>initializer.modifier</code>)
  293. * Delimiter between hostNames also may be customized in the <code>initializer.modifier</code>
  294. * Port-value is calculated according to <code>initializer.portKey</code> or <code>initializer.port</code> values
  295. * If calculated port-value is empty, it will be skipped (and ':' too)
  296. * Value examples: 'SOME_COOL_PREFIXhost1:port,host2:port,host2:portSOME_COOL_SUFFIX', 'host1:port|||host2:port|||host2:port'
  297. *
  298. * @param {configProperty} configProperty
  299. * @param {topologyLocalDB} localDB
  300. * @param {object} dependencies
  301. * @param {object} initializer
  302. * @returns {object}
  303. * @private
  304. * @method _initAsHostsWithPort
  305. */
  306. _initAsHostsWithPort: function (configProperty, localDB, dependencies, initializer) {
  307. var hostNames, hosts;
  308. if (Em.isArray(initializer.component)) {
  309. hosts = localDB.masterComponentHosts.filter(function(masterComponent) {
  310. return initializer.component.contains(masterComponent.component);
  311. }).sortProperty('hostName');
  312. } else {
  313. hosts = localDB.masterComponentHosts.filterProperty('component', initializer.component);
  314. }
  315. if (Em.isNone(initializer.componentExists)) {
  316. hostNames = hosts.mapProperty('hostName');
  317. } else {
  318. hostNames = hosts.filterProperty('isInstalled', initializer.componentExists).mapProperty('hostName');
  319. }
  320. var port = this.__getPort(dependencies, initializer);
  321. var value = initializer.modifier.prefix + hostNames.uniq().map(function (hostName) {
  322. return hostName + (port ? ':' + port : '');
  323. }).join(initializer.modifier.delimiter) + initializer.modifier.suffix;
  324. Em.setProperties(configProperty, {
  325. value: value,
  326. recommendedValue: value
  327. });
  328. return configProperty;
  329. },
  330. /**
  331. * Returns port-value from <code>dependencies</code> accorfing to <code>initializer.portKey</code> or <code>initializer.port</code> values
  332. *
  333. * @param {object} dependencies
  334. * @param {object} initializer
  335. * @returns {string|number}
  336. * @private
  337. * @method __getPort
  338. */
  339. __getPort: function (dependencies, initializer) {
  340. var portKey = initializer.portKey;
  341. if (portKey) {
  342. return dependencies[portKey];
  343. }
  344. return initializer.port;
  345. },
  346. /**
  347. *
  348. * @param {string} component component name
  349. * @param {boolean} componentExists
  350. * @returns {object}
  351. */
  352. getHostsListComponentConfig: function(component, componentExists, delimiter) {
  353. return {
  354. type: 'hosts_list_with_component',
  355. component: component,
  356. componentExists: componentExists,
  357. modifier: {
  358. delmitier: Em.isNone(delimiter) ? ',' : delimiter
  359. }
  360. };
  361. },
  362. /**
  363. *
  364. * @param {configProperty} configProperty
  365. * @param {topologyLocalDB} localDB
  366. * @param {object} dependencies
  367. * @param {object} initializer
  368. * @returns {configProperty}
  369. */
  370. _initAsHostsListWithComponent: function(configProperty, localDB, dependencies, initializer) {
  371. var hostNames = localDB.masterComponentHosts
  372. .filterProperty('component', initializer.component)
  373. .filterProperty('isInstalled', initializer.componentExists)
  374. .mapProperty('hostName')
  375. .join(initializer.modifier.delimiter);
  376. Em.setProperties(configProperty, {
  377. value: hostNames,
  378. recommendedValue: hostNames
  379. });
  380. return configProperty;
  381. }
  382. });