/*
* Licensed 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.ambari.server.topology.validators;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.apache.ambari.server.controller.internal.Stack;
import org.apache.ambari.server.topology.Blueprint;
import org.apache.ambari.server.topology.ClusterTopology;
import org.apache.ambari.server.topology.Configuration;
import org.apache.ambari.server.topology.HostGroup;
import org.apache.ambari.server.topology.InvalidTopologyException;
import org.easymock.EasyMock;
import org.easymock.EasyMockRule;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
public class RequiredConfigPropertiesValidatorTest extends EasyMockSupport {
@Rule
public EasyMockRule mocks = new EasyMockRule(this);
@Mock
private ClusterTopology clusterTopologyMock;
@Mock
private Configuration topologyConfigurationMock;
@Mock
private Blueprint blueprintMock;
@Mock
private Stack stackMock;
@Mock
private HostGroup slaveHostGroupMock;
@Mock
private HostGroup masterHostGroupMock;
@Mock
private Configuration slaveHostGroupConfigurationMock;
@Mock
private Configuration masterHostGroupConfigurationMock;
private Map<String, Map<String, String>> topologyConfigurationMap = new HashMap<>();
private Map<String, Map<String, String>> masterHostGroupConfigurationMap = new HashMap<>();
private Map<String, Map<String, String>> slaveHostGroupConfigurationMap = new HashMap<>();
private Collection<String> bpServices = new HashSet<>();
private Collection<String> slaveHostGroupServices = new HashSet<>();
private Collection<String> masterHostGroupServices = new HashSet<>();
private Map<String, HostGroup> hostGroups = new HashMap<>();
private Map<String, Collection<String>> missingProps = new HashMap<>();
@TestSubject
private RequiredConfigPropertiesValidator testSubject = new RequiredConfigPropertiesValidator();
/**
* Assembles the basic default fixture of the test:
* The blueprint has 2 hostgroups, both of them contains the KERBEROS service (or KERBEROS_CLIENT)
* The changing items are the configurations, that my come from the topology (bp + cct) or the hostg roups
*/
@Before
public void setup() {
resetAll();
EasyMock.expect(clusterTopologyMock.getConfiguration()).andReturn(topologyConfigurationMock);
EasyMock.expect(topologyConfigurationMock.getFullProperties(1)).andReturn(topologyConfigurationMap);
EasyMock.expect(clusterTopologyMock.getBlueprint()).andReturn(blueprintMock).anyTimes();
EasyMock.expect(blueprintMock.getHostGroups()).andReturn(hostGroups);
EasyMock.expect(blueprintMock.getServices()).andReturn(bpServices);
EasyMock.expect(blueprintMock.getStack()).andReturn(stackMock).anyTimes();
EasyMock.expect(masterHostGroupMock.getName()).andReturn("master").anyTimes();
EasyMock.expect(masterHostGroupMock.getConfiguration()).andReturn(masterHostGroupConfigurationMock).anyTimes();
EasyMock.expect(masterHostGroupMock.getServices()).andReturn(masterHostGroupServices);
EasyMock.expect(slaveHostGroupMock.getName()).andReturn("slave").anyTimes();
EasyMock.expect(slaveHostGroupMock.getConfiguration()).andReturn(slaveHostGroupConfigurationMock).anyTimes();
EasyMock.expect(slaveHostGroupMock.getServices()).andReturn(slaveHostGroupServices);
// there are 2 hostgroups to be considered by the test
hostGroups.put("master", masterHostGroupMock);
hostGroups.put("slave", slaveHostGroupMock);
// services in the blueprint
bpServices.addAll(Arrays.asList("KERBEROS", "OOZIE"));
// host group services
masterHostGroupServices.addAll(Arrays.asList("KERBEROS"));
slaveHostGroupServices.addAll(Arrays.asList("KERBEROS"));
EasyMock.expect(masterHostGroupConfigurationMock.getProperties()).andReturn(masterHostGroupConfigurationMap);
EasyMock.expect(slaveHostGroupConfigurationMock.getProperties()).andReturn(slaveHostGroupConfigurationMap);
// services in the blueprint
bpServices.addAll(Arrays.asList("KERBEROS", "OOZIE"));
// required properties for listed services
EasyMock.expect(stackMock.getRequiredConfigurationProperties("KERBEROS")).
andReturn(Arrays.asList(
new Stack.ConfigProperty("kerberos-env", "realm", "value"),
new Stack.ConfigProperty("kerberos-env", "kdc_type", "value"), // this is missing!
new Stack.ConfigProperty("krb5-conf", "domains", "smthg")));
EasyMock.expect(stackMock.getRequiredConfigurationProperties("OOZIE")).andReturn(Collections.EMPTY_LIST);
}
@Test
public void testShouldValidationFailWhenNoHostGroupConfigurationProvidedAndRequiredConfigTypesAreMissing() throws Exception {
// GIVEN
// all the configuration comes from the bp, cct hg configs are empty
topologyConfigurationMap.put("kerberos-env", new HashMap<String, String>());
topologyConfigurationMap.get("kerberos-env").put("realm", "etwas");
topologyConfigurationMap.get("kerberos-env").put("kdc_type", "mit-kdc");
// note, that the krb-5 config type is missing! (see the required properties in the fixture!)
missingProps.put("slave", Arrays.asList("domains"));
missingProps.put("master", Arrays.asList("domains"));
replayAll();
// WHEN
String expectedMsg = String.format("Missing required properties. Specify a value for these properties in the blueprint or cluster creation template configuration. %s", missingProps);
String actualMsg = "";
try {
testSubject.validate(clusterTopologyMock);
} catch (InvalidTopologyException e) {
actualMsg = e.getMessage();
}
// THEN
// Exception is thrown, as the krb5-conf typeeis not provided
Assert.assertEquals("The exception message should be the expected one", expectedMsg, actualMsg);
}
@Test
public void testShouldValidationFailWhenNoHostGroupConfigurationProvidedAndRequiredPropertiesAreMissing() throws Exception {
// GIVEN
// configuration from the blueprint / cluster creation template
topologyConfigurationMap.put("kerberos-env", new HashMap<String, String>());
topologyConfigurationMap.get("kerberos-env").put("realm", "etwas");
// note, that tehe kdc_type is mssing from the operational config
topologyConfigurationMap.put("krb5-conf", new HashMap<String, String>());
topologyConfigurationMap.get("krb5-conf").put("domains", "smthg");
missingProps.put("master", Arrays.asList("kdc_type"));
missingProps.put("slave", Arrays.asList("kdc_type"));
replayAll();
// WHEN
String expectedMsg = String.format("Missing required properties. Specify a value for these properties in the blueprint or cluster creation template configuration. %s", missingProps);
String actualMsg = "";
try {
testSubject.validate(clusterTopologyMock);
} catch (InvalidTopologyException e) {
actualMsg = e.getMessage();
}
// THEN
// Exception is thrown, as the krb5-conf typee is not provideds
Assert.assertEquals("The exception message should be the expected one", expectedMsg, actualMsg);
}
@Test
public void testShouldValidationFailWhenHostGroupConfigurationProvidedAndRequiredConfigTypesAreMissingFromBothHostgroups() throws Exception {
// GIVEN
// configuration come in the host groups, there are missing config types in both hostgroups
missingProps.put("master", Arrays.asList("kdc_type", "domains", "realm"));
missingProps.put("slave", Arrays.asList("kdc_type", "domains", "realm"));
replayAll();
// WHEN
String expectedMsg = String.format("Missing required properties. Specify a value for these properties in the blueprint or cluster creation template configuration. %s", missingProps);
String actualMsg = "";
try {
testSubject.validate(clusterTopologyMock);
} catch (InvalidTopologyException e) {
actualMsg = e.getMessage();
}
// THEN
// Exception is thrown, as the krb5-conf typee is not provideds
Assert.assertEquals("The exception message should be the expected one", expectedMsg, actualMsg);
}
@Test
public void testShouldValidationFailWhenHostGroupConfigurationProvidedAndRequiredConfigTypesAreMissingFromSlaveHostgroup() throws Exception {
// GIVEN
// configuration come in the host groups, there are missing config types in both hostgroups
masterHostGroupConfigurationMap.put("kerberos-env", new HashMap<String, String>());
masterHostGroupConfigurationMap.get("kerberos-env").put("realm", "etwas");
masterHostGroupConfigurationMap.get("kerberos-env").put("kdc_type", "mit-kdc");
masterHostGroupConfigurationMap.put("krb5-conf", new HashMap<String, String>());
masterHostGroupConfigurationMap.get("krb5-conf").put("domains", "smthg");
missingProps.put("slave", Arrays.asList("kdc_type", "domains", "realm"));
replayAll();
// WHEN
String expectedMsg = String.format("Missing required properties. Specify a value for these properties in the blueprint or cluster creation template configuration. %s", missingProps);
String actualMsg = "";
try {
testSubject.validate(clusterTopologyMock);
} catch (InvalidTopologyException e) {
actualMsg = e.getMessage();
}
// THEN
// Exception is thrown, as the krb5-conf typee is not provideds
Assert.assertEquals("The exception message should be the expected one", expectedMsg, actualMsg);
}
@Test
public void testShouldValidationPassWhenAllRequiredPropertiesAreProvidedInHostGroupConfiguration() throws Exception {
// GIVEN
masterHostGroupConfigurationMap.put("kerberos-env", new HashMap<String, String>());
masterHostGroupConfigurationMap.get("kerberos-env").put("realm", "etwas");
masterHostGroupConfigurationMap.get("kerberos-env").put("kdc_type", "mit-kdc");
masterHostGroupConfigurationMap.put("krb5-conf", new HashMap<String, String>());
masterHostGroupConfigurationMap.get("krb5-conf").put("domains", "smthg");
slaveHostGroupConfigurationMap.put("kerberos-env", new HashMap<String, String>());
slaveHostGroupConfigurationMap.get("kerberos-env").put("realm", "etwas");
slaveHostGroupConfigurationMap.get("kerberos-env").put("kdc_type", "mit-kdc");
slaveHostGroupConfigurationMap.put("krb5-conf", new HashMap<String, String>());
slaveHostGroupConfigurationMap.get("krb5-conf").put("domains", "smthg");
replayAll();
// WHEN
testSubject.validate(clusterTopologyMock);
// THEN
// no exceptions thrown
}
@Test
public void testShouldValidationPassWhenAllRequiredPropertiesAreProvidedInTopologyConfiguration() throws Exception {
// GIVEN
// configuration from the blueprint / cluster creation template
topologyConfigurationMap.put("kerberos-env", new HashMap<String, String>());
topologyConfigurationMap.get("kerberos-env").put("realm", "etwas");
topologyConfigurationMap.get("kerberos-env").put("kdc_type", "value");
topologyConfigurationMap.put("krb5-conf", new HashMap<String, String>());
topologyConfigurationMap.get("krb5-conf").put("domains", "smthg");
replayAll();
// WHEN
testSubject.validate(clusterTopologyMock);
// THEN
// no exceptions thrown
}
}