You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/10/26 17:20:44 UTC
[2/2] knox git commit: KNOX-1039 - Added admin APIs for managing
shared provider configurations and descriptors (Phil Zampino via Sandeep
More)
KNOX-1039 - Added admin APIs for managing shared provider configurations and descriptors (Phil Zampino via Sandeep More)
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/9ad9bcdb
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/9ad9bcdb
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/9ad9bcdb
Branch: refs/heads/master
Commit: 9ad9bcdbbdb82acdabd05fe1500da9a6f8d22634
Parents: 41952dd
Author: Sandeep More <mo...@apache.org>
Authored: Thu Oct 26 13:20:35 2017 -0400
Committer: Sandeep More <mo...@apache.org>
Committed: Thu Oct 26 13:20:35 2017 -0400
----------------------------------------------------------------------
.../ambari/AmbariServiceDiscovery.java | 3 +-
.../apache/hadoop/gateway/GatewayMessages.java | 34 +-
.../gateway/config/impl/GatewayConfigImpl.java | 3 +-
.../topology/impl/DefaultTopologyService.java | 221 +++++--
.../topology/DefaultTopologyServiceTest.java | 402 +++++++++++--
.../topology/file/provider-config-one.xml | 74 +++
.../topology/file/simple-descriptor-five.json | 14 +
.../topology/file/simple-descriptor-six.json | 18 +
.../service/admin/HrefListingMarshaller.java | 75 +++
.../service/admin/TopologiesResource.java | 379 +++++++++++-
.../hadoop/gateway/i18n/GatewaySpiMessages.java | 10 +-
.../services/topology/TopologyService.java | 33 +-
.../gateway/GatewayAdminTopologyFuncTest.java | 586 +++++++++++++++++++
13 files changed, 1736 insertions(+), 116 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
index 37f68ae..b7f9f53 100644
--- a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
+++ b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariServiceDiscovery.java
@@ -247,10 +247,11 @@ class AmbariServiceDiscovery implements ServiceDiscovery {
}
if (aliasService != null) {
- // If not password alias is configured, then try the default alias
+ // If no password alias is configured, then try the default alias
if (passwordAlias == null) {
passwordAlias = DEFAULT_PWD_ALIAS;
}
+
try {
char[] pwd = aliasService.getPasswordFromAliasForGateway(passwordAlias);
if (pwd != null) {
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
index 6f73c1e..4cb4c40 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
@@ -514,8 +514,40 @@ public interface GatewayMessages {
void topologyPortMappingCannotFindTopology(final String topology, final int port);
+ @Message( level = MessageLevel.INFO, text = "Monitoring simple descriptors in directory: {0}" )
+ void monitoringDescriptorChangesInDirectory(String descriptorsDir);
+
+
+ @Message( level = MessageLevel.INFO, text = "Monitoring shared provider configurations in directory: {0}" )
+ void monitoringProviderConfigChangesInDirectory(String sharedProviderDir);
+
+ @Message( level = MessageLevel.INFO, text = "Prevented deletion of shared provider configuration because there are referencing descriptors: {0}" )
+ void preventedDeletionOfSharedProviderConfiguration(String providerConfigurationPath);
+
+ @Message( level = MessageLevel.INFO, text = "Generated topology {0} because the associated descriptor {1} changed." )
+ void generatedTopologyForDescriptorChange(String topologyName, String descriptorName);
+
@Message( level = MessageLevel.ERROR, text = "An error occurred while processing {0} : {1}" )
void simpleDescriptorHandlingError(final String simpleDesc,
- @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+ @StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+ @Message(level = MessageLevel.DEBUG, text = "Successfully wrote configuration: {0}")
+ void wroteConfigurationFile(final String filePath);
+
+ @Message(level = MessageLevel.ERROR, text = "Failed to write configuration: {0}")
+ void failedToWriteConfigurationFile(final String filePath,
+ @StackTrace(level = MessageLevel.DEBUG) Exception e );
+
+ @Message( level = MessageLevel.INFO, text = "Deleting topology {0} because the associated descriptor {1} was deleted." )
+ void deletingTopologyForDescriptorDeletion(String topologyName, String descriptorName);
+
+ @Message( level = MessageLevel.INFO, text = "Deleting descriptor {0} because the associated topology {1} was deleted." )
+ void deletingDescriptorForTopologyDeletion(String descriptorName, String topologyName);
+
+ @Message( level = MessageLevel.DEBUG, text = "Added descriptor {0} reference to provider configuration {1}." )
+ void addedProviderConfigurationReference(String descriptorName, String providerConfigurationName);
+
+ @Message( level = MessageLevel.DEBUG, text = "Removed descriptor {0} reference to provider configuration {1}." )
+ void removedProviderConfigurationReference(String descriptorName, String providerConfigurationName);
}
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
index 0956a4a..4202a18 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
@@ -17,6 +17,7 @@
*/
package org.apache.hadoop.gateway.config.impl;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
@@ -250,7 +251,7 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
@Override
public String getGatewayConfDir() {
String value = getVar( GATEWAY_CONF_HOME_VAR, getGatewayHomeDir() + File.separator + "conf" );
- return value;
+ return FilenameUtils.normalize(value);
}
@Override
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/main/java/org/apache/hadoop/gateway/services/topology/impl/DefaultTopologyService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/topology/impl/DefaultTopologyService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/topology/impl/DefaultTopologyService.java
index 13e1a3d..39e8029 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/topology/impl/DefaultTopologyService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/topology/impl/DefaultTopologyService.java
@@ -62,6 +62,7 @@ import java.io.FileFilter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -91,8 +92,11 @@ public class DefaultTopologyService
private static DigesterLoader digesterLoader = newLoader(new KnoxFormatXmlTopologyRules(), new AmbariFormatXmlTopologyRules());
private List<FileAlterationMonitor> monitors = new ArrayList<>();
private File topologiesDirectory;
+ private File sharedProvidersDirectory;
private File descriptorsDirectory;
+ private DescriptorsMonitor descriptorsMonitor;
+
private Set<TopologyListener> listeners;
private volatile Map<File, Topology> topologies;
private AliasService aliasService;
@@ -211,8 +215,7 @@ public class DefaultTopologyService
}
private File calculateAbsoluteTopologiesDir(GatewayConfig config) {
- String normalizedTopologyDir = FilenameUtils.normalize(config.getGatewayTopologyDir());
- File topoDir = new File(normalizedTopologyDir);
+ File topoDir = new File(config.getGatewayTopologyDir());
topoDir = topoDir.getAbsoluteFile();
return topoDir;
}
@@ -220,15 +223,10 @@ public class DefaultTopologyService
private File calculateAbsoluteConfigDir(GatewayConfig config) {
File configDir = null;
- String path = FilenameUtils.normalize(config.getGatewayConfDir());
- if (path != null) {
- configDir = new File(config.getGatewayConfDir());
- } else {
- configDir = (new File(config.getGatewayTopologyDir())).getParentFile();
- }
- configDir = configDir.getAbsoluteFile();
+ String path = config.getGatewayConfDir();
+ configDir = (path != null) ? new File(path) : (new File(config.getGatewayTopologyDir())).getParentFile();
- return configDir;
+ return configDir.getAbsoluteFile();
}
private void initListener(FileAlterationMonitor monitor,
@@ -250,31 +248,34 @@ public class DefaultTopologyService
private Map<File, Topology> loadTopologies(File directory) {
Map<File, Topology> map = new HashMap<>();
if (directory.isDirectory() && directory.canRead()) {
- for (File file : directory.listFiles(this)) {
- try {
- Topology loadTopology = loadTopology(file);
- if (null != loadTopology) {
- map.put(file, loadTopology);
- } else {
+ File[] existingTopologies = directory.listFiles(this);
+ if (existingTopologies != null) {
+ for (File file : existingTopologies) {
+ try {
+ Topology loadTopology = loadTopology(file);
+ if (null != loadTopology) {
+ map.put(file, loadTopology);
+ } else {
+ auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
+ ActionOutcome.FAILURE);
+ log.failedToLoadTopology(file.getAbsolutePath());
+ }
+ } catch (IOException e) {
+ // Maybe it makes sense to throw exception
auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
- ActionOutcome.FAILURE);
- log.failedToLoadTopology(file.getAbsolutePath());
+ ActionOutcome.FAILURE);
+ log.failedToLoadTopology(file.getAbsolutePath(), e);
+ } catch (SAXException e) {
+ // Maybe it makes sense to throw exception
+ auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
+ ActionOutcome.FAILURE);
+ log.failedToLoadTopology(file.getAbsolutePath(), e);
+ } catch (Exception e) {
+ // Maybe it makes sense to throw exception
+ auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
+ ActionOutcome.FAILURE);
+ log.failedToLoadTopology(file.getAbsolutePath(), e);
}
- } catch (IOException e) {
- // Maybe it makes sense to throw exception
- auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
- ActionOutcome.FAILURE);
- log.failedToLoadTopology(file.getAbsolutePath(), e);
- } catch (SAXException e) {
- // Maybe it makes sense to throw exception
- auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
- ActionOutcome.FAILURE);
- log.failedToLoadTopology(file.getAbsolutePath(), e);
- } catch (Exception e) {
- // Maybe it makes sense to throw exception
- auditor.audit(Action.LOAD, file.getAbsolutePath(), ResourceType.TOPOLOGY,
- ActionOutcome.FAILURE);
- log.failedToLoadTopology(file.getAbsolutePath(), e);
}
}
}
@@ -356,8 +357,7 @@ public class DefaultTopologyService
File topoDir = topologiesDirectory;
if(topoDir.isDirectory() && topoDir.canRead()) {
- File[] results = topoDir.listFiles();
- for (File f : results) {
+ for (File f : listFiles(topoDir)) {
String fName = FilenameUtils.getBaseName(f.getName());
if(fName.equals(t.getName())) {
f.delete();
@@ -381,9 +381,9 @@ public class DefaultTopologyService
public Map<String, List<String>> getServiceTestURLs(Topology t, GatewayConfig config) {
File tFile = null;
Map<String, List<String>> urls = new HashMap<>();
- if(topologiesDirectory.isDirectory() && topologiesDirectory.canRead()) {
- for(File f : topologiesDirectory.listFiles()){
- if(FilenameUtils.removeExtension(f.getName()).equals(t.getName())){
+ if (topologiesDirectory.isDirectory() && topologiesDirectory.canRead()) {
+ for (File f : listFiles(topologiesDirectory)) {
+ if (FilenameUtils.removeExtension(f.getName()).equals(t.getName())) {
tFile = f;
}
}
@@ -405,6 +405,63 @@ public class DefaultTopologyService
}
@Override
+ public boolean deployProviderConfiguration(String name, String content) {
+ return writeConfig(sharedProvidersDirectory, name, content);
+ }
+
+ @Override
+ public Collection<File> getProviderConfigurations() {
+ List<File> providerConfigs = new ArrayList<>();
+ for (File providerConfig : listFiles(sharedProvidersDirectory)) {
+ if (SharedProviderConfigMonitor.SUPPORTED_EXTENSIONS.contains(FilenameUtils.getExtension(providerConfig.getName()))) {
+ providerConfigs.add(providerConfig);
+ }
+ }
+ return providerConfigs;
+ }
+
+ @Override
+ public boolean deleteProviderConfiguration(String name) {
+ boolean result = false;
+
+ File providerConfig = getExistingFile(sharedProvidersDirectory, name);
+ if (providerConfig != null) {
+ List<String> references = descriptorsMonitor.getReferencingDescriptors(providerConfig.getAbsolutePath());
+ if (references.isEmpty()) {
+ result = providerConfig.delete();
+ } else {
+ log.preventedDeletionOfSharedProviderConfiguration(providerConfig.getAbsolutePath());
+ }
+ } else {
+ result = true; // If it already does NOT exist, then the delete effectively succeeded
+ }
+
+ return result;
+ }
+
+ @Override
+ public boolean deployDescriptor(String name, String content) {
+ return writeConfig(descriptorsDirectory, name, content);
+ }
+
+ @Override
+ public Collection<File> getDescriptors() {
+ List<File> descriptors = new ArrayList<>();
+ for (File descriptor : listFiles(descriptorsDirectory)) {
+ if (DescriptorsMonitor.SUPPORTED_EXTENSIONS.contains(FilenameUtils.getExtension(descriptor.getName()))) {
+ descriptors.add(descriptor);
+ }
+ }
+ return descriptors;
+ }
+
+ @Override
+ public boolean deleteDescriptor(String name) {
+ File descriptor = getExistingFile(descriptorsDirectory, name);
+ return (descriptor == null) || descriptor.delete();
+ }
+
+ @Override
public void addTopologyChangeListener(TopologyListener listener) {
listeners.add(listener);
}
@@ -448,6 +505,7 @@ public class DefaultTopologyService
File simpleDesc =
new File(descriptorsDirectory, FilenameUtils.getBaseName(file.getName()) + "." + ext);
if (simpleDesc.exists()) {
+ log.deletingDescriptorForTopologyDeletion(simpleDesc.getName(), file.getName());
simpleDesc.delete();
}
}
@@ -481,20 +539,22 @@ public class DefaultTopologyService
File configDirectory = calculateAbsoluteConfigDir(config);
descriptorsDirectory = new File(configDirectory, "descriptors");
- File sharedProvidersDirectory = new File(configDirectory, "shared-providers");
+ sharedProvidersDirectory = new File(configDirectory, "shared-providers");
// Add support for conf/topologies
initListener(topologiesDirectory, this, this);
// Add support for conf/descriptors
- DescriptorsMonitor dm = new DescriptorsMonitor(topologiesDirectory, aliasService);
+ descriptorsMonitor = new DescriptorsMonitor(topologiesDirectory, aliasService);
initListener(descriptorsDirectory,
- dm,
- dm);
+ descriptorsMonitor,
+ descriptorsMonitor);
+ log.monitoringDescriptorChangesInDirectory(descriptorsDirectory.getAbsolutePath());
// Add support for conf/shared-providers
- SharedProviderConfigMonitor spm = new SharedProviderConfigMonitor(dm, descriptorsDirectory);
+ SharedProviderConfigMonitor spm = new SharedProviderConfigMonitor(descriptorsMonitor, descriptorsDirectory);
initListener(sharedProvidersDirectory, spm, spm);
+ log.monitoringProviderConfigChangesInDirectory(sharedProvidersDirectory.getAbsolutePath());
// For all the descriptors currently in the descriptors dir at start-up time, trigger topology generation.
// This happens prior to the start-up loading of the topologies.
@@ -502,7 +562,7 @@ public class DefaultTopologyService
if (descriptorFilenames != null) {
for (String descriptorFilename : descriptorFilenames) {
if (DescriptorsMonitor.isDescriptorFile(descriptorFilename)) {
- dm.onFileChange(new File(descriptorsDirectory, descriptorFilename));
+ descriptorsMonitor.onFileChange(new File(descriptorsDirectory, descriptorFilename));
}
}
}
@@ -514,6 +574,70 @@ public class DefaultTopologyService
/**
+ * Utility method for listing the files in the specified directory.
+ * This method is "nicer" than the File#listFiles() because it will not return null.
+ *
+ * @param directory The directory whose files should be returned.
+ *
+ * @return A List of the Files on the directory.
+ */
+ private static List<File> listFiles(File directory) {
+ List<File> result = null;
+ File[] files = directory.listFiles();
+ if (files != null) {
+ result = Arrays.asList(files);
+ } else {
+ result = Collections.emptyList();
+ }
+ return result;
+ }
+
+ /**
+ * Search for a file in the specified directory whose base name (filename without extension) matches the
+ * specified basename.
+ *
+ * @param directory The directory in which to search.
+ * @param basename The basename of interest.
+ *
+ * @return The matching File
+ */
+ private static File getExistingFile(File directory, String basename) {
+ File match = null;
+ for (File file : listFiles(directory)) {
+ if (FilenameUtils.getBaseName(file.getName()).equals(basename)) {
+ match = file;
+ break;
+ }
+ }
+ return match;
+ }
+
+ /**
+ * Write the specified content to a file.
+ *
+ * @param dest The destination directory.
+ * @param name The name of the file.
+ * @param content The contents of the file.
+ *
+ * @return true, if the write succeeds; otherwise, false.
+ */
+ private static boolean writeConfig(File dest, String name, String content) {
+ boolean result = false;
+
+ File destFile = new File(dest, name);
+ try {
+ FileUtils.writeStringToFile(destFile, content);
+ log.wroteConfigurationFile(destFile.getAbsolutePath());
+ result = true;
+ } catch (IOException e) {
+ log.failedToWriteConfigurationFile(destFile.getAbsolutePath(), e);
+ }
+
+ return result;
+ }
+
+
+ /**
* Change handler for simple descriptors
*/
public static class DescriptorsMonitor extends FileAlterationListenerAdaptor
@@ -543,7 +667,7 @@ public class DefaultTopologyService
}
List<String> getReferencingDescriptors(String providerConfigPath) {
- List<String> result = providerConfigReferences.get(providerConfigPath);
+ List<String> result = providerConfigReferences.get(FilenameUtils.normalize(providerConfigPath));
if (result == null) {
result = Collections.emptyList();
}
@@ -562,6 +686,7 @@ public class DefaultTopologyService
File topologyFile =
new File(topologiesDir, FilenameUtils.getBaseName(file.getName()) + "." + ext);
if (topologyFile.exists()) {
+ log.deletingTopologyForDescriptorDeletion(topologyFile.getName(), file.getName());
topologyFile.delete();
}
}
@@ -574,8 +699,10 @@ public class DefaultTopologyService
break;
}
}
+
if (reference != null) {
providerConfigReferences.get(reference).remove(normalizedFilePath);
+ log.removedProviderConfigurationReference(normalizedFilePath, reference);
}
}
@@ -584,6 +711,7 @@ public class DefaultTopologyService
try {
// When a simple descriptor has been created or modified, generate the new topology descriptor
Map<String, File> result = SimpleDescriptorHandler.handle(file, topologiesDir, aliasService);
+ log.generatedTopologyForDescriptorChange(result.get("topology").getName(), file.getName());
// Add the provider config reference relationship for handling updates to the provider config
String providerConfig = FilenameUtils.normalize(result.get("reference").getAbsolutePath());
@@ -602,6 +730,7 @@ public class DefaultTopologyService
// Add the current reference relationship
refs.add(descriptorName);
+ log.addedProviderConfigurationReference(descriptorName, providerConfig);
}
} catch (Exception e) {
log.simpleDescriptorHandlingError(file.getName(), e);
@@ -662,7 +791,7 @@ public class DefaultTopologyService
private List<File> getReferencingDescriptors(File sharedProviderConfig) {
List<File> references = new ArrayList<>();
- for (File descriptor : descriptorsDir.listFiles()) {
+ for (File descriptor : listFiles(descriptorsDir)) {
if (DescriptorsMonitor.SUPPORTED_EXTENSIONS.contains(FilenameUtils.getExtension(descriptor.getName()))) {
for (String reference : descriptorsMonitor.getReferencingDescriptors(FilenameUtils.normalize(sharedProviderConfig.getAbsolutePath()))) {
references.add(new File(reference));
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/test/java/org/apache/hadoop/gateway/services/topology/DefaultTopologyServiceTest.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/java/org/apache/hadoop/gateway/services/topology/DefaultTopologyServiceTest.java b/gateway-server/src/test/java/org/apache/hadoop/gateway/services/topology/DefaultTopologyServiceTest.java
index 498d750..2357ad6 100644
--- a/gateway-server/src/test/java/org/apache/hadoop/gateway/services/topology/DefaultTopologyServiceTest.java
+++ b/gateway-server/src/test/java/org/apache/hadoop/gateway/services/topology/DefaultTopologyServiceTest.java
@@ -18,16 +18,15 @@
package org.apache.hadoop.gateway.services.topology;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.hadoop.gateway.config.GatewayConfig;
import org.apache.hadoop.gateway.services.security.AliasService;
import org.apache.hadoop.gateway.services.topology.impl.DefaultTopologyService;
import org.apache.hadoop.gateway.topology.*;
-import org.apache.hadoop.gateway.topology.discovery.ServiceDiscovery;
-import org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryConfig;
-import org.apache.hadoop.gateway.topology.discovery.ServiceDiscoveryFactory;
import org.apache.hadoop.test.TestUtils;
import org.easymock.EasyMock;
import org.junit.After;
@@ -38,13 +37,24 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.isA;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -86,12 +96,6 @@ public class DefaultTopologyServiceTest {
File dir = createDir();
File topologyDir = new File(dir, "topologies");
- File descriptorsDir = new File(dir, "descriptors");
- descriptorsDir.mkdirs();
-
- File sharedProvidersDir = new File(dir, "shared-providers");
- sharedProvidersDir.mkdirs();
-
long time = topologyDir.lastModified();
try {
createFile(topologyDir, "one.xml", "org/apache/hadoop/gateway/topology/file/topology-one.xml", time);
@@ -104,7 +108,7 @@ public class DefaultTopologyServiceTest {
GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
- EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
+ EasyMock.expect(config.getGatewayConfDir()).andReturn(topologyDir.getParentFile().getAbsolutePath()).anyTimes();
EasyMock.replay(config);
provider.init(config, c);
@@ -167,59 +171,371 @@ public class DefaultTopologyServiceTest {
assertThat(topology.getName(), is("one"));
assertThat(topology.getTimestamp(), is(time));
+ } finally {
+ FileUtils.deleteQuietly(dir);
+ }
+ }
+
+ /**
+ * KNOX-1014
+ *
+ * Test the lifecycle relationship between simple descriptors and topology files.
+ *
+ * N.B. This test depends on the DummyServiceDiscovery extension being configured:
+ * org.apache.hadoop.gateway.topology.discovery.test.extension.DummyServiceDiscovery
+ */
+ @Test
+ public void testSimpleDescriptorsTopologyGeneration() throws Exception {
+
+ File dir = createDir();
+ File topologyDir = new File(dir, "topologies");
+ topologyDir.mkdirs();
+
+ File descriptorsDir = new File(dir, "descriptors");
+ descriptorsDir.mkdirs();
+
+ File sharedProvidersDir = new File(dir, "shared-providers");
+ sharedProvidersDir.mkdirs();
+
+ try {
+ TestTopologyListener topoListener = new TestTopologyListener();
+ FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
+
+ TopologyService provider = new DefaultTopologyService();
+ Map<String, String> c = new HashMap<>();
+
+ GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
+ EasyMock.replay(config);
+
+ provider.init(config, c);
+ provider.addTopologyChangeListener(topoListener);
+ provider.reloadTopologies();
+
+
// Add a simple descriptor to the descriptors dir to verify topology generation and loading (KNOX-1006)
- // N.B. This part of the test depends on the DummyServiceDiscovery extension being configured:
- // org.apache.hadoop.gateway.topology.discovery.test.extension.DummyServiceDiscovery
AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
EasyMock.expect(aliasService.getPasswordFromAliasForGateway(anyObject(String.class))).andReturn(null).anyTimes();
EasyMock.replay(aliasService);
DefaultTopologyService.DescriptorsMonitor dm =
- new DefaultTopologyService.DescriptorsMonitor(topologyDir, aliasService);
+ new DefaultTopologyService.DescriptorsMonitor(topologyDir, aliasService);
+
+ // Listener to simulate the topologies directory monitor, to notice when a topology has been deleted
+ provider.addTopologyChangeListener(new TestTopologyDeleteListener((DefaultTopologyService)provider));
// Write out the referenced provider config first
File provCfgFile = createFile(sharedProvidersDir,
"ambari-cluster-policy.xml",
"org/apache/hadoop/gateway/topology/file/ambari-cluster-policy.xml",
- 1L);
+ System.currentTimeMillis());
try {
// Create the simple descriptor in the descriptors dir
- File simpleDesc =
- createFile(descriptorsDir,
- "four.json",
- "org/apache/hadoop/gateway/topology/file/simple-topology-four.json",
- 1L);
+ File simpleDesc = createFile(descriptorsDir,
+ "four.json",
+ "org/apache/hadoop/gateway/topology/file/simple-topology-four.json",
+ System.currentTimeMillis());
// Trigger the topology generation by noticing the simple descriptor
dm.onFileChange(simpleDesc);
// Load the generated topology
provider.reloadTopologies();
+ Collection<Topology> topologies = provider.getTopologies();
+ assertThat(topologies.size(), is(1));
+ Iterator<Topology> iterator = topologies.iterator();
+ Topology topology = iterator.next();
+ assertThat("four", is(topology.getName()));
+ int serviceCount = topology.getServices().size();
+ assertEquals("Expected the same number of services as are declared in the simple dscriptor.", 10, serviceCount);
+
+ // Overwrite the simple descriptor with a different set of services, and check that the changes are
+ // propagated to the associated topology
+ simpleDesc = createFile(descriptorsDir,
+ "four.json",
+ "org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json",
+ System.currentTimeMillis());
+ dm.onFileChange(simpleDesc);
+ provider.reloadTopologies();
+ topologies = provider.getTopologies();
+ topology = topologies.iterator().next();
+ assertNotEquals(serviceCount, topology.getServices().size());
+ assertEquals(6, topology.getServices().size());
+
+ // Delete the simple descriptor, and make sure that the associated topology file is deleted
+ simpleDesc.delete();
+ dm.onFileDelete(simpleDesc);
+ provider.reloadTopologies();
+ topologies = provider.getTopologies();
+ assertTrue(topologies.isEmpty());
+
+ // Delete a topology file, and make sure that the associated simple descriptor is deleted
+ // Overwrite the simple descriptor with a different set of services, and check that the changes are
+ // propagated to the associated topology
+ simpleDesc = createFile(descriptorsDir,
+ "deleteme.json",
+ "org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json",
+ System.currentTimeMillis());
+ dm.onFileChange(simpleDesc);
+ provider.reloadTopologies();
topologies = provider.getTopologies();
- assertThat(topologies.size(), is(2));
- names = new HashSet<>(Arrays.asList("one", "four"));
- iterator = topologies.iterator();
- topology = iterator.next();
- assertThat(names, hasItem(topology.getName()));
- names.remove(topology.getName());
- topology = iterator.next();
- assertThat(names, hasItem(topology.getName()));
- names.remove(topology.getName());
- assertThat(names.size(), is(0));
+ assertFalse(topologies.isEmpty());
+ topology = topologies.iterator().next();
+ assertEquals("deleteme", topology.getName());
+ File topologyFile = new File(topologyDir, topology.getName() + ".xml");
+ assertTrue(topologyFile.exists());
+ topologyFile.delete();
+ provider.reloadTopologies();
+ assertFalse("Simple descriptor should have been deleted because the associated topology was.",
+ simpleDesc.exists());
+
} finally {
provCfgFile.delete();
-
}
} finally {
FileUtils.deleteQuietly(dir);
}
}
+ /**
+ * KNOX-1014
+ *
+ * Test the lifecycle relationship between provider configuration files, simple descriptors, and topology files.
+ *
+ * N.B. This test depends on the DummyServiceDiscovery extension being configured:
+ * org.apache.hadoop.gateway.topology.discovery.test.extension.DummyServiceDiscovery
+ */
+ @Test
+ public void testTopologiesUpdateFromProviderConfigChange() throws Exception {
+ File dir = createDir();
+ File topologyDir = new File(dir, "topologies");
+ topologyDir.mkdirs();
+
+ File descriptorsDir = new File(dir, "descriptors");
+ descriptorsDir.mkdirs();
+
+ File sharedProvidersDir = new File(dir, "shared-providers");
+ sharedProvidersDir.mkdirs();
+
+ try {
+ TestTopologyListener topoListener = new TestTopologyListener();
+ FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
+
+ TopologyService ts = new DefaultTopologyService();
+ Map<String, String> c = new HashMap<>();
+
+ GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
+ EasyMock.replay(config);
+
+ ts.init(config, c);
+ ts.addTopologyChangeListener(topoListener);
+ ts.reloadTopologies();
+
+ java.lang.reflect.Field dmField = ts.getClass().getDeclaredField("descriptorsMonitor");
+ dmField.setAccessible(true);
+ DefaultTopologyService.DescriptorsMonitor dm = (DefaultTopologyService.DescriptorsMonitor) dmField.get(ts);
+
+ // Write out the referenced provider configs first
+ createFile(sharedProvidersDir,
+ "provider-config-one.xml",
+ "org/apache/hadoop/gateway/topology/file/provider-config-one.xml",
+ System.currentTimeMillis());
+
+ // Create the simple descriptor, which depends on provider-config-one.xml
+ File simpleDesc = createFile(descriptorsDir,
+ "six.json",
+ "org/apache/hadoop/gateway/topology/file/simple-descriptor-six.json",
+ System.currentTimeMillis());
+
+ // "Notice" the simple descriptor change, and generate a topology based on it
+ dm.onFileChange(simpleDesc);
+
+ // Load the generated topology
+ ts.reloadTopologies();
+ Collection<Topology> topologies = ts.getTopologies();
+ assertThat(topologies.size(), is(1));
+ Iterator<Topology> iterator = topologies.iterator();
+ Topology topology = iterator.next();
+ assertFalse("The Shiro provider is disabled in provider-config-one.xml",
+ topology.getProvider("authentication", "ShiroProvider").isEnabled());
+
+ // Overwrite the referenced provider configuration with a different ShiroProvider config, and check that the
+ // changes are propagated to the associated topology
+ File providerConfig = createFile(sharedProvidersDir,
+ "provider-config-one.xml",
+ "org/apache/hadoop/gateway/topology/file/ambari-cluster-policy.xml",
+ System.currentTimeMillis());
+
+ // "Notice" the simple descriptor change as a result of the referenced config change
+ dm.onFileChange(simpleDesc);
+
+ // Load the generated topology
+ ts.reloadTopologies();
+ topologies = ts.getTopologies();
+ assertFalse(topologies.isEmpty());
+ topology = topologies.iterator().next();
+ assertTrue("The Shiro provider is enabled in ambari-cluster-policy.xml",
+ topology.getProvider("authentication", "ShiroProvider").isEnabled());
+
+ // Delete the provider configuration, and make sure that the associated topology file is unaffected.
+ // The topology file should not be affected because the simple descriptor handling will fail to resolve the
+ // referenced provider configuration.
+ providerConfig.delete(); // Delete the file
+ dm.onFileChange(simpleDesc); // The provider config deletion will trigger a descriptor change notification
+ ts.reloadTopologies();
+ topologies = ts.getTopologies();
+ assertFalse(topologies.isEmpty());
+ assertTrue("The Shiro provider is enabled in ambari-cluster-policy.xml",
+ topology.getProvider("authentication", "ShiroProvider").isEnabled());
+
+ } finally {
+ FileUtils.deleteQuietly(dir);
+ }
+ }
+
+ /**
+ * KNOX-1039
+ */
+ @Test
+ public void testConfigurationCRUDAPI() throws Exception {
+ File dir = createDir();
+ File topologyDir = new File(dir, "topologies");
+ topologyDir.mkdirs();
+
+ File descriptorsDir = new File(dir, "descriptors");
+ descriptorsDir.mkdirs();
+
+ File sharedProvidersDir = new File(dir, "shared-providers");
+ sharedProvidersDir.mkdirs();
+
+ try {
+ TestTopologyListener topoListener = new TestTopologyListener();
+ FileAlterationMonitor monitor = new FileAlterationMonitor(Long.MAX_VALUE);
+
+ TopologyService ts = new DefaultTopologyService();
+ Map<String, String> c = new HashMap<>();
+
+ GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(config.getGatewayTopologyDir()).andReturn(topologyDir.getAbsolutePath()).anyTimes();
+ EasyMock.expect(config.getGatewayConfDir()).andReturn(descriptorsDir.getParentFile().getAbsolutePath()).anyTimes();
+ EasyMock.replay(config);
+
+ ts.init(config, c);
+ ts.addTopologyChangeListener(topoListener);
+ ts.reloadTopologies();
+
+ java.lang.reflect.Field dmField = ts.getClass().getDeclaredField("descriptorsMonitor");
+ dmField.setAccessible(true);
+ DefaultTopologyService.DescriptorsMonitor dm = (DefaultTopologyService.DescriptorsMonitor) dmField.get(ts);
+
+ final String simpleDescName = "six.json";
+ final String provConfOne = "provider-config-one.xml";
+ final String provConfTwo = "ambari-cluster-policy.xml";
+
+ // "Deploy" the referenced provider configs first
+ boolean isDeployed =
+ ts.deployProviderConfiguration(provConfOne,
+ FileUtils.readFileToString(new File(ClassLoader.getSystemResource("org/apache/hadoop/gateway/topology/file/provider-config-one.xml").toURI())));
+ assertTrue(isDeployed);
+ File provConfOneFile = new File(sharedProvidersDir, provConfOne);
+ assertTrue(provConfOneFile.exists());
+
+ isDeployed =
+ ts.deployProviderConfiguration(provConfTwo,
+ FileUtils.readFileToString(new File(ClassLoader.getSystemResource("org/apache/hadoop/gateway/topology/file/ambari-cluster-policy.xml").toURI())));
+ assertTrue(isDeployed);
+ File provConfTwoFile = new File(sharedProvidersDir, provConfTwo);
+ assertTrue(provConfTwoFile.exists());
+
+ // Validate the provider configurations known by the topology service
+ Collection<File> providerConfigurations = ts.getProviderConfigurations();
+ assertNotNull(providerConfigurations);
+ assertEquals(2, providerConfigurations.size());
+ assertTrue(providerConfigurations.contains(provConfOneFile));
+ assertTrue(providerConfigurations.contains(provConfTwoFile));
+
+ // "Deploy" the simple descriptor, which depends on provConfOne
+ isDeployed =
+ ts.deployDescriptor(simpleDescName,
+ FileUtils.readFileToString(new File(ClassLoader.getSystemResource("org/apache/hadoop/gateway/topology/file/simple-descriptor-six.json").toURI())));
+ assertTrue(isDeployed);
+ File simpleDesc = new File(descriptorsDir, simpleDescName);
+ assertTrue(simpleDesc.exists());
+
+ // Validate the simple descriptors known by the topology service
+ Collection<File> descriptors = ts.getDescriptors();
+ assertNotNull(descriptors);
+ assertEquals(1, descriptors.size());
+ assertTrue(descriptors.contains(simpleDesc));
+
+ // "Notice" the simple descriptor, so the provider configuration dependency relationship is recorded
+ dm.onFileChange(simpleDesc);
+
+ // Attempt to delete the referenced provConfOne
+ assertFalse("Should not be able to delete a provider configuration that is referenced by one or more descriptors",
+ ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfOne)));
+
+ // Overwrite the simple descriptor with content that changes the provider config reference to provConfTwo
+ isDeployed =
+ ts.deployDescriptor(simpleDescName,
+ FileUtils.readFileToString(new File(ClassLoader.getSystemResource("org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json").toURI())));
+ assertTrue(isDeployed);
+ assertTrue(simpleDesc.exists());
+ ts.getProviderConfigurations();
+
+ // "Notice" the simple descriptor, so the provider configuration dependency relationship is updated
+ dm.onFileChange(simpleDesc);
+
+ // Attempt to delete the referenced provConfOne
+ assertTrue("Should be able to delete the provider configuration, now that it's not referenced by any descriptors",
+ ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfOne)));
+
+ // Re-validate the provider configurations known by the topology service
+ providerConfigurations = ts.getProviderConfigurations();
+ assertNotNull(providerConfigurations);
+ assertEquals(1, providerConfigurations.size());
+ assertFalse(providerConfigurations.contains(provConfOneFile));
+ assertTrue(providerConfigurations.contains(provConfTwoFile));
+
+ // Attempt to delete the referenced provConfTwo
+ assertFalse("Should not be able to delete a provider configuration that is referenced by one or more descriptors",
+ ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfTwo)));
+
+ // Delete the referencing simple descriptor
+ assertTrue(ts.deleteDescriptor(FilenameUtils.getBaseName(simpleDescName)));
+ assertFalse(simpleDesc.exists());
+
+ // Re-validate the simple descriptors known by the topology service
+ descriptors = ts.getDescriptors();
+ assertNotNull(descriptors);
+ assertTrue(descriptors.isEmpty());
+
+ // "Notice" the simple descriptor, so the provider configuration dependency relationship is updated
+ dm.onFileDelete(simpleDesc);
+
+ // Attempt to delete the referenced provConfTwo
+ assertTrue("Should be able to delete the provider configuration, now that it's not referenced by any descriptors",
+ ts.deleteProviderConfiguration(FilenameUtils.getBaseName(provConfTwo)));
+
+ // Re-validate the provider configurations known by the topology service
+ providerConfigurations = ts.getProviderConfigurations();
+ assertNotNull(providerConfigurations);
+ assertTrue(providerConfigurations.isEmpty());
+
+ } finally {
+ FileUtils.deleteQuietly(dir);
+ }
+ }
+
private void kickMonitor(FileAlterationMonitor monitor) {
for (FileAlterationObserver observer : monitor.getObservers()) {
observer.checkAndNotify();
}
}
+
@Test
public void testProviderParamsOrderIsPreserved() {
@@ -252,7 +568,7 @@ public class DefaultTopologyServiceTest {
private class TestTopologyListener implements TopologyListener {
- public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>();
+ ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>();
@Override
public void handleTopologyEvent(List<TopologyEvent> events) {
@@ -261,4 +577,24 @@ public class DefaultTopologyServiceTest {
}
+
+ private class TestTopologyDeleteListener implements TopologyListener {
+
+ FileAlterationListener delegate;
+
+ TestTopologyDeleteListener(FileAlterationListener delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void handleTopologyEvent(List<TopologyEvent> events) {
+ for (TopologyEvent event : events) {
+ if (event.getType().equals(TopologyEvent.Type.DELETED)) {
+ delegate.onFileDelete(new File(event.getTopology().getUri()));
+ }
+ }
+ }
+
+ }
+
}
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/provider-config-one.xml
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/provider-config-one.xml b/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/provider-config-one.xml
new file mode 100644
index 0000000..95465a4
--- /dev/null
+++ b/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/provider-config-one.xml
@@ -0,0 +1,74 @@
+<gateway>
+ <provider>
+ <role>authentication</role>
+ <name>ShiroProvider</name>
+ <enabled>false</enabled>
+ <param>
+ <!--
+ session timeout in minutes, this is really idle timeout,
+ defaults to 30mins, if the property value is not defined,,
+ current client authentication would expire if client idles contiuosly for more than this value
+ -->
+ <name>sessionTimeout</name>
+ <value>30</value>
+ </param>
+ <param>
+ <name>main.ldapRealm</name>
+ <value>org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm</value>
+ </param>
+ <param>
+ <name>main.ldapContextFactory</name>
+ <value>org.apache.hadoop.gateway.shirorealm.KnoxLdapContextFactory</value>
+ </param>
+ <param>
+ <name>main.ldapRealm.contextFactory</name>
+ <value>$ldapContextFactory</value>
+ </param>
+ <param>
+ <name>main.ldapRealm.userDnTemplate</name>
+ <value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
+ </param>
+ <param>
+ <name>main.ldapRealm.contextFactory.url</name>
+ <value>ldap://localhost:33389</value>
+ </param>
+ <param>
+ <name>main.ldapRealm.contextFactory.authenticationMechanism</name>
+ <value>simple</value>
+ </param>
+ <param>
+ <name>urls./**</name>
+ <value>authcBasic</value>
+ </param>
+ </provider>
+
+ <provider>
+ <role>identity-assertion</role>
+ <name>Default</name>
+ <enabled>true</enabled>
+ </provider>
+
+ <!--
+ Defines rules for mapping host names internal to a Hadoop cluster to externally accessible host names.
+ For example, a hadoop service running in AWS may return a response that includes URLs containing the
+ some AWS internal host name. If the client needs to make a subsequent request to the host identified
+ in those URLs they need to be mapped to external host names that the client Knox can use to connect.
+
+ If the external hostname and internal host names are same turn of this provider by setting the value of
+ enabled parameter as false.
+
+ The name parameter specifies the external host names in a comma separated list.
+ The value parameter specifies corresponding internal host names in a comma separated list.
+
+ Note that when you are using Sandbox, the external hostname needs to be localhost, as seen in out
+ of box sandbox.xml. This is because Sandbox uses port mapping to allow clients to connect to the
+ Hadoop services using localhost. In real clusters, external host names would almost never be localhost.
+ -->
+ <provider>
+ <role>hostmap</role>
+ <name>static</name>
+ <enabled>true</enabled>
+ <param><name>localhost</name><value>sandbox,sandbox.hortonworks.com</value></param>
+ </provider>
+
+</gateway>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json b/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json
new file mode 100644
index 0000000..52cec35
--- /dev/null
+++ b/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-five.json
@@ -0,0 +1,14 @@
+{
+ "discovery-type":"DUMMY",
+ "discovery-address":"http://c6401.ambari.apache.org:8080",
+ "provider-config-ref":"../shared-providers/ambari-cluster-policy.xml",
+ "cluster":"dummy",
+ "services":[
+ {"name":"NAMENODE"},
+ {"name":"JOBTRACKER"},
+ {"name":"WEBHDFS"},
+ {"name":"OOZIE"},
+ {"name":"HIVE"},
+ {"name":"RESOURCEMANAGER"}
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-six.json
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-six.json b/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-six.json
new file mode 100644
index 0000000..e78f193
--- /dev/null
+++ b/gateway-server/src/test/resources/org/apache/hadoop/gateway/topology/file/simple-descriptor-six.json
@@ -0,0 +1,18 @@
+{
+ "discovery-type":"DUMMY",
+ "discovery-address":"http://c6401.ambari.apache.org:8080",
+ "provider-config-ref":"../shared-providers/provider-config-one.xml",
+ "cluster":"dummy",
+ "services":[
+ {"name":"NAMENODE"},
+ {"name":"JOBTRACKER"},
+ {"name":"WEBHDFS"},
+ {"name":"WEBHCAT"},
+ {"name":"OOZIE"},
+ {"name":"WEBHBASE"},
+ {"name":"HIVE"},
+ {"name":"RESOURCEMANAGER"},
+ {"name":"AMBARI", "urls":["http://c6401.ambari.apache.org:8080"]},
+ {"name":"AMBARIUI", "urls":["http://c6401.ambari.apache.org:8080"]}
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/HrefListingMarshaller.java
----------------------------------------------------------------------
diff --git a/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/HrefListingMarshaller.java b/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/HrefListingMarshaller.java
new file mode 100644
index 0000000..c251213
--- /dev/null
+++ b/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/HrefListingMarshaller.java
@@ -0,0 +1,75 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.hadoop.gateway.service.admin;
+
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+@Provider
+@Produces({MediaType.APPLICATION_JSON})
+public class HrefListingMarshaller implements MessageBodyWriter<TopologiesResource.HrefListing> {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return (TopologiesResource.HrefListing.class == type);
+ }
+
+ @Override
+ public long getSize(TopologiesResource.HrefListing instance,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(TopologiesResource.HrefListing instance,
+ Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException, WebApplicationException {
+ try {
+ Map<String, Object> properties = new HashMap<>(1);
+ properties.put( JAXBContextProperties.MEDIA_TYPE, mediaType.toString());
+ JAXBContext context = JAXBContext.newInstance(new Class[]{TopologiesResource.HrefListing.class}, properties);
+ Marshaller m = context.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ m.marshal(instance, entityStream);
+ } catch (JAXBException e) {
+ throw new IOException(e);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/TopologiesResource.java
----------------------------------------------------------------------
diff --git a/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/TopologiesResource.java b/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/TopologiesResource.java
index 1504eca..28573bf 100644
--- a/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/TopologiesResource.java
+++ b/gateway-service-admin/src/main/java/org/apache/hadoop/gateway/service/admin/TopologiesResource.java
@@ -17,6 +17,11 @@
*/
package org.apache.hadoop.gateway.service.admin;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
import org.apache.hadoop.gateway.service.admin.beans.BeanConverter;
import org.apache.hadoop.gateway.service.admin.beans.Topology;
import org.apache.hadoop.gateway.services.GatewayServices;
@@ -37,25 +42,47 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
+import java.io.File;
+import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+
import static javax.ws.rs.core.Response.ok;
+import static javax.ws.rs.core.Response.created;
+import static javax.ws.rs.core.Response.notModified;
+import static javax.ws.rs.core.Response.status;
+
@Path("/api/v1")
public class TopologiesResource {
+
+ private static final String XML_EXT = ".xml";
+ private static final String JSON_EXT = ".json";
+
+ private static final String TOPOLOGIES_API_PATH = "topologies";
+ private static final String SINGLE_TOPOLOGY_API_PATH = TOPOLOGIES_API_PATH + "/{id}";
+ private static final String PROVIDERCONFIG_API_PATH = "providerconfig";
+ private static final String SINGLE_PROVIDERCONFIG_API_PATH = PROVIDERCONFIG_API_PATH + "/{name}";
+ private static final String DESCRIPTORS_API_PATH = "descriptors";
+ private static final String SINGLE_DESCRIPTOR_API_PATH = DESCRIPTORS_API_PATH + "/{name}";
+
+ private static GatewaySpiMessages log = MessagesFactory.get(GatewaySpiMessages.class);
+
@Context
private HttpServletRequest request;
@GET
@Produces({APPLICATION_JSON, APPLICATION_XML})
- @Path("topologies/{id}")
+ @Path(SINGLE_TOPOLOGY_API_PATH)
public Topology getTopology(@PathParam("id") String id) {
GatewayServices services = (GatewayServices) request.getServletContext()
.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
@@ -78,7 +105,7 @@ public class TopologiesResource {
@GET
@Produces({APPLICATION_JSON, APPLICATION_XML})
- @Path("topologies")
+ @Path(TOPOLOGIES_API_PATH)
public SimpleTopologyWrapper getTopologies() {
GatewayServices services = (GatewayServices) request.getServletContext()
.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
@@ -106,7 +133,7 @@ public class TopologiesResource {
@PUT
@Consumes({APPLICATION_JSON, APPLICATION_XML})
- @Path("topologies/{id}")
+ @Path(SINGLE_TOPOLOGY_API_PATH)
public Topology uploadTopology(@PathParam("id") String id, Topology t) {
GatewayServices gs = (GatewayServices) request.getServletContext()
@@ -122,7 +149,7 @@ public class TopologiesResource {
@DELETE
@Produces(APPLICATION_JSON)
- @Path("topologies/{id}")
+ @Path(SINGLE_TOPOLOGY_API_PATH)
public Response deleteTopology(@PathParam("id") String id) {
boolean deleted = false;
if(!"admin".equals(id)) {
@@ -143,6 +170,244 @@ public class TopologiesResource {
return ok().entity("{ \"deleted\" : " + deleted + " }").build();
}
+ @GET
+ @Produces({APPLICATION_JSON})
+ @Path(PROVIDERCONFIG_API_PATH)
+ public HrefListing getProviderConfigurations() {
+ HrefListing listing = new HrefListing();
+ listing.setHref(buildHref(request));
+
+ GatewayServices services =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ List<HrefListItem> configs = new ArrayList<>();
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+ // Get all the simple descriptor file names
+ for (File providerConfig : ts.getProviderConfigurations()){
+ String id = FilenameUtils.getBaseName(providerConfig.getName());
+ configs.add(new HrefListItem(buildHref(id, request), providerConfig.getName()));
+ }
+
+ listing.setItems(configs);
+ return listing;
+ }
+
+ @GET
+ @Produces({APPLICATION_XML})
+ @Path(SINGLE_PROVIDERCONFIG_API_PATH)
+ public Response getProviderConfiguration(@PathParam("name") String name) {
+ Response response;
+
+ GatewayServices services =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ File providerConfigFile = null;
+
+ for (File pc : ts.getProviderConfigurations()){
+ // If the file name matches the specified id
+ if (FilenameUtils.getBaseName(pc.getName()).equals(name)) {
+ providerConfigFile = pc;
+ break;
+ }
+ }
+
+ if (providerConfigFile != null) {
+ byte[] content = null;
+ try {
+ content = FileUtils.readFileToByteArray(providerConfigFile);
+ response = ok().entity(content).build();
+ } catch (IOException e) {
+ log.failedToReadConfigurationFile(providerConfigFile.getAbsolutePath(), e);
+ response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+
+ } else {
+ response = Response.status(Response.Status.NOT_FOUND).build();
+ }
+ return response;
+ }
+
+ @DELETE
+ @Produces(APPLICATION_JSON)
+ @Path(SINGLE_PROVIDERCONFIG_API_PATH)
+ public Response deleteProviderConfiguration(@PathParam("name") String name) {
+ Response response;
+ GatewayServices services =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+ if (ts.deleteProviderConfiguration(name)) {
+ response = ok().entity("{ \"deleted\" : \"provider config " + name + "\" }").build();
+ } else {
+ response = notModified().build();
+ }
+ return response;
+ }
+
+
+ @DELETE
+ @Produces(APPLICATION_JSON)
+ @Path(SINGLE_DESCRIPTOR_API_PATH)
+ public Response deleteSimpleDescriptor(@PathParam("name") String name) {
+ Response response = null;
+ if(!"admin".equals(name)) {
+ GatewayServices services =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+ if (ts.deleteDescriptor(name)) {
+ response = ok().entity("{ \"deleted\" : \"descriptor " + name + "\" }").build();
+ }
+ }
+
+ if (response == null) {
+ response = notModified().build();
+ }
+
+ return response;
+ }
+
+
+ @PUT
+ @Consumes({APPLICATION_XML})
+ @Path(SINGLE_PROVIDERCONFIG_API_PATH)
+ public Response uploadProviderConfiguration(@PathParam("name") String name, String content) {
+ Response response = null;
+
+ GatewayServices gs =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ boolean isUpdate = configFileExists(ts.getProviderConfigurations(), name);
+
+ String filename = name.endsWith(XML_EXT) ? name : name + XML_EXT;
+ if (ts.deployProviderConfiguration(filename, content)) {
+ try {
+ if (isUpdate) {
+ response = Response.noContent().build();
+ } else{
+ response = created(new URI(buildHref(request))).build();
+ }
+ } catch (URISyntaxException e) {
+ log.invalidResourceURI(e.getInput(), e.getReason(), e);
+ response = status(Response.Status.BAD_REQUEST).entity("{ \"error\" : \"Failed to deploy provider configuration " + name + "\" }").build();
+ }
+ }
+
+ return response;
+ }
+
+
+ private boolean configFileExists(Collection<File> existing, String candidateName) {
+ boolean result = false;
+ for (File exists : existing) {
+ if (FilenameUtils.getBaseName(exists.getName()).equals(candidateName)) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ @PUT
+ @Consumes({APPLICATION_JSON})
+ @Path(SINGLE_DESCRIPTOR_API_PATH)
+ public Response uploadSimpleDescriptor(@PathParam("name") String name, String content) {
+ Response response = null;
+
+ GatewayServices gs =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ boolean isUpdate = configFileExists(ts.getDescriptors(), name);
+
+ String filename = name.endsWith(JSON_EXT) ? name : name + JSON_EXT;
+ if (ts.deployDescriptor(filename, content)) {
+ try {
+ if (isUpdate) {
+ response = Response.noContent().build();
+ } else {
+ response = created(new URI(buildHref(request))).build();
+ }
+ } catch (URISyntaxException e) {
+ log.invalidResourceURI(e.getInput(), e.getReason(), e);
+ response = status(Response.Status.BAD_REQUEST).entity("{ \"error\" : \"Failed to deploy descriptor " + name + "\" }").build();
+ }
+ }
+
+ return response;
+ }
+
+
+ @GET
+ @Produces({APPLICATION_JSON})
+ @Path(DESCRIPTORS_API_PATH)
+ public HrefListing getSimpleDescriptors() {
+ HrefListing listing = new HrefListing();
+ listing.setHref(buildHref(request));
+
+ GatewayServices services =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ List<HrefListItem> descriptors = new ArrayList<>();
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+ for (File descriptor : ts.getDescriptors()){
+ String id = FilenameUtils.getBaseName(descriptor.getName());
+ descriptors.add(new HrefListItem(buildHref(id, request), descriptor.getName()));
+ }
+
+ listing.setItems(descriptors);
+ return listing;
+ }
+
+
+ @GET
+ @Produces({APPLICATION_JSON, TEXT_PLAIN})
+ @Path(SINGLE_DESCRIPTOR_API_PATH)
+ public Response getSimpleDescriptor(@PathParam("name") String name) {
+ Response response;
+
+ GatewayServices services =
+ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ File descriptorFile = null;
+
+ for (File sd : ts.getDescriptors()){
+ // If the file name matches the specified id
+ if (FilenameUtils.getBaseName(sd.getName()).equals(name)) {
+ descriptorFile = sd;
+ break;
+ }
+ }
+
+ if (descriptorFile != null) {
+ String mediaType = APPLICATION_JSON;
+
+ byte[] content = null;
+ try {
+ if ("yml".equals(FilenameUtils.getExtension(descriptorFile.getName()))) {
+ mediaType = TEXT_PLAIN;
+ }
+ content = FileUtils.readFileToByteArray(descriptorFile);
+ response = ok().type(mediaType).entity(content).build();
+ } catch (IOException e) {
+ log.failedToReadConfigurationFile(descriptorFile.getAbsolutePath(), e);
+ response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ } else {
+ response = Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ return response;
+ }
+
private static class TopologyComparator implements Comparator<SimpleTopology> {
@Override
@@ -151,13 +416,14 @@ public class TopologiesResource {
}
}
- String buildURI(org.apache.hadoop.gateway.topology.Topology topology, GatewayConfig config, HttpServletRequest req){
+
+ String buildURI(org.apache.hadoop.gateway.topology.Topology topology, GatewayConfig config, HttpServletRequest req){
String uri = buildXForwardBaseURL(req);
-// Strip extra context
+ // Strip extra context
uri = uri.replace(req.getContextPath(), "");
-// Add the gateway path
+ // Add the gateway path
String gatewayPath;
if(config.getGatewayPath() != null){
gatewayPath = config.getGatewayPath();
@@ -170,20 +436,31 @@ public class TopologiesResource {
return uri;
}
- String buildHref(org.apache.hadoop.gateway.topology.Topology t, HttpServletRequest req) {
+ String buildHref(HttpServletRequest req) {
+ return buildHref((String)null, req);
+ }
+
+ String buildHref(String id, HttpServletRequest req) {
String href = buildXForwardBaseURL(req);
-// Make sure that the pathInfo doesn't have any '/' chars at the end.
+ // Make sure that the pathInfo doesn't have any '/' chars at the end.
String pathInfo = req.getPathInfo();
- if(pathInfo.endsWith("/")) {
- while(pathInfo.endsWith("/")) {
- pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
- }
+ while(pathInfo.endsWith("/")) {
+ pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
+ }
+
+ href += pathInfo;
+
+ if (id != null) {
+ href += "/" + id;
}
- href += pathInfo + "/" + t.getName();
return href;
}
+ String buildHref(org.apache.hadoop.gateway.topology.Topology t, HttpServletRequest req) {
+ return buildHref(t.getName(), req);
+ }
+
private SimpleTopology getSimpleTopology(org.apache.hadoop.gateway.topology.Topology t, GatewayConfig config) {
String uri = buildURI(t, config, request);
String href = buildHref(t, request);
@@ -200,34 +477,34 @@ public class TopologiesResource {
String baseURL = "";
-// Get Protocol
+ // Get Protocol
if(req.getHeader(X_Forwarded_Proto) != null){
baseURL += req.getHeader(X_Forwarded_Proto) + "://";
} else {
baseURL += req.getProtocol() + "://";
}
-// Handle Server/Host and Port Here
+ // Handle Server/Host and Port Here
if (req.getHeader(X_Forwarded_Host) != null && req.getHeader(X_Forwarded_Port) != null){
-// Double check to see if host has port
+ // Double check to see if host has port
if(req.getHeader(X_Forwarded_Host).contains(req.getHeader(X_Forwarded_Port))){
baseURL += req.getHeader(X_Forwarded_Host);
} else {
-// If there's no port, add the host and port together;
+ // If there's no port, add the host and port together;
baseURL += req.getHeader(X_Forwarded_Host) + ":" + req.getHeader(X_Forwarded_Port);
}
} else if(req.getHeader(X_Forwarded_Server) != null && req.getHeader(X_Forwarded_Port) != null){
-// Tack on the server and port if they're available. Try host if server not available
+ // Tack on the server and port if they're available. Try host if server not available
baseURL += req.getHeader(X_Forwarded_Server) + ":" + req.getHeader(X_Forwarded_Port);
} else if(req.getHeader(X_Forwarded_Port) != null) {
-// if we at least have a port, we can use it.
+ // if we at least have a port, we can use it.
baseURL += req.getServerName() + ":" + req.getHeader(X_Forwarded_Port);
} else {
-// Resort to request members
+ // Resort to request members
baseURL += req.getServerName() + ":" + req.getLocalPort();
}
-// Handle Server context
+ // Handle Server context
if( req.getHeader(X_Forwarded_Context) != null ) {
baseURL += req.getHeader( X_Forwarded_Context );
} else {
@@ -237,6 +514,64 @@ public class TopologiesResource {
return baseURL;
}
+
+ static class HrefListing {
+ @JsonProperty
+ String href;
+
+ @JsonProperty
+ List<HrefListItem> items;
+
+ HrefListing() {}
+
+ public void setHref(String href) {
+ this.href = href;
+ }
+
+ public String getHref() {
+ return href;
+ }
+
+ public void setItems(List<HrefListItem> items) {
+ this.items = items;
+ }
+
+ public List<HrefListItem> getItems() {
+ return items;
+ }
+ }
+
+ static class HrefListItem {
+ @JsonProperty
+ String href;
+
+ @JsonProperty
+ String name;
+
+ HrefListItem() {}
+
+ HrefListItem(String href, String name) {
+ this.href = href;
+ this.name = name;
+ }
+
+ public void setHref(String href) {
+ this.href = href;
+ }
+
+ public String getHref() {
+ return href;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getName() {
+ return name;
+ }
+ }
+
+
@XmlAccessorType(XmlAccessType.NONE)
public static class SimpleTopology {
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
index 45fcb54..aad4d8a 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/i18n/GatewaySpiMessages.java
@@ -79,7 +79,13 @@ public interface GatewaySpiMessages {
@Message( level = MessageLevel.ERROR, text = "Gateway has failed to start. Unable to prompt user for master secret setup. Please consider using knoxcli.sh create-master" )
void unableToPromptForMasterUseKnoxCLI();
- @Message( level = MessageLevel.ERROR, text = "Error in generating certificate: {0}" )
- void failedToGenerateCertificate( @StackTrace( level = MessageLevel.ERROR ) Exception e );
+ @Message( level = MessageLevel.ERROR, text = "Error in generating certificate: {0}" )
+ void failedToGenerateCertificate( @StackTrace( level = MessageLevel.ERROR ) Exception e );
+
+ @Message(level = MessageLevel.ERROR, text = "Failed to read configuration: {0}")
+ void failedToReadConfigurationFile(final String filePath, @StackTrace(level = MessageLevel.DEBUG) Exception e );
+
+ @Message(level = MessageLevel.ERROR, text = "Invalid resource URI {0} : {1}")
+ void invalidResourceURI(final String uri, final String reason, @StackTrace(level = MessageLevel.DEBUG) Exception e );
}
http://git-wip-us.apache.org/repos/asf/knox/blob/9ad9bcdb/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/topology/TopologyService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/topology/TopologyService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/topology/TopologyService.java
index a964f38..017b3ec 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/topology/TopologyService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/topology/TopologyService.java
@@ -22,6 +22,7 @@ import org.apache.hadoop.gateway.services.Service;
import org.apache.hadoop.gateway.topology.Topology;
import org.apache.hadoop.gateway.topology.TopologyListener;
+import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -29,22 +30,34 @@ import java.util.Map;
public interface TopologyService extends Service {
- public void reloadTopologies();
+ void reloadTopologies();
- public void deployTopology(Topology t);
+ void deployTopology(Topology t);
- public void redeployTopologies(String topologyName);
+ void redeployTopologies(String topologyName);
- public void addTopologyChangeListener(TopologyListener listener);
+ void addTopologyChangeListener(TopologyListener listener);
- public void startMonitor() throws Exception;
+ void startMonitor() throws Exception;
- public void stopMonitor() throws Exception;
+ void stopMonitor() throws Exception;
- public Collection<Topology> getTopologies();
+ Collection<Topology> getTopologies();
- public void deleteTopology(Topology t);
+ boolean deployProviderConfiguration(String name, String content);
- public Map<String, List<String>> getServiceTestURLs(Topology t, GatewayConfig config);
+ Collection<File> getProviderConfigurations();
- }
+ boolean deployDescriptor(String name, String content);
+
+ Collection<File> getDescriptors();
+
+ void deleteTopology(Topology t);
+
+ boolean deleteDescriptor(String name);
+
+ boolean deleteProviderConfiguration(String name);
+
+ Map<String, List<String>> getServiceTestURLs(Topology t, GatewayConfig config);
+
+}