Skip to content

Commit

Permalink
KNOX-3026 - End-users can exclude certain services or roles from CM s…
Browse files Browse the repository at this point in the history
…ervice discovery
  • Loading branch information
smolnar82 committed Mar 27, 2024
1 parent 1e9a39b commit 6f2ad96
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


/**
Expand Down Expand Up @@ -92,6 +93,8 @@ public class ClouderaManagerServiceDiscovery implements ServiceDiscovery, Cluste
private final AtomicInteger retryAttempts = new AtomicInteger(0);
private final int retrySleepSeconds = 3; // It's been agreed that we not expose this config
private int maxRetryAttempts = -1;
private Collection<String> excludedServiceTypes = Collections.emptySet();
private Collection<String> excludedRoleTypes = Collections.emptySet();

ClouderaManagerServiceDiscovery(GatewayConfig gatewayConfig) {
this(false, gatewayConfig);
Expand All @@ -116,6 +119,8 @@ public class ClouderaManagerServiceDiscovery implements ServiceDiscovery, Cluste
if (gatewayConfig != null) {
repository.setCacheEntryTTL(gatewayConfig.getClouderaManagerServiceDiscoveryRepositoryEntryTTL());
configureRetryParams(gatewayConfig);
excludedServiceTypes = gatewayConfig.getClouderaManagerServiceDiscoveryExcludedServiceTypes();
excludedRoleTypes = gatewayConfig.getClouderaManagerServiceDiscoveryExcludedRoleTypes();
}
}

Expand Down Expand Up @@ -356,6 +361,14 @@ private List<ApiService> getClusterServices(ServiceDiscoveryConfig serviceDiscov
final ApiServiceList serviceList = servicesResourceApi.readServices(serviceDiscoveryConfig.getCluster(), VIEW_SUMMARY);
services = serviceList == null ? new ArrayList<>() : serviceList.getItems();

services = services.stream().filter(service -> {
if (excludedServiceTypes.contains(service.getType())) {
log.skipServiceDiscovery(service.getName(), service.getType());
return false;
}
return true;
}).collect(Collectors.toList());

// make sure that services are populated in the repository
services.forEach(service -> repository.addService(serviceDiscoveryConfig, service));
} catch (ApiException e) {
Expand Down Expand Up @@ -409,6 +422,8 @@ private ApiRoleList getRoles(ServiceDiscoveryConfig serviceDiscoveryConfig, Role
log.noRoles();
}

roles = excludeRoles(roles);

// make sure that role is populated in the service discovery repository to avoid subsequent CM calls
if (roles != null && roles.getItems() != null) {
repository.addRoles(serviceDiscoveryConfig, service, roles);
Expand All @@ -422,6 +437,21 @@ private ApiRoleList getRoles(ServiceDiscoveryConfig serviceDiscoveryConfig, Role
return roles;
}

private ApiRoleList excludeRoles(ApiRoleList roles) {
if (roles == null || roles.getItems() == null) {
return roles;
}
final ApiRoleList filteredRoles = new ApiRoleList();
roles.getItems().forEach(role -> {
if (excludedRoleTypes.contains(role.getType())) {
log.skipRoleDiscovery(role.getName(), role.getType());
} else {
filteredRoles.addItemsItem(role);
}
});
return filteredRoles;
}

private ApiConfigList getRoleConfig(ServiceDiscoveryConfig serviceDiscoveryConfig, RolesResourceApi rolesResourceApi, ApiService service, ApiRole role) throws ApiException {
log.lookupRoleConfigsFromRepository();
// first, try in the service discovery repository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public interface ClouderaManagerServiceDiscoveryMessages {
@Message(level = MessageLevel.INFO, text = "Discovering service role: {0} ({1}) ...")
void discoveringServiceRole(String roleName, String roleType);

@Message(level = MessageLevel.INFO, text = "Skipping role discovery: {0} ({1})")
void skipRoleDiscovery(String roleName, String roleType);

@Message(level = MessageLevel.INFO, text = "Discovered service role: {0} ({1})")
void discoveredServiceRole(String roleName, String roleType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import java.lang.reflect.Type;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -402,7 +403,26 @@ public void testPhoenixDiscoverySSL() {
}

@Test
public void testWebHCatDiscovery() {
public void testIncludeHiveServiceIncludeWebHCatDiscovery() {
testWebHCatDiscovery(true, true);
}

@Test
public void testExcludeHiveServiceIncludeWebHCatDiscovery() {
testWebHCatDiscovery(false, true);
}

@Test
public void testIncludeHiveServiceExcludeWebHCatDiscovery() {
testWebHCatDiscovery(true, false);
}

@Test
public void testExcludeHiveServiceExcludeWebHCatDiscovery() {
testWebHCatDiscovery(false, false);
}

private void testWebHCatDiscovery(boolean excludeHiveService, boolean excludeWebHCatRole) {
final String hostName = "webhcat-host";
final String port = "22222";
final String expectedURL = "http://" + hostName + ":" + port + "/templeton";
Expand All @@ -417,12 +437,18 @@ public void testWebHCatDiscovery() {
"HIVE-1-WEBHCAT-1",
WebHCatServiceModelGenerator.ROLE_TYPE,
Collections.emptyMap(),
roleProperties);
roleProperties,
false,
excludeHiveService ? WebHCatServiceModelGenerator.SERVICE_TYPE : null,
excludeWebHCatRole ? WebHCatServiceModelGenerator.ROLE_TYPE : null);

List<String> urls = cluster.getServiceURLs("WEBHCAT");
assertNotNull(urls);
assertEquals(1, urls.size());
assertEquals(expectedURL, urls.get(0));
final boolean expectExclusion = excludeHiveService || excludeWebHCatRole;
assertEquals(expectExclusion ? 0 : 1, urls.size());
if (!expectExclusion) {
assertEquals(expectedURL, urls.get(0));
}
}

@Test
Expand Down Expand Up @@ -1168,14 +1194,27 @@ private ServiceDiscovery.Cluster doTestDiscovery(final String hostName,
return doTestDiscovery(hostName, serviceName, serviceType, roleName, roleType, serviceProperties, roleProperties, false);
}

private ServiceDiscovery.Cluster doTestDiscovery(final String hostName,
final String serviceName,
final String serviceType,
final String roleName,
final String roleType,
final Map<String, String> serviceProperties,
final Map<String, String> roleProperties,
boolean testRetry) {
return doTestDiscovery(hostName, serviceName, serviceType, roleName, roleType, serviceProperties, roleProperties, testRetry, null, null);
}

private ServiceDiscovery.Cluster doTestDiscovery(final String hostName,
final String serviceName,
final String serviceType,
final String roleName,
final String roleType,
final Map<String, String> serviceProperties,
final Map<String, String> roleProperties,
boolean testRetry) {
boolean testRetry,
String excludedServiceType,
String excludedRoleType) {
final String clusterName = "cluster-1";

GatewayConfig gwConf = EasyMock.createNiceMock(GatewayConfig.class);
Expand All @@ -1185,6 +1224,16 @@ private ServiceDiscovery.Cluster doTestDiscovery(final String hostName,
}
EasyMock.expect(gwConf.getIncludedSSLCiphers()).andReturn(Collections.emptyList()).anyTimes();
EasyMock.expect(gwConf.getIncludedSSLProtocols()).andReturn(Collections.emptySet()).anyTimes();
if (excludedServiceType == null) {
EasyMock.expect(gwConf.getClouderaManagerServiceDiscoveryExcludedServiceTypes()).andReturn(Collections.emptySet()).anyTimes();
} else {
EasyMock.expect(gwConf.getClouderaManagerServiceDiscoveryExcludedServiceTypes()).andReturn(Arrays.asList(excludedServiceType)).anyTimes();
}
if (excludedRoleType == null) {
EasyMock.expect(gwConf.getClouderaManagerServiceDiscoveryExcludedRoleTypes()).andReturn(Collections.emptySet()).anyTimes();
} else {
EasyMock.expect(gwConf.getClouderaManagerServiceDiscoveryExcludedRoleTypes()).andReturn(Arrays.asList(excludedRoleType)).anyTimes();
}
EasyMock.replay(gwConf);

ServiceDiscoveryConfig sdConfig = createMockDiscoveryConfig(clusterName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
private static final String CLOUDERA_MANAGER_SERVICE_DISCOVERY_CONNECT_TIMEOUT = GATEWAY_CONFIG_FILE_PREFIX + ".cloudera.manager.service.discovery.connect.timeout.ms";
private static final String CLOUDERA_MANAGER_SERVICE_DISCOVERY_READ_TIMEOUT = GATEWAY_CONFIG_FILE_PREFIX + ".cloudera.manager.service.discovery.read.timeout.ms";
private static final String CLOUDERA_MANAGER_SERVICE_DISCOVERY_WRITE_TIMEOUT = GATEWAY_CONFIG_FILE_PREFIX + ".cloudera.manager.service.discovery.write.timeout.ms";
private static final String CLOUDERA_MANAGER_SERVICE_DISCOVERY_EXCLUDED_SERVICE_TYPES = GATEWAY_CONFIG_FILE_PREFIX + ".cloudera.manager.service.discovery.excluded.service.types";
private static final String CLOUDERA_MANAGER_SERVICE_DISCOVERY_EXCLUDED_ROLE_TYPES = GATEWAY_CONFIG_FILE_PREFIX + ".cloudera.manager.service.discovery.excluded.role.types";

private static final long CLOUDERA_MANAGER_SERVICE_DISCOVERY_CONNECT_TIMEOUT_DEFAULT = 10000;
private static final long CLOUDERA_MANAGER_SERVICE_DISCOVERY_READ_TIMEOUT_DEFAULT = 10000;
Expand Down Expand Up @@ -1301,6 +1303,16 @@ public int getClouderaManagerServiceDiscoveryMaximumRetryAttempts() {
return getInt(CLOUDERA_MANAGER_SERVICE_DISCOVERY_MAX_RETRY_ATTEMPS, DEFAULT_CM_SERVICE_DISCOVERY_MAX_RETRY_ATTEMPTS);
}

@Override
public Collection<String> getClouderaManagerServiceDiscoveryExcludedServiceTypes() {
return getTrimmedStringCollection(CLOUDERA_MANAGER_SERVICE_DISCOVERY_EXCLUDED_SERVICE_TYPES);
}

@Override
public Collection<String> getClouderaManagerServiceDiscoveryExcludedRoleTypes() {
return getTrimmedStringCollection(CLOUDERA_MANAGER_SERVICE_DISCOVERY_EXCLUDED_ROLE_TYPES);
}

@Override
public boolean isServerManagedTokenStateEnabled() {
return getBoolean(TOKEN_STATE_SERVER_MANAGED, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,16 @@ public int getClouderaManagerServiceDiscoveryMaximumRetryAttempts() {
return -1;
}

@Override
public Collection<String> getClouderaManagerServiceDiscoveryExcludedServiceTypes() {
return Collections.emptySet();
}

@Override
public Collection<String> getClouderaManagerServiceDiscoveryExcludedRoleTypes() {
return Collections.emptySet();
}

@Override
public boolean isServerManagedTokenStateEnabled() {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,18 @@ public interface GatewayConfig {
*/
int getClouderaManagerServiceDiscoveryMaximumRetryAttempts();

/**
* @return a collection of comma separated service types that should be excluded
* from CM service discovery (e.g. HDFS, KNOX, RANGER, HIVE, etc...)
*/
Collection<String> getClouderaManagerServiceDiscoveryExcludedServiceTypes();

/**
* @return a collection of comma separated role types that should be excluded
* from CM service discovery (e.g. KNOX_GATEWAY, IDBROKER, DATANODE, HIVEMETASTORE, etc...)
*/
Collection<String> getClouderaManagerServiceDiscoveryExcludedRoleTypes();

/**
* @return true, if state for tokens issued by the Knox Token service should be managed by Knox.
*/
Expand Down

0 comments on commit 6f2ad96

Please sign in to comment.