From 0408b4b7f4f5cf549ccc0fc0f8029d12ef02dd22 Mon Sep 17 00:00:00 2001 From: Dave Johnson Date: Tue, 20 Jan 2015 11:58:31 -0500 Subject: [PATCH 1/3] Addition of deleteIndex() method, improvements to logging and minor formatting changes. --- .../persistence/index/EntityIndex.java | 2 + .../index/impl/EsEntityIndexBatchImpl.java | 14 +-- .../index/impl/EsEntityIndexImpl.java | 115 ++++++++---------- .../persistence/index/impl/EsIndexCache.java | 12 +- 4 files changed, 62 insertions(+), 81 deletions(-) diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java index eb9f61e440..e221f0e858 100644 --- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java +++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/EntityIndex.java @@ -100,6 +100,8 @@ public interface EntityIndex { * Check health of this specific index. */ public Health getIndexHealth(); + + public void deleteIndex(); } diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java index c9a4769b3c..20669b3b94 100644 --- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java +++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java @@ -123,16 +123,10 @@ public EntityIndexBatch index( final IndexScope indexScope, final Entity entity final String entityType = entity.getId().getType(); if ( log.isDebugEnabled() ) { - log.debug( "Indexing entity {}:{} in scope\n app {}\n " - + "owner {}\n name {}\n type {} \n scope type {}", new Object[] { - entity.getId().getType(), - entity.getId().getUuid(), - applicationScope.getApplication(), - indexScope.getOwner(), - indexScope.getName(), - entityType, - context - } ); + log.debug( "Indexing entity {}:{}\n alias: {}\n" + + " app: {}\n scope owner: {}\n scope name: {}\n context: {}", + entity.getId().getType(), entity.getId().getUuid(), alias.getWriteAlias(), + applicationScope.getApplication(), indexScope.getOwner(), indexScope.getName(), context ); } ValidationUtils.verifyEntityWrite( entity ); diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java index b743d83868..9e9cebf6a0 100644 --- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java +++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java @@ -21,29 +21,13 @@ import com.google.common.collect.ImmutableMap; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.usergrid.persistence.core.scope.ApplicationScope; import org.apache.usergrid.persistence.core.util.Health; import org.apache.usergrid.persistence.core.util.ValidationUtils; -import org.apache.usergrid.persistence.index.AliasedEntityIndex; -import org.apache.usergrid.persistence.index.AliasedEntityIndex.AliasType; -import org.apache.usergrid.persistence.index.EntityIndexBatch; -import org.apache.usergrid.persistence.index.IndexFig; -import org.apache.usergrid.persistence.index.IndexIdentifier; -import org.apache.usergrid.persistence.index.IndexScope; -import org.apache.usergrid.persistence.index.SearchTypes; +import org.apache.usergrid.persistence.index.*; import org.apache.usergrid.persistence.index.exceptions.IndexException; -import static org.apache.usergrid.persistence.index.impl.IndexingUtils.BOOLEAN_PREFIX; -import static org.apache.usergrid.persistence.index.impl.IndexingUtils.ENTITYID_ID_FIELDNAME; -import static org.apache.usergrid.persistence.index.impl.IndexingUtils.ENTITY_VERSION_FIELDNAME; -import static org.apache.usergrid.persistence.index.impl.IndexingUtils.NUMBER_PREFIX; -import static org.apache.usergrid.persistence.index.impl.IndexingUtils.SPLITTER; -import static org.apache.usergrid.persistence.index.impl.IndexingUtils.STRING_PREFIX; import org.apache.usergrid.persistence.index.query.CandidateResult; import org.apache.usergrid.persistence.index.query.CandidateResults; import org.apache.usergrid.persistence.index.query.Query; @@ -68,13 +52,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.index.query.FilterBuilder; -import org.elasticsearch.index.query.FilterBuilders; -import org.elasticsearch.index.query.FilteredQueryBuilder; -import org.elasticsearch.index.query.MatchAllQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.index.query.TermQueryBuilder; +import org.elasticsearch.index.query.*; import org.elasticsearch.indices.IndexAlreadyExistsException; import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.search.SearchHit; @@ -87,6 +65,14 @@ import rx.Observable; import rx.functions.Func1; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.usergrid.persistence.index.impl.IndexingUtils.*; + /** * Implements index using ElasticSearch Java API. @@ -197,23 +183,25 @@ public void addAlias(final String indexSuffix) { String[] indexNames = getIndexes(AliasType.Write); - for(String currentIndex : indexNames){ + for (String currentIndex : indexNames){ isAck = adminClient.indices().prepareAliases().removeAlias(currentIndex, alias.getWriteAlias()).execute().actionGet().isAcknowledged(); - logger.info("Removed Index Name [{}] from Alias=[{}] ACK=[{}]",currentIndex, alias, isAck); + logger.info("Removed Index Name [{}] from Alias=[{}] ACK=[{}]", currentIndex, alias, isAck); } - //add read alias + // add read alias isAck = adminClient.indices().prepareAliases().addAlias( indexName, alias.getReadAlias()).execute().actionGet().isAcknowledged(); - logger.info("Created new read Alias Name [{}] ACK=[{}]", alias, isAck); - - //add write alias + logger.info("Created new read Alias Name [{}] ACK=[{}]", alias.getReadAlias(), isAck); + + // add write alias isAck = adminClient.indices().prepareAliases().addAlias( indexName, alias.getWriteAlias()).execute().actionGet().isAcknowledged(); - logger.info("Created new write Alias Name [{}] ACK=[{}]", alias, isAck); + logger.info("Created new write Alias Name [{}] ACK=[{}]", alias.getWriteAlias(), isAck); + aliasCache.invalidate(alias); + } catch (Exception e) { logger.warn("Failed to create alias ", e); } @@ -236,7 +224,7 @@ private void testNewIndex() { // to receive documents. Occasionally we see errors. // See this post: http://s.apache.org/index-missing-exception - logger.debug( "Testing new index name [{}]", alias); + logger.debug( "Testing new index name: read {} write {}", alias.getReadAlias(), alias.getWriteAlias()); final RetryOperation retryOperation = new RetryOperation() { @Override @@ -244,18 +232,19 @@ public boolean doOp() { final String tempId = UUIDGenerator.newTimeUUID().toString(); esProvider.getClient().prepareIndex( alias.getWriteAlias(), VERIFY_TYPE, tempId ) - .setSource(DEFAULT_PAYLOAD).get(); + .setSource(DEFAULT_PAYLOAD).get(); logger.info( "Successfully created new document with docId {} " - + "in index {} and type {}", tempId, alias, VERIFY_TYPE ); + + "in index read {} write {} and type {}", + tempId, alias.getReadAlias(), alias.getWriteAlias(), VERIFY_TYPE ); // delete all types, this way if we miss one it will get cleaned up - esProvider.getClient().prepareDeleteByQuery( alias.getWriteAlias() ) - .setTypes(VERIFY_TYPE) + esProvider.getClient().prepareDeleteByQuery( alias.getWriteAlias()) + .setTypes(VERIFY_TYPE) .setQuery(MATCH_ALL_QUERY_BUILDER).get(); - logger.info( "Successfully deleted all documents in index {} and type {}", - alias, VERIFY_TYPE ); + logger.info( "Successfully deleted all documents in index {} read {} write {} and type {}", + alias.getReadAlias(), alias.getWriteAlias(), VERIFY_TYPE ); return true; } @@ -359,16 +348,15 @@ public CandidateResults search( final IndexScope indexScope, final SearchTypes s if ( logger.isDebugEnabled() ) { - logger.debug( "Searching index {}\n scope{} \n type {}\n query {} ", - new Object[] { this.alias, context, entityTypes, srb - } ); + logger.debug( "Searching index (read alias): {}\n scope: {} \n type: {}\n query: {} ", + this.alias.getReadAlias(), context, entityTypes, srb ); } try { searchResponse = srb.execute().actionGet(); } catch ( Throwable t ) { - logger.error( "Unable to communicate with elasticsearch", t ); + logger.error( "Unable to communicate with Elasticsearch", t ); failureMonitor.fail( "Unable to execute batch", t ); throw t; } @@ -445,17 +433,14 @@ public void refresh() { @Override public boolean doOp() { try { - String[] indexes = getIndexes(AliasType.Read); - Observable.from(indexes).map(new Func1() { - @Override - public String call(String index) { - esProvider.getClient().admin().indices().prepareRefresh( index ).execute().actionGet(); - return index; - } - }).toBlocking().last(); - - logger.debug( "Refreshed index: " + alias); - + String[] indexes = ArrayUtils.addAll( getIndexes(AliasType.Write), getIndexes(AliasType.Write) ); + if ( indexes.length == 0 ) { + logger.debug( "Not refreshing indexes, none found for app {}", + applicationScope.getApplication().getUuid() ); + return true; + } + esProvider.getClient().admin().indices().prepareRefresh( indexes ).execute().actionGet(); + logger.debug("Refreshed indexes: {}", StringUtils.join(indexes, ", ")); return true; } catch ( IndexMissingException e ) { @@ -466,8 +451,6 @@ public String call(String index) { }; doInRetry( retryOperation ); - - logger.debug( "Refreshed index: " + alias); } @@ -517,7 +500,7 @@ public CandidateResults getEntityVersions( final IndexScope scope, final Id id ) @Override public void deleteAllVersionsOfEntity( Id entityId ) { - String idString = IndexingUtils.idString( entityId ).toLowerCase(); + String idString = IndexingUtils.idString(entityId).toLowerCase(); final TermQueryBuilder tqb = QueryBuilders.termQuery( ENTITYID_ID_FIELDNAME, idString ); @@ -526,7 +509,7 @@ public void deleteAllVersionsOfEntity( Id entityId ) { logger.debug( "Deleted entity {}:{} from all index scopes with response status = {}", - new Object[] { entityId.getType(), entityId.getUuid(), response.status().toString() }); + entityId.getType(), entityId.getUuid(), response.status().toString()); checkDeleteByQueryResponse( tqb, response ); @@ -539,8 +522,8 @@ public void deletePreviousVersions( final Id entityId, final UUID version ) { String idString = IndexingUtils.idString( entityId ).toLowerCase(); final FilteredQueryBuilder fqb = QueryBuilders.filteredQuery( - QueryBuilders.termQuery( ENTITYID_ID_FIELDNAME, idString ), - FilterBuilders.rangeFilter( ENTITY_VERSION_FIELDNAME ).lt( version.timestamp() ) + QueryBuilders.termQuery(ENTITYID_ID_FIELDNAME, idString), + FilterBuilders.rangeFilter(ENTITY_VERSION_FIELDNAME).lt(version.timestamp()) ); final DeleteByQueryResponse response = esProvider.getClient() @@ -549,7 +532,7 @@ public void deletePreviousVersions( final Id entityId, final UUID version ) { //error message needs to be retooled so that it describes the entity more throughly logger.debug( "Deleted entity {}:{} with version {} from all " + "index scopes with response status = {}", - new Object[] { entityId.getType(), entityId.getUuid(), version, response.status().toString() } ); + entityId.getType(), entityId.getUuid(), version, response.status().toString() ); checkDeleteByQueryResponse( fqb, response ); } @@ -565,10 +548,10 @@ private void checkDeleteByQueryResponse( final ShardOperationFailedException[] failures = indexDeleteByQueryResponse.getFailures(); for ( ShardOperationFailedException failedException : failures ) { - throw new IndexException( String.format("Unable to delete by query %s. " + throw new IndexException( String.format("Unable to delete by query %s. " + "Failed with code %d and reason %s on shard %s in index %s", query.toString(), - failedException.status(), + failedException.status().getStatus(), failedException.reason(), failedException.shardId(), failedException.index() ) ); @@ -579,7 +562,7 @@ private void checkDeleteByQueryResponse( /** - * For testing only. + * Completely delete an index. */ public void deleteIndex() { AdminClient adminClient = esProvider.getClient().admin(); @@ -588,10 +571,10 @@ public void deleteIndex() { .prepareDelete( indexIdentifier.getIndex(null) ).get(); if ( response.isAcknowledged() ) { - logger.info( "Deleted index: " + alias); + logger.info( "Deleted index: read {} write {}", alias.getReadAlias(), alias.getWriteAlias()); } else { - logger.info( "Failed to delete index " + alias); + logger.info( "Failed to delete index: read {} write {}", alias.getReadAlias(), alias.getWriteAlias()); } } diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsIndexCache.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsIndexCache.java index c607222c1f..0c07a34302 100644 --- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsIndexCache.java +++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsIndexCache.java @@ -45,6 +45,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; + /** * Cache for Es index operations */ @@ -58,8 +59,10 @@ public class EsIndexCache { @Inject public EsIndexCache(final EsProvider provider, final IndexFig indexFig) { + this.refreshExecutors = MoreExecutors .listeningDecorator(Executors.newScheduledThreadPool(indexFig.getIndexCacheMaxWorkers())); + aliasIndexCache = CacheBuilder.newBuilder().maximumSize(1000) .refreshAfterWrite(5,TimeUnit.MINUTES) .build(new CacheLoader() { @@ -78,17 +81,16 @@ public String[] call() { public String[] load(final String aliasName) { final AdminClient adminClient = provider.getClient().admin(); //remove write alias, can only have one - ImmutableOpenMap> aliasMap = adminClient.indices().getAliases(new GetAliasesRequest(aliasName)).actionGet().getAliases(); + ImmutableOpenMap> aliasMap = + adminClient.indices().getAliases(new GetAliasesRequest(aliasName)).actionGet().getAliases(); return aliasMap.keys().toArray(String.class); } }) ; } + /** * Get indexes for an alias - * @param alias - * @param aliasType - * @return */ public String[] getIndexes(IndexIdentifier.IndexAlias alias, AliasedEntityIndex.AliasType aliasType) { String[] indexes; @@ -101,9 +103,9 @@ public String[] getIndexes(IndexIdentifier.IndexAlias alias, AliasedEntityIndex. return indexes; } + /** * clean up cache - * @param alias */ public void invalidate(IndexIdentifier.IndexAlias alias){ aliasIndexCache.invalidate(alias.getWriteAlias()); From 7335f9411aa20357bc3c4b3c866b12dfdadb23a3 Mon Sep 17 00:00:00 2001 From: Dave Johnson Date: Tue, 20 Jan 2015 11:59:34 -0500 Subject: [PATCH 2/3] Addition of emf.deleteApplicaton() method and a test for it in EntityManagerFacotryImplIT. --- .../CpEntityManagerFactory.java | 56 ++++++++++++--- .../HybridEntityManagerFactory.java | 9 ++- .../persistence/EntityManagerFactory.java | 11 ++- .../cassandra/EntityManagerFactoryImpl.java | 11 ++- .../cassandra/EntityManagerFactoryImplIT.java | 71 ++++++++++++------- 5 files changed, 115 insertions(+), 43 deletions(-) diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java index 7016d3cfa2..93eb15e9fc 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java @@ -123,8 +123,6 @@ public CpEntityManagerFactory( this.cass = cass; this.counterUtils = counterUtils; - - } @@ -136,8 +134,8 @@ private void init() { if ( em.getApplication() == null ) { logger.info("Creating system application"); Map sysAppProps = new HashMap(); - sysAppProps.put( PROPERTY_NAME, "systemapp"); - em.create( CpNamingUtils.SYSTEM_APP_ID, TYPE_APPLICATION, sysAppProps ); + sysAppProps.put(PROPERTY_NAME, "systemapp"); + em.create(CpNamingUtils.SYSTEM_APP_ID, TYPE_APPLICATION, sysAppProps); em.getApplication(); em.createIndex(); em.refreshIndex(); @@ -165,7 +163,7 @@ public ManagerCache getManagerCache() { @Override - public String getImpementationDescription() throws Exception { + public String getImplementationDescription() throws Exception { return IMPLEMENTATION_DESCRIPTION; } @@ -187,7 +185,7 @@ private EntityManager _getEntityManager( UUID applicationId ) { EntityManager em = new CpEntityManager(); em.init( this, applicationId ); - // only need to do this once + // only need to do this once if ( !applicationIndexesCreated.contains( applicationId ) ) { em.createIndex(); applicationIndexesCreated.add( applicationId ); @@ -285,6 +283,36 @@ public UUID initializeApplication( String organizationName, UUID applicationId, } + /** + * Delete Application. + * + *

The Application Entity is be moved to a Deleted_Applications collection and the + * Application index will be removed. + * + *

TODO: add scheduled task that can completely delete all deleted application data.

+ * + * @param applicationId UUID of Application to be deleted. + */ + @Override + public void deleteApplication(UUID applicationId) throws Exception { + + // remove old appinfo Entity, which is in the System App's appinfos collection + EntityManager em = getEntityManager(CpNamingUtils.SYSTEM_APP_ID); + Query q = Query.fromQL(String.format("select * where applicationUuid = '%s'", applicationId.toString())); + Results results = em.searchCollection( em.getApplicationRef(), "appinfos", q); + Entity appToDelete = results.getEntity(); + em.delete( appToDelete ); + + // create new Entity in deleted_appinfos collection, with same UUID and properties as deleted appinfo + em.create( "deleted_appinfo", appToDelete.getProperties() ); + + em.refreshIndex(); + + // delete the application's index + EntityIndex ei = managerCache.getEntityIndex(new ApplicationScopeImpl( + new SimpleId(applicationId, TYPE_APPLICATION))); + ei.deleteIndex(); + } @Override @@ -395,6 +423,11 @@ public Map getApplications() throws Exception { managerCache.getEntityCollectionManager( collScope ).load( targetId ) .toBlockingObservable().lastOrDefault(null); + if ( e == null ) { + logger.warn("Applicaion {} in index but not found in collections", targetId ); + continue; + } + appMap.put( (String)e.getField( PROPERTY_NAME ).getValue(), (UUID)e.getField( "applicationUuid" ).getValue()); @@ -407,6 +440,7 @@ public Map getApplications() throws Exception { @Override public void setup() throws Exception { getSetup().init(); + init(); } @@ -460,7 +494,7 @@ public boolean updateServiceProperties(Map properties) { propsEntity = EntityFactory.newEntity( UUIDUtils.newTimeUUID(), "propertymap"); } - // intentionally going only one-level deep into fields and treating all + // intentionally going only one-level deep into fields and treating all // values as strings because that is all we need for service properties for ( String key : properties.keySet() ) { propsEntity.setProperty( key, properties.get(key).toString() ); @@ -711,13 +745,13 @@ public void addIndex(final UUID applicationId,final String indexSuffix,final int public Health getEntityStoreHealth() { // could use any collection scope here, does not matter - EntityCollectionManager ecm = getManagerCache().getEntityCollectionManager( - new CollectionScopeImpl( + EntityCollectionManager ecm = getManagerCache().getEntityCollectionManager( + new CollectionScopeImpl( new SimpleId( CpNamingUtils.SYSTEM_APP_ID, "application"), new SimpleId( CpNamingUtils.SYSTEM_APP_ID, "application"), "dummy" )); - + return ecm.getHealth(); - } + } } diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/HybridEntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/HybridEntityManagerFactory.java index af4acdb9d0..a8dd404a5f 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/HybridEntityManagerFactory.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/HybridEntityManagerFactory.java @@ -57,8 +57,8 @@ public EntityManagerFactory getImplementation() { } @Override - public String getImpementationDescription() throws Exception { - return factory.getImpementationDescription(); + public String getImplementationDescription() throws Exception { + return factory.getImplementationDescription(); } @Override @@ -77,6 +77,11 @@ public UUID createApplication(String organizationName, String name, return factory.createApplication(organizationName, name, properties); } + @Override + public void deleteApplication(UUID applicationId) throws Exception { + factory.deleteApplication( applicationId ); + } + @Override public UUID importApplication(String organization, UUID applicationId, String name, Map properties) throws Exception { diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java index 3d4827b6cf..b4bfbd2f56 100644 --- a/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java +++ b/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java @@ -40,7 +40,7 @@ public interface EntityManagerFactory { * * @throws Exception the exception */ - public abstract String getImpementationDescription() throws Exception; + public abstract String getImplementationDescription() throws Exception; /** * Gets the entity manager. @@ -73,9 +73,16 @@ public interface EntityManagerFactory { * * @throws Exception the exception */ - public abstract UUID createApplication( + public abstract UUID createApplication( String organizationName, String name, Map properties ) throws Exception; + /** + * Delete Application. + * + * @param applicationId UUID of Application to be deleted. + */ + public abstract void deleteApplication( UUID applicationId ) throws Exception; + public abstract UUID importApplication( String organization, UUID applicationId, String name, Map properties ) throws Exception; diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java b/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java index f073da7fd8..a598a8251a 100644 --- a/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java +++ b/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java @@ -119,10 +119,10 @@ public EntityManagerFactoryImpl( CassandraService cass, CounterUtils counterUtil /* * (non-Javadoc) * - * @see org.apache.usergrid.core.Datastore#getImpementationDescription() + * @see org.apache.usergrid.core.Datastore#getImplementationDescription() */ @Override - public String getImpementationDescription() { + public String getImplementationDescription() { return IMPLEMENTATION_DESCRIPTION; } @@ -218,6 +218,13 @@ public UUID createApplication( String organizationName, String name, Map properties1 = new LinkedHashMap(); + properties1.put( "Name", "12 Angry Men" ); + properties1.put( "Year", 1957 ); + Entity film1 = em.create("film", properties1); + + Map properties2 = new LinkedHashMap(); + properties2.put( "Name", "Reservoir Dogs" ); + properties2.put( "Year", 1992 ); + Entity film2 = em.create( "film", properties2 ); + + em.refreshIndex(); + + // delete the application + + setup.getEmf().deleteApplication( applicationId ); + + // attempt to get entities in application's collections in various ways should all fail + + assertNull( setup.getEmf().lookupApplication("test-app-" + rand) ); + + Map appMap = setup.getEmf().getApplications(); + for ( String appName : appMap.keySet() ) { + UUID appId = appMap.get( appName ); + assertNotEquals( appId, applicationId ); + assertNotEquals( appName, "test-app-" + rand ); + } } @@ -119,7 +137,8 @@ public void testCreateAndGet() throws Exception { traceTagManager.attach( traceTag ); logger.info( "EntityDaoTest.testCreateAndGet" ); - UUID applicationId = createApplication( "EntityManagerFactoryImplIT", "testCreateAndGet" + RandomStringUtils.randomAlphabetic(20) ); + UUID applicationId = createApplication( "EntityManagerFactoryImplIT", "testCreateAndGet" + + RandomStringUtils.randomAlphabetic(20) ); logger.info( "Application id " + applicationId ); EntityManager em = emf.getEntityManager( applicationId ); From 4384975fa91d2c7e5ffad06f9adf4a16855d3839 Mon Sep 17 00:00:00 2001 From: Dave Johnson Date: Tue, 20 Jan 2015 16:30:53 -0500 Subject: [PATCH 3/3] Beginnings of a REST test. --- .../applications/ApplicationResource.java | 32 ++++++++--- .../applications/ApplicationDeleteTest.java | 54 +++++++++++++++++++ 2 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java index 6144940873..6a3c94c1bc 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java @@ -38,6 +38,13 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.apache.usergrid.persistence.Entity; +import org.apache.usergrid.persistence.exceptions.EntityNotFoundException; +import org.apache.usergrid.rest.ApiResponse; +import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess; +import org.apache.usergrid.services.ServiceAction; +import org.apache.usergrid.services.ServiceResults; +import org.apache.usergrid.services.assets.data.AssetUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; @@ -495,15 +502,28 @@ public Response handleAuthorizeForm( @Context UriInfo ui, @DELETE - @RequireApplicationAccess + @RequireOrganizationAccess @Override - public JSONWithPadding executeDelete( @Context UriInfo ui, - @QueryParam("callback") @DefaultValue("callback") String callback ) - throws Exception { + public JSONWithPadding executeDelete( @Context UriInfo ui, + @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception { + + if ( applicationId == null ) { + throw new IllegalArgumentException("Application ID not specified in request"); + } + + ApplicationInfo app = management.getApplicationInfo( applicationId ); + if ( app == null ) { + throw new EntityNotFoundException("Application ID " + applicationId + " not found"); + } + + emf.deleteApplication( applicationId ); - logger.debug( "ApplicationResource.executeDelete" ); + ApiResponse response = createApiResponse(); + response.setAction( "delete" ); + response.setApplication( services.getApplication() ); + response.setParams( ui.getQueryParameters() ); - throw new NotImplementedException( "Application delete is not allowed yet" ); + return new JSONWithPadding( response, callback ); } diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java new file mode 100644 index 0000000000..e74b32460f --- /dev/null +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.usergrid.rest.applications; + + +import org.apache.usergrid.rest.AbstractRestIT; +import org.apache.usergrid.rest.TestContextSetup; +import org.junit.Rule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ApplicationDeleteTest extends AbstractRestIT { + private static final Logger log = LoggerFactory.getLogger(ApplicationDeleteTest.class); + + @Rule + public TestContextSetup context = new TestContextSetup( this ); + + @Test + public void testBasicOperation() throws Exception { + + // create a user + + // crete an organization + + // create an application + + // create a collection with two entities + + // test that we can query those entities + + // delete the application + + // test that we cannot delete the application a second time + + // test that we can no longer query for those entities + } +}