
org.usergrid.tools.DupOrgRepair Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of usergrid-tools Show documentation
Show all versions of usergrid-tools Show documentation
Command line tools for Usergrid system.
The newest version!
/*******************************************************************************
* Copyright 2012 Apigee Corporation
*
* 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.
******************************************************************************/
package org.usergrid.tools;
import java.io.FileWriter;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usergrid.management.OrganizationInfo;
import org.usergrid.management.UserInfo;
import org.usergrid.persistence.Entity;
import org.usergrid.persistence.EntityManager;
import org.usergrid.persistence.Query;
import org.usergrid.persistence.Results;
import org.usergrid.persistence.SimpleEntityRef;
import org.usergrid.persistence.cassandra.CassandraService;
import org.usergrid.persistence.entities.Application;
import org.usergrid.utils.JsonUtils;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* This is a utility to load all entities in an application and re-save them,
* this forces the secondary indexing to be updated.
*
* @author tnine
*
*/
public class DupOrgRepair extends ExportingToolBase {
/**
*
*/
private static final int PAGE_SIZE = 100;
private static final Logger logger = LoggerFactory.getLogger(DupOrgRepair.class);
@Override
@SuppressWarnings("static-access")
public Options createOptions() {
Option hostOption = OptionBuilder.withArgName("host").hasArg().isRequired(true).withDescription("Cassandra host")
.create("host");
Option outputOption = OptionBuilder.withArgName("output").hasArg().isRequired(true)
.withDescription("Cassandra host").create("output");
Options options = new Options();
options.addOption(hostOption);
options.addOption(outputOption);
return options;
}
/*
* (non-Javadoc)
*
* @see
* org.usergrid.tools.ToolBase#runTool(org.apache.commons.cli.CommandLine)
*/
@Override
public void runTool(CommandLine line) throws Exception {
String outputDir = line.getOptionValue("output");
createDir(outputDir);
startSpring();
logger.info("Starting crawl of all admins");
EntityManager em = emf.getEntityManager(CassandraService.MANAGEMENT_APPLICATION_ID);
Application app = em.getApplication();
// search for all orgs
Query query = new Query();
query.setLimit(PAGE_SIZE);
Results r = null;
Multimap orgs = HashMultimap.create();
do {
r = em.searchCollection(app, "groups", query);
for (Entity entity : r.getEntities()) {
String name = entity.getProperty("path").toString().toLowerCase();
orgs.put(name, entity.getUuid());
}
query.setCursor(r.getCursor());
logger.info("Searching next page");
} while (r != null && r.size() == PAGE_SIZE);
// now go through and print out duplicate emails
for (String name : orgs.keySet()) {
Collection ids = orgs.get(name);
if (ids.size() > 1) {
logger.warn("Found multiple orgs with the name {}", name);
// look this up the same way the REST tier does. This way we will always
// map the same way and the user will not notice a background merge
OrganizationInfo orgInfo = managementService.getOrganizationByName(name);
UUID targetOrgId = orgInfo.getUuid();
ids.remove(targetOrgId);
for (UUID sourceId : ids) {
mergeOrganizations(outputDir, sourceId, targetOrgId);
}
}
}
logger.info("Merge complete");
}
/**
* Merge the source orgId into the targetId in the following way.
*
* 1) link all admins from the source org to the target org 2) link all apps
* from the source org to the target or 3) delete the target org
*
* @param sourceOrgId
* @param targetOrgId
* @throws Exception
*/
@SuppressWarnings("unchecked")
private void mergeOrganizations(String outputDir, UUID sourceOrgId, UUID targetOrgId) throws Exception {
OrganizationInfo sourceOrgInfo = managementService.getOrganizationByUuid(sourceOrgId);
Map sourceOrg = managementService.getOrganizationData(sourceOrgInfo);
OrganizationInfo targetOrgInfo = managementService.getOrganizationByUuid(targetOrgId);
Map targetOrg = managementService.getOrganizationData(targetOrgInfo);
// Dump the output on these two orgs
FileWriter file = new FileWriter(String.format("%s/%s.%s.orig", outputDir, sourceOrgInfo.getName(), sourceOrgId));
file.write(JsonUtils.mapToFormattedJsonString(sourceOrg));
file.write("\n\n");
file.write(JsonUtils.mapToFormattedJsonString(targetOrg));
file.flush();
file.close();
// BiMap targetApps =
// managementService.getApplicationsForOrganization(targetOrgId);
// now perform the merge
// add all the admins
Map admins = (Map) sourceOrg.get("users");
for (Entry adminEntry : admins.entrySet()) {
UserInfo admin = adminEntry.getValue();
logger.info("adding admin with uuid {} and email {} to org with name {} and uuid {}",
new Object[] { admin.getUuid(), admin.getEmail(), targetOrgInfo.getName(), targetOrgInfo.getUuid() });
// copy the admins over
managementService.addAdminUserToOrganization(admin, targetOrgInfo, false);
}
// get the root entity manager
EntityManager em = emf.getEntityManager(CassandraService.MANAGEMENT_APPLICATION_ID);
// Add the apps to the org
Map sourceApps = (Map) sourceOrg.get("applications");
Map targetApps = (Map) targetOrg.get("applications");
for (Entry app : sourceApps.entrySet()) {
// we have colliding app names
if (targetApps.get(app.getKey()) != null) {
// already added, skip it
if (app.getValue().equals(targetApps.get(app.getKey()))) {
continue;
}
// check to see if this orgname/appname lookup returns the app we're
// about to re-assign. If it does NOT, then we need to rename this app
// before performing the link.
UUID appIdToKeep = emf.lookupApplication(app.getKey());
UUID appIdToChange = appIdToKeep.equals(app.getValue()) ? targetApps.get(app.getKey()) : app.getValue();
// get the existing target entity
Entity appEntity = em.get(appIdToChange);
if (appEntity != null) {
String oldName = appEntity.getProperty("name").toString();
String newName = oldName + appEntity.getUuid();
//force the property to be updated
em.setProperty(appEntity, "name", newName, true);
logger.info("Renamed app from {} to {}", oldName, newName);
}
}
logger.info("Adding application with name {} and id {} to organization with uuid {}", new Object[] {
app.getKey(), app.getValue(), targetOrgId });
managementService.addApplicationToOrganization(targetOrgId, app.getValue());
}
// now delete the original org
logger.info("Deleting org with the name {} and uuid {}", sourceOrgInfo.getName(), sourceOrgInfo.getUuid());
// delete the source org
em.delete(new SimpleEntityRef("group", sourceOrgId));
// re-dump the target from the cassandra stat
targetOrgInfo = managementService.getOrganizationByUuid(targetOrgId);
targetOrg = managementService.getOrganizationData(targetOrgInfo);
file = new FileWriter(String.format("%s/%s.%s.new", outputDir, targetOrgInfo.getName(), targetOrgId));
file.write(JsonUtils.mapToFormattedJsonString(targetOrg));
file.flush();
file.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy