diff --git a/distro/pom.xml b/distro/pom.xml index d7e95888949..cde50ff75e7 100644 --- a/distro/pom.xml +++ b/distro/pom.xml @@ -35,7 +35,7 @@ false false - atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.HBaseBasedAuditRepository + solr #Solr #Solr cloud mode properties @@ -60,11 +60,11 @@ atlas.graph.index.search.solr.wait-searcher=false # plugins: https://docs.janusgraph.org/latest/elasticsearch.html #atlas.graph.index.search.hostname=localhost #atlas.graph.index.search.elasticsearch.client-only=true - hbase2 + #Hbase #For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here -atlas.graph.storage.hostname= +#for distributed mode, specify zookeeper quorum here (comma-separated); empty values break Janus STRING options. +atlas.graph.storage.hostname=localhost atlas.graph.storage.hbase.regions-per-server=1 #In order to use Cassandra as a backend, comment out the hbase specific properties above, and uncomment the @@ -588,6 +588,101 @@ atlas.graph.storage.hbase.regions-per-server=1 + + + storage-berkeleyje + + false + + + # BerkeleyJE — local graph under ATLAS_HOME; edit paths if needed +atlas.graph.storage.directory=${sys:atlas.home}/data/berkeley +atlas.graph.storage.lock.clean-expired=true +atlas.graph.storage.lock.expiry-time=500 +atlas.graph.storage.lock.wait-time=300 + + + + storage-rdbms + + false + + + # RDBMS — PostgreSQL example; edit host, db, user, password before starting Atlas +atlas.graph.storage.rdbms.jpa.hikari.connectionTestQuery=select 1 +atlas.graph.storage.rdbms.jpa.hikari.connectionTimeout=30000 +atlas.graph.storage.rdbms.jpa.hikari.driverClassName=org.postgresql.Driver +atlas.graph.storage.rdbms.jpa.hikari.idleTimeout=300000 +atlas.graph.storage.rdbms.jpa.hikari.jdbcUrl=jdbc:postgresql://localhost:5432/atlas +atlas.graph.storage.rdbms.jpa.hikari.maxLifetime=1800000 +atlas.graph.storage.rdbms.jpa.hikari.maximumPoolSize=40 +atlas.graph.storage.rdbms.jpa.hikari.minimumIdle=5 +atlas.graph.storage.rdbms.jpa.hikari.password=atlas +atlas.graph.storage.rdbms.jpa.hikari.username=atlas +atlas.graph.storage.rdbms.jpa.javax.persistence.jdbc.dialect=org.eclipse.persistence.platform.database.PostgreSQLPlatform +atlas.graph.storage.rdbms.jpa.javax.persistence.schema-generation.create-database-schemas=true +atlas.graph.storage.rdbms.jpa.javax.persistence.schema-generation.create-script-source=META-INF/postgres/create_schema.sql +atlas.graph.storage.rdbms.jpa.javax.persistence.schema-generation.create-source=script +atlas.graph.storage.rdbms.jpa.javax.persistence.schema-generation.database.action=create + + + + index-elasticsearch + + false + + + elasticsearch + # Elasticsearch — set hostname to your cluster or load balancer +atlas.graph.index.search.elasticsearch.client-only=true +atlas.graph.index.search.hostname=localhost + + + + storage-cassandra + + false + + + # Janus CQL — point at your Cassandra nodes (comma-separated). Keyspace is created/used by Janus as configured. +atlas.graph.storage.cql.keyspace=janusgraph +atlas.graph.storage.hostname=127.0.0.1 + + + + audit-cassandra + + false + + + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.CassandraBasedAuditRepository + + + + index-solr + + false + + + # Solr Cloud (set zookeeper-url to your Solr/ZK ensemble) +atlas.graph.index.search.solr.mode=cloud +atlas.graph.index.search.solr.zookeeper-url=localhost:2181 +atlas.graph.index.search.solr.zookeeper-connect-timeout=60000 +atlas.graph.index.search.solr.zookeeper-session-timeout=60000 +atlas.graph.index.search.solr.wait-searcher=false + +# Solr http mode (alternative) +#atlas.graph.index.search.solr.mode=http +#atlas.graph.index.search.solr.http-urls=http://localhost:8983/solr + + + embedded-cassandra-solr diff --git a/distro/src/bin/atlas_config.py b/distro/src/bin/atlas_config.py index 70030ac5cce..7e78593cf70 100755 --- a/distro/src/bin/atlas_config.py +++ b/distro/src/bin/atlas_config.py @@ -104,7 +104,14 @@ def hbaseBinDir(dir): return os.path.join(dir, "hbase", BIN) def hbaseConfDir(dir): - return os.environ.get(HBASE_CONF_DIR, os.path.join(dir, "hbase", CONF)) + """Resolve HBase client conf dir. Relative HBASE_CONF_DIR is resolved against Atlas home so + atlas_start.py works when run from bin/ (cwd is not the install root).""" + conf = os.environ.get(HBASE_CONF_DIR) + if conf: + if not os.path.isabs(conf): + conf = os.path.normpath(os.path.join(dir, conf)) + return conf + return os.path.join(dir, "hbase", CONF) def zookeeperBinDir(dir): return os.environ.get(SOLR_BIN, os.path.join(dir, "zk", BIN)) diff --git a/distro/src/conf/atlas-application.properties b/distro/src/conf/atlas-application.properties index b5734d7a8de..c1b6798a530 100755 --- a/distro/src/conf/atlas-application.properties +++ b/distro/src/conf/atlas-application.properties @@ -18,21 +18,25 @@ ######### Graph Database Configs ######### +atlas.build.storage.backend=${atlas.storage.backend} +atlas.build.index.backend=${atlas.index.backend} + # Graph Database #Configures the graph database to use. Defaults to JanusGraph #atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase # Graph Storage -# Set atlas.graph.storage.backend to the correct value for your desired storage -# backend. Possible values: +# Set atlas.graph.storage.backend to the JanusGraph storage short name (see Janus docs). +# Common values: # -# hbase -# cassandra -# embeddedcassandra - Should only be set by building Atlas with -Pdist,embedded-cassandra-solr +# hbase2 (HBase 2.x; Atlas builds often set this via Maven graph.storage.backend) +# cql (Cassandra via Janus CQL backend — use this, not the word "cassandra", or Janus will look for a Java class) +# embeddedcassandra - Only when building with -Pdist,embedded-cassandra-solr (Atlas embedded stack) # berkeleyje +# rdbms # -# See the configuration documentation for more information about configuring the various storage backends. +# See the configuration documentation for more information about configuring the various storage backends. # atlas.graph.storage.backend=${graph.storage.backend} atlas.graph.storage.hbase.table=apache_atlas_janus diff --git a/distro/src/main/assemblies/atlas-server-package.xml b/distro/src/main/assemblies/atlas-server-package.xml index ba2e2665207..4bf1170ad84 100755 --- a/distro/src/main/assemblies/atlas-server-package.xml +++ b/distro/src/main/assemblies/atlas-server-package.xml @@ -52,6 +52,15 @@ 0755 + + + src/main/hbase-conf + hbase/conf + 0644 + 0755 + + target/hbase hbase diff --git a/distro/src/main/assemblies/standalone-package.xml b/distro/src/main/assemblies/standalone-package.xml index 56b338232eb..a747060cf18 100755 --- a/distro/src/main/assemblies/standalone-package.xml +++ b/distro/src/main/assemblies/standalone-package.xml @@ -64,6 +64,13 @@ 0755 + + src/main/hbase-conf + hbase/conf + 0644 + 0755 + + target/hbase hbase diff --git a/distro/src/main/hbase-conf/hbase-site.xml b/distro/src/main/hbase-conf/hbase-site.xml new file mode 100644 index 00000000000..efebdc6a9f4 --- /dev/null +++ b/distro/src/main/hbase-conf/hbase-site.xml @@ -0,0 +1,31 @@ + + + + + + hbase.zookeeper.quorum + localhost + + + hbase.zookeeper.property.clientPort + 2181 + + diff --git a/graphdb/janus/pom.xml b/graphdb/janus/pom.xml index cd07c909800..228bf720eeb 100644 --- a/graphdb/janus/pom.xml +++ b/graphdb/janus/pom.xml @@ -35,6 +35,7 @@ Some dependencies, like slf4j are excluded from the jar because they are included in Atlas --> + hbase true false @@ -51,23 +52,10 @@ atlas-graphdb-common ${project.version} - - org.apache.atlas - hbase-shaded-client-fixed - ${project.version} - - - org.apache.atlas - janusgraph-rdbms - ${project.version} - - - ch.qos.logback - * - - - + org.apache.commons commons-configuration2 @@ -84,22 +72,6 @@ commons-text ${commons-text.version} - - org.apache.hadoop - hadoop-distcp - ${hadoop.version} - - - org.apache.hbase - hbase-shaded-mapreduce - ${hbase.version}-hadoop3 - - - org.apache.hadoop - hadoop-distcp - - - org.apache.lucene lucene-analyzers-common @@ -167,89 +139,6 @@ tinkergraph-gremlin ${tinkerpop.version} - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - org.janusgraph - janusgraph-berkeleyje - ${janusgraph.version} - - - ch.qos.logback - * - - - org.noggit - noggit - - - - - - org.janusgraph - janusgraph-cassandra - ${janusgraph.cassandra.version} - - - ch.qos.logback - * - - - com.codahale.metrics - metrics-core - - - - - - org.janusgraph - janusgraph-cql - ${janusgraph.version} - - - ch.qos.logback - * - - - - - - org.janusgraph - janusgraph-es - ${janusgraph.version} - - - ch.qos.logback - * - - - - - - org.janusgraph - janusgraph-hbase - ${janusgraph.version} - - - ch.qos.logback - * - - - org.apache.hbase - hbase-shaded-client - - - org.apache.hbase - hbase-shaded-mapreduce - - - - org.janusgraph janusgraph-lucene @@ -287,6 +176,26 @@ org.apache.tinkerpop gremlin-shaded + + org.janusgraph + janusgraph-berkeleyje + + + org.janusgraph + janusgraph-cassandra + + + org.janusgraph + janusgraph-cql + + + org.janusgraph + janusgraph-es + + + org.janusgraph + janusgraph-hbase + org.noggit noggit @@ -384,4 +293,144 @@ + + + atlas-storage-hbase + + + atlas.storage.backend + hbase + + + + + org.apache.atlas + hbase-shaded-client-fixed + ${project.version} + + + org.apache.hadoop + hadoop-distcp + ${hadoop.version} + + + org.apache.hbase + hbase-shaded-mapreduce + ${hbase.version}-hadoop3 + + + org.apache.hadoop + hadoop-distcp + + + + + org.janusgraph + janusgraph-hbase + ${janusgraph.version} + + + ch.qos.logback + * + + + org.apache.hbase + hbase-shaded-client + + + org.apache.hbase + hbase-shaded-mapreduce + + + + + + + atlas-storage-cassandra + + + atlas.storage.backend + cassandra + + + + + org.janusgraph + janusgraph-cql + ${janusgraph.version} + + + ch.qos.logback + * + + + + + + + atlas-storage-berkeleyje + + + atlas.storage.backend + berkeleyje + + + + + org.janusgraph + janusgraph-berkeleyje + ${janusgraph.version} + + + ch.qos.logback + * + + + org.noggit + noggit + + + + + + + atlas-storage-rdbms + + + atlas.storage.backend + rdbms + + + + + org.apache.atlas + janusgraph-rdbms + ${project.version} + + + ch.qos.logback + * + + + + + + + atlas-index-elasticsearch + + + atlas.index.backend + elasticsearch + + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch.version} + + + + + diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java index 2286231fab0..1f575c76d5a 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java @@ -137,7 +137,7 @@ public AtlasJanusGraph(JanusGraph graphInstance) { } if (StringUtils.equalsIgnoreCase(AtlasConfiguration.STORAGE_BACKEND_TYPE.getString(), "rdbms")) { - uniqueKeyHandler = new AtlasJanusRdbmsUniqueKeyHandler(); + uniqueKeyHandler = newRdbmsUniqueKeyHandlerOrNull(); } else { uniqueKeyHandler = null; } @@ -150,6 +150,20 @@ public AtlasJanusGraph(JanusGraph graphInstance) { janusGraph = (StandardJanusGraph) graphInstance; } + private static AtlasUniqueKeyHandler newRdbmsUniqueKeyHandlerOrNull() { + final String handlerClass = "org.apache.atlas.repository.graphdb.janus.AtlasJanusRdbmsUniqueKeyHandler"; + + try { + Class clz = Class.forName(handlerClass); + + return (AtlasUniqueKeyHandler) clz.getDeclaredConstructor().newInstance(); + } catch (Throwable t) { + LOG.warn("RDBMS storage is configured but {} is not available on the classpath", handlerClass, t); + + return null; + } + } + @Override public AtlasEdge addEdge(AtlasVertex outVertex, AtlasVertex inVertex, String edgeLabel) { try { diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java index 186b817d4fa..9e5f8c9d3ea 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java @@ -31,6 +31,7 @@ import org.apache.atlas.typesystem.types.DataTypes.TypeCategory; import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.ConfigurationConverter; +import org.apache.commons.lang3.StringUtils; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphException; @@ -38,10 +39,6 @@ import org.janusgraph.core.schema.JanusGraphManagement; import org.janusgraph.diskstorage.StandardIndexProvider; import org.janusgraph.diskstorage.StandardStoreManager; -import org.janusgraph.diskstorage.es.ElasticSearch7Index; -import org.janusgraph.diskstorage.hbase.HBaseStoreManager; -import org.janusgraph.diskstorage.rdbms.RdbmsStoreManager; -import org.janusgraph.diskstorage.solr.Solr6Index; import org.janusgraph.graphdb.database.serialize.attribute.SerializableSerializer; import org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry; import org.slf4j.Logger; @@ -54,7 +51,10 @@ import java.math.BigInteger; import java.time.Duration; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; @@ -71,17 +71,28 @@ public class AtlasJanusGraphDatabase implements GraphDatabase FQCN in Janus {@code StandardStoreManager} without loading the class first. + * Pre-loading with {@link Class#forName(String)} caused missing map entries when the class was not yet + * visible to the caller's loader at static init time, leading Janus to treat {@code hbase2} as a class name. + * Implementation classes are loaded when the graph opens. + */ + private static void safeRegisterStoreManager(String shortName, String managerClassName) { try { - Field field = StandardStoreManager.class.getDeclaredField("ALL_MANAGER_CLASSES"); + injectStoreManager(shortName, managerClassName); + } catch (Throwable t) { + LOG.warn("Failed to register Janus storage backend '{}' -> {}", shortName, managerClassName, t); + } + } - field.setAccessible(true); + private static void injectStoreManager(String shortName, String managerClassName) throws Exception { + Field field = StandardStoreManager.class.getDeclaredField("ALL_MANAGER_CLASSES"); - Field modifiersField = Field.class.getDeclaredField("modifiers"); + field.setAccessible(true); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + Field modifiersField = Field.class.getDeclaredField("modifiers"); - Map customMap = new HashMap<>(StandardStoreManager.getAllManagerClasses()); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - customMap.put("hbase2", HBaseStoreManager.class.getName()); + Map customMap = new HashMap<>(StandardStoreManager.getAllManagerClasses()); - ImmutableMap immap = ImmutableMap.copyOf(customMap); + customMap.put(shortName, managerClassName); - field.set(null, immap); + field.set(null, ImmutableMap.copyOf(customMap)); - LOG.debug("Injected HBase2 support - {}", HBaseStoreManager.class.getName()); - } catch (Exception e) { - throw new RuntimeException(e); - } + LOG.debug("Registered Janus storage backend {} -> {}", shortName, managerClassName); } - private static void addRdbmsSupport() { + private static void safeRegisterIndexProvider(String shortName, String providerClassName) { try { - Field field = StandardStoreManager.class.getDeclaredField("ALL_MANAGER_CLASSES"); + injectIndexProvider(shortName, providerClassName); + } catch (Throwable t) { + LOG.warn("Failed to register Janus index provider '{}' -> {}", shortName, providerClassName, t); + } + } - field.setAccessible(true); + private static void injectIndexProvider(String shortName, String providerClassName) throws Exception { + Field field = StandardIndexProvider.class.getDeclaredField("ALL_MANAGER_CLASSES"); - Field modifiersField = Field.class.getDeclaredField("modifiers"); + field.setAccessible(true); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + Field modifiersField = Field.class.getDeclaredField("modifiers"); - Map customMap = new HashMap<>(StandardStoreManager.getAllManagerClasses()); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - customMap.put("rdbms", RdbmsStoreManager.class.getName()); + Map customMap = new HashMap<>(StandardIndexProvider.getAllProviderClasses()); - ImmutableMap immap = ImmutableMap.copyOf(customMap); + customMap.put(shortName, providerClassName); - field.set(null, immap); + field.set(null, ImmutableMap.copyOf(customMap)); - LOG.debug("Injected RDBMS support - {}", RdbmsStoreManager.class.getName()); - } catch (Exception e) { - throw new RuntimeException(e); - } + LOG.debug("Registered Janus index provider {} -> {}", shortName, providerClassName); } - private static void addSolr6Index() { - try { - Field field = StandardIndexProvider.class.getDeclaredField("ALL_MANAGER_CLASSES"); + private static void registerJanusOptionalBackends() { + registerStoreIfLoadable("hbase2", HBASE2_STORE_MANAGER_CLASS); + registerStoreIfLoadable("cql", CQL_STORE_MANAGER_CLASS); + registerStoreIfLoadable("rdbms", RDBMS_STORE_MANAGER_CLASS); + registerIndexIfLoadable("solr", SOLR6_INDEX_CLASS); + registerIndexIfLoadable("elasticsearch", ELASTICSEARCH7_INDEX_CLASS); + } - field.setAccessible(true); + private static void registerStoreIfLoadable(String shortName, String managerClassName) { + if (!isClassLoadable(managerClassName)) { + LOG.debug("Skipping Janus storage backend {}: {} not on classpath", shortName, managerClassName); - Field modifiersField = Field.class.getDeclaredField("modifiers"); + return; + } - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + safeRegisterStoreManager(shortName, managerClassName); + } - Map customMap = new HashMap<>(StandardIndexProvider.getAllProviderClasses()); + private static void registerIndexIfLoadable(String shortName, String providerClassName) { + if (!isClassLoadable(providerClassName)) { + LOG.debug("Skipping Janus index provider {}: {} not on classpath", shortName, providerClassName); - customMap.put("solr", Solr6Index.class.getName()); + return; + } - ImmutableMap immap = ImmutableMap.copyOf(customMap); + safeRegisterIndexProvider(shortName, providerClassName); + } - field.set(null, immap); + private static boolean isClassLoadable(String className) { + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader atlasLoader = AtlasJanusGraphDatabase.class.getClassLoader(); - LOG.debug("Injected solr6 index - {}", Solr6Index.class.getName()); - } catch (Exception e) { - throw new RuntimeException(e); + if (contextLoader != null && isClassLoadable(className, contextLoader)) { + return true; } - } - - private static void addElasticSearch7Index() { - try { - Field field = StandardIndexProvider.class.getDeclaredField("ALL_MANAGER_CLASSES"); - field.setAccessible(true); + if (atlasLoader != null && isClassLoadable(className, atlasLoader)) { + return true; + } - Field modifiersField = Field.class.getDeclaredField("modifiers"); + return isClassLoadable(className, ClassLoader.getSystemClassLoader()); + } - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + private static boolean isClassLoadable(String className, ClassLoader loader) { + if (loader == null) { + return false; + } - Map customMap = new HashMap<>(StandardIndexProvider.getAllProviderClasses()); + try { + Class.forName(className, false, loader); - customMap.put("elasticsearch", ElasticSearch7Index.class.getName()); + return true; + } catch (ClassNotFoundException e) { + return false; + } catch (LinkageError e) { + LOG.debug("Class {} not loadable with loader {}: {}", className, loader, e.toString()); - ImmutableMap immap = ImmutableMap.copyOf(customMap); + return false; + } + } - field.set(null, immap); + private static boolean isClasspathResourcePresent(String resourcePath) { + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader atlasLoader = AtlasJanusGraphDatabase.class.getClassLoader(); - LOG.debug("Injected es7 index - {}", ElasticSearch7Index.class.getName()); - } catch (Exception e) { - throw new RuntimeException(e); - } + return (contextLoader != null && contextLoader.getResource(resourcePath) != null) + || (atlasLoader != null && atlasLoader.getResource(resourcePath) != null); } private static void updateGlobalConfiguration(Map map) { @@ -438,10 +588,160 @@ private static void updateGlobalConfiguration(Map map) { } } + /** + * Spring/YAML list properties and {@code setProperty(key, String[])} (e.g. Solr ZK URLs) become {@code String[]}. + * JanusGraph {@code ConfigOption} values typed as STRING reject arrays and fail with + * {@code Invalid configuration value for [root.storage.hostname]: [Ljava.lang.String;@...}. + */ + private static void normalizeStringArrayValuesForJanus(Configuration janusConfig) { + ArrayList keys = new ArrayList<>(); + + for (Iterator it = janusConfig.getKeys(); it.hasNext(); ) { + keys.add(it.next()); + } + + for (String key : keys) { + Object val = janusConfig.getProperty(key); + + if (val instanceof String[]) { + String[] arr = (String[]) val; + + if (arr.length == 0) { + janusConfig.clearProperty(key); + } else { + janusConfig.setProperty(key, String.join(",", arr)); + } + } else if (val instanceof List) { + List list = (List) val; + + if (list.isEmpty()) { + janusConfig.clearProperty(key); + } else { + janusConfig.setProperty(key, joinCommaList(list)); + } + } + } + } + + /** + * {@link Configuration#getKeys()} on subset configs can omit keys that are only + * present as multi-valued / list types, so {@link #normalizeStringArrayValuesForJanus} may skip them. + * Janus {@code storage.hostname} is a STRING for HBase and CQL ({@link org.janusgraph.diskstorage.common.DistributedStoreManager}). + */ + private static void coerceCriticalJanusStringOptions(Configuration janusConfig) { + coerceSingleJanusString(janusConfig, "storage.hostname"); + } + + private static void coerceSingleJanusString(Configuration cfg, String key) { + Object val = cfg.getProperty(key); + + if (val == null || val instanceof String) { + return; + } + + if (val instanceof String[]) { + String[] arr = (String[]) val; + + cfg.setProperty(key, arr.length == 0 ? "" : String.join(",", arr)); + } else if (val instanceof List) { + cfg.setProperty(key, joinCommaList((List) val)); + } else { + cfg.setProperty(key, val.toString()); + } + } + + private static String joinCommaList(List list) { + StringBuilder sb = new StringBuilder(); + + for (Object o : list) { + if (sb.length() > 0) { + sb.append(','); + } + + sb.append(o != null ? o.toString() : ""); + } + + return sb.toString(); + } + + /** + * {@link ConfigurationConverter#getProperties} can leave {@code String[]} / {@link List} values inside + * {@link Properties}; {@link org.apache.commons.configuration2.ConfigurationConverter#getConfiguration(Properties)} + * then passes those through to JanusGraph unchanged. + */ + private static void sanitizePropertiesForJanus(Properties properties) { + synchronized (properties) { + for (Enumeration e = properties.keys(); e.hasMoreElements(); ) { + String key = String.valueOf(e.nextElement()); + Object val = properties.get(key); + + if (val instanceof String[]) { + String[] arr = (String[]) val; + + properties.put(key, arr.length == 0 ? "" : String.join(",", arr)); + } else if (val instanceof List) { + properties.put(key, joinCommaList((List) val)); + } + } + + // Hashtable-backed Properties may still omit non-String values from keys(); force known Janus STRING keys. + Object hostnameVal = properties.get("storage.hostname"); + + if (hostnameVal instanceof String[]) { + String[] arr = (String[]) hostnameVal; + + properties.put("storage.hostname", arr.length == 0 ? "" : String.join(",", arr)); + } else if (hostnameVal instanceof List) { + properties.put("storage.hostname", joinCommaList((List) hostnameVal)); + } + } + } + private static org.apache.commons.configuration2.Configuration createConfiguration2(Configuration conf) { + normalizeStringArrayValuesForJanus(conf); + coerceCriticalJanusStringOptions(conf); + Properties properties = ConfigurationConverter.getProperties(conf); - return org.apache.commons.configuration2.ConfigurationConverter.getConfiguration(properties); + sanitizePropertiesForJanus(properties); + + org.apache.commons.configuration2.Configuration cfg2 = + org.apache.commons.configuration2.ConfigurationConverter.getConfiguration(properties); + + // getConfiguration(Properties) can still surface String[] for keys Janus expects as STRING (e.g. storage.hostname). + coerceStringArraysInConfiguration2(cfg2); + + return cfg2; + } + + /** + * Final pass: Janus {@code storage.hostname} (and similar STRING options) must not be {@code String[]} after + * {@link org.apache.commons.configuration2.ConfigurationConverter#getConfiguration(Properties)}. + */ + private static void coerceStringArraysInConfiguration2(org.apache.commons.configuration2.Configuration cfg) { + if (cfg == null) { + return; + } + + ArrayList keys = new ArrayList<>(); + + for (Iterator it = cfg.getKeys(); it.hasNext(); ) { + keys.add(it.next()); + } + + for (String key : keys) { + Object val = cfg.getProperty(key); + + if (val instanceof String[]) { + String[] arr = (String[]) val; + + cfg.setProperty(key, arr.length == 0 ? "" : String.join(",", arr)); + } else if (val instanceof List) { + List list = (List) val; + + cfg.setProperty(key, list.isEmpty() ? "" : joinCommaList(list)); + } + } } private static void startEmbeddedSolr() throws AtlasException { @@ -479,11 +779,6 @@ private static void stopEmbeddedSolr() throws AtlasException { } static { - addHBase2Support(); - addRdbmsSupport(); - - addSolr6Index(); - - addElasticSearch7Index(); + registerJanusOptionalBackends(); } } diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java index 8b81d54ef5b..343177f1dcf 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java @@ -42,13 +42,12 @@ import org.apache.solr.client.solrj.response.TermsResponse; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.util.NamedList; -import org.janusgraph.diskstorage.es.ElasticSearch7Index; -import org.janusgraph.diskstorage.es.ElasticSearchClient; import org.janusgraph.diskstorage.solr.Solr6Index; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -476,11 +475,28 @@ private boolean isSolrHealthy() throws SolrServerException, IOException { return client != null && client.ping(Constants.VERTEX_INDEX).getStatus() == SOLR_HEALTHY_STATUS; } - private boolean isElasticsearchHealthy() throws IOException { - ElasticSearchClient client = ElasticSearch7Index.getElasticSearchClient(); - String janusVertexIndex = ApplicationProperties.DEFAULT_INDEX_NAME + "_" + Constants.VERTEX_INDEX; + private boolean isElasticsearchHealthy() { + try { + Class esIndexClass = Class.forName("org.janusgraph.diskstorage.es.ElasticSearch7Index"); + Method getClient = esIndexClass.getMethod("getElasticSearchClient"); + Object client = getClient.invoke(null); + + if (client == null) { + return false; + } - return client != null && client.indexExists(janusVertexIndex); + Method indexExists = client.getClass().getMethod("indexExists", String.class); + String janusVertexIndex = ApplicationProperties.DEFAULT_INDEX_NAME + "_" + Constants.VERTEX_INDEX; + Object exists = indexExists.invoke(client, janusVertexIndex); + + return Boolean.TRUE.equals(exists); + } catch (ClassNotFoundException e) { + LOG.debug("Elasticsearch index implementation not on classpath; skipping health check"); + return false; + } catch (ReflectiveOperationException e) { + LOG.debug("Elasticsearch health check failed: {}", e.getMessage()); + return false; + } } private SolrResponse updateFreeTextRequestHandler(SolrClient solrClient, String collectionName, Map indexFieldName2SearchWeightMap, Solr6Index.Mode mode) throws IOException, SolrServerException, AtlasBaseException { diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasBuildBackendAlignmentTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasBuildBackendAlignmentTest.java new file mode 100644 index 00000000000..3482e1c0d97 --- /dev/null +++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasBuildBackendAlignmentTest.java @@ -0,0 +1,48 @@ +/** + * 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. + */ +package org.apache.atlas.repository.graphdb.janus; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class AtlasBuildBackendAlignmentTest { + @Test + public void testStorageBackendCompatibility() { + assertTrue(AtlasJanusGraphDatabase.isStorageBackendCompatible("hbase", "hbase2")); + assertTrue(AtlasJanusGraphDatabase.isStorageBackendCompatible("hbase", "hbase")); + assertFalse(AtlasJanusGraphDatabase.isStorageBackendCompatible("hbase", "rdbms")); + + assertTrue(AtlasJanusGraphDatabase.isStorageBackendCompatible("cassandra", "cql")); + assertTrue(AtlasJanusGraphDatabase.isStorageBackendCompatible("cassandra", "embeddedcassandra")); + assertFalse(AtlasJanusGraphDatabase.isStorageBackendCompatible("cassandra", "hbase2")); + + assertTrue(AtlasJanusGraphDatabase.isStorageBackendCompatible("rdbms", "rdbms")); + assertFalse(AtlasJanusGraphDatabase.isStorageBackendCompatible("rdbms", "cql")); + + assertTrue(AtlasJanusGraphDatabase.isStorageBackendCompatible("berkeleyje", "berkeleyje")); + } + + @Test + public void testIndexBackendCompatibility() { + assertTrue(AtlasJanusGraphDatabase.isIndexBackendCompatible("solr", "solr")); + assertFalse(AtlasJanusGraphDatabase.isIndexBackendCompatible("solr", "elasticsearch")); + assertTrue(AtlasJanusGraphDatabase.isIndexBackendCompatible("elasticsearch", "elasticsearch")); + } +} diff --git a/graphdb/janusgraph-rdbms/pom.xml b/graphdb/janusgraph-rdbms/pom.xml index a501515cd40..9ac9fed1234 100644 --- a/graphdb/janusgraph-rdbms/pom.xml +++ b/graphdb/janusgraph-rdbms/pom.xml @@ -40,7 +40,8 @@ org.apache.atlas - atlas-intg + atlas-graphdb-api + ${project.version} org.eclipse.persistence diff --git a/hbase-shaded-client-fixed/pom.xml b/hbase-shaded-client-fixed/pom.xml index 09e75bae4aa..2d89578da33 100644 --- a/hbase-shaded-client-fixed/pom.xml +++ b/hbase-shaded-client-fixed/pom.xml @@ -73,6 +73,29 @@ + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-unpacked-hbase-to-classes + + copy-resources + + process-resources + + ${project.build.directory}/classes + + + ${project.build.directory}/unpacked + + + + + + + org.apache.maven.plugins diff --git a/pom.xml b/pom.xml index c0f4c05b022..c29131dc8df 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,12 @@ 4.7 1.0 1.8.7 + hbase + solr + hbase + + 1.7.5 1.16.0 false @@ -111,12 +116,13 @@ 2.7.15 7.17.8 org.apache.atlas.repository.audit.InMemoryEntityAuditRepository + atlas.EntityAuditRepository.impl=${entity.repository.impl} 2.13.2 2.18.1 0.8 6.5.16 solr - berkeleyje + hbase2 2.9.0 25.1-jre 4.1.0 @@ -2285,12 +2291,98 @@ - embedded-cassandra-solr + dist + + false + - ${guava.version} + hbase + solr + hbase + + + org.apache.atlas.repository.audit.HBaseBasedAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.HBaseBasedAuditRepository + solr + hbase2 + false + + + + audit-cassandra + + + atlas.audit.backend + cassandra + + + + cassandra + WEB-INF/lib/hbase-shaded-client-fixed-*.jar, + org.apache.atlas.repository.audit.CassandraBasedAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.CassandraBasedAuditRepository + + + + audit-hbase + + + atlas.audit.backend + hbase + + + + hbase + + org.apache.atlas.repository.audit.HBaseBasedAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.HBaseBasedAuditRepository + + + + audit-inmemory + + + atlas.audit.backend + inmemory + + + + inmemory + WEB-INF/lib/hbase-shaded-client-fixed-*.jar, + org.apache.atlas.repository.audit.InMemoryEntityAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository + + + + audit-noop + + + atlas.audit.backend + noop + + + + noop + WEB-INF/lib/hbase-shaded-client-fixed-*.jar, + org.apache.atlas.repository.audit.NoopEntityAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.NoopEntityAuditRepository + + + + audit-rdbms + + + atlas.audit.backend + rdbms + + + + rdbms + WEB-INF/lib/hbase-shaded-client-fixed-*.jar, + org.apache.atlas.repository.audit.rdbms.RdbmsBasedAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.rdbms.RdbmsBasedAuditRepository - distributed @@ -2298,24 +2390,23 @@ false + hbase + solr + hbase org.apache.atlas.repository.audit.HBaseBasedAuditRepository + atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.HBaseBasedAuditRepository solr - hbase + hbase2 localhost localhost:9983 - - dist - - false - + embedded-cassandra-solr - false + ${guava.version} - - graph-provider-default @@ -2337,8 +2427,10 @@ + solr WEB-INF/lib/je-*.jar,WEB-INF/lib/solr-test-framework-*.jar, WEB-INF/lib/jts-*.jar,WEB-INF/lib/dom4j-*.jar,WEB-INF/lib/ant-*.jar solr + hbase2 atlas-graphdb-janus org.apache.atlas org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase @@ -2346,7 +2438,6 @@ true - graph-provider-janus @@ -2356,8 +2447,10 @@ + solr WEB-INF/lib/je-*.jar,WEB-INF/lib/solr-test-framework-*.jar, WEB-INF/lib/jts-*.jar,WEB-INF/lib/dom4j-*.jar,WEB-INF/lib/ant-*.jar solr + hbase2 atlas-graphdb-janus org.apache.atlas org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase @@ -2365,13 +2458,63 @@ true - + + index-elasticsearch + + + atlas.index.backend + elasticsearch + + + + elasticsearch + elasticsearch + + + + index-solr + + solr + + skipMinify build - + + storage-berkeleyje + + berkeleyje + WEB-INF/lib/janusgraph-hbase-*.jar,WEB-INF/lib/hadoop-distcp-*.jar,WEB-INF/lib/hbase-shaded-mapreduce-*.jar, + berkeleyje + + + + storage-cassandra + + + cassandra + WEB-INF/lib/janusgraph-hbase-*.jar,WEB-INF/lib/hadoop-distcp-*.jar,WEB-INF/lib/hbase-shaded-mapreduce-*.jar, + cql + + + + storage-hbase + + hbase + + hbase2 + + + + storage-rdbms + + rdbms + WEB-INF/lib/janusgraph-hbase-*.jar,WEB-INF/lib/hadoop-distcp-*.jar,WEB-INF/lib/hbase-shaded-mapreduce-*.jar, + rdbms + + diff --git a/repository/pom.xml b/repository/pom.xml index 000c5197ac2..0f6874ebe9b 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -61,7 +61,6 @@ - com.opencsv opencsv @@ -157,7 +156,6 @@ - org.apache.commons commons-lang3 @@ -215,12 +213,6 @@ mockito-all - - org.postgresql - postgresql - ${postgresql.version} - - org.springframework spring-aop @@ -233,6 +225,12 @@ ${spring.version} + + org.postgresql + postgresql + ${postgresql.version} + + org.testng testng @@ -282,6 +280,7 @@ test-jar test + org.cassandraunit cassandra-unit @@ -294,7 +293,6 @@ - diff --git a/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java b/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java index cf8fef41be3..22cf7994245 100644 --- a/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java +++ b/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java @@ -20,7 +20,6 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.repository.audit.EntityAuditRepository; -import org.apache.atlas.repository.audit.HBaseBasedAuditRepository; import org.apache.atlas.repository.graphdb.GraphDatabase; import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; @@ -58,6 +57,8 @@ public class AtlasRepositoryConfiguration { private static final String DEFAULT_GRAPH_DATABASE_IMPLEMENTATION_CLASS = JANUS_GRAPH_DATABASE_IMPLEMENTATION_CLASS; private static final String ENTITY_NOTIFICATION_VERSION_PROPERTY = "atlas.notification.entity.version"; private static final String AUDIT_REPOSITORY_IMPLEMENTATION_PROPERTY = "atlas.EntityAuditRepository.impl"; + /** Default when property unset; implementation class is in atlas-repository. */ + private static final String DEFAULT_AUDIT_REPOSITORY_IMPL_CLASS = "org.apache.atlas.repository.audit.HBaseBasedAuditRepository"; private static final String DELETE_HANDLER_V1_IMPLEMENTATION_PROPERTY = "atlas.DeleteHandlerV1.impl"; private static final boolean DEFAULT_GREMLIN_OPTIMZER_ENABLED = true; @@ -103,7 +104,7 @@ public static Class getAuditRepositoryImpl() { try { Configuration config = ApplicationProperties.get(); - return ApplicationProperties.getClass(config, AUDIT_REPOSITORY_IMPLEMENTATION_PROPERTY, HBaseBasedAuditRepository.class.getName(), EntityAuditRepository.class); + return ApplicationProperties.getClass(config, AUDIT_REPOSITORY_IMPLEMENTATION_PROPERTY, DEFAULT_AUDIT_REPOSITORY_IMPL_CLASS, EntityAuditRepository.class); } catch (AtlasException e) { throw new RuntimeException(e); } diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociatorTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociatorTest.java index 0e787d78970..09a48997613 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociatorTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociatorTest.java @@ -31,11 +31,12 @@ import org.apache.atlas.utils.AtlasJson; import org.apache.atlas.utils.TestResourceFileUtils; import org.apache.commons.lang3.StringUtils; -import org.elasticsearch.common.util.CollectionUtils; import org.testng.annotations.Test; import java.io.IOException; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -125,7 +126,9 @@ public void updaterEntityWithUniqueName() throws IOException, AtlasBaseException AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); AtlasTypeRegistry.AtlasTransientTypeRegistry ttr = typeRegistry.lockTypeRegistryForUpdate(); - ttr.addTypes(CollectionUtils.newSingletonArrayList(ed)); + List entityDefs = new ArrayList<>(1); + entityDefs.add(ed); + ttr.addTypes(entityDefs); AtlasGraph atlasGraph = mock(AtlasGraph.class); ClassificationAssociatorUpdaterForSpy updater = new ClassificationAssociatorUpdaterForSpy(atlasGraph, ttr, entitiesStore, "col-entity-PII"); diff --git a/tools/atlas-index-repair/pom.xml b/tools/atlas-index-repair/pom.xml index 595034315c9..18a94c3c1e6 100644 --- a/tools/atlas-index-repair/pom.xml +++ b/tools/atlas-index-repair/pom.xml @@ -69,4 +69,23 @@ + + + + index-elasticsearch + + + atlas.index.backend + elasticsearch + + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch.version} + + + + diff --git a/webapp/pom.xml b/webapp/pom.xml index 87760e5d226..a8296521a78 100755 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -208,11 +208,24 @@ atlas-server-api + + + org.apache.atlas + hbase-shaded-client-fixed + ${project.version} + + org.apache.commons commons-collections4 + + org.apache.commons + commons-configuration2 + ${commons-conf2.version} + + org.apache.commons commons-lang3 @@ -261,6 +274,12 @@ + + org.apache.hadoop + hadoop-distcp + ${hadoop.version} + + org.apache.hadoop hadoop-hdfs @@ -299,6 +318,17 @@ + + org.apache.hbase + hbase-shaded-mapreduce + ${hbase.version}-hadoop3 + + + org.apache.hadoop + hadoop-distcp + + + org.apache.httpcomponents @@ -336,18 +366,6 @@ jetty-webapp - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - org.elasticsearch - elasticsearch - - - - org.glassfish javax.el @@ -527,7 +545,7 @@ true - WEB-INF/lib/hbase-shaded-client-${hbase.version}-hadoop3.jar,WEB-INF/lib/dom4j-*.jar,WEB-INF/lib/jsp-api*.jar,${packages.to.exclude} + WEB-INF/lib/hbase-shaded-client-*-hadoop3.jar,WEB-INF/lib/dom4j-*.jar,WEB-INF/lib/jsp-api*.jar,${atlas.war.audit.excludes}${atlas.war.storage.excludes}${packages.to.exclude} @@ -810,6 +828,120 @@ + + storage-berkeleyje + + WEB-INF/lib/janusgraph-hbase-*.jar,WEB-INF/lib/hadoop-distcp-*.jar,WEB-INF/lib/hbase-shaded-mapreduce-*.jar, + + + + org.janusgraph + janusgraph-berkeleyje + ${janusgraph.version} + + + ch.qos.logback + * + + + org.noggit + noggit + + + + + + + storage-cassandra + + WEB-INF/lib/janusgraph-hbase-*.jar,WEB-INF/lib/hadoop-distcp-*.jar,WEB-INF/lib/hbase-shaded-mapreduce-*.jar, + + + + org.janusgraph + janusgraph-cql + ${janusgraph.version} + + + ch.qos.logback + * + + + + + + + storage-hbase + + + atlas.storage.backend + hbase + + + + + org.janusgraph + janusgraph-hbase + ${janusgraph.version} + + + ch.qos.logback + * + + + org.apache.hbase + hbase-shaded-client + + + org.apache.hbase + hbase-shaded-mapreduce + + + + + + + storage-rdbms + + WEB-INF/lib/janusgraph-hbase-*.jar,WEB-INF/lib/hadoop-distcp-*.jar,WEB-INF/lib/hbase-shaded-mapreduce-*.jar, + + + + org.apache.atlas + janusgraph-rdbms + ${project.version} + + + ch.qos.logback + * + + + + + + + index-elasticsearch + + + atlas.index.backend + elasticsearch + + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch.version} + + + org.elasticsearch + elasticsearch + + + + + + dist diff --git a/webapp/src/test/java/org/apache/atlas/web/service/AtlasDebugMetricsSinkTest.java b/webapp/src/test/java/org/apache/atlas/web/service/AtlasDebugMetricsSinkTest.java index 5fb150b0903..64e053b5d12 100644 --- a/webapp/src/test/java/org/apache/atlas/web/service/AtlasDebugMetricsSinkTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/AtlasDebugMetricsSinkTest.java @@ -19,7 +19,6 @@ package org.apache.atlas.web.service; import org.apache.atlas.web.model.DebugMetrics; -import org.apache.hadoop.hbase.shaded.org.apache.commons.configuration2.SubsetConfiguration; import org.apache.hadoop.metrics2.AbstractMetric; import org.apache.hadoop.metrics2.MetricsRecord; import org.mockito.Mock; @@ -45,9 +44,6 @@ public class AtlasDebugMetricsSinkTest { @Mock private AbstractMetric metric; - @Mock - private SubsetConfiguration subsetConfiguration; - private AtlasDebugMetricsSink debugMetricsSink; @BeforeMethod @@ -316,7 +312,7 @@ public void testFlush() { @Test public void testInit() { // Test that init method doesn't throw any exception - debugMetricsSink.init(subsetConfiguration); + debugMetricsSink.init(null); } @Test