Ver código fonte

AMBARI-8314. Repository Version Management - Add validation for created repo versions (Yurii Shylov via ncole)

Nate Cole 10 anos atrás
pai
commit
e35126fedf

+ 11 - 0
LICENSE.txt

@@ -279,6 +279,17 @@ A "contributor" is any person that distributes its contribution under this licen
 (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
 (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
 
+For fge/json-schema, used to validate json structures:
+http://github.com/fge/json-schema-validator/blob/master/LICENSE
+
+This software is dual-licensed under:
+the Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
+the Apache Software License (ASL) version 2.0.
+
+LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
+ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
+Apache Software License version 2.0 selected.
+
 For Kokki, resource management library derived from:
 
 Copyright (c) 2009 Samuel Stauffer <samuel@descolada.com>

+ 5 - 0
ambari-server/pom.xml

@@ -1674,6 +1674,11 @@
       <artifactId>smtp</artifactId>
       <version>1.5.2</version>
     </dependency>
+    <dependency>
+      <groupId>com.github.fge</groupId>
+      <artifactId>json-schema-validator</artifactId>
+      <version>2.2.6</version>
+    </dependency>
   </dependencies>
 
   <pluginRepositories>

+ 2 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java

@@ -498,7 +498,7 @@ public class AmbariMetaInfo {
     }
     return needRestartServices;
   }
-  
+
   public Collection<StackInfo> getStacks() {
     return stackManager.getStacks();
   }
@@ -517,8 +517,7 @@ public class AmbariMetaInfo {
     StackInfo stackInfoResult = stackManager.getStack(stackName, version);
 
     if (stackInfoResult == null) {
-      throw new StackAccessException("stackName=" + stackName
-          + ", stackVersion=" + version);
+      throw new StackAccessException("Stack " + stackName + " " + version + " is not found in Ambari metainfo");
     }
 
     return stackInfoResult;

+ 119 - 51
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProvider.java

@@ -20,13 +20,14 @@ package org.apache.ambari.server.controller.internal;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
@@ -44,9 +45,17 @@ import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.state.OperatingSystemInfo;
+import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.StackInfo;
 import org.apache.ambari.server.state.stack.UpgradePack;
-
+import org.apache.commons.lang.StringUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.github.fge.jackson.JsonLoader;
+import com.github.fge.jsonschema.core.report.ProcessingMessage;
+import com.github.fge.jsonschema.core.report.ProcessingReport;
+import com.github.fge.jsonschema.main.JsonSchema;
+import com.github.fge.jsonschema.main.JsonSchemaFactory;
 import com.google.gson.Gson;
 import com.google.inject.Inject;
 
@@ -90,6 +99,22 @@ public class RepositoryVersionResourceProvider extends AbstractResourceProvider
     }
   };
 
+  /**
+   * Json schema used for repositories validation.
+   */
+  private static JsonSchema repositoriesJsonSchema;
+  static {
+    final String schema = "{\"type\":\"array\",\"$schema\":\"http://json-schema.org/draft-04/schema#\","
+        + "\"items\":{\"type\":\"object\",\"required\":[\"baseurls\",\"os\"],\"properties\":{\"baseurls\":{\"type\":\"array\",\"items\":"
+        + "{\"type\":\"object\",\"required\":[\"type\",\"baseurl\",\"id\"],\"properties\":{\"type\":{\"type\":\"string\"},\"baseurl\":"
+        + "{\"type\":\"string\"},\"id\":{\"type\":\"string\"}}},\"minItems\":1},\"os\":{\"type\":\"string\"}}}\r\n,\"minItems\":1}";
+    try {
+      repositoriesJsonSchema = JsonSchemaFactory.byDefault().getJsonSchema(JsonLoader.fromString(schema));
+    } catch (Exception e) {
+      LOG.error("Could not create instance of json schema for validating repositories");
+    }
+  }
+
   @Inject
   private RepositoryVersionDAO repositoryVersionDAO;
 
@@ -205,46 +230,54 @@ public class RepositoryVersionResourceProvider extends AbstractResourceProvider
     throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
     final Set<Map<String, Object>> propertyMaps = request.getProperties();
 
-    for (Map<String, Object> propertyMap : propertyMaps) {
-      final Long id;
-      try {
-        id = Long.parseLong(propertyMap.get(REPOSITORY_VERSION_ID_PROPERTY_ID).toString());
-      } catch (Exception ex) {
-        throw new SystemException("Repository version should have numerical id");
-      }
+    modifyResources(new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        for (Map<String, Object> propertyMap : propertyMaps) {
+          final Long id;
+          try {
+            id = Long.parseLong(propertyMap.get(REPOSITORY_VERSION_ID_PROPERTY_ID).toString());
+          } catch (Exception ex) {
+            throw new AmbariException("Repository version should have numerical id");
+          }
 
-      final RepositoryVersionEntity entity = repositoryVersionDAO.findByPK(id);
-      if (entity == null) {
-        throw new NoSuchResourceException("There is no repository version with id " + id);
-      }
+          final RepositoryVersionEntity entity = repositoryVersionDAO.findByPK(id);
+          if (entity == null) {
+            throw new ObjectNotFoundException("There is no repository version with id " + id);
+          }
 
-      if (propertyMap.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID) != null
-          || propertyMap.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID) != null) {
+          if (propertyMap.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID) != null
+              || propertyMap.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID) != null) {
 
-        final List<ClusterVersionEntity> clusterVersionEntities =
-            clusterVersionDAO.findByStackAndVersion(entity.getStack(), entity.getVersion());
+            final List<ClusterVersionEntity> clusterVersionEntities =
+                clusterVersionDAO.findByStackAndVersion(entity.getStack(), entity.getVersion());
 
-        if (!clusterVersionEntities.isEmpty()) {
-          final ClusterVersionEntity firstClusterVersion = clusterVersionEntities.get(0);
-          throw new SystemException("Repository version can't be updated as it is " +
-            firstClusterVersion.getState().name() + " on cluster " + firstClusterVersion.getClusterEntity().getClusterName());
-        }
+            if (!clusterVersionEntities.isEmpty()) {
+              final ClusterVersionEntity firstClusterVersion = clusterVersionEntities.get(0);
+              throw new AmbariException("Repository version can't be updated as it is " +
+                firstClusterVersion.getState().name() + " on cluster " + firstClusterVersion.getClusterEntity().getClusterName());
+            }
 
-        if (propertyMap.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID) != null) {
-          entity.setRepositories(propertyMap.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID).toString());
-        }
+            if (propertyMap.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID) != null) {
+              final Object repositories = propertyMap.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID);
+              entity.setRepositories(new Gson().toJson(repositories));
+            }
 
-        if (propertyMap.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID) != null) {
-          entity.setUpgradePackage(propertyMap.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID).toString());
-        }
-      }
+            if (propertyMap.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID) != null) {
+              entity.setUpgradePackage(propertyMap.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID).toString());
+            }
+          }
 
-      if (propertyMap.get(REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID) != null) {
-        entity.setDisplayName(propertyMap.get(REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID).toString());
-      }
+          if (propertyMap.get(REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID) != null) {
+            entity.setDisplayName(propertyMap.get(REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID).toString());
+          }
 
-      repositoryVersionDAO.merge(entity);
-    }
+          validateRepositoryVersion(entity);
+          repositoryVersionDAO.merge(entity);
+        }
+        return null;
+      }
+    });
 
     return getRequestStatus(null);
   }
@@ -299,41 +332,76 @@ public class RepositoryVersionResourceProvider extends AbstractResourceProvider
    * @throws AmbariException exception with error message
    */
   protected void validateRepositoryVersion(RepositoryVersionEntity repositoryVersion) throws AmbariException {
-    final StackInfo stackInfo = ambariMetaInfo.getStack(repositoryVersion.getStack(), repositoryVersion.getVersion());
-    if (stackInfo == null) {
-      throw new AmbariException("Stack " + repositoryVersion.getStack() + " " + repositoryVersion.getVersion() + " is not found");
+    final StackId requiredStack = new StackId(repositoryVersion.getStack());
+    final String stackName = requiredStack.getStackName();
+    final String stackMajorVersion = requiredStack.getStackVersion();
+    final String stackFullName = requiredStack.getStackId();
+
+    // check that stack exists
+    final StackInfo stackInfo = ambariMetaInfo.getStack(stackName, stackMajorVersion);
+    if (stackInfo.getUpgradePacks() == null) {
+      throw new AmbariException("Stack " + stackFullName + " doesn't have upgrade packages");
     }
-    final UpgradePack upgradePack = stackInfo.getUpgradePacks().get(repositoryVersion.getUpgradePackage());
-    if (upgradePack == null) {
-      throw new AmbariException("Upgrade pack " + repositoryVersion.getUpgradePackage()
-          + " is not available for stack " + repositoryVersion.getStack() + " " + repositoryVersion.getVersion());
+
+    // check that given repositories node is a valid json
+    ProcessingReport jsonValidationReport;
+    JsonNode repositoriesJson;
+    try {
+      repositoriesJson = JsonLoader.fromString(repositoryVersion.getRepositories());
+      jsonValidationReport = repositoriesJsonSchema.validate(repositoriesJson);
+    } catch (Exception ex) {
+      throw new AmbariException("Could not process repositories json");
     }
+    if (!jsonValidationReport.isSuccess()) {
+      final StringBuilder errors = new StringBuilder();
+      final Iterator<ProcessingMessage> iterator = jsonValidationReport.iterator();
+      while (iterator.hasNext()) {
+        errors.append(iterator.next().toString());
+      }
+      throw new AmbariException("Failed to validate repositories json: " + errors.toString());
+    }
+
+    // check that repositories contain only supported operating systems
     final Set<String> osSupported = new HashSet<String>();
-    for (OperatingSystemInfo osInfo: ambariMetaInfo.getOperatingSystems(repositoryVersion.getStack(), repositoryVersion.getVersion())) {
+    for (OperatingSystemInfo osInfo: ambariMetaInfo.getOperatingSystems(stackName, stackMajorVersion)) {
       osSupported.add(osInfo.getOsType());
     }
     final Set<String> osRepositoryVersion = new HashSet<String>();
-    final Matcher osMatcher = Pattern.compile("\"os\":\\s*\"(.+)\"").matcher(new Gson().fromJson(repositoryVersion.getRepositories(), Object.class).toString());
-    while (osMatcher.find()) {
-      osRepositoryVersion.add(osMatcher.group(1));
+    final Iterator<JsonNode> repositoriesIterator = repositoriesJson.elements();
+    while (repositoriesIterator.hasNext()) {
+      osRepositoryVersion.add(repositoriesIterator.next().get("os").asText());
     }
     if (osRepositoryVersion.isEmpty()) {
       throw new AmbariException("At least one set of repositories for OS should be provided");
     }
     for (String os: osRepositoryVersion) {
       if (!osSupported.contains(os)) {
-        throw new AmbariException("Operating system type " + os + " is not supported by stack "
-            + repositoryVersion.getStack() + " " + repositoryVersion.getVersion());
+        throw new AmbariException("Operating system type " + os + " is not supported by stack " + stackFullName);
       }
     }
-    // converting 2.2.*.* -> 2\.2\.\d+\.\d+(-\d+)?
+
+    // check that upgrade pack for the stack exists
+    final UpgradePack upgradePack = stackInfo.getUpgradePacks().get(repositoryVersion.getUpgradePackage());
+    if (upgradePack == null) {
+      throw new AmbariException("Upgrade pack " + repositoryVersion.getUpgradePackage()
+          + " is not available for stack " + stackFullName);
+    }
+
+    // check that upgrade pack has <target> node
+    if (StringUtils.isBlank(upgradePack.getTarget())) {
+      throw new AmbariException("Upgrade pack " + repositoryVersion.getUpgradePackage()
+          + " is corrupted, it should contain <target> node");
+    }
+
+    // check that upgrade pack can be applied to selected stack
+    // converting 2.2.*.* -> 2\.2(\.\d+)?(\.\d+)?(-\d+)?
     String regexPattern = upgradePack.getTarget();
-    regexPattern = regexPattern.replaceAll("\\.", "\\\\.");
-    regexPattern = regexPattern.replaceAll("\\*", "\\\\d+");
+    regexPattern = regexPattern.replaceAll("\\.", "\\\\."); // . -> \.
+    regexPattern = regexPattern.replaceAll("\\\\\\.\\*", "(\\\\\\.\\\\d+)?"); // \.* -> (\.\d+)?
     regexPattern = regexPattern.concat("(-\\d+)?");
     if (!Pattern.matches(regexPattern, repositoryVersion.getVersion())) {
       throw new AmbariException("Upgrade pack " + repositoryVersion.getUpgradePackage()
-          + " can't be applied to stack " + repositoryVersion.getStack() + " " + repositoryVersion.getVersion());
+          + " can't be applied to stack " + stackFullName);
     }
   }
 }

+ 30 - 15
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java

@@ -62,9 +62,12 @@ public class RepositoryVersionResourceProviderTest {
 
   private static Injector injector;
 
+  private static Object jsonStructureRedhat6 = new Gson().fromJson("[{\"os\":\"redhat6\",\"baseurls\":[{\"id\":\"HDP-2.2.0.1-885\",\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]", Object.class);
+  private static Object jsonStructureRedhat7 = new Gson().fromJson("[{\"os\":\"redhat7\",\"baseurls\":[{\"id\":\"HDP-2.2.0.1-885\",\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]", Object.class);
+
   @Before
   public void before() throws Exception {
-    final Set<String> validVersions = Sets.newHashSet("1.1.1.1", "1.1.343432.2", "1.1.343432.2-234234324");
+    final Set<String> validVersions = Sets.newHashSet("1.1", "1.1-17", "1.1.1.1", "1.1.343432.2", "1.1.343432.2-234234324");
     final AmbariMetaInfo ambariMetaInfo = Mockito.mock(AmbariMetaInfo.class);
     final AbstractModule injectorModule = new InMemoryDefaultTestModule() {
       protected void configure() {
@@ -138,8 +141,8 @@ public class RepositoryVersionResourceProviderTest {
     final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
     final Map<String, Object> properties = new LinkedHashMap<String, Object>();
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, "name");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, "[{\"os\":\"redhat6\"}]");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "HDP");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, jsonStructureRedhat6);
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "HDP-1.1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID, "pack1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_VERSION_PROPERTY_ID, "1.1.1.1");
     propertySet.add(properties);
@@ -159,8 +162,8 @@ public class RepositoryVersionResourceProviderTest {
     final RepositoryVersionDAO repositoryVersionDAO = injector.getInstance(RepositoryVersionDAO.class);
     final RepositoryVersionEntity entity = new RepositoryVersionEntity();
     entity.setDisplayName("name");
-    entity.setRepositories("[{\"os\":\"redhat6\"}]");
-    entity.setStack("HDP");
+    entity.setRepositories("[{\"os\":\"redhat6\",\"baseurls\":[{\"id\":\"HDP-2.2.0.1-885\",\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]");
+    entity.setStack("HDP-1.1");
     entity.setUpgradePackage("pack1");
     entity.setVersion("1.1.1.1");
 
@@ -179,20 +182,31 @@ public class RepositoryVersionResourceProviderTest {
 
     final RepositoryVersionEntity entity = new RepositoryVersionEntity();
     entity.setDisplayName("name");
-    entity.setStack("HDP");
+    entity.setStack("HDP-1.1");
     entity.setUpgradePackage("pack1");
-    entity.setVersion("1.1.1.1");
-    entity.setRepositories(new Gson().toJson("[{\"os\":\"redhat6\"}]"));
+    entity.setVersion("1.1");
+    entity.setRepositories("[{\"os\":\"redhat6\",\"baseurls\":[{\"id\":\"HDP-2.2.0.1-885\",\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]");
 
     // test valid usecases
     provider.validateRepositoryVersion(entity);
+    entity.setVersion("1.1-17");
+    provider.validateRepositoryVersion(entity);
+    entity.setVersion("1.1.1.1");
+    provider.validateRepositoryVersion(entity);
     entity.setVersion("1.1.343432.2");
     provider.validateRepositoryVersion(entity);
     entity.setVersion("1.1.343432.2-234234324");
     provider.validateRepositoryVersion(entity);
 
     // test invalid usecases
-    entity.setRepositories("[{\"os\":\"redhat8\"}]");
+    entity.setRepositories("[{\"os\":\"redhat8\",\"baseurls\":[{\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]");
+    try {
+      provider.validateRepositoryVersion(entity);
+      Assert.fail("Should throw exception");
+    } catch (Exception ex) {
+    }
+
+    entity.setRepositories("[{\"os\":\"redhat8\",\"baseurls\":[{\"id\":\"HDP-2.2.0.1-885\",\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]");
     try {
       provider.validateRepositoryVersion(entity);
       Assert.fail("Should throw exception");
@@ -228,8 +242,8 @@ public class RepositoryVersionResourceProviderTest {
     final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
     final Map<String, Object> properties = new LinkedHashMap<String, Object>();
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, "name");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, "[{\"os\":\"redhat6\"}]");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "HDP");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, jsonStructureRedhat6);
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "HDP-1.1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID, "pack1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_VERSION_PROPERTY_ID, "1.1.1.1");
     propertySet.add(properties);
@@ -255,8 +269,8 @@ public class RepositoryVersionResourceProviderTest {
     final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
     final Map<String, Object> properties = new LinkedHashMap<String, Object>();
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, "name");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, "[{\"os\":\"redhat6\"}]");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "HDP");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, jsonStructureRedhat6);
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "HDP-1.1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID, "pack1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_VERSION_PROPERTY_ID, "1.1.1.1");
     propertySet.add(properties);
@@ -275,13 +289,14 @@ public class RepositoryVersionResourceProviderTest {
 
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_ID_PROPERTY_ID, "1");
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, "name2");
-    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, "[{\"os\":\"redhat7\"}]");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, jsonStructureRedhat7);
     properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID, "pack2");
     final Request updateRequest = PropertyHelper.getUpdateRequest(properties, null);
     provider.updateResources(updateRequest, null);
 
     Assert.assertEquals("name2", provider.getResources(getRequest, null).iterator().next().getPropertyValue(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID));
-    Assert.assertEquals("[{\"os\":\"redhat7\"}]", new Gson().toJson(provider.getResources(getRequest, null).iterator().next().getPropertyValue(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID)));
+    Assert.assertEquals("[{\"os\":\"redhat7\",\"baseurls\":[{\"id\":\"HDP-2.2.0.1-885\",\"type\":\"HDP\",\"baseurl\":\"http://host1/hdp\"},{\"id\":\"HDP-UTILS-1.0.0.20\",\"type\":\"HDP-UTILS\",\"baseurl\":\"http://host1/hdp-utils\"}]}]",
+        new Gson().toJson(provider.getResources(getRequest, null).iterator().next().getPropertyValue(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID)));
     Assert.assertEquals("pack2", provider.getResources(getRequest, null).iterator().next().getPropertyValue(RepositoryVersionResourceProvider.REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID));
   }