blob: 7fa4fc8dc2d35d10fab704636e84c8fea6f7eb64 [file] [log] [blame]
/**
* 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.atlas.web.integration;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasServiceException;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.v1.model.typedef.*;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.typesystem.types.DataTypes;
import org.apache.atlas.v1.typesystem.types.utils.TypesUtil;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.util.*;
import static org.apache.atlas.v1.typesystem.types.utils.TypesUtil.createOptionalAttrDef;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
/**
* Integration test for types jersey resource.
*/
public class TypesJerseyResourceIT extends BaseResourceIT {
private List<HierarchicalTypeDefinition> typeDefinitions;
@BeforeClass
public void setUp() throws Exception {
super.setUp();
typeDefinitions = createHiveTypes();
}
@AfterClass
public void tearDown() throws Exception {
typeDefinitions.clear();
}
@Test
public void testSubmit() throws Exception {
for (HierarchicalTypeDefinition typeDefinition : typeDefinitions) {
try{
atlasClientV1.getType(typeDefinition.getTypeName());
} catch (AtlasServiceException ase){
TypesDef typesDef = null;
if (typeDefinition instanceof ClassTypeDefinition) {
typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), Collections.singletonList((ClassTypeDefinition) typeDefinition));
} else if (typeDefinition instanceof TraitTypeDefinition) {
typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(),
Collections.singletonList((TraitTypeDefinition) typeDefinition), Collections.emptyList());
}
String typesAsJSON = AtlasType.toV1Json(typesDef);
System.out.println("typesAsJSON = " + typesAsJSON);
ObjectNode response = atlasClientV1.callAPIWithBody(AtlasClient.API_V1.CREATE_TYPE, typesAsJSON);
Assert.assertNotNull(response);
ArrayNode typesAdded = (ArrayNode) response.get(AtlasClient.TYPES);
assertEquals(typesAdded.size(), 1);
assertEquals(typesAdded.get(0).get(NAME).asText(), typeDefinition.getTypeName());
Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));}
}
}
@Test
public void testDuplicateSubmit() throws Exception {
ClassTypeDefinition type = TypesUtil.createClassTypeDef(randomString(), null,
Collections.<String>emptySet(), TypesUtil.createUniqueRequiredAttrDef(NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING));
TypesDef typesDef =
new TypesDef(Collections.<EnumTypeDefinition>emptyList(), Collections.<StructTypeDefinition>emptyList(),
Collections.<TraitTypeDefinition>emptyList(), Collections.singletonList(type));
atlasClientV1.createType(typesDef);
try {
atlasClientV1.createType(typesDef);
fail("Expected 409");
} catch (AtlasServiceException e) {
assertEquals(e.getStatus().getStatusCode(), Response.Status.CONFLICT.getStatusCode());
}
}
@Test
public void testUpdate() throws Exception {
ClassTypeDefinition classTypeDef = TypesUtil
.createClassTypeDef(randomString(), null, "1.0", Collections.<String>emptySet(),
TypesUtil.createUniqueRequiredAttrDef(NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING));
TypesDef typesDef = new TypesDef(Collections.<EnumTypeDefinition>emptyList(), Collections.<StructTypeDefinition>emptyList(), Collections.<TraitTypeDefinition>emptyList(), Collections.singletonList(classTypeDef));
List<String> typesCreated = atlasClientV1.createType(AtlasType.toV1Json(typesDef));
assertEquals(typesCreated.size(), 1);
assertEquals(typesCreated.get(0), classTypeDef.getTypeName());
//Add attribute description
classTypeDef = TypesUtil.createClassTypeDef(classTypeDef.getTypeName(), null, "2.0",
Collections.<String>emptySet(),
TypesUtil.createUniqueRequiredAttrDef(NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING),
createOptionalAttrDef(DESCRIPTION, AtlasBaseTypeDef.ATLAS_TYPE_STRING));
TypesDef typeDef = new TypesDef(Collections.<EnumTypeDefinition>emptyList(), Collections.<StructTypeDefinition>emptyList(), Collections.<TraitTypeDefinition>emptyList(), Collections.singletonList(classTypeDef));
List<String> typesUpdated = atlasClientV1.updateType(typeDef);
assertEquals(typesUpdated.size(), 1);
Assert.assertTrue(typesUpdated.contains(classTypeDef.getTypeName()));
TypesDef updatedTypeDef = atlasClientV1.getType(classTypeDef.getTypeName());
assertNotNull(updatedTypeDef);
ClassTypeDefinition updatedType = updatedTypeDef.getClassTypes().get(0);
assertEquals(updatedType.getAttributeDefinitions().size(), 2);
}
@Test(dependsOnMethods = "testSubmit")
public void testGetDefinition() throws Exception {
for (HierarchicalTypeDefinition typeDefinition : typeDefinitions) {
System.out.println("typeName = " + typeDefinition.getTypeName());
ObjectNode response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API_V1.LIST_TYPES, null, typeDefinition.getTypeName());
Assert.assertNotNull(response);
Assert.assertNotNull(response.get(AtlasClient.DEFINITION));
Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
TypesDef typesDef = AtlasType.fromV1Json(response.get(AtlasClient.DEFINITION).asText(), TypesDef.class);
List<? extends HierarchicalTypeDefinition> hierarchicalTypeDefs = Collections.emptyList();
if (typeDefinition instanceof ClassTypeDefinition) {
hierarchicalTypeDefs = typesDef.getClassTypes();
} else if (typeDefinition instanceof TraitTypeDefinition) {
hierarchicalTypeDefs = typesDef.getTraitTypes();
}
for (HierarchicalTypeDefinition hierarchicalTypes : hierarchicalTypeDefs) {
for (AttributeDefinition attrDef : hierarchicalTypes.getAttributeDefinitions()) {
if (NAME.equals(attrDef.getName())) {
assertEquals(attrDef.getIsIndexable(), true);
assertEquals(attrDef.getIsUnique(), true);
}
}
}
}
}
@Test(expectedExceptions = AtlasServiceException.class)
public void testGetDefinitionForNonexistentType() throws Exception {
ObjectNode response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API_V1.LIST_TYPES, null, "blah");
}
@Test(dependsOnMethods = "testSubmit")
public void testGetTypeNames() throws Exception {
ObjectNode response = atlasClientV1.callAPIWithBodyAndParams(AtlasClient.API_V1.LIST_TYPES, null, (String[]) null);
Assert.assertNotNull(response);
Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
final ArrayNode list = (ArrayNode) response.get(AtlasClient.RESULTS);
Assert.assertNotNull(list);
//Verify that primitive and core types are not returned
String typesString = list.toString();
Assert.assertFalse(typesString.contains(" \"__IdType\" "));
Assert.assertFalse(typesString.contains(" \"string\" "));
}
@Test
public void testGetTraitNames() throws Exception {
String[] traitsAdded = addTraits();
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
queryParams.add("type", DataTypes.TypeCategory.TRAIT.name());
ObjectNode response = atlasClientV1.callAPIWithQueryParams(AtlasClient.API_V1.LIST_TYPES, queryParams);
Assert.assertNotNull(response);
Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
final ArrayNode list = (ArrayNode) response.get(AtlasClient.RESULTS);
Assert.assertNotNull(list);
Assert.assertTrue(list.size() >= traitsAdded.length);
}
@Test
public void testListTypesByFilter() throws Exception {
AttributeDefinition attr = TypesUtil.createOptionalAttrDef("attr", AtlasBaseTypeDef.ATLAS_TYPE_STRING);
ClassTypeDefinition classTypeDef = TypesUtil.createClassTypeDef("A" + randomString(), null, Collections.emptySet(), attr);
TypesDef typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef));
String a = createType(AtlasType.toV1Json(typesDef)).get(0);
classTypeDef = TypesUtil.createClassTypeDef("A1" + randomString(), null, Collections.singleton(a), attr);
typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef));
String a1 = createType(AtlasType.toV1Json(typesDef)).get(0);
classTypeDef = TypesUtil.createClassTypeDef("B" + randomString(), null, Collections.<String>emptySet(), attr);
typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef));
String b = createType(AtlasType.toV1Json(typesDef)).get(0);
classTypeDef = TypesUtil.createClassTypeDef("C" + randomString(), null, new HashSet<>(Arrays.asList(a, b)), attr);
typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef));
String c = createType(AtlasType.toV1Json(typesDef)).get(0);
List<String> results = atlasClientV1.listTypes(DataTypes.TypeCategory.CLASS, a, b);
assertEquals(results, Arrays.asList(a1), "Results: " + results);
}
private String[] addTraits() throws Exception {
String[] traitNames = {"class_trait", "secure_trait", "pii_trait", "ssn_trait", "salary_trait", "sox_trait",};
for (String traitName : traitNames) {
TraitTypeDefinition traitTypeDef =
TypesUtil.createTraitTypeDef(traitName, null, Collections.<String>emptySet());
TypesDef typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.singletonList(traitTypeDef), Collections.emptyList());
String json = AtlasType.toV1Json(typesDef);
createType(json);
}
return traitNames;
}
private List<HierarchicalTypeDefinition> createHiveTypes() throws Exception {
ArrayList<HierarchicalTypeDefinition> typeDefinitions = new ArrayList<>();
ClassTypeDefinition databaseTypeDefinition = TypesUtil
.createClassTypeDef("database", null, Collections.<String>emptySet(),
TypesUtil.createUniqueRequiredAttrDef(NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING),
TypesUtil.createRequiredAttrDef(DESCRIPTION, AtlasBaseTypeDef.ATLAS_TYPE_STRING),
TypesUtil.createRequiredAttrDef(QUALIFIED_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING));
typeDefinitions.add(databaseTypeDefinition);
ClassTypeDefinition tableTypeDefinition = TypesUtil
.createClassTypeDef("table", null, Collections.<String>emptySet(),
TypesUtil.createUniqueRequiredAttrDef(NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING),
TypesUtil.createRequiredAttrDef(DESCRIPTION, AtlasBaseTypeDef.ATLAS_TYPE_STRING),
TypesUtil.createRequiredAttrDef(QUALIFIED_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING),
createOptionalAttrDef("columnNames", AtlasBaseTypeDef.getArrayTypeName(AtlasBaseTypeDef.ATLAS_TYPE_STRING)),
createOptionalAttrDef("created", AtlasBaseTypeDef.ATLAS_TYPE_DATE),
createOptionalAttrDef("parameters",
AtlasBaseTypeDef.getMapTypeName(AtlasBaseTypeDef.ATLAS_TYPE_STRING, AtlasBaseTypeDef.ATLAS_TYPE_STRING)),
TypesUtil.createRequiredAttrDef("type", AtlasBaseTypeDef.ATLAS_TYPE_STRING),
new AttributeDefinition("database", "database", Multiplicity.REQUIRED, false, null));
typeDefinitions.add(tableTypeDefinition);
TraitTypeDefinition fetlTypeDefinition = TypesUtil
.createTraitTypeDef("fetl", null, Collections.<String>emptySet(),
TypesUtil.createRequiredAttrDef("level", AtlasBaseTypeDef.ATLAS_TYPE_INT));
typeDefinitions.add(fetlTypeDefinition);
return typeDefinitions;
}
}