class AmbariContext {

  public void createAmbariResources(ClusterTopology topology, String clusterName, SecurityType securityType,
                                    String repoVersionString, Long repoVersionId) {
    Stack stack = topology.getBlueprint().getStack();
    StackId stackId = new StackId(stack.getName(), stack.getVersion());

    RepositoryVersionEntity repoVersion = null;
    if (StringUtils.isEmpty(repoVersionString) && null == repoVersionId) {
      List<RepositoryVersionEntity> stackRepoVersions = repositoryVersionDAO.findByStack(stackId);

      if (stackRepoVersions.isEmpty()) {
        // !!! no repos, try to get the version for the stack
        VersionDefinitionResourceProvider vdfProvider = getVersionDefinitionResourceProvider();

        Map<String, Object> properties = new HashMap<>();
        properties.put(VersionDefinitionResourceProvider.VERSION_DEF_AVAILABLE_DEFINITION, stackId.toString());

        Request request = new RequestImpl(Collections.<String>emptySet(),
            Collections.singleton(properties), Collections.<String, String>emptyMap(), null);

        Long defaultRepoVersionId = null;

        try {
          RequestStatus requestStatus = vdfProvider.createResources(request);
          if (!requestStatus.getAssociatedResources().isEmpty()) {
            Resource resource = requestStatus.getAssociatedResources().iterator().next();
            defaultRepoVersionId = (Long) resource.getPropertyValue(VersionDefinitionResourceProvider.VERSION_DEF_ID);
          }
        } catch (Exception e) {
          throw new IllegalArgumentException(String.format(
              "Failed to create a default repository version definition for stack %s. "
              + "This typically is a result of not loading the stack correctly or being able "
              + "to load information about released versions.  Create a repository version "
              + " and try again.", stackId), e);
        }

        repoVersion = repositoryVersionDAO.findByPK(defaultRepoVersionId);
        // !!! better not!
        if (null == repoVersion) {
          throw new IllegalArgumentException(String.format(
              "Failed to load the default repository version definition for stack %s. "
              + "Check for a valid repository version and try again.", stackId));
        }

      } else if (stackRepoVersions.size() > 1) {

        Function<RepositoryVersionEntity, String> function = new Function<RepositoryVersionEntity, String>() {
          @Override
          public String apply(RepositoryVersionEntity input) {
            return input.getVersion();
          }
        };

        Collection<String> versions = Collections2.transform(stackRepoVersions, function);

        throw new IllegalArgumentException(String.format("Several repositories were found for %s:  %s.  Specify the version"
            + " with '%s'", stackId, StringUtils.join(versions, ", "), ProvisionClusterRequest.REPO_VERSION_PROPERTY));
      } else {
        repoVersion = stackRepoVersions.get(0);
        LOG.warn("Cluster is being provisioned using the single matching repository version {}", repoVersion.getVersion());
      }
    } else if (null != repoVersionId){
      repoVersion = repositoryVersionDAO.findByPK(repoVersionId);

      if (null == repoVersion) {
        throw new IllegalArgumentException(String.format(
          "Could not identify repository version with repository version id %s for installing services. "
            + "Specify a valid repository version id with '%s'",
          repoVersionId, ProvisionClusterRequest.REPO_VERSION_ID_PROPERTY));
      }
    } else {
      repoVersion = repositoryVersionDAO.findByStackAndVersion(stackId, repoVersionString);

      if (null == repoVersion) {
        throw new IllegalArgumentException(String.format(
          "Could not identify repository version with stack %s and version %s for installing services. "
            + "Specify a valid version with '%s'",
          stackId, repoVersionString, ProvisionClusterRequest.REPO_VERSION_PROPERTY));
      }
    }

    // only use a STANDARD repo when creating a new cluster
    if (repoVersion.getType() != RepositoryType.STANDARD) {
      throw new IllegalArgumentException(String.format(
          "Unable to create a cluster using the following repository since it is not a STANDARD type: %s",
          repoVersion));
    }

    createAmbariClusterResource(clusterName, stack.getName(), stack.getVersion(), securityType);
    createAmbariServiceAndComponentResources(topology, clusterName, stackId, repoVersion.getId());
  }

}