package com.sequenceiq.cloudbreak.service.cluster.flow.blueprint; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.junit.Assert; import org.junit.Test; import com.fasterxml.jackson.databind.JsonNode; import com.sequenceiq.cloudbreak.util.FileReaderUtils; import com.sequenceiq.cloudbreak.util.JsonUtil; public class JacksonBlueprintProcessorTest { private static final String HOST_GROUPS_NODE = "host_groups"; private JacksonBlueprintProcessor underTest = new JacksonBlueprintProcessor(); @Test public void testAddConfigEntriesAddsRootConfigurationsNodeIfMissing() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, true); JsonNode configNode = JsonUtil.readTree(result).path("configurations"); Assert.assertFalse(configNode.isMissingNode()); } @Test public void testModifyStackVersionWithThreeTag() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); String result = underTest.modifyHdpVersion(testBlueprint, "2.2.4.4"); JsonNode configNode = JsonUtil.readTree(result).path("Blueprints"); String stackVersion = configNode.get("stack_version").asText(); Assert.assertEquals("2.2", stackVersion); } @Test public void testModifyStackVersionWithTwoTag() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); String result = underTest.modifyHdpVersion(testBlueprint, "2.6"); JsonNode configNode = JsonUtil.readTree(result).path("Blueprints"); String stackVersion = configNode.get("stack_version").asText(); Assert.assertEquals("2.6", stackVersion); } @Test public void testAddConfigEntriesAddsConfigFileEntryIfMissing() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-with-empty-config-block.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.AbstractFileSystem.wasb.impl", "org.apache.hadoop.fs.azure.Wasb")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, true); JsonNode coreSiteNode = JsonUtil.readTree(result).findPath("core-site"); Assert.assertFalse(coreSiteNode.isMissingNode()); } @Test public void testAddConfigEntriesAddsConfigEntriesToCorrectConfigBlockWithCorrectValues() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-with-empty-config-block.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.AbstractFileSystem.wasb.impl", "org.apache.hadoop.fs.azure.Wasb")); configurationEntries.add(new BlueprintConfigurationEntry("hdfs-site", "dfs.blocksize", "134217728")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, true); String configValue1 = JsonUtil.readTree(result).findPath("core-site").findPath("fs.AbstractFileSystem.wasb.impl").textValue(); Assert.assertEquals("org.apache.hadoop.fs.azure.Wasb", configValue1); String configValue2 = JsonUtil.readTree(result).findPath("hdfs-site").findPath("dfs.blocksize").textValue(); Assert.assertEquals("134217728", configValue2); } @Test public void testAddConfigEntriesAddsConfigEntriesToExistingConfigBlockAndKeepsExistingEntries() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-with-core-site.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.AbstractFileSystem.wasb.impl", "org.apache.hadoop.fs.azure.Wasb")); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "io.serializations", "org.apache.hadoop.io.serializer.WritableSerialization")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, true); String configValue1 = JsonUtil.readTree(result).findPath("core-site").path("fs.AbstractFileSystem.wasb.impl").textValue(); Assert.assertEquals("org.apache.hadoop.fs.azure.Wasb", configValue1); String configValue2 = JsonUtil.readTree(result).findPath("core-site").path("io.serializations").textValue(); Assert.assertEquals("org.apache.hadoop.io.serializer.WritableSerialization", configValue2); String configValue3 = JsonUtil.readTree(result).findPath("core-site").path("fs.trash.interval").textValue(); Assert.assertEquals("360", configValue3); String configValue4 = JsonUtil.readTree(result).findPath("core-site").path("io.file.buffer.size").textValue(); Assert.assertEquals("131072", configValue4); } @Test public void testAddConfigEntriesAddsConfigEntriesToExistingConfigPropertiesBlockAndKeepsExistingEntries() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-with-core-site-properties.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.AbstractFileSystem.wasb.impl", "org.apache.hadoop.fs.azure.Wasb")); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "io.serializations", "org.apache.hadoop.io.serializer.WritableSerialization")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, true); String configValue1 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("fs.AbstractFileSystem.wasb.impl").textValue(); Assert.assertEquals("org.apache.hadoop.fs.azure.Wasb", configValue1); String configValue2 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("io.serializations").textValue(); Assert.assertEquals("org.apache.hadoop.io.serializer.WritableSerialization", configValue2); String configValue3 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("fs.trash.interval").textValue(); Assert.assertEquals("360", configValue3); String configValue4 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("io.file.buffer.size").textValue(); Assert.assertEquals("131072", configValue4); } @Test public void testAddConfigEntriesAddsConfigEntriesToExistingConfigPropertiesBlockAndUpdatesExistingEntries() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-with-core-site-properties-defaultfs.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.defaultFS", "wasb://cloudbreak@dduihoab6jt1jl.cloudapp.net")); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "io.serializations", "org.apache.hadoop.io.serializer.WritableSerialization")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, true); String configValue1 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("fs.defaultFS").textValue(); Assert.assertEquals("wasb://cloudbreak@dduihoab6jt1jl.cloudapp.net", configValue1); String configValue2 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("io.serializations").textValue(); Assert.assertEquals("org.apache.hadoop.io.serializer.WritableSerialization", configValue2); String configValue3 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("fs.trash.interval").textValue(); Assert.assertEquals("360", configValue3); String configValue4 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("io.file.buffer.size").textValue(); Assert.assertEquals("131072", configValue4); } @Test public void testAddConfigEntriesAddsConfigEntriesToExistingConfigPropertiesBlockAndDoesNotUpdateExistingEntriesWhenOverrideIsFalse() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-with-core-site-properties-defaultfs.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.defaultFS", "wasb://cloudbreak@dduihoab6jt1jl.cloudapp.net")); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "io.serializations", "org.apache.hadoop.io.serializer.WritableSerialization")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, false); String configValue1 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("fs.defaultFS").textValue(); Assert.assertEquals("hdfs://%HOSTGROUP::host_group_master_1%:8020", configValue1); String configValue2 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("io.serializations").textValue(); Assert.assertEquals("org.apache.hadoop.io.serializer.WritableSerialization", configValue2); String configValue3 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("fs.trash.interval").textValue(); Assert.assertEquals("360", configValue3); String configValue4 = JsonUtil.readTree(result).findPath("core-site").path("properties").path("io.file.buffer.size").textValue(); Assert.assertEquals("131072", configValue4); } @Test public void testAddConfigEntriesBehavesCorrectlyWhenThereIsNoConfigurationsNode() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "fs.defaultFS", "wasb://cloudbreak@dduihoab6jt1jl.cloudapp.net")); configurationEntries.add(new BlueprintConfigurationEntry("core-site", "io.serializations", "org.apache.hadoop.io.serializer.WritableSerialization")); String result = underTest.addConfigEntries(testBlueprint, configurationEntries, false); String configValue1 = JsonUtil.readTree(result).findPath("core-site").path("fs.defaultFS").textValue(); Assert.assertEquals("wasb://cloudbreak@dduihoab6jt1jl.cloudapp.net", configValue1); String configValue2 = JsonUtil.readTree(result).findPath("core-site").path("io.serializations").textValue(); Assert.assertEquals("org.apache.hadoop.io.serializer.WritableSerialization", configValue2); } @Test public void testRemoveComponentFromBlueprint() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); String result = underTest.removeComponentFromBlueprint("NAGIOS_SERVER", testBlueprint); Assert.assertFalse(result.contains("NAGIOS_SERVER")); } @Test(expected = BlueprintProcessingException.class) public void testAddConfigEntriesThrowsExceptionIfBlueprintCannotBeParsed() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-invalid.bp"); List<BlueprintConfigurationEntry> configurationEntries = new ArrayList<>(); underTest.addConfigEntries(testBlueprint, configurationEntries, true); } @Test public void testGetServicesInHostgroup() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); Set<String> result = underTest.getComponentsInHostGroup(testBlueprint, "slave_1"); Set<String> expected = new HashSet<>(); expected.add("DATANODE"); expected.add("HDFS_CLIENT"); expected.add("NODEMANAGER"); expected.add("YARN_CLIENT"); expected.add("MAPREDUCE2_CLIENT"); expected.add("ZOOKEEPER_CLIENT"); Assert.assertEquals(expected, result); } @Test(expected = BlueprintProcessingException.class) public void testGetServicesInHostgroupThrowsExceptionIfBlueprintCannotBeParsed() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-invalid.bp"); underTest.getComponentsInHostGroup(testBlueprint, "slave_1"); } @Test public void testAddComponentToHostgroupsIfComponentIsMissing() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); String result = underTest.addComponentToHostgroups("HST_SERVER", Collections.singletonList("slave_1"), testBlueprint); Assert.assertTrue(underTest.componentExistsInBlueprint("HST_SERVER", result)); } @Test public void testAddComponentToHostgroupsShouldAddComponentToEverySpecifiedHostGroupIfComponentIsMissing() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); String componentToAdd = "HST_AGENT"; String result = underTest.addComponentToHostgroups(componentToAdd, Arrays.asList("master", "slave_1"), testBlueprint); Iterator<JsonNode> hostGroups = JsonUtil.readTree(result).path(HOST_GROUPS_NODE).elements(); while (hostGroups.hasNext()) { JsonNode hostGroup = hostGroups.next(); Assert.assertTrue(componentExistsInHostgroup(componentToAdd, hostGroup)); } } @Test public void testAddComponentToHostgroupsShouldNotModifyBlueprintIfComponentExists() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-without-config-block.bp"); String componentToAdd = "NAMENODE"; String result = underTest.addComponentToHostgroups(componentToAdd, Collections.singletonList("master"), testBlueprint); Assert.assertEquals(testBlueprint.replaceAll("\\s", ""), result); } @Test public void addToBlueprint() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/test-bp-zeppelin-shiro.bp"); List<BlueprintConfigurationEntry> configs = new ArrayList<>(); configs.add(new BlueprintConfigurationEntry("zeppelin-env", "shiro_ini_content", "changed")); String result = underTest.addConfigEntries(testBlueprint, configs, false); Assert.assertEquals(testBlueprint.replaceAll("\\s", ""), result); } @Test public void addSettingsToBlueprintWhenNoSettingsBlock() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/bp-without-settings-array.bp"); String res = FileReaderUtils.readFileFromClasspath("blueprints/settings-bp-result.bp"); List<BlueprintConfigurationEntry> configs = new ArrayList<>(); configs.add(new BlueprintConfigurationEntry("recovery_settings", "recovery_enabled", "true")); configs.add(new BlueprintConfigurationEntry("cluster-env", "recovery_enabled", "true")); configs.add(new BlueprintConfigurationEntry("cluster-env", "recovery_type", "AUTO_START")); String result = underTest.addSettingsEntries(testBlueprint, configs, false); Assert.assertEquals(res.replaceAll("\\s", ""), result.replaceAll("\\s", "")); } @Test public void addSettingsToBlueprintWhenSettingsBlockExists() throws Exception { String testBlueprint = FileReaderUtils.readFileFromClasspath("blueprints/bp-with-settings-array.bp"); String res = FileReaderUtils.readFileFromClasspath("blueprints/with-settings-bp-result.bp"); List<BlueprintConfigurationEntry> configs = new ArrayList<>(); configs.add(new BlueprintConfigurationEntry("recovery_settings", "recovery_enabled", "true")); configs.add(new BlueprintConfigurationEntry("cluster-env", "recovery_enabled", "true")); configs.add(new BlueprintConfigurationEntry("cluster-env", "recovery_type", "AUTO_START")); String result = underTest.addSettingsEntries(testBlueprint, configs, false); Assert.assertEquals(res.replaceAll("\\s", ""), result.replaceAll("\\s", "")); } private boolean componentExistsInHostgroup(String component, JsonNode hostGroupNode) { boolean componentExists = false; Iterator<JsonNode> components = hostGroupNode.path("components").elements(); while (components.hasNext()) { if (component.equals(components.next().path("name").textValue())) { componentExists = true; break; } } return componentExists; } }