This is an automated email from the ASF dual-hosted git repository. akuznetsov pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new 0af4fdf IGNITE-11182 Web console: Actualized cluster configuration. 0af4fdf is described below commit 0af4fdf839fb1fb58e34a81bba473ec86792062b Author: Vasiliy Sisko <vsi...@gridgain.com> AuthorDate: Fri Apr 5 13:15:57 2019 +0700 IGNITE-11182 Web console: Actualized cluster configuration. --- .../eviction/lru/LruEvictionPolicyFactory.java | 1 - modules/web-console/backend/app/schemas.js | 71 +++++- .../components/cache-edit-form/template.tpl.pug | 2 + .../cache-edit-form/templates/general.pug | 42 ++-- .../cache-edit-form/templates/key-cfg.pug | 66 ++++++ .../cache-edit-form/templates/memory.pug | 21 ++ .../components/cache-edit-form/templates/misc.pug | 95 ++++++++ .../components/cache-edit-form/templates/query.pug | 45 +++- .../components/cache-edit-form/templates/store.pug | 9 + .../components/cluster-edit-form/templates/ssl.pug | 28 +++ .../igfs-edit-form/templates/secondary.pug | 252 ++++++++++++++++++++- .../generator/generator/AbstractTransformer.js | 14 +- .../app/configuration/generator/generator/Beans.js | 7 + .../generator/generator/ConfigurationGenerator.js | 163 ++++++++++++- .../generator/generator/JavaTransformer.service.js | 8 + .../generator/generator/Maven.service.js | 2 +- .../generator/SpringTransformer.service.js | 2 + .../generator/generator/defaults/Cache.service.js | 9 +- .../generator/generator/defaults/IGFS.service.js | 15 +- .../frontend/app/configuration/services/Caches.ts | 3 +- .../frontend/app/configuration/services/IGFSs.ts | 16 +- .../WebConsoleConfigurationSelfTest.java | 69 +++++- 22 files changed, 878 insertions(+), 62 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java b/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java index 8f7fbc5..ff873ac 100644 --- a/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/cache/eviction/lru/LruEvictionPolicyFactory.java @@ -68,5 +68,4 @@ public class LruEvictionPolicyFactory<K, V> extends AbstractEvictionPolicyFactor return policy; } - } diff --git a/modules/web-console/backend/app/schemas.js b/modules/web-console/backend/app/schemas.js index 29ec9b4..ce48932 100644 --- a/modules/web-console/backend/app/schemas.js +++ b/modules/web-console/backend/app/schemas.js @@ -185,6 +185,21 @@ module.exports.factory = function(mongoose) { offHeapMaxMemory: Number, startSize: Number, swapEnabled: Boolean, + cacheWriterFactory: String, + cacheLoaderFactory: String, + expiryPolicyFactory: String, + interceptor: String, + storeByValue: Boolean, + eagerTtl: {type: Boolean, default: true}, + encryptionEnabled: Boolean, + eventsDisabled: Boolean, + + keyConfiguration: [{ + typeName: String, + affinityKeyFieldName: String + }], + + cacheStoreSessionListenerFactories: [String], onheapCacheEnabled: Boolean, @@ -255,6 +270,8 @@ module.exports.factory = function(mongoose) { hibernateProperties: [{name: String, value: String}] } }, + storeConcurrentLoadAllThreshold: Number, + maxQueryIteratorsCount: Number, storeKeepBinary: Boolean, loadPreviousValue: Boolean, readThrough: Boolean, @@ -377,9 +394,57 @@ module.exports.factory = function(mongoose) { trashPurgeTimeout: Number, secondaryFileSystemEnabled: Boolean, secondaryFileSystem: { + userName: String, + kind: {type: String, enum: ['Caching', 'Kerberos', 'Custom'], default: 'Caching'}, uri: String, cfgPath: String, - userName: String + cfgPaths: [String], + userNameMapper: { + kind: {type: String, enum: ['Chained', 'Basic', 'Kerberos', 'Custom']}, + Chained: { + mappers: [{ + kind: {type: String, enum: ['Basic', 'Kerberos', 'Custom']}, + Basic: { + defaultUserName: String, + useDefaultUserName: Boolean, + mappings: [{ + name: String, + value: String + }] + }, + Kerberos: { + instance: String, + realm: String + }, + Custom: { + className: String, + } + }] + }, + Basic: { + defaultUserName: String, + useDefaultUserName: Boolean, + mappings: [{ + name: String, + value: String + }] + }, + Kerberos: { + instance: String, + realm: String + }, + Custom: { + className: String, + } + }, + Kerberos: { + keyTab: String, + keyTabPrincipal: String, + reloginInterval: Number + }, + Custom: { + className: String + } }, colocateMetadata: Boolean, relaxedConsistency: Boolean, @@ -714,7 +779,9 @@ module.exports.factory = function(mongoose) { protocol: String, trustStoreFilePath: String, trustStoreType: String, - trustManagers: [String] + trustManagers: [String], + cipherSuites: [String], + protocols: [String] }, rebalanceThreadPoolSize: Number, odbc: { diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug index 7305a39..5d98d77 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/template.tpl.pug @@ -26,6 +26,8 @@ form( include ./templates/affinity include ./templates/concurrency + include ./templates/key-cfg + include ./templates/misc include ./templates/near-cache-client include ./templates/near-cache-server include ./templates/node-filter diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug index 00a544f..9b875ab 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/general.pug @@ -103,28 +103,28 @@ panel-collapsible(opened=`::true` ng-form=form) name: '"partitionLossPolicy"', placeholder: 'IGNORE', options: '[\ - {value: "READ_ONLY_SAFE", label: "READ_ONLY_SAFE"},\ - {value: "READ_ONLY_ALL", label: "READ_ONLY_ALL"},\ - {value: "READ_WRITE_SAFE", label: "READ_WRITE_SAFE"},\ - {value: "READ_WRITE_ALL", label: "READ_WRITE_ALL"},\ - {value: "IGNORE", label: "IGNORE"}\ - ]', + {value: "READ_ONLY_SAFE", label: "READ_ONLY_SAFE"},\ + {value: "READ_ONLY_ALL", label: "READ_ONLY_ALL"},\ + {value: "READ_WRITE_SAFE", label: "READ_WRITE_SAFE"},\ + {value: "READ_WRITE_ALL", label: "READ_WRITE_ALL"},\ + {value: "IGNORE", label: "IGNORE"}\ + ]', tip: 'Partition loss policies:\ - <ul>\ - <li>READ_ONLY_SAFE - in this mode all writes to the cache will be failed with an exception,\ - reads will only be allowed for keys in non-lost partitions.\ - Reads from lost partitions will be failed with an exception.</li>\ - <li>READ_ONLY_ALL - in this mode all writes to the cache will be failed with an exception.\ - All reads will proceed as if all partitions were in a consistent state.\ - The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\ - <li>READ_WRITE_SAFE - in this mode all reads and writes will be allowed for keys in valid partitions.\ - All reads and writes for keys in lost partitions will be failed with an exception.</li>\ - <li>READ_WRITE_ALL - in this mode all reads and writes will proceed as if all partitions were in a consistent state.\ - The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\ - <li>IGNORE - in this mode if partition is lost, reset it state and do not clear intermediate data.\ - The result of reading from a previously lost and not cleared partition is undefined and may be different\ - on different nodes in the cluster.</li>\ - </ul>' + <ul>\ + <li>READ_ONLY_SAFE - in this mode all writes to the cache will be failed with an exception,\ + reads will only be allowed for keys in non-lost partitions.\ + Reads from lost partitions will be failed with an exception.</li>\ + <li>READ_ONLY_ALL - in this mode all writes to the cache will be failed with an exception.\ + All reads will proceed as if all partitions were in a consistent state.\ + The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\ + <li>READ_WRITE_SAFE - in this mode all reads and writes will be allowed for keys in valid partitions.\ + All reads and writes for keys in lost partitions will be failed with an exception.</li>\ + <li>READ_WRITE_ALL - in this mode all reads and writes will proceed as if all partitions were in a consistent state.\ + The result of reading from a lost partition is undefined and may be different on different nodes in the cluster.</li>\ + <li>IGNORE - in this mode if partition is lost, reset it state and do not clear intermediate data.\ + The result of reading from a previously lost and not cleared partition is undefined and may be different\ + on different nodes in the cluster.</li>\ + </ul>' }) .pc-form-grid-col-60(ng-show=`${model}.cacheMode === 'PARTITIONED' && ${model}.backups`) +form-field__checkbox({ diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/key-cfg.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/key-cfg.pug new file mode 100644 index 0000000..4527906 --- /dev/null +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/key-cfg.pug @@ -0,0 +1,66 @@ +//- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + +include /app/helpers/jade/mixins +include /app/configuration/mixins + +-var form = 'cacheKeyCfg' +-var model = '$ctrl.clonedCache.keyConfiguration' + +panel-collapsible(ng-show='$ctrl.available("2.1.0")' ng-form=form on-open=`ui.loadPanel('${form}')`) + panel-title Key configuration + panel-description + | Configuration defining various aspects of cache keys without explicit usage of annotations on user classes. + panel-content.pca-form-row(ng-if=`ui.isPanelLoaded('${form}')`) + .pca-form-column-6 + .ignite-form-field + +form-field__label({ label: 'Key configuration:', name: '"KeyConfiguration"' }) + + list-editable.pc-list-editable-with-form-grid(ng-model=model name='keyConfiguration') + list-editable-item-edit.pc-form-grid-row + - form = '$parent.form' + .pc-form-grid-col-60 + +form-field__java-class({ + label: 'Type name:', + model: '$item.typeName', + name: '"keyTypeName"', + required: 'true', + tip: 'Type name' + })( + ignite-form-field-input-autofocus='true' + ignite-unique=model + ignite-unique-property='typeName' + ) + +form-field__error({ error: 'igniteUnique', message: 'Type name should be unique.' }) + .pc-form-grid-col-60 + +form-field__text({ + label: 'Affinity key field name:', + model: '$item.affinityKeyFieldName', + name: '"affinityKeyFieldName"', + placeholder: 'Enter field name', + tip: 'Affinity key field name', + required: true + }) + + list-editable-no-items + list-editable-add-item-button( + add-item=`(${model} = ${model} || []).push({})` + label-single='configuration' + label-multiple='configurations' + ) + + .pca-form-column-6 + +preview-xml-java(model, 'cacheKeyConfiguration') diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug index f4403a7..cf69d65 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/memory.pug @@ -226,6 +226,27 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) name: '"swapEnabled"', tip: 'Flag indicating whether swap storage is enabled or not for this cache' }) + .pc-form-grid-col-60 + +form-field__java-class({ + label: 'Cache writer factory:', + model: `${model}.cacheWriterFactory`, + name: `"CacheWriterFactory"`, + tip: 'Factory for writer that is used for write-through to an external resource' + }) + .pc-form-grid-col-60 + +form-field__java-class({ + label: 'Cache loader factory:', + model: `${model}.cacheLoaderFactory`, + name: `"CacheLoaderFactory"`, + tip: 'Factory for loader that is used for a cache is read-through or when loading data into a cache via the Cache.loadAll(java.util.Set, boolean, CompletionListener) method' + }) + .pc-form-grid-col-60 + +form-field__java-class({ + label: 'Expiry policy factory:', + model: `${model}.expiryPolicyFactory`, + name: `"ExpiryPolicyFactory"`, + tip: 'Factory for functions that determine when cache entries will expire based on creation, access and modification operations' + }) .pca-form-column-6 +preview-xml-java(model, 'cacheMemory') diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/misc.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/misc.pug new file mode 100644 index 0000000..8267f1c --- /dev/null +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/misc.pug @@ -0,0 +1,95 @@ +//- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + +include /app/helpers/jade/mixins +include /app/configuration/mixins + +-var form = 'misc' +-var model = '$ctrl.clonedCache' + +panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) + panel-title Miscellaneous + panel-description Various miscellaneous cache settings. + panel-content.pca-form-row(ng-if=`ui.isPanelLoaded('${form}')`) + .pca-form-column-6.pc-form-grid-row + .pc-form-grid-col-60 + +form-field__java-class({ + label: 'Interceptor:', + model: `${model}.interceptor`, + name: '"interceptor"', + tip: 'Cache interceptor can be used for getting callbacks before and after cache get, put, and remove operations' + }) + .pc-form-grid-col-60(ng-if='$ctrl.available("2.0.0")') + +form-field__checkbox({ + label: 'Store by value', + model: `${model}.storeByValue`, + name: '"storeByValue"', + tip: 'Use store-by-value or store-by-reference semantics' + }) + .pc-form-grid-col-60 + +form-field__checkbox({ + label: 'Eager TTL', + model: `${model}.eagerTtl`, + name: '"eagerTtl"', + tip: 'Eagerly remove expired cache entries' + }) + .pc-form-grid-col-60(ng-if='$ctrl.available("2.7.0")') + +form-field__checkbox({ + label: 'Enable encryption', + model: `${model}.encryptionEnabled`, + name: '"encryptionEnabled"', + tip: 'Enable encription of data on the disk' + }) + .pc-form-grid-col-60(ng-if='$ctrl.available("2.5.0")') + +form-field__checkbox({ + label: 'Disable events', + model: `${model}.eventsDisabled`, + name: '"eventsDisabled"', + tip: 'Disable events on this cache' + }) + .pc-form-grid-col-60 + mixin store-session-listener-factories() + .ignite-form-field + -let items = `${model}.cacheStoreSessionListenerFactories`; + + list-editable( + ng-model=items + list-editable-cols=`::[{ + name: 'Store session listener factories:', + tip: 'Cache store session listener factories' + }]`) + list-editable-item-view {{ $item }} + + list-editable-item-edit + +list-java-class-field('Listener', '$item', '"Listener"', items) + +form-field__error({ + error: 'igniteUnique', + message: 'Listener with such class name already exists!' + }) + + list-editable-no-items + list-editable-add-item-button( + add-item=`$editLast((${items} = ${items} || []).push(""))` + label-single='listener' + label-multiple='listeners' + ) + + - var form = '$parent.form' + +store-session-listener-factories + - var form = 'misc' + + .pca-form-column-6 + +preview-xml-java(model, 'cacheMisc') diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug index b0fe00b..edbcb25 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/query.pug @@ -118,16 +118,6 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) tip: 'Flag indicating whether SQL indexes should support snapshots' }) - .pc-form-grid-col-60 - +form-field__checkbox({ - label: 'Escape table and filed names', - model: `${model}.sqlEscapeAll`, - name: '"sqlEscapeAll"', - tip: 'If enabled than all schema, table and field names will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\ - This enforces case sensitivity for field names and also allows having special characters in table and field names.<br/>\ - Escaped names will be used for creation internal structures in Ignite SQL engine.' - }) - //- Since ignite 2.0 .pc-form-grid-col-30(ng-if-start='$ctrl.available("2.0.0")') +form-field__number({ @@ -147,6 +137,41 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) min: '-1', tip: 'Maximum inline size for sql indexes' }) + .pc-form-grid-col-60(ng-if-start='$ctrl.available("2.4.0")') + +form-field__checkbox({ + label: 'Onheap cache enabled', + model: `${model}.sqlOnheapCacheEnabled`, + name: '"sqlOnheapCacheEnabled"', + tip: 'When enabled, Ignite will cache SQL rows as they are accessed by query engine' + }) + .pc-form-grid-col-60(ng-if-end) + +form-field__number({ + label: 'Onheap cache max size:', + model: `${model}.sqlOnheapCacheMaxSize`, + name: '"SqlOnheapCacheMaxSize"', + disabled: `!${model}.sqlOnheapCacheEnabled`, + placeholder: '0', + min: '0', + tip: 'Maximum SQL on-heap cache' + }) + .pc-form-grid-col-60 + +form-field__number({ + label: 'Max query iterators count:', + model: `${model}.maxQueryIteratorsCount`, + name: '"MaxQueryIteratorsCount"', + placeholder: '1024', + min: '1', + tip: 'Maximum number of query iterators that can be stored' + }) + .pc-form-grid-col-60 + +form-field__checkbox({ + label: 'Escape table and filed names', + model: `${model}.sqlEscapeAll`, + name: '"sqlEscapeAll"', + tip: 'If enabled than all schema, table and field names will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\ + This enforces case sensitivity for field names and also allows having special characters in table and field names.<br/>\ + Escaped names will be used for creation internal structures in Ignite SQL engine.' + }) .pca-form-column-6 +preview-xml-java(model, 'cacheQuery', 'domains') diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug index 96ce5a4..b4baac5 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug @@ -297,6 +297,15 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) - form = 'store' .pc-form-grid-col-60 + +form-field__number({ + label: 'Concurrent load all threshold:', + model: `${model}.storeConcurrentLoadAllThreshold`, + name: '"storeConcurrentLoadAllThreshold"', + placeholder: '5', + min: '1', + tip: 'Threshold used in cases when values for multiple keys are being loaded from an underlying cache store in parallel' + }) + .pc-form-grid-col-60 +form-field__checkbox({ label: 'Keep binary in store', model: `${model}.storeKeepBinary`, diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug index a062425..dea087e 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/ssl.pug @@ -128,5 +128,33 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) options: '["JKS", "PCKS11", "PCKS12"]', tip: 'Trust store type used in context initialization' }) + .pc-form-grid-col-60(ng-if-start='$ctrl.available("2.7.0")') + .ignite-form-field + +list-text-field({ + items: `${model}.cipherSuites`, + lbl: 'Cipher suite', + name: 'cipherSuite', + itemName: 'cipher suite', + itemsName: 'cipher suites' + + })( + list-editable-cols=`::[{name: 'Suites:'}]` + ng-disabled=`!(${enabled})` + ) + +form-field__error({error: 'igniteUnique', message: 'Such suite is already configured!'}) + .pc-form-grid-col-60(ng-if-end) + .ignite-form-field + +list-text-field({ + items: `${model}.protocols`, + lbl: 'Protocol', + name: 'protocols', + itemName: 'protocol', + itemsName: 'protocols' + + })( + list-editable-cols=`::[{name: 'Protocols:'}]` + ng-disabled=`!(${enabled})` + ) + +form-field__error({error: 'igniteUnique', message: 'Such protocol already exists!'}) .pca-form-column-6 +preview-xml-java(cluster, 'clusterSsl') diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug index 7d42a04..ac91770 100644 --- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug +++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/igfs-edit-form/templates/secondary.pug @@ -19,6 +19,76 @@ include /app/configuration/mixins -var form = 'secondaryFileSystem' -var model = 'backupItem' +-var enabled = `${model}.secondaryFileSystemEnabled` + +mixin basic-name-mapper(basicModel, prefix) + .pc-form-grid-col-60 + +form-field__text({ + label: 'Default user name:', + model: `${basicModel}.defaultUserName`, + name: `"${prefix}BasicDefaultUserName"`, + required: `${basicModel}.useDefaultUserName`, + disabled: `!(${enabled})`, + placeholder: 'Input default user name', + tip: 'Default user name' + }) + .pc-form-grid-col-60 + +form-field__checkbox({ + label: 'Use default user name', + model: `${basicModel}.useDefaultUserName`, + name: `"${prefix}BasicUseDefaultUserName"`, + required: `!${basicModel}.mappings`, + disabled: `!(${enabled})`, + tip: 'Whether to use default user name' + }) + .pc-form-grid-col-60 + .ignite-form-field + +form-field__label({label: 'Name mappings:', name: `"${prefix}BasicNameMappings"`}) + +form-field__tooltip({title: `Maps one user name to another`}) + + +list-pair-edit({ + items: `${basicModel}.mappings`, + keyLbl: 'Old name', + valLbl: 'New name', + itemName: 'name', + itemsName: 'names' + }) + + .form-field__errors( + ng-messages=`receiverAddresses.$error` + ng-show=`receiverAddresses.$invalid` + ) + +form-field__error({error: 'required', message: 'Name mappings should be configured'}) + +mixin kerberos-name-mapper(kerberosModel, prefix) + .pc-form-grid-col-60 + +form-field__text({ + label: 'Instance:', + model: `${kerberosModel}.instance`, + name: `"${prefix}KerberosInstance"`, + disabled: `!(${enabled})`, + placeholder: 'Input instance', + tip: 'Kerberos instance' + }) + .pc-form-grid-col-60 + +form-field__text({ + label: 'Realm:', + model: `${kerberosModel}.realm`, + name: `"${prefix}KerberosRealm"`, + disabled: `!(${enabled})`, + placeholder: 'Input realm', + tip: 'Kerberos realm' + }) + +mixin custom-name-mapper(customModel, prefix) + .pc-form-grid-col-60 + +form-field__java-class({ + label: 'Class:', + model: `${customModel}.className`, + name: `"${prefix}CustomClassName"`, + required: true, + tip: 'User name mapper implementation class name' + }) panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) panel-title Secondary file system @@ -27,8 +97,8 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) a.link-success(href="https://apacheignite-fs.readme.io/docs/secondary-file-system" target="_blank") More info panel-content.pca-form-row(ng-if=`ui.isPanelLoaded('${form}')`) .pca-form-column-6.pc-form-grid-row - -var enabled = `${model}.secondaryFileSystemEnabled` -var secondaryFileSystem = `${model}.secondaryFileSystem` + -var nameMapperModel = `${secondaryFileSystem}.userNameMapper` .pc-form-grid-col-60 +form-field__checkbox({ @@ -48,6 +118,35 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) +form-field__error({ error: 'requiredWhenPathModeProxyMode', message: 'Secondary file system should be configured for "PROXY" path mode' }) .pc-form-grid-col-60 +form-field__text({ + label: 'User name:', + model: `${secondaryFileSystem}.userName`, + name: '"userName"', + disabled: `!(${enabled})`, + placeholder: 'Input user name', + tip: 'User name' + }) + .pc-form-grid-col-60 + +form-field__dropdown({ + label: 'File system factory:', + model: `${secondaryFileSystem}.kind`, + name: '"FileSystemFactory"', + disabled: `!(${enabled})`, + placeholder: 'Default', + options: '[\ + {value: "Caching", label: "Caching"},\ + {value: "Kerberos", label: "Kerberos"},\ + {value: "Custom", label: "Custom"},\ + {value: null, label: "Default"}\ + ]', + tip: 'File system factory:\ + <ul>\ + <li>Caching - Caches File system instances on per-user basis</li>\ + <li>Kerberos - Secure Hadoop file system factory that can work with underlying file system protected with Kerberos</li>\ + <li>Custom - Custom file system factory</li>\ + </ul>' + }) + .pc-form-grid-col-60(ng-if-start=`${secondaryFileSystem}.kind !== "Custom"`) + +form-field__text({ label: 'URI:', model: `${secondaryFileSystem}.uri`, name: '"hadoopURI"', @@ -56,22 +155,153 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`) tip: 'URI of file system' }) .pc-form-grid-col-60 + mixin secondary-fs-cfg-paths() + .ignite-form-field + -let items = `${secondaryFileSystem}.cfgPaths`; + + list-editable( + ng-model=items + list-editable-cols=`::[{ + name: 'Config paths:', + tip: 'Additional pathes to Hadoop configurations' + }]` + ng-disabled=`!(${enabled})` + ) + list-editable-item-view {{ $item }} + + list-editable-item-edit + .pc-form-grid-row + .pc-form-grid-col-60 + +form-field__text({ + label: 'Path:', + model: '$item', + name: '"path"', + required: true, + placeholder: 'Enter path' + })(ignite-auto-focus) + + list-editable-no-items + list-editable-add-item-button( + add-item=`$editLast((${items} = ${items} || []).push(""))` + label-single='Config path' + label-multiple='Config paths' + ) + + - var form = '$parent.form' + +secondary-fs-cfg-paths + - var form = 'secondaryFileSystem' + .pc-form-grid-col-60(ng-if-start=`${secondaryFileSystem}.kind === "Kerberos"`) +form-field__text({ - label: 'Config path:', - model: `${secondaryFileSystem}.cfgPath`, - name: '"cfgPath"', + label: 'Keytab file:', + model: `${secondaryFileSystem}.Kerberos.keyTab`, + name: '"KerberosKeyTab"', + required: true, disabled: `!(${enabled})`, - placeholder: 'Path to additional config', - tip: 'Additional path to Hadoop configuration' + placeholder: 'Input keytab full file name', + tip: 'Keytab full file name' }) .pc-form-grid-col-60 +form-field__text({ - label: 'User name:', - model: `${secondaryFileSystem}.userName`, - name: '"userName"', + label: 'Keytab principal:', + model: `${secondaryFileSystem}.Kerberos.keyTabPrincipal`, + name: '"KerberosKeyTabPrincipals"', + required: true, disabled: `!(${enabled})`, - placeholder: 'Input user name', - tip: 'User name' + placeholder: 'Input keytab principals', + tip: 'Keytab principals short name' + }) + .pc-form-grid-col-60(ng-if-end) + +form-field__number({ + label: 'Relogin interval:', + model: `${secondaryFileSystem}.Kerberos.reloginInterval`, + name: '"KerberosReloginInterval"', + placeholder: '600000', + min: '0', + tip: 'Total time in ms for execution of retry attempt' }) + .pc-form-grid-col-60(ng-if-end) + +form-field__dropdown({ + label: 'User name mapper:', + model: `${nameMapperModel}.kind`, + name: '"NameMapperKind"', + disabled: `!(${enabled})`, + placeholder: 'Not set', + options: '[\ + {value: "Chained", label: "Chained"},\ + {value: "Basic", label: "Basic"},\ + {value: "Kerberos", label: "Kerberos"},\ + {value: "Custom", label: "Custom"},\ + {value: null, label: "Not set"}\ + ]', + tip: 'File system factory:\ + <ul>\ + <li>Chained - Delegate name conversion to child mappers</li>\ + <li>Basic - Maps one user name to another based on predefined dictionary</li>\ + <li>Kerberos - Map simple user name to Kerberos principal</li>\ + <li>Custom - Custom user name mapper</li>\ + </ul>' + }) + .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind !== "Custom" && ${nameMapperModel}.kind === "Chained"`) + .pc-form-grid-col-60 + .ignite-form-field + -var chainedMapperModel = `${nameMapperModel}.Chained` + + +form-field__label({label: 'Chained name mappers:', name: '"ChainedNameMappers"'}) + +form-field__tooltip({title: `Chained name mappers`}) + + -var items = `${chainedMapperModel}.mappers` + list-editable.pc-list-editable-with-form-grid(ng-model=items name='chainedNameMappers') + list-editable-item-edit.pc-form-grid-row + - form = '$parent.form' + .pc-form-grid-col-60 + +form-field__dropdown({ + label: 'Name mapper:', + model: '$item.kind', + name: '"ChainedNameMapperKind"', + disabled: `!(${enabled})`, + placeholder: 'Custom', + options: '[\ + {value: "Basic", label: "Basic"},\ + {value: "Kerberos", label: "Kerberos"},\ + {value: "Custom", label: "Custom"}\ + ]', + tip: 'File system factory:\ + <ul>\ + <li>Basic - Maps one user name to another based on predefined dictionary</li>\ + <li>Kerberos - Map simple user name to Kerberos principal</li>\ + <li>Custom - Custom user name mapper</li>\ + </ul>' + }) + .pc-form-group.pc-form-grid-row(ng-if=`$item.kind === "Basic"`) + +basic-name-mapper(`$item.Basic`) + .pc-form-group.pc-form-grid-row(ng-if=`$item.kind === "Kerberos"`) + +kerberos-name-mapper(`$item.Kerberos`) + .pc-form-group.pc-form-grid-row(ng-if=`$item.kind === "Custom"`) + +custom-name-mapper(`$item.Custom`, '') + + list-editable-no-items + list-editable-add-item-button( + add-item=`$ctrl.IGFSs.addSecondaryFsNameMapper(${model})` + label-single='name mapper' + label-multiple='name mappers' + ) + + - form = 'secondaryFileSystem' + .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind !== "Custom" && ${nameMapperModel}.kind === "Basic"`) + +basic-name-mapper(`${nameMapperModel}.Basic`) + .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind !== "Custom" && ${nameMapperModel}.kind === "Kerberos"`) + +kerberos-name-mapper(`${nameMapperModel}.Kerberos`) + .pc-form-group.pc-form-grid-row(ng-if=`${secondaryFileSystem}.kind !== "Custom" && ${nameMapperModel}.kind === "Custom"`) + +custom-name-mapper(`${nameMapperModel}.Custom`, '') + .pc-form-grid-col-60(ng-if=`${secondaryFileSystem}.kind === "Custom"`) + +form-field__java-class({ + label: 'Class:', + model: `${secondaryFileSystem}.Custom.className`, + name: '"customFilesystemFactory"', + required: true, + tip: 'File system factory implementation class name', + validationActive: required + }) + .pca-form-column-6 +preview-xml-java(model, 'igfsSecondFS') diff --git a/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js b/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js index 73b0a08..2a81b4d 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/AbstractTransformer.js @@ -191,8 +191,8 @@ export default class AbstractTransformer { } // Generate ssl group. - static clusterSsl(cluster) { - return this.toSection(this.generator.clusterSsl(cluster)); + static clusterSsl(cluster, available) { + return this.toSection(this.generator.clusterSsl(cluster, available)); } // Generate swap group. @@ -260,6 +260,11 @@ export default class AbstractTransformer { return this.toSection(this.generator.cacheAffinity(cache, available)); } + // Generate cache key configuration. + static cacheKeyConfiguration(cache, available) { + return this.toSection(this.generator.cacheKeyConfiguration(cache, available)); + } + // Generate cache memory group. static cacheMemory(cache, available) { return this.toSection(this.generator.cacheMemory(cache, available)); @@ -280,6 +285,11 @@ export default class AbstractTransformer { return this.toSection(this.generator.cacheConcurrency(cache, available)); } + // Generate cache misc group. + static cacheMisc(cache, available) { + return this.toSection(this.generator.cacheMisc(cache, available)); + } + // Generate cache node filter group. static cacheNodeFilter(cache, igfss) { return this.toSection(this.generator.cacheNodeFilter(cache, igfss)); diff --git a/modules/web-console/frontend/app/configuration/generator/generator/Beans.js b/modules/web-console/frontend/app/configuration/generator/generator/Beans.js index 3bd0c0f..7eae6f9 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/Beans.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/Beans.js @@ -260,6 +260,13 @@ export class Bean extends EmptyBean { return this._property(this.properties, 'PATH', model, name, nonEmpty); } + pathArrayProperty(id, name, items, varArg) { + if (items && items.length) + this.properties.push({clsName: 'PATH_ARRAY', id, name, items, varArg, typeClsName: 'PATH'}); + + return this; + } + classProperty(model, name = model) { return this._property(this.properties, 'java.lang.Class', model, name, nonEmpty); } diff --git a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js index 973db07..26833be 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js @@ -123,7 +123,7 @@ export default class IgniteConfigurationGenerator { this.clusterQuery(cluster, available, cfg); this.clusterServiceConfiguration(cluster.serviceConfigurations, cluster.caches, cfg); - this.clusterSsl(cluster, cfg); + this.clusterSsl(cluster, available, cfg); // Deprecated in ignite 2.0 if (available(['1.0.0', '2.0.0'])) @@ -1784,7 +1784,7 @@ export default class IgniteConfigurationGenerator { } // Java code generator for cluster's SSL configuration. - static clusterSsl(cluster, cfg = this.igniteConfigurationBean(cluster)) { + static clusterSsl(cluster, available, cfg = this.igniteConfigurationBean(cluster)) { if (cluster.sslEnabled && nonNil(cluster.sslContextFactory)) { const bean = new Bean('org.apache.ignite.ssl.SslContextFactory', 'sslCtxFactory', cluster.sslContextFactory); @@ -1812,6 +1812,11 @@ export default class IgniteConfigurationGenerator { bean.intProperty('trustStoreType'); } + if (available('2.7.0')) { + bean.varArgProperty('cipherSuites', 'cipherSuites', cluster.sslContextFactory.cipherSuites) + .varArgProperty('protocols', 'protocols', cluster.sslContextFactory.protocols); + } + cfg.beanProperty('sslContextFactory', bean); } @@ -2132,6 +2137,29 @@ export default class IgniteConfigurationGenerator { return ccfg; } + // Generate key configurations of cache. + static cacheKeyConfiguration(keyCfgs, available, cfg = this.igniteConfigurationBean()) { + if (available('2.1.0')) { + const items = _.reduce(keyCfgs, (acc, keyCfg) => { + if (keyCfg.typeName && keyCfg.affinityKeyFieldName) { + acc.push(new Bean('org.apache.ignite.cache.CacheKeyConfiguration', null, keyCfg) + .stringConstructorArgument('typeName') + .stringConstructorArgument('affinityKeyFieldName')); + } + + return acc; + }, []); + + if (_.isEmpty(items)) + return cfg; + + cfg.arrayProperty('keyConfiguration', 'keyConfiguration', items, + 'org.apache.ignite.cache.CacheKeyConfiguration'); + } + + return cfg; + } + // Generate cache memory group. static cacheMemory(cache, available, ccfg = this.cacheConfigurationBean(cache)) { // Since ignite 2.0 @@ -2172,6 +2200,15 @@ export default class IgniteConfigurationGenerator { .boolProperty('swapEnabled'); } + if (cache.cacheWriterFactory) + ccfg.beanProperty('cacheWriterFactory', new EmptyBean(cache.cacheWriterFactory)); + + if (cache.cacheLoaderFactory) + ccfg.beanProperty('cacheLoaderFactory', new EmptyBean(cache.cacheLoaderFactory)); + + if (cache.expiryPolicyFactory) + ccfg.beanProperty('expiryPolicyFactory', new EmptyBean(cache.expiryPolicyFactory)); + return ccfg; } @@ -2207,6 +2244,13 @@ export default class IgniteConfigurationGenerator { .intProperty('sqlIndexMaxInlineSize'); } + if (available('2.4.0') && cache.sqlOnheapCacheEnabled) { + ccfg.boolProperty('sqlOnheapCacheEnabled') + .intProperty('sqlOnheapCacheMaxSize'); + } + + ccfg.intProperty('maxQueryIteratorsCount'); + return ccfg; } @@ -2301,7 +2345,8 @@ export default class IgniteConfigurationGenerator { ccfg.beanProperty('cacheStoreFactory', bean); } - ccfg.boolProperty('storeKeepBinary') + ccfg.intProperty('storeConcurrentLoadAllThreshold') + .boolProperty('storeKeepBinary') .boolProperty('loadPreviousValue') .boolProperty('readThrough') .boolProperty('writeThrough'); @@ -2399,6 +2444,31 @@ export default class IgniteConfigurationGenerator { return ccfg; } + // Generate miscellaneous configuration. + static cacheMisc(cache, available, cfg = this.cacheConfigurationBean(cache)) { + if (cache.interceptor) + cfg.beanProperty('interceptor', new EmptyBean(cache.interceptor)); + + if (available('2.0.0')) + cfg.boolProperty('storeByValue'); + + cfg.boolProperty('eagerTtl'); + + if (available('2.7.0')) + cfg.boolProperty('encryptionEnabled'); + + if (available('2.5.0')) + cfg.boolProperty('eventsDisabled'); + + if (cache.cacheStoreSessionListenerFactories) { + const factories = _.map(cache.cacheStoreSessionListenerFactories, (factory) => new EmptyBean(factory)); + + cfg.varArgProperty('cacheStoreSessionListenerFactories', 'cacheStoreSessionListenerFactories', factories, 'javax.cache.configuration.Factory'); + } + + return cfg; + } + // Generate server near cache group. static cacheNearServer(cache, available, ccfg = this.cacheConfigurationBean(cache)) { if (ccfg.valueOf('cacheMode') === 'PARTITIONED' && _.get(cache, 'nearConfiguration.enabled')) { @@ -2463,11 +2533,13 @@ export default class IgniteConfigurationGenerator { this.cacheMemory(cache, available, ccfg); this.cacheQuery(cache, cache.domains, available, ccfg); this.cacheStore(cache, cache.domains, available, deps, ccfg); + this.cacheKeyConfiguration(cache.keyConfiguration, available, ccfg); const igfs = _.get(cache, 'nodeFilter.IGFS.instance'); this.cacheNodeFilter(cache, igfs ? [igfs] : [], ccfg); this.cacheConcurrency(cache, available, ccfg); this.cacheRebalance(cache, ccfg); + this.cacheMisc(cache, available, ccfg); this.cacheNearServer(cache, available, ccfg); this.cacheStatistics(cache, ccfg); this.cacheDomains(cache.domains, available, ccfg); @@ -2493,6 +2565,48 @@ export default class IgniteConfigurationGenerator { return cfg; } + static _userNameMapperBean(mapper) { + let bean = null; + + switch (mapper.kind) { + case 'Chained': + bean = new Bean('org.apache.ignite.hadoop.util.ChainedUserNameMapper', 'mameMapper', mapper.Chained); + + bean.arrayProperty('mappers', 'mappers', + _.map(_.get(mapper, 'Chained.mappers'), IgniteConfigurationGenerator._userNameMapperBean), + 'org.apache.ignite.hadoop.util.UserNameMapper'); + + break; + + case 'Basic': + bean = new Bean('org.apache.ignite.hadoop.util.BasicUserNameMapper', 'mameMapper', mapper.Basic, igfsDflts.secondaryFileSystem.userNameMapper.Basic); + + bean.stringProperty('defaultUserName') + .boolProperty('useDefaultUserName') + .mapProperty('mappings', 'mappings'); + + break; + + case 'Kerberos': + bean = new Bean('org.apache.ignite.hadoop.util.KerberosUserNameMapper', 'nameMapper', mapper.Kerberos); + + bean.stringProperty('instance') + .stringProperty('realm'); + + break; + + case 'Custom': + if (_.get(mapper, 'Custom.className')) + bean = new EmptyBean(mapper.Custom.className); + + break; + + default: + } + + return bean; + } + // Generate IGFS secondary file system group. static igfsSecondFS(igfs, cfg = this.igfsConfigurationBean(igfs)) { if (igfs.secondaryFileSystemEnabled) { @@ -2503,11 +2617,46 @@ export default class IgniteConfigurationGenerator { bean.stringProperty('userName', 'defaultUserName'); - const factoryBean = new Bean('org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory', - 'fac', secondFs); + let factoryBean = null; - factoryBean.stringProperty('uri') - .pathProperty('cfgPath', 'configPaths'); + switch (secondFs.kind || 'Caching') { + case 'Caching': + factoryBean = new Bean('org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory', 'fac', secondFs); + break; + + case 'Kerberos': + factoryBean = new Bean('org.apache.ignite.hadoop.fs.KerberosHadoopFileSystemFactory', 'fac', secondFs, igfsDflts.secondaryFileSystem); + break; + + case 'Custom': + if (_get(secondFs, 'Custom.className')) + factoryBean = new Bean(secondFs.Custom.className, 'fac', null); + + break; + + default: + } + + if (!factoryBean) + return cfg; + + if (secondFs.kind !== 'Custom') { + factoryBean.stringProperty('uri') + .pathArrayProperty('cfgPaths', 'configPaths', secondFs.cfgPaths, true); + + if (secondFs.kind === 'Kerberos') { + factoryBean.stringProperty('Kerberos.keyTab', 'keyTab') + .stringProperty('Kerberos.keyTabPrincipal', 'keyTabPrincipal') + .longProperty('Kerberos.reloginInterval', 'reloginInterval'); + } + + if (_.get(secondFs, 'userNameMapper.kind')) { + const mapper = IgniteConfigurationGenerator._userNameMapperBean(secondFs.userNameMapper); + + if (mapper) + factoryBean.beanProperty('userNameMapper', mapper); + } + } bean.beanProperty('fileSystemFactory', factoryBean); diff --git a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js index 9ea1e7f..fdaf829 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js @@ -400,6 +400,7 @@ export default class IgniteJavaTransformer extends AbstractTransformer { case 'java.lang.String': return `"${item.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`; case 'PATH': + case 'PATH_ARRAY': return `"${item.replace(/\\/g, '\\\\')}"`; case 'java.lang.Class': return `${this.javaTypes.shortClassName(item)}.class`; @@ -614,6 +615,13 @@ export default class IgniteJavaTransformer extends AbstractTransformer { this._setArray(sb, id, prop, vars, limitLines); break; + case 'PATH_ARRAY': + if (prop.varArg) + this._setVarArg(sb, id, prop, this._toObject(prop.clsName, prop.items), limitLines); + else + this._setArray(sb, id, prop, this._toObject(prop.clsName, prop.items), limitLines); + + break; case 'COLLECTION': const nonBean = !this._isBean(prop.typeClsName); diff --git a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js index 5442b79..83ffdeb 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js @@ -193,7 +193,7 @@ export default class IgniteMavenGenerator { if (_.get(cache, 'nodeFilter.kind') === 'Exclude') this.addDependency(deps, 'org.apache.ignite', 'ignite-extdata-p2p', igniteVer); - if (cache.diskPageCompression) + if (cache.diskPageCompression && versionService.since(igniteVer, '2.8.0')) this.addDependency(deps, 'org.apache.ignite', 'ignite-compress', igniteVer); }); diff --git a/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js b/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js index 21efd11..db9109b 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js @@ -100,6 +100,7 @@ export default class IgniteSpringTransformer extends AbstractTransformer { return `${item}`; case 'java.lang.String': case 'PATH': + case 'PATH_ARRAY': return this.escapeXml(item); default: return item; @@ -209,6 +210,7 @@ export default class IgniteSpringTransformer extends AbstractTransformer { break; case 'ARRAY': + case 'PATH_ARRAY': case 'COLLECTION': this._setCollection(sb, prop); diff --git a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js index e3c69b6..ff06400 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js @@ -48,6 +48,7 @@ const DFLT_CACHE = { sqlEscapeAll: false } }, + storeConcurrentLoadAllThreshold: 5, readThrough: false, writeThrough: false, writeBehindEnabled: false, @@ -123,7 +124,13 @@ const DFLT_CACHE = { memoryPolicyName: 'default', diskPageCompression: { clsName: 'org.apache.ignite.configuration.DiskPageCompression' - } + }, + sqlOnheapCacheEnabled: false, + sqlOnheapCacheMaxSize: 0, + storeByValue: false, + encryptionEnabled: false, + eventsDisabled: false, + maxQueryIteratorsCount: 1024 }; export default class IgniteCacheDefaults { diff --git a/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js b/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js index ff72d50..056742a 100644 --- a/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js +++ b/modules/web-console/frontend/app/configuration/generator/generator/defaults/IGFS.service.js @@ -21,7 +21,20 @@ const DFLT_IGFS = { value: 'DUAL_ASYNC' }, secondaryFileSystem: { - + userNameMapper: { + Basic: { + mappings: { + keyClsName: 'java.lang.String', + valClsName: 'java.lang.String', + keyField: 'name', + valField: 'value', + entries: [] + } + } + }, + Kerberos: { + reloginInterval: 600000 + } }, ipcEndpointConfiguration: { type: { diff --git a/modules/web-console/frontend/app/configuration/services/Caches.ts b/modules/web-console/frontend/app/configuration/services/Caches.ts index 4a15c93..8ee2b48 100644 --- a/modules/web-console/frontend/app/configuration/services/Caches.ts +++ b/modules/web-console/frontend/app/configuration/services/Caches.ts @@ -69,7 +69,8 @@ export default class Caches { writeBehindCoalescing: true, nearConfiguration: {}, sqlFunctionClasses: [], - domains: [] + domains: [], + eagerTtl: true }; } diff --git a/modules/web-console/frontend/app/configuration/services/IGFSs.ts b/modules/web-console/frontend/app/configuration/services/IGFSs.ts index b4c3039..3cfa99e 100644 --- a/modules/web-console/frontend/app/configuration/services/IGFSs.ts +++ b/modules/web-console/frontend/app/configuration/services/IGFSs.ts @@ -41,7 +41,10 @@ export default class IGFSs { ipcEndpointEnabled: true, fragmentizerEnabled: true, colocateMetadata: true, - relaxedConsistency: true + relaxedConsistency: true, + secondaryFileSystem: { + kind: 'Caching' + } }; } @@ -76,4 +79,15 @@ export default class IGFSs { }; normalize = omit(['__v', 'space', 'clusters']); + + addSecondaryFsNameMapper(igfs) { + if (!_.get(igfs, 'secondaryFileSystem.userNameMapper.Chained.mappers')) + _.set(igfs, 'secondaryFileSystem.userNameMapper.Chained.mappers', []); + + const item = {_id: ObjectID.generate(), kind: 'Basic'}; + + _.get(igfs, 'secondaryFileSystem.userNameMapper.Chained.mappers').push(item); + + return item; + } } diff --git a/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java b/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java index c15b4c7..4665fee 100644 --- a/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java +++ b/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.ignite.binary.BinaryTypeConfiguration; +import org.apache.ignite.cache.CacheKeyConfiguration; import org.apache.ignite.cache.QueryEntity; import org.apache.ignite.cache.QueryIndex; import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction; @@ -54,7 +55,11 @@ import org.apache.ignite.configuration.SqlConnectorConfiguration; import org.apache.ignite.configuration.TransactionConfiguration; import org.apache.ignite.hadoop.fs.CachingHadoopFileSystemFactory; import org.apache.ignite.hadoop.fs.IgniteHadoopIgfsSecondaryFileSystem; +import org.apache.ignite.hadoop.fs.KerberosHadoopFileSystemFactory; import org.apache.ignite.hadoop.mapreduce.IgniteHadoopWeightedMapReducePlanner; +import org.apache.ignite.hadoop.util.BasicUserNameMapper; +import org.apache.ignite.hadoop.util.ChainedUserNameMapper; +import org.apache.ignite.hadoop.util.KerberosUserNameMapper; import org.apache.ignite.igfs.IgfsGroupDataBlocksKeyMapper; import org.apache.ignite.igfs.IgfsIpcEndpointConfiguration; import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller; @@ -167,7 +172,6 @@ public class WebConsoleConfigurationSelfTest { igniteCfgProps.add("serviceThreadPoolSize"); igniteCfgProps.add("managementThreadPoolSize"); igniteCfgProps.add("igfsThreadPoolSize"); - igniteCfgProps.add("rebalanceThreadPoolSize"); igniteCfgProps.add("utilityCacheThreadPoolSize"); igniteCfgProps.add("utilityCacheKeepAliveTime"); igniteCfgProps.add("asyncCallbackPoolSize"); @@ -208,6 +212,12 @@ public class WebConsoleConfigurationSelfTest { metadata.put(IgniteConfiguration.class, new MetadataInfo(igniteCfgProps, igniteCfgPropsDep, igniteCfgPropsExcl)); + Set<String> cacheKeyCfgProps = new HashSet<>(); + cacheKeyCfgProps.add("typeName"); + cacheKeyCfgProps.add("affinityKeyFieldName"); + + metadata.put(CacheKeyConfiguration.class, new MetadataInfo(cacheKeyCfgProps, EMPTY_FIELDS, EMPTY_FIELDS)); + Set<String> atomicCfgProps = new HashSet<>(); atomicCfgProps.add("cacheMode"); atomicCfgProps.add("atomicSequenceReserveSize"); @@ -619,6 +629,8 @@ public class WebConsoleConfigurationSelfTest { // Only on code generation. sslCfgProps.add("trustStorePassword"); sslCfgProps.add("trustStoreType"); + sslCfgProps.add("cipherSuites"); + sslCfgProps.add("protocols"); metadata.put(SslContextFactory.class, new MetadataInfo(sslCfgProps, EMPTY_FIELDS, EMPTY_FIELDS)); Set<String> executorProps = new HashSet<>(); @@ -646,7 +658,7 @@ public class WebConsoleConfigurationSelfTest { cacheCfgProps.add("partitionLossPolicy"); cacheCfgProps.add("readFromBackup"); cacheCfgProps.add("copyOnRead"); - cacheCfgProps.add("isInvalidate"); + cacheCfgProps.add("invalidate"); cacheCfgProps.add("affinityMapper"); cacheCfgProps.add("topologyValidator"); cacheCfgProps.add("maxConcurrentAsyncOperations"); @@ -658,7 +670,7 @@ public class WebConsoleConfigurationSelfTest { // cacheCfgProps.add("memoryMode"); // cacheCfgProps.add("offHeapMode"); // cacheCfgProps.add("offHeapMaxMemory"); - cacheCfgProps.add("evictionPolicy"); + cacheCfgProps.add("evictionPolicyFactory"); cacheCfgProps.add("evictionFilter"); // Removed since 2.0. // cacheCfgProps.add("startSize"); @@ -696,15 +708,37 @@ public class WebConsoleConfigurationSelfTest { cacheCfgProps.add("indexedTypes"); cacheCfgProps.add("queryEntities"); cacheCfgProps.add("pluginConfigurations"); + cacheCfgProps.add("cacheWriterFactory"); + cacheCfgProps.add("cacheLoaderFactory"); + cacheCfgProps.add("expiryPolicyFactory"); + cacheCfgProps.add("storeConcurrentLoadAllThreshold"); + cacheCfgProps.add("sqlIndexMaxInlineSize"); + cacheCfgProps.add("sqlOnheapCacheEnabled"); + cacheCfgProps.add("sqlOnheapCacheMaxSize"); + cacheCfgProps.add("diskPageCompression"); + cacheCfgProps.add("diskPageCompressionLevel"); + cacheCfgProps.add("interceptor"); + cacheCfgProps.add("storeByValue"); + cacheCfgProps.add("eagerTtl"); + cacheCfgProps.add("encryptionEnabled"); + cacheCfgProps.add("eventsDisabled"); + cacheCfgProps.add("maxQueryIteratorsCount"); + cacheCfgProps.add("keyConfiguration"); + cacheCfgProps.add("cacheStoreSessionListenerFactories"); + cacheCfgProps.add("affinity"); Set<String> cacheCfgPropsDep = new HashSet<>(); // Removed since 2.0. // cacheCfgPropsDep.add("atomicWriteOrderMode"); cacheCfgPropsDep.add("memoryPolicyName"); cacheCfgPropsDep.add("longQueryWarningTimeout"); + cacheCfgPropsDep.add("rebalanceThreadPoolSize"); + cacheCfgPropsDep.add("transactionManagerLookupClassName"); + cacheCfgPropsDep.add("evictionPolicy"); Set<String> cacheCfgPropsExcl = new HashSet<>(); cacheCfgPropsExcl.add("nodeFilter"); + cacheCfgPropsExcl.add("types"); metadata.put(CacheConfiguration.class, new MetadataInfo(cacheCfgProps, cacheCfgPropsDep, cacheCfgPropsExcl)); @@ -815,9 +849,38 @@ public class WebConsoleConfigurationSelfTest { Set<String> cachingIgfsCfgProps = new HashSet<>(); cachingIgfsCfgProps.add("uri"); cachingIgfsCfgProps.add("configPaths"); + cachingIgfsCfgProps.add("userNameMapper"); metadata.put(CachingHadoopFileSystemFactory.class, new MetadataInfo(cachingIgfsCfgProps, EMPTY_FIELDS, EMPTY_FIELDS)); + Set<String> kerberosIgfsCfgProps = new HashSet<>(); + kerberosIgfsCfgProps.add("uri"); + kerberosIgfsCfgProps.add("configPaths"); + kerberosIgfsCfgProps.add("userNameMapper"); + kerberosIgfsCfgProps.add("keyTab"); + kerberosIgfsCfgProps.add("keyTabPrincipal"); + kerberosIgfsCfgProps.add("reloginInterval"); + + metadata.put(KerberosHadoopFileSystemFactory.class, new MetadataInfo(kerberosIgfsCfgProps, EMPTY_FIELDS, EMPTY_FIELDS)); + + Set<String> chainedIgfsUsrNameMapperProps = new HashSet<>(); + chainedIgfsUsrNameMapperProps.add("mappers"); + + metadata.put(ChainedUserNameMapper.class, new MetadataInfo(chainedIgfsUsrNameMapperProps, EMPTY_FIELDS, EMPTY_FIELDS)); + + Set<String> basicIgfsUsrNameMapperProps = new HashSet<>(); + basicIgfsUsrNameMapperProps.add("defaultUserName"); + basicIgfsUsrNameMapperProps.add("useDefaultUserName"); + basicIgfsUsrNameMapperProps.add("mappings"); + + metadata.put(BasicUserNameMapper.class, new MetadataInfo(basicIgfsUsrNameMapperProps, EMPTY_FIELDS, EMPTY_FIELDS)); + + Set<String> kerberosIgfsUsrNameMapperProps = new HashSet<>(); + kerberosIgfsUsrNameMapperProps.add("instance"); + kerberosIgfsUsrNameMapperProps.add("realm"); + + metadata.put(KerberosUserNameMapper.class, new MetadataInfo(kerberosIgfsUsrNameMapperProps, EMPTY_FIELDS, EMPTY_FIELDS)); + Set<String> ipcEndpointProps = new HashSet<>(); ipcEndpointProps.add("type"); ipcEndpointProps.add("host");