Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
atlas
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dataplatform
atlas
Commits
ef9ef3c1
Commit
ef9ef3c1
authored
Apr 04, 2016
by
Suma Shivaprasad
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ATLAS-607 Add Support for delete entity through a qualifiedName (sumasai via yhemanth)
parent
98f4d40a
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
180 additions
and
21 deletions
+180
-21
AtlasClient.java
client/src/main/java/org/apache/atlas/AtlasClient.java
+18
-1
release-log.txt
release-log.txt
+1
-0
GraphBackedMetadataRepository.java
...atlas/repository/graph/GraphBackedMetadataRepository.java
+0
-2
DefaultMetadataService.java
...ava/org/apache/atlas/services/DefaultMetadataService.java
+19
-2
DefaultMetadataServiceTest.java
.../org/apache/atlas/service/DefaultMetadataServiceTest.java
+72
-10
MetadataService.java
.../main/java/org/apache/atlas/services/MetadataService.java
+11
-0
EntityResource.java
...n/java/org/apache/atlas/web/resources/EntityResource.java
+29
-6
EntityJerseyResourceIT.java
...rg/apache/atlas/web/resources/EntityJerseyResourceIT.java
+30
-0
No files found.
client/src/main/java/org/apache/atlas/AtlasClient.java
View file @
ef9ef3c1
...
...
@@ -346,7 +346,7 @@ public class AtlasClient {
UPDATE_ENTITY_PARTIAL
(
BASE_URI
+
URI_ENTITY
,
HttpMethod
.
POST
,
Response
.
Status
.
OK
),
LIST_ENTITIES
(
BASE_URI
+
URI_ENTITY
,
HttpMethod
.
GET
,
Response
.
Status
.
OK
),
DELETE_ENTITIES
(
BASE_URI
+
URI_ENTITY
,
HttpMethod
.
DELETE
,
Response
.
Status
.
OK
),
DELETE_ENTITY
(
BASE_URI
+
URI_ENTITY
,
HttpMethod
.
DELETE
,
Response
.
Status
.
OK
),
//Trait operations
ADD_TRAITS
(
BASE_URI
+
URI_ENTITY
,
HttpMethod
.
POST
,
Response
.
Status
.
CREATED
),
...
...
@@ -612,6 +612,23 @@ public class AtlasClient {
}
/**
* Supports Deletion of an entity identified by its unique attribute value
* @param entityType Type of the entity being deleted
* @param uniqueAttributeName Attribute Name that uniquely identifies the entity
* @param uniqueAttributeValue Attribute Value that uniquely identifies the entity
* @return List of deleted entity guids(including composite references from that entity)
*/
public
List
<
String
>
deleteEntity
(
String
entityType
,
String
uniqueAttributeName
,
String
uniqueAttributeValue
)
throws
AtlasServiceException
{
API
api
=
API
.
DELETE_ENTITY
;
WebResource
resource
=
getResource
(
api
);
resource
=
resource
.
queryParam
(
TYPE
,
entityType
);
resource
=
resource
.
queryParam
(
ATTRIBUTE_NAME
,
uniqueAttributeName
);
resource
=
resource
.
queryParam
(
ATTRIBUTE_VALUE
,
uniqueAttributeValue
);
JSONObject
jsonResponse
=
callAPIWithResource
(
API
.
DELETE_ENTITIES
,
resource
,
null
);
return
extractResults
(
jsonResponse
,
GUID
);
}
/**
* Get an entity given the entity id
* @param guid entity id
* @return result object
...
...
release-log.txt
View file @
ef9ef3c1
...
...
@@ -13,6 +13,7 @@ ATLAS-409 Atlas will not import avro tables with schema read from a file (dosset
ATLAS-379 Create sqoop and falcon metadata addons (venkatnrangan,bvellanki,sowmyaramesh via shwethags)
ALL CHANGES:
ATLAS-607 Add Support for delete entity through a qualifiedName (sumasai via yhemanth)
ATLAS-571 Modify Atlas client for necessary changes in context of HA (yhemanth via sumasai)
ATLAS-620 Disable hbase based entity audit (shwethags)
ATLAS-618 Fix assembly for hdfs-module (sumasai via yhemanth)
...
...
repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepository.java
View file @
ef9ef3c1
...
...
@@ -252,8 +252,6 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
}
try
{
final
String
entityTypeName
=
GraphHelper
.
getTypeName
(
instanceVertex
);
String
relationshipLabel
=
GraphHelper
.
getTraitLabel
(
entityTypeName
,
traitNameToBeDeleted
);
Iterator
<
Edge
>
results
=
instanceVertex
.
getEdges
(
Direction
.
OUT
,
relationshipLabel
).
iterator
();
...
...
repository/src/main/java/org/apache/atlas/services/DefaultMetadataService.java
View file @
ef9ef3c1
...
...
@@ -76,7 +76,6 @@ import java.util.Collection;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.atomic.AtomicBoolean
;
/**
* Simple wrapper over TypeSystem and MetadataRepository services with hooks
...
...
@@ -691,7 +690,25 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
*/
@Override
public
List
<
String
>
deleteEntities
(
List
<
String
>
deleteCandidateGuids
)
throws
AtlasException
{
ParamChecker
.
notEmpty
(
deleteCandidateGuids
,
"delete candidate guids cannot be empty"
);
ParamChecker
.
notEmpty
(
deleteCandidateGuids
,
"delete candidate guids"
);
return
deleteGuids
(
deleteCandidateGuids
);
}
@Override
public
List
<
String
>
deleteEntityByUniqueAttribute
(
String
typeName
,
String
uniqueAttributeName
,
String
attrValue
)
throws
AtlasException
{
ParamChecker
.
notEmpty
(
typeName
,
"delete candidate typeName"
);
ParamChecker
.
notEmpty
(
uniqueAttributeName
,
"delete candidate unique attribute name"
);
ParamChecker
.
notEmpty
(
attrValue
,
"delete candidate unique attribute value"
);
//Throws EntityNotFoundException if the entity could not be found by its unique attribute
ITypedReferenceableInstance
instance
=
getEntityDefinitionReference
(
typeName
,
uniqueAttributeName
,
attrValue
);
final
Id
instanceId
=
instance
.
getId
();
List
<
String
>
deleteCandidateGuids
=
new
ArrayList
<
String
>()
{{
add
(
instanceId
.
_getId
());}};
return
deleteGuids
(
deleteCandidateGuids
);
}
private
List
<
String
>
deleteGuids
(
List
<
String
>
deleteCandidateGuids
)
throws
AtlasException
{
Pair
<
List
<
String
>,
List
<
ITypedReferenceableInstance
>>
deleteEntitiesResult
=
repository
.
deleteEntities
(
deleteCandidateGuids
);
if
(
deleteEntitiesResult
.
right
.
size
()
>
0
)
{
onEntitiesDeleted
(
deleteEntitiesResult
.
right
);
...
...
repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java
View file @
ef9ef3c1
...
...
@@ -24,14 +24,21 @@ import com.google.inject.Inject;
import
com.thinkaurelius.titan.core.TitanGraph
;
import
com.thinkaurelius.titan.core.util.TitanCleanup
;
import
org.apache.atlas.AtlasClient
;
import
org.apache.atlas.repository.audit.EntityAuditRepository
;
import
org.apache.atlas.repository.audit.HBaseBasedAuditRepository
;
import
org.apache.atlas.repository.audit.HBaseTestUtils
;
import
org.apache.atlas.typesystem.exception.TypeNotFoundException
;
import
org.apache.atlas.typesystem.exception.EntityNotFoundException
;
import
org.apache.atlas.typesystem.types.ClassType
;
import
org.apache.atlas.typesystem.types.DataTypes
;
import
org.apache.atlas.typesystem.types.HierarchicalTypeDefinition
;
import
org.apache.atlas.typesystem.types.utils.TypesUtil
;
import
org.apache.atlas.utils.ParamChecker
;
import
org.apache.atlas.AtlasException
;
import
org.apache.atlas.RepositoryMetadataModule
;
import
org.apache.atlas.RequestContext
;
import
org.apache.atlas.TestUtils
;
import
org.apache.atlas.listener.EntityChangeListener
;
import
org.apache.atlas.repository.audit.EntityAuditRepository
;
import
org.apache.atlas.repository.audit.HBaseBasedAuditRepository
;
import
org.apache.atlas.repository.audit.HBaseTestUtils
;
import
org.apache.atlas.repository.graph.GraphProvider
;
import
org.apache.atlas.services.MetadataService
;
import
org.apache.atlas.typesystem.IReferenceableInstance
;
...
...
@@ -40,19 +47,12 @@ import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import
org.apache.atlas.typesystem.Referenceable
;
import
org.apache.atlas.typesystem.Struct
;
import
org.apache.atlas.typesystem.TypesDef
;
import
org.apache.atlas.typesystem.exception.EntityNotFoundException
;
import
org.apache.atlas.typesystem.exception.TypeNotFoundException
;
import
org.apache.atlas.typesystem.json.InstanceSerialization
;
import
org.apache.atlas.typesystem.json.TypesSerialization
;
import
org.apache.atlas.typesystem.persistence.Id
;
import
org.apache.atlas.typesystem.types.ClassType
;
import
org.apache.atlas.typesystem.types.DataTypes
;
import
org.apache.atlas.typesystem.types.EnumValue
;
import
org.apache.atlas.typesystem.types.HierarchicalTypeDefinition
;
import
org.apache.atlas.typesystem.types.TypeSystem
;
import
org.apache.atlas.typesystem.types.ValueConversionException
;
import
org.apache.atlas.typesystem.types.utils.TypesUtil
;
import
org.apache.atlas.utils.ParamChecker
;
import
org.apache.commons.lang.RandomStringUtils
;
import
org.codehaus.jettison.json.JSONArray
;
import
org.codehaus.jettison.json.JSONException
;
...
...
@@ -919,6 +919,68 @@ public class DefaultMetadataServiceTest {
}
@Test
public
void
testDeleteEntityByUniqueAttribute
()
throws
Exception
{
// Create 2 table entities, each with 3 composite column entities
Referenceable
dbEntity
=
createDBEntity
();
String
dbGuid
=
createInstance
(
dbEntity
);
Id
dbId
=
new
Id
(
dbGuid
,
0
,
TestUtils
.
DATABASE_TYPE
);
Referenceable
table1Entity
=
createTableEntity
(
dbId
);
Referenceable
col1
=
createColumnEntity
();
Referenceable
col2
=
createColumnEntity
();
Referenceable
col3
=
createColumnEntity
();
table1Entity
.
set
(
COLUMNS_ATTR_NAME
,
ImmutableList
.
of
(
col1
,
col2
,
col3
));
createInstance
(
table1Entity
);
// to get their guids and the composite column guids.
String
entityJson
=
metadataService
.
getEntityDefinition
(
TestUtils
.
TABLE_TYPE
,
NAME
,
(
String
)
table1Entity
.
get
(
NAME
));
Assert
.
assertNotNull
(
entityJson
);
table1Entity
=
InstanceSerialization
.
fromJsonReferenceable
(
entityJson
,
true
);
Object
val
=
table1Entity
.
get
(
COLUMNS_ATTR_NAME
);
Assert
.
assertTrue
(
val
instanceof
List
);
List
<
IReferenceableInstance
>
table1Columns
=
(
List
<
IReferenceableInstance
>)
val
;
// Register an EntityChangeListener to verify the notification mechanism
// is working for deleteEntityByUniqueAttribute().
DeleteEntitiesChangeListener
listener
=
new
DeleteEntitiesChangeListener
();
metadataService
.
registerListener
(
listener
);
// Delete the table entities. The deletion should cascade
// to their composite columns.
List
<
String
>
deletedGuids
=
metadataService
.
deleteEntityByUniqueAttribute
(
TestUtils
.
TABLE_TYPE
,
NAME
,
(
String
)
table1Entity
.
get
(
NAME
));
// Verify that deleteEntities() response has guids for tables and their composite columns.
Assert
.
assertTrue
(
deletedGuids
.
contains
(
table1Entity
.
getId
().
_getId
()));
for
(
IReferenceableInstance
column
:
table1Columns
)
{
Assert
.
assertTrue
(
deletedGuids
.
contains
(
column
.
getId
().
_getId
()));
}
// Verify that tables and their composite columns have been deleted from the repository.
for
(
String
guid
:
deletedGuids
)
{
try
{
metadataService
.
getEntityDefinition
(
guid
);
Assert
.
fail
(
EntityNotFoundException
.
class
.
getSimpleName
()
+
" expected but not thrown. The entity with guid "
+
guid
+
" still exists in the repository after being deleted."
);
}
catch
(
EntityNotFoundException
e
)
{
// The entity does not exist in the repository, so deletion was successful.
}
}
// Verify that the listener was notified about the deleted entities.
Collection
<
ITypedReferenceableInstance
>
deletedEntitiesFromListener
=
listener
.
getDeletedEntities
();
Assert
.
assertNotNull
(
deletedEntitiesFromListener
);
Assert
.
assertEquals
(
deletedEntitiesFromListener
.
size
(),
deletedGuids
.
size
());
List
<
String
>
deletedGuidsFromListener
=
new
ArrayList
<>(
deletedGuids
.
size
());
for
(
ITypedReferenceableInstance
deletedEntity
:
deletedEntitiesFromListener
)
{
deletedGuidsFromListener
.
add
(
deletedEntity
.
getId
().
_getId
());
}
Assert
.
assertEquals
(
deletedGuidsFromListener
.
size
(),
deletedGuids
.
size
());
Assert
.
assertTrue
(
deletedGuidsFromListener
.
containsAll
(
deletedGuids
));
}
@Test
public
void
testTypeUpdateWithReservedAttributes
()
throws
AtlasException
,
JSONException
{
String
typeName
=
"test_type_"
+
RandomStringUtils
.
randomAlphanumeric
(
10
);
HierarchicalTypeDefinition
<
ClassType
>
typeDef
=
TypesUtil
.
createClassTypeDef
(
...
...
server-api/src/main/java/org/apache/atlas/services/MetadataService.java
View file @
ef9ef3c1
...
...
@@ -196,4 +196,15 @@ public interface MetadataService {
* @param listener the listener to unregister
*/
void
unregisterListener
(
EntityChangeListener
listener
);
/**
* Delete the specified entity from the repository identified by its unique attribute (including its composite references)
*
* @param typeName The entity's type
* @param uniqueAttributeName attribute name by which the entity could be identified uniquely
* @param attrValue attribute value by which the entity could be identified uniquely
* @return List of guids for deleted entities (including their composite references)
* @throws AtlasException
*/
List
<
String
>
deleteEntityByUniqueAttribute
(
String
typeName
,
String
uniqueAttributeName
,
String
attrValue
)
throws
AtlasException
;
}
webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
View file @
ef9ef3c1
...
...
@@ -56,6 +56,7 @@ import javax.ws.rs.core.Response;
import
javax.ws.rs.core.UriBuilder
;
import
javax.ws.rs.core.UriInfo
;
import
java.net.URI
;
import
java.util.ArrayList
;
import
java.util.List
;
...
...
@@ -313,19 +314,34 @@ public class EntityResource {
}
/**
* Delete entities from the repository
* Delete entities from the repository identified by their guids (including their composite references)
* or
* Deletes a single entity identified by its type and unique attribute value from the repository (including their composite references)
*
* @param guids deletion candidate guids
* @param request
* @return response payload as json
* @param guids list of deletion candidate guids
* or
* @param entityType the entity type
* @param attribute the unique attribute used to identify the entity
* @param value the unique attribute value used to identify the entity
* @param request - Ignored
* @return response payload as json - including guids of entities(including composite references from that entity) that were deleted
*/
@DELETE
@Consumes
(
Servlets
.
JSON_MEDIA_TYPE
)
@Produces
(
Servlets
.
JSON_MEDIA_TYPE
)
public
Response
deleteEntities
(
@QueryParam
(
"guid"
)
List
<
String
>
guids
,
@Context
HttpServletRequest
request
)
{
public
Response
deleteEntities
(
@QueryParam
(
"guid"
)
List
<
String
>
guids
,
@QueryParam
(
"type"
)
String
entityType
,
@QueryParam
(
"property"
)
String
attribute
,
@QueryParam
(
"value"
)
String
value
,
@Context
HttpServletRequest
request
)
{
try
{
List
<
String
>
deletedGuids
=
metadataService
.
deleteEntities
(
guids
);
List
<
String
>
deletedGuids
=
new
ArrayList
<>();
if
(
guids
!=
null
&&
!
guids
.
isEmpty
())
{
deletedGuids
=
metadataService
.
deleteEntities
(
guids
);
}
else
{
deletedGuids
=
metadataService
.
deleteEntityByUniqueAttribute
(
entityType
,
attribute
,
value
);
}
JSONObject
response
=
new
JSONObject
();
response
.
put
(
AtlasClient
.
REQUEST_ID
,
Servlets
.
getRequestId
());
JSONArray
guidArray
=
new
JSONArray
(
deletedGuids
.
size
());
...
...
@@ -334,6 +350,13 @@ public class EntityResource {
}
response
.
put
(
AtlasClient
.
GUID
,
guidArray
);
return
Response
.
ok
(
response
).
build
();
}
catch
(
EntityNotFoundException
e
)
{
if
(
guids
!=
null
||
!
guids
.
isEmpty
())
{
LOG
.
error
(
"An entity with GUID={} does not exist"
,
guids
,
e
);
}
else
{
LOG
.
error
(
"An entity with qualifiedName {}-{}-{} does not exist"
,
entityType
,
attribute
,
value
,
e
);
}
throw
new
WebApplicationException
(
Servlets
.
getErrorResponse
(
e
,
Response
.
Status
.
NOT_FOUND
));
}
catch
(
AtlasException
|
IllegalArgumentException
e
)
{
LOG
.
error
(
"Unable to delete entities {}"
,
guids
,
e
);
throw
new
WebApplicationException
(
Servlets
.
getErrorResponse
(
e
,
Response
.
Status
.
BAD_REQUEST
));
...
...
webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
View file @
ef9ef3c1
...
...
@@ -808,4 +808,34 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
}
}
@Test
public
void
testDeleteEntityByUniqAttribute
()
throws
Exception
{
// Create database entity
Referenceable
db1
=
new
Referenceable
(
DATABASE_TYPE
);
String
dbName
=
randomString
();
db1
.
set
(
"name"
,
dbName
);
db1
.
set
(
"description"
,
randomString
());
Id
db1Id
=
createInstance
(
db1
);
// Delete the database entity
List
<
String
>
deletedGuidsList
=
serviceClient
.
deleteEntity
(
DATABASE_TYPE
,
"name"
,
dbName
);
// Verify that deleteEntities() response has database entity guids
Assert
.
assertEquals
(
deletedGuidsList
.
size
(),
1
);
Assert
.
assertTrue
(
deletedGuidsList
.
contains
(
db1Id
.
_getId
()));
// Verify entities were deleted from the repository.
for
(
String
guid
:
deletedGuidsList
)
{
try
{
serviceClient
.
getEntity
(
guid
);
Assert
.
fail
(
AtlasServiceException
.
class
.
getSimpleName
()
+
" was expected but not thrown. The entity with guid "
+
guid
+
" still exists in the repository after being deleted."
);
}
catch
(
AtlasServiceException
e
)
{
Assert
.
assertTrue
(
e
.
getMessage
().
contains
(
Integer
.
toString
(
Response
.
Status
.
NOT_FOUND
.
getStatusCode
())));
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment