package com.thinkbiganalytics.feedmgr.nifi; /*- * #%L * thinkbig-feed-manager-controller * %% * Copyright (C) 2017 ThinkBig Analytics * %% * 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. * #L% */ import com.thinkbiganalytics.discovery.model.DefaultTableSchema; import com.thinkbiganalytics.feedmgr.rest.model.FeedCategory; import com.thinkbiganalytics.feedmgr.rest.model.FeedMetadata; import com.thinkbiganalytics.feedmgr.rest.model.schema.TableSetup; import com.thinkbiganalytics.nifi.rest.model.NifiProperty; import org.apache.commons.lang3.text.StrSubstitutor; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import javax.inject.Inject; @ContextConfiguration(classes = PropertyExpressionResolverConfig.class) @RunWith(SpringJUnit4ClassRunner.class) public class PropertyExpressionResolverTest { /** * Default processor group id or name */ private static final String DEFAULT_GROUP = "group"; /** * Default property key name */ private static final String DEFAULT_KEY = "key"; /** * Default processor type */ private static final String DEFAULT_TYPE = "com.example.UpdateAttributes"; private static final String DEFAULT_PROCESSOR_NAME="Processor Name"; /** * Property key name for static configuration */ private static final String STATIC_KEY = "App Key"; /** * Resolves expressions in property values */ @Inject private PropertyExpressionResolver resolver; @Test public void testContainsVariable() { Assert.assertTrue(resolver.containsVariablesPatterns("abc 123 ${var}")); } @Test public void testStrSubstitutor() { String template1 = "${metadata.feedName}_config.xx"; Map<String, String> map1 = new HashMap<>(); map1.put("metadata.feedName", "category.feed"); StrSubstitutor ss1 = new StrSubstitutor(map1); ss1.setEnableSubstitutionInVariables(true); Assert.assertEquals("category.feed_config.xx", ss1.replace(template1)); String template2 = "$${${metadata.feedName}_config.xx}"; StrSubstitutor ss2 = new StrSubstitutor(map1); ss2.setEnableSubstitutionInVariables(true); Assert.assertEquals("${category.feed_config.xx}", ss2.replace(template2)); String template3 = "${${metadata.feedName}_config.xx}"; map1.put("category.feed_config.xx", "runtime value"); StrSubstitutor ss3 = new StrSubstitutor(map1); ss3.setEnableSubstitutionInVariables(true); Assert.assertEquals("runtime value", ss3.replace(template3)); } /** * Verifies resolving expressions in property values. */ @Test public void resolveExpression() { final FeedMetadata metadata = new FeedMetadata(); metadata.setSystemFeedName("myfeed"); // Verify config variable final NifiProperty prop1 = createProperty("${config.test.value}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop1)); Assert.assertEquals("hello-world", prop1.getValue()); // Verify metadata variable final NifiProperty prop2 = createProperty("${metadata.systemFeedName}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop2)); Assert.assertEquals("myfeed", prop2.getValue()); // Verify static config final NifiProperty prop3 = createProperty(STATIC_KEY, "${metadata.systemFeedName}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop3)); Assert.assertEquals("myapp", prop3.getValue()); final NifiProperty prop4 = createProperty(STATIC_KEY, "${config.test.value}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop4)); Assert.assertEquals("hello-world", prop4.getValue()); final NifiProperty prop5 = createProperty(STATIC_KEY, ""); Assert.assertTrue(resolver.resolveExpression(metadata, prop5)); Assert.assertEquals("myapp", prop5.getValue()); // Verify multiple variables final NifiProperty prop6 = createProperty("${metadata.systemFeedName}.${config.test.value}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop6)); Assert.assertEquals("myfeed.hello-world", prop6.getValue()); // Verify multiple variables final NifiProperty prop7 = createProperty("$${${metadata.systemFeedName}.${config.test.value}}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop7)); Assert.assertEquals("${myfeed.hello-world}", prop7.getValue()); // Verify multiple variables final NifiProperty prop8 = createProperty("${config.${metadata.systemFeedName}.${config.test.value}}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop8)); Assert.assertEquals("runtime value", prop8.getValue()); // Verify static text final NifiProperty prop9 = createProperty("config.test.value"); Assert.assertFalse(resolver.resolveExpression(metadata, prop9)); Assert.assertEquals("config.test.value", prop9.getValue()); //verify replacement with NiFi el final NifiProperty prop10 = createProperty("property1","a value"); Assert.assertTrue(resolver.resolveExpression(metadata, prop10)); Assert.assertEquals("/path/to/property1,${nifi.expression.property}", prop10.getValue()); //verify replacement without NiFi el final NifiProperty prop11 = createProperty("Another Processor","property1","a value"); Assert.assertTrue(resolver.resolveExpression(metadata, prop11)); Assert.assertEquals("/path/to/another_processor/property1/location", prop11.getValue()); //verify replacement without NiFi el using default processor type replacement final NifiProperty prop12 = createProperty("My New Processor","property1","a value"); Assert.assertTrue(resolver.resolveExpression(metadata, prop12)); Assert.assertEquals("/path/to/property1/location", prop12.getValue()); } /** * Verifies invalid expressions are resolved properly. */ @Test public void resolveExpressionInvalid() { final FeedMetadata metadata = new FeedMetadata(); // Verify missing config variable final NifiProperty prop1 = createProperty("${config.test.invalid}"); Assert.assertFalse(resolver.resolveExpression(metadata, prop1)); Assert.assertEquals("${config.test.invalid}", prop1.getValue()); // Verify missing metadata variable final NifiProperty prop2 = createProperty("${metadata.invalid}"); Assert.assertFalse(resolver.resolveExpression(metadata, prop2)); Assert.assertEquals("${metadata.invalid}", prop2.getValue()); // Verify empty variable final NifiProperty prop3 = createProperty("${}"); Assert.assertFalse(resolver.resolveExpression(metadata, prop3)); Assert.assertEquals("${}", prop3.getValue()); } /** * Creates a new property with the specified value. * * @param value the value * @return the new property */ @Nonnull public NifiProperty createProperty(@Nonnull final String value) { return createProperty(DEFAULT_KEY, value); } /** * Creates a new property with the specified key and value. * * @param key the key name * @param value the value * @return the new property */ @Nonnull public NifiProperty createProperty(@Nonnull final String key, @Nonnull final String value) { return createProperty(DEFAULT_PROCESSOR_NAME,key,value); } /** * Creates a new property with the specified key and value. *@param processorName the name of the processor * @param key the key name * @param value the value * @return the new property */ @Nonnull public NifiProperty createProperty(@Nonnull final String processorName,@Nonnull final String key, @Nonnull final String value) { final NifiProperty property = new NifiProperty(DEFAULT_GROUP, DEFAULT_GROUP, key, value); property.setProcessorType(DEFAULT_TYPE); property.setProcessorName(processorName); return property; } @Test public void testFeedMetadataProperties() { FeedMetadata metadata = new FeedMetadata(); metadata.setSystemFeedName("feedSystemName"); metadata.setCategory(new FeedCategory()); metadata.setTable(new TableSetup()); metadata.getTable().setSourceTableSchema(new DefaultTableSchema()); metadata.getTable().setTableSchema(new DefaultTableSchema()); metadata.getTable().getSourceTableSchema().setName("sourceTableName"); metadata.getTable().getTableSchema().setName("tableSchemaName"); final NifiProperty prop1 = createProperty("${metadata.table.sourceTableSchema.name}"); Assert.assertTrue(resolver.resolveExpression(metadata, prop1)); Assert.assertEquals("sourceTableName", prop1.getValue()); } @Test public void testResolveValues() { List<NifiProperty> props = new ArrayList<>(); props.add(newProperty("test.property", "${a}/${b} ")); props.add(newProperty("test.property2", "${a2}/${c} ")); props.add(newProperty("d", "fred")); props.add(newProperty("a", "${b} ")); props.add(newProperty("b", "${c}")); props.add(newProperty("c", "${d}")); PropertyExpressionResolver.ResolvedVariables variables = resolver.resolveVariables("${a} - ${b} - ${test.property2}", props); Assert.assertEquals("fred - fred - ${a2}/fred", variables.getResolvedString()); Map<String, String> resolvedVariables = variables.getResolvedVariables(); Assert.assertEquals("fred", resolvedVariables.get("a")); Assert.assertEquals("fred", resolvedVariables.get("b")); Assert.assertEquals("fred", resolvedVariables.get("c")); Assert.assertEquals("fred", resolvedVariables.get("d")); Assert.assertEquals("${a2}/fred", resolvedVariables.get("test.property2")); Assert.assertEquals(5, resolvedVariables.size()); System.out.println(resolvedVariables); } private NifiProperty newProperty(String key, String value) { NifiProperty p = new NifiProperty(); p.setKey(key); p.setValue(value); return p; } }