private void processComponent( BlockComponent block ) { ComponentData data = this.componentNameToComponentData.get( block.getName()); if( data != null ) { data.blocks.add( block ); } else { data = new ComponentData(); data.object = new Component( block.getName()); data.object.exportedVariables.putAll( ModelUtils.getExportedVariables( block )); data.object.setInstallerName( ModelUtils.getPropertyValue( block, ParsingConstants.PROPERTY_COMPONENT_INSTALLER )); for( String s : ModelUtils.getPropertyValues( block, ParsingConstants.PROPERTY_COMPONENT_IMPORTS )) { Boolean optional = s.toLowerCase().endsWith( ParsingConstants.PROPERTY_COMPONENT_OPTIONAL_IMPORT ); if( optional ) s = s.substring( 0, s.length() - ParsingConstants.PROPERTY_COMPONENT_OPTIONAL_IMPORT.length()).trim(); Boolean external = s.toLowerCase().startsWith( ParsingConstants.PROPERTY_COMPONENT_EXTERNAL_IMPORT ); if( external ) s = s.substring( ParsingConstants.PROPERTY_COMPONENT_EXTERNAL_IMPORT.length()).trim(); data.object.addImportedVariable( new ImportedVariable( s, optional, external )); } data.extendedComponentName = ModelUtils.getPropertyValue( block, ParsingConstants.PROPERTY_GRAPH_EXTENDS ); data.childrenNames.addAll( ModelUtils.getPropertyValues( block, ParsingConstants.PROPERTY_GRAPH_CHILDREN )); data.facetNames.addAll( ModelUtils.getPropertyValues( block, ParsingConstants.PROPERTY_COMPONENT_FACETS )); data.blocks.add( block ); this.componentNameToComponentData.put( block.getName(), data ); } }
@Test public void testFindPrefixesForMandatoryImportedVariables() { Component component = new Component( "comp" ); component.addImportedVariable( new ImportedVariable( "comp.ip", false, false )); component.addImportedVariable( new ImportedVariable( "comp.split.property", false, false )); component.addImportedVariable( new ImportedVariable( "comp.port", false, false )); component.addImportedVariable( new ImportedVariable( "facet.desc", true, false )); component.addImportedVariable( new ImportedVariable( "facet-n.prop1", true, false )); component.addImportedVariable( new ImportedVariable( "facet-n.prop2", false, false )); Instance instance = new Instance( "inst" ).component( component ); Set<String> prefixes = VariableHelpers.findPrefixesForMandatoryImportedVariables( instance ); Assert.assertEquals( 2, prefixes.size()); Assert.assertTrue( prefixes.contains( "comp" )); Assert.assertTrue( prefixes.contains( "facet-n" )); component.importedVariables.clear(); prefixes = VariableHelpers.findPrefixesForMandatoryImportedVariables( instance ); Assert.assertEquals( 0, prefixes.size()); }
@Test public void testFindPrefixesForImportedVariables() { Component component = new Component( "comp" ); component.addImportedVariable( new ImportedVariable( "comp.ip", false, false )); component.addImportedVariable( new ImportedVariable( "comp.split.property", false, false )); component.addImportedVariable( new ImportedVariable( "comp.port", false, false )); component.addImportedVariable( new ImportedVariable( "facet.desc", false, false )); Instance instance = new Instance( "inst" ).component( component ); Set<String> prefixes = VariableHelpers.findPrefixesForImportedVariables( instance ); Assert.assertEquals( 2, prefixes.size()); Assert.assertTrue( prefixes.contains( "comp" )); Assert.assertTrue( prefixes.contains( "facet" )); component.importedVariables.clear(); prefixes = VariableHelpers.findPrefixesForImportedVariables( instance ); Assert.assertEquals( 0, prefixes.size()); }
@Test public void testPuppetValidation_invalidPuppetClass() throws Exception { Assume.assumeTrue(puppetIsInstalled()); File appDir = this.folder.newFolder(); Component comp = new Component( "toto" ).installerName( "puppet" ); comp.addImportedVariable( new ImportedVariable( "Test.ip", true, false )); comp.addImportedVariable( new ImportedVariable( "Test.port", true, false )); comp.addImportedVariable( new ImportedVariable( "Oops.ip", true, false )); File directory = ResourceUtils.findInstanceResourcesDirectory( appDir, comp ); Assert.assertTrue( new File( directory, "roboconf_toto/manifests" ).mkdirs()); File targetFile = new File( directory, "roboconf_toto/manifests/start.pp" ); Utils.writeStringInto( "Not a valid puppet class...", targetFile ); List<ModelError> errors = RecipesValidator.validateComponentRecipes( appDir, comp ); Assert.assertEquals( 1, errors.size()); Assert.assertEquals( ErrorCode.REC_PUPPET_SYNTAX_ERROR, errors.get( 0 ).getErrorCode()); }
@Test public void testPuppetValidation_oneModuleButWildCardImports() throws Exception { File appDir = this.folder.newFolder(); Component comp = new Component( "toto" ).installerName( "puppet" ); comp.addImportedVariable( new ImportedVariable( "Other.*", true, false )); File directory = ResourceUtils.findInstanceResourcesDirectory( appDir, comp ); Assert.assertTrue( new File( directory, "roboconf_toto" ).mkdirs()); List<ModelError> errors = RecipesValidator.validateComponentRecipes( appDir, comp ); Assert.assertEquals( 1, errors.size()); Assert.assertEquals( ErrorCode.REC_PUPPET_DISLIKES_WILDCARD_IMPORTS, errors.get( 0 ).getErrorCode()); }
@Test public void testPuppetValidation_withMatchingImport() throws Exception { File appDir = this.folder.newFolder(); Component comp = new Component( "toto" ).installerName( "puppet" ); comp.addImportedVariable( new ImportedVariable( "WithInit.value", true, false )); File directory = ResourceUtils.findInstanceResourcesDirectory( appDir, comp ); Assert.assertTrue( new File( directory, "roboconf_toto/manifests" ).mkdirs()); File targetFile = new File( directory, "roboconf_toto/manifests/start.pp" ); File inputFile = TestUtils.findTestFile( "/recipes/update.pp" ); Utils.copyStream( inputFile, targetFile ); // We only parse what we know... List<ModelError> errors = RecipesValidator.validateComponentRecipes( appDir, comp ); Assert.assertEquals( 0, errors.size()); }
@Test public void testBuildTailoredImport() { String instancePath = "/whatever/this/is/a-test"; Component comp = new Component( "comp" ); comp.addImportedVariable( new ImportedVariable( "comp1.port", false, false )); comp.addImportedVariable( new ImportedVariable( "comp1.ip", false, false )); comp.addImportedVariable( new ImportedVariable( "comp2.option", true, false )); Instance inst = new Instance( "inst" ).component( comp ); // Null map Import imp = ImportHelpers.buildTailoredImport( inst, instancePath, "comp", null ); Assert.assertEquals( instancePath, imp.getInstancePath()); Assert.assertEquals( 0, imp.getExportedVars().size()); // Empty map imp = ImportHelpers.buildTailoredImport( inst, instancePath, "comp", new HashMap<String,String> ()); Assert.assertEquals( 0, imp.getExportedVars().size()); // Map with various variable Map<String,String> map = new HashMap<String,String> (); map.put( "comp1.ip", "127.0.0.1" ); map.put( "comp2.option", "ciao!" ); map.put( "not.a.valid.variable", "yeah" ); map.put( null, "null" ); map.put( "", "hop" ); imp = ImportHelpers.buildTailoredImport( inst, instancePath, "comp", map ); Assert.assertEquals( instancePath, imp.getInstancePath()); Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "comp", imp.getComponentName()); Assert.assertEquals( "127.0.0.1", imp.getExportedVars().get( "comp1.ip" )); Assert.assertEquals( "ciao!", imp.getExportedVars().get( "comp2.option" )); }
@Test public void testBuildTailoredImport_withWildcard() { String instancePath = "/whatever/this/is/a-test"; Component comp = new Component( "comp" ); comp.addImportedVariable( new ImportedVariable( "comp1.*", false, false )); comp.addImportedVariable( new ImportedVariable( "comp2.option", true, false )); Instance inst = new Instance( "inst" ).component( comp ); // Null map Import imp = ImportHelpers.buildTailoredImport( inst, instancePath, "comp", null ); Assert.assertEquals( instancePath, imp.getInstancePath()); Assert.assertEquals( 0, imp.getExportedVars().size()); // Empty map imp = ImportHelpers.buildTailoredImport( inst, instancePath, "comp", new HashMap<String,String> ()); Assert.assertEquals( 0, imp.getExportedVars().size()); // Map with various variable Map<String,String> map = new HashMap<String,String> (); map.put( "comp1.ip", "127.0.0.1" ); map.put( "comp2.option", "ciao!" ); map.put( "not.a.valid.variable", "yeah" ); map.put( null, "null" ); map.put( "", "hop" ); imp = ImportHelpers.buildTailoredImport( inst, instancePath, "comp", map ); Assert.assertEquals( instancePath, imp.getInstancePath()); Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "comp", imp.getComponentName()); Assert.assertEquals( "127.0.0.1", imp.getExportedVars().get( "comp1.ip" )); Assert.assertEquals( "ciao!", imp.getExportedVars().get( "comp2.option" )); }
root.addChild( serverWithApp ); serverWithApp.addImportedVariable( new ImportedVariable( "database.ip", false, false )); serverWithApp.addImportedVariable( new ImportedVariable( "database.port", true, false )); serverWithApp.addExportedVariable( new ExportedVariable( "url", "something" )); serverWithAnotherApp.addImportedVariable( new ImportedVariable( "database.port", false, false )); serverWithAnotherApp.addImportedVariable( new ImportedVariable( "whatever", false, false ));
comp1.addImportedVariable( new ImportedVariable( "tomcat.port", false, false )); iterator = RuntimeModelValidator.validate( graphs ).iterator(); Assert.assertEquals( ErrorCode.RM_UNRESOLVABLE_VARIABLE, iterator.next().getErrorCode()); Assert.assertFalse( iterator.hasNext()); comp1.addImportedVariable( new ImportedVariable( "tomcat.port", true, false )); iterator = RuntimeModelValidator.validate( graphs ).iterator(); Assert.assertEquals( ErrorCode.RM_UNRESOLVABLE_VARIABLE, iterator.next().getErrorCode());
@Test public void testPuppetValidation_missingParameterFromImports() throws Exception { File appDir = this.folder.newFolder(); Component comp = new Component( "toto" ).installerName( "puppet" ); comp.addImportedVariable( new ImportedVariable( "Test.ip", true, false )); comp.addImportedVariable( new ImportedVariable( "Test.port", true, false )); comp.addImportedVariable( new ImportedVariable( "Oops.ip", true, false )); File directory = ResourceUtils.findInstanceResourcesDirectory( appDir, comp ); Assert.assertTrue( new File( directory, "roboconf_toto/manifests" ).mkdirs()); File targetFile = new File( directory, "roboconf_toto/manifests/start.pp" ); File inputFile = TestUtils.findTestFile( "/recipes/update.pp" ); Utils.copyStream( inputFile, targetFile ); List<ModelError> errors = RecipesValidator.validateComponentRecipes( appDir, comp ); Assert.assertEquals( 2, errors.size()); Assert.assertEquals( ErrorCode.REC_PUPPET_MISSING_PARAM_FROM_IMPORT, errors.get( 0 ).getErrorCode()); Assert.assertEquals( 3, errors.get( 0 ).getDetails().length ); Assert.assertEquals( ErrorDetailsKind.NAME, errors.get( 0 ).getDetails()[ 0 ].getErrorDetailsKind()); Assert.assertEquals( "toto", errors.get( 0 ).getDetails()[ 0 ].getElementName()); Assert.assertEquals( ErrorDetailsKind.FILE, errors.get( 0 ).getDetails()[ 1 ].getErrorDetailsKind()); Assert.assertEquals( ErrorDetailsKind.EXPECTED, errors.get( 0 ).getDetails()[ 2 ].getErrorDetailsKind()); Assert.assertEquals( "test", errors.get( 0 ).getDetails()[ 2 ].getElementName()); Assert.assertEquals( ErrorCode.REC_PUPPET_MISSING_PARAM_FROM_IMPORT, errors.get( 1 ).getErrorCode()); Assert.assertEquals( 3, errors.get( 1 ).getDetails().length ); Assert.assertEquals( ErrorDetailsKind.NAME, errors.get( 1 ).getDetails()[ 0 ].getErrorDetailsKind()); Assert.assertEquals( "toto", errors.get( 1 ).getDetails()[ 0 ].getElementName()); Assert.assertEquals( ErrorDetailsKind.FILE, errors.get( 1 ).getDetails()[ 1 ].getErrorDetailsKind()); Assert.assertEquals( ErrorDetailsKind.EXPECTED, errors.get( 1 ).getDetails()[ 2 ].getErrorDetailsKind()); Assert.assertEquals( "oops", errors.get( 1 ).getDetails()[ 2 ].getElementName()); }
@Test public void testFromGraphs_noFacet() throws Exception { // Build a model Graphs graphs = new Graphs(); Component cA = new Component( "A" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cA ); cA.addExportedVariable( new ExportedVariable( "A.port", "9000" )); cA.addExportedVariable( new ExportedVariable( "A.ip", null )); cA.addImportedVariable( new ImportedVariable( "B.port", false, false )); cA.addImportedVariable( new ImportedVariable( "B.ip", true, false )); Component cB = new Component( "B" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cB ); cB.addExportedVariable( new ExportedVariable( "port", "9000" )); cB.addExportedVariable( new ExportedVariable( "ip", null )); // Write it into a file, load a new graph from this file and compare it with the current one compareGraphs( graphs, false ); // Verify exported variables are written correctly FileDefinition defToWrite = new FromGraphs().buildFileDefinition( graphs, null, false ); String s = ParsingModelIo.writeConfigurationFile( defToWrite, false, System.getProperty( "line.separator" )); Assert.assertTrue( s.contains( "port=\"9000\"" )); Assert.assertTrue( s.contains( "exports: ip, port=\"9000\";" )); }
@Test public void testFromGraphs_withExternal() throws Exception { Graphs graphs = new Graphs(); Component cA = new Component( "A" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cA ); cA.addExportedVariable( new ExportedVariable( "A.port", "9000" )); cA.addExportedVariable( new ExportedVariable( "A.ip", null )); cA.addImportedVariable( new ImportedVariable( "B.port", false, true )); cA.addImportedVariable( new ImportedVariable( "B.ip", true, false )); Component cB = new Component( "B" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cB ); cB.addExportedVariable( new ExportedVariable( "B.port", "9000" )); cB.addExportedVariable( new ExportedVariable( "B.ip", null )); compareGraphs( graphs, false ); }
@Test public void testFromGraphs_oneFacet() throws Exception { Graphs graphs = new Graphs(); Component cA = new Component( "A" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cA ); cA.addImportedVariable( new ImportedVariable( "facetF.props", false, false )); cA.addExportedVariable( new ExportedVariable( "A.port", "9000" )); cA.addExportedVariable( new ExportedVariable( "A.ip", null )); cA.addImportedVariable( new ImportedVariable( "B.port", true, false )); cA.addImportedVariable( new ImportedVariable( "B.ip", true, false )); Component cB = new Component( "B" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cB ); Facet facetF = new Facet( "facetF" ); facetF.addExportedVariable( new ExportedVariable( "facetF.props", "something" )); cB.associateFacet( facetF ); cB.addExportedVariable( new ExportedVariable( "B.port", "9000" )); cB.addExportedVariable( new ExportedVariable( "B.ip", null )); compareGraphs( graphs, false ); }
@Test public void testHasAllRequiredImports_required() throws Exception { Component dbComponent = new Component( "database" ).installerName( "whatever" ); dbComponent.addExportedVariable( new ExportedVariable( "database.ip", null )); dbComponent.addExportedVariable( new ExportedVariable( "database.port", "3009" )); dbComponent.addExportedVariable( new ExportedVariable( "database.collection", "whatever" )); Component appServerComponent = new Component( "app-server" ).installerName( "whatever" ); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.ip", null )); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.port", "8009" )); appServerComponent.addImportedVariable( new ImportedVariable( "database.ip", false, false )); appServerComponent.addImportedVariable( new ImportedVariable( "database.port", false, false )); appServerComponent.addImportedVariable( new ImportedVariable( "database.collection", true, false )); Instance appServer = new Instance( "app server" ).component( appServerComponent ); appServer.overriddenExports.put( "app-server.ip", "192.168.1.15" ); appServer.setStatus( InstanceStatus.STARTING ); Instance database = new Instance( "database" ).component( dbComponent ); database.overriddenExports.put( "database.ip", "192.168.1.28" ); // The application server does not know about the database Assert.assertFalse( ImportHelpers.hasAllRequiredImports( appServer, Logger.getAnonymousLogger())); // The application server is now aware of the database ImportHelpers.addImport( appServer, "database", new Import( database )); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( appServer, null )); appServer.getImports().clear(); Assert.assertFalse( ImportHelpers.hasAllRequiredImports( appServer, null )); }
@Test public void testFromGraphs_threeFacets() throws Exception { Graphs graphs = new Graphs(); Component cA = new Component( "A" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cA ); Facet facet = new Facet( "my-facet-1" ); facet.addExportedVariable( new ExportedVariable( "data", "coucou" )); cA.associateFacet( facet ); cA.addExportedVariable( new ExportedVariable( "A.port", "9000" )); cA.addExportedVariable( new ExportedVariable( "A.ip", null )); cA.addImportedVariable( new ImportedVariable( "B.port", true, false )); cA.addImportedVariable( new ImportedVariable( "B.ip", true, false )); cA.addImportedVariable( new ImportedVariable( "facetF.props", false, false )); Component cB = new Component( "B" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( cB ); facet = new Facet( "facetF" ); facet.addExportedVariable( new ExportedVariable( "facetF.props", "some value" )); cB.associateFacet( facet ); facet = new Facet( "my-facet-2" ); facet.addExportedVariable( new ExportedVariable( "my-facet-2.woo", "woo" )); cB.associateFacet( facet ); cB.addExportedVariable( new ExportedVariable( "B.port", "9000" )); cB.addExportedVariable( new ExportedVariable( "B.ip", null )); compareGraphs( graphs, false ); }
@Test public void testHasAllRequiredImports_optional() throws Exception { Component clusterNodeComponent = new Component( "cluster" ).installerName( "whatever" ); clusterNodeComponent.addImportedVariable( new ImportedVariable( "cluster.ip", true, false )); clusterNodeComponent.addImportedVariable( new ImportedVariable( "cluster.port", true, false )); clusterNodeComponent.addExportedVariable( new ExportedVariable( "cluster.ip", null )); clusterNodeComponent.addExportedVariable( new ExportedVariable( "cluster.port", "9007" )); Instance i1 = new Instance( "inst 1" ).component( clusterNodeComponent ); i1.overriddenExports.put( "cluster.ip", "192.168.1.15" ); i1.setStatus( InstanceStatus.STARTING ); Instance i2 = new Instance( "inst 2" ).component( clusterNodeComponent ); i2.overriddenExports.put( "cluster.ip", "192.168.1.28" ); // The cluster node does not know about the other node Assert.assertTrue( ImportHelpers.hasAllRequiredImports( i1, null )); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( i2, null )); // The node is now aware of another node ImportHelpers.addImport( i1, "cluster", new Import( i2 )); i1.setStatus( InstanceStatus.STARTING ); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( i1, null )); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( i2, null )); i1.getImports().clear(); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( i1, null )); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( i2, null )); }
@Test public void testHasAllRequiredImports_withWildcard() throws Exception { // Same test than "testHasAllRequiredImports_required" // but here, variable imports use a wild card. Component dbComponent = new Component( "database" ).installerName( "whatever" ); dbComponent.addExportedVariable( new ExportedVariable( "database.ip", null )); dbComponent.addExportedVariable( new ExportedVariable( "database.port", "3009" )); dbComponent.addExportedVariable( new ExportedVariable( "database.collection", "whatever" )); Component appServerComponent = new Component( "app-server" ).installerName( "whatever" ); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.ip", null )); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.port", "8009" )); appServerComponent.addImportedVariable( new ImportedVariable( "database.*", false, false )); Instance appServer = new Instance( "app server" ).component( appServerComponent ); appServer.overriddenExports.put( "app-server.ip", "192.168.1.15" ); appServer.setStatus( InstanceStatus.STARTING ); Instance database = new Instance( "database" ).component( dbComponent ); database.overriddenExports.put( "database.ip", "192.168.1.28" ); // The application server does not know about the database Assert.assertFalse( ImportHelpers.hasAllRequiredImports( appServer, Logger.getAnonymousLogger())); // The application server is now aware of the database ImportHelpers.addImport( appServer, "database", new Import( database )); Assert.assertTrue( ImportHelpers.hasAllRequiredImports( appServer, null )); appServer.getImports().clear(); Assert.assertFalse( ImportHelpers.hasAllRequiredImports( appServer, null )); }
warComponent.addExportedVariable( new ExportedVariable( "port", "8080" )); warComponent.addExportedVariable( new ExportedVariable( "ip", null )); warComponent.addImportedVariable( new ImportedVariable( "mysql.port", false, false )); warComponent.addImportedVariable( new ImportedVariable( "mysql.ip", false, false )); this.war = new Instance( "hello-world" ).component( warComponent );
cA.addExportedVariable( new ExportedVariable( "A.ip", null )); cA.addImportedVariable( new ImportedVariable( "B.ip", true, false )); cA.addImportedVariable( new ImportedVariable( "facetF.props", false, false ));