use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactRepositoryTest method testGrandparentsAreInvalid.
@Test(expected = InvalidArtifactException.class)
public void testGrandparentsAreInvalid() throws Exception {
// create child artifact
Id.Artifact childId = Id.Artifact.from(Id.Namespace.DEFAULT, "child", "1.0.0");
Manifest manifest = createManifest(ManifestFields.EXPORT_PACKAGE, Plugin1.class.getPackage().getName());
File jarFile = createPluginJar(Plugin1.class, new File(tmpDir, "child-1.0.0.jar"), manifest);
// add the artifact
Set<ArtifactRange> parents = ImmutableSet.of(new ArtifactRange(APP_ARTIFACT_ID.getNamespace().getId(), APP_ARTIFACT_ID.getName(), new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
artifactRepository.addArtifact(childId, jarFile, parents);
// try and create grandchild, should throw exception
Id.Artifact grandchildId = Id.Artifact.from(Id.Namespace.DEFAULT, "grandchild", "1.0.0");
manifest = createManifest(ManifestFields.EXPORT_PACKAGE, Plugin2.class.getPackage().getName());
jarFile = createPluginJar(Plugin2.class, new File(tmpDir, "grandchild-1.0.0.jar"), manifest);
parents = ImmutableSet.of(new ArtifactRange(childId.getNamespace().getId(), childId.getName(), new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0")));
artifactRepository.addArtifact(grandchildId, jarFile, parents);
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactRangeTest method testIsInRange.
@Test
public void testIsInRange() {
ArtifactRange range = new ArtifactRange(NamespaceId.DEFAULT.getNamespace(), "test", new ArtifactVersion("1.0.0"), new ArtifactVersion("2.0.0"));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("0.0.9")));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("0.9.0")));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("0.9")));
// 1 < 1.0 < 1.0.0-SNAPSHOT < 1.0.0
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("1")));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("1.0")));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("1.0.0-SNAPSHOT")));
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("1.0.0")));
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("1.0.1-SNAPSHOT")));
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("1.0.1")));
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("1.1.0")));
// 2 < 2.0 < 2.0.0-SNAPSHOT < 2.0.0
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("2")));
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("2.0")));
Assert.assertTrue(range.versionIsInRange(new ArtifactVersion("2.0.0-SNAPSHOT")));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("2.0.0")));
Assert.assertFalse(range.versionIsInRange(new ArtifactVersion("2.0.1")));
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactHttpHandler method getArtifactVersions.
@GET
@Path("/namespaces/{namespace-id}/artifacts/{artifact-name}")
public void getArtifactVersions(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @PathParam("artifact-name") String artifactName, @QueryParam("scope") @DefaultValue("user") String scope, @QueryParam("artifactVersion") String versionRange, @QueryParam("limit") @DefaultValue("2147483647") String limit, @QueryParam("order") @DefaultValue("UNORDERED") String order) throws Exception {
NamespaceId namespace = validateAndGetScopedNamespace(Ids.namespace(namespaceId), scope);
ArtifactRange range = versionRange == null ? null : new ArtifactRange(namespaceId, artifactName, ArtifactVersionRange.parse(versionRange));
int limitNumber = Integer.valueOf(limit);
limitNumber = limitNumber <= 0 ? Integer.MAX_VALUE : limitNumber;
ArtifactSortOrder sortOrder = ArtifactSortOrder.valueOf(order);
try {
if (range == null) {
responder.sendJson(HttpResponseStatus.OK, artifactRepository.getArtifactSummaries(namespace, artifactName, limitNumber, sortOrder));
} else {
responder.sendJson(HttpResponseStatus.OK, artifactRepository.getArtifactSummaries(range, limitNumber, sortOrder));
}
} catch (IOException e) {
LOG.error("Exception reading artifacts named {} for namespace {} from the store.", artifactName, namespaceId, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error reading artifact metadata from the store.");
}
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactHttpHandler method addArtifact.
@POST
@Path("/namespaces/{namespace-id}/artifacts/{artifact-name}")
@AuditPolicy(AuditDetail.HEADERS)
public BodyConsumer addArtifact(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") final String namespaceId, @PathParam("artifact-name") final String artifactName, @HeaderParam(VERSION_HEADER) final String artifactVersion, @HeaderParam(EXTENDS_HEADER) final String parentArtifactsStr, @HeaderParam(PLUGINS_HEADER) String pluginClasses) throws NamespaceNotFoundException, BadRequestException {
final NamespaceId namespace = validateAndGetNamespace(namespaceId);
// and validated there
if (artifactVersion != null && !artifactVersion.isEmpty()) {
validateAndGetArtifactId(namespace, artifactName, artifactVersion);
}
final Set<ArtifactRange> parentArtifacts = parseExtendsHeader(namespace, parentArtifactsStr);
final Set<PluginClass> additionalPluginClasses;
if (pluginClasses == null) {
additionalPluginClasses = ImmutableSet.of();
} else {
try {
additionalPluginClasses = GSON.fromJson(pluginClasses, PLUGINS_TYPE);
} catch (JsonParseException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, String.format("%s header '%s' is invalid: %s", PLUGINS_HEADER, pluginClasses, e.getMessage()));
return null;
}
}
try {
// copy the artifact contents to local tmp directory
final File destination = File.createTempFile("artifact-", ".jar", tmpDir);
return new AbstractBodyConsumer(destination) {
@Override
protected void onFinish(HttpResponder responder, File uploadedFile) {
try {
String version = (artifactVersion == null || artifactVersion.isEmpty()) ? getBundleVersion(uploadedFile) : artifactVersion;
Id.Artifact artifactId = validateAndGetArtifactId(namespace, artifactName, version);
// add the artifact to the repo
artifactRepository.addArtifact(artifactId, uploadedFile, parentArtifacts, additionalPluginClasses);
responder.sendString(HttpResponseStatus.OK, "Artifact added successfully");
} catch (ArtifactRangeNotFoundException e) {
responder.sendString(HttpResponseStatus.NOT_FOUND, e.getMessage());
} catch (ArtifactAlreadyExistsException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (WriteConflictException e) {
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Conflict while writing artifact, please try again.");
} catch (IOException e) {
LOG.error("Exception while trying to write artifact {}-{}-{}.", namespaceId, artifactName, artifactVersion, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error performing IO while writing artifact.");
} catch (BadRequestException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
} catch (UnauthorizedException e) {
responder.sendString(HttpResponseStatus.FORBIDDEN, e.getMessage());
} catch (Exception e) {
LOG.error("Error while writing artifact {}-{}-{}", namespaceId, artifactName, artifactVersion, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Error while adding artifact.");
}
}
private String getBundleVersion(File file) throws BadRequestException, IOException {
try (JarFile jarFile = new JarFile(file)) {
Manifest manifest = jarFile.getManifest();
if (manifest == null) {
throw new BadRequestException("Unable to derive version from artifact because it does not contain a manifest. " + "Please package the jar with a manifest, or explicitly specify the artifact version.");
}
Attributes attributes = manifest.getMainAttributes();
String version = attributes == null ? null : attributes.getValue(ManifestFields.BUNDLE_VERSION);
if (version == null) {
throw new BadRequestException("Unable to derive version from artifact because manifest does not contain Bundle-Version attribute. " + "Please include Bundle-Version in the manifest, or explicitly specify the artifact version.");
}
return version;
} catch (ZipException e) {
throw new BadRequestException("Artifact is not in zip format. Please make sure it is a jar file.");
}
}
};
} catch (IOException e) {
LOG.error("Exception creating temp file to place artifact {} contents", artifactName, e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Server error creating temp file for artifact.");
return null;
}
}
use of co.cask.cdap.api.artifact.ArtifactRange in project cdap by caskdata.
the class ArtifactHttpHandlerTest method testSystemArtifactIsolation.
/**
* Tests that system artifacts can be accessed in a user namespace only if appropriately scoped.
*
* @throws Exception
*/
@Test
public void testSystemArtifactIsolation() throws Exception {
// add the app in the default namespace
File systemArtifact = buildAppArtifact(WordCountApp.class, "wordcount-1.0.0.jar");
Id.Artifact defaultId = Id.Artifact.from(Id.Namespace.DEFAULT, "wordcount", "1.0.0");
// add a system artifact. currently can't do this through the rest api (by design)
// so bypass it and use the repository directly
Id.Artifact systemId = Id.Artifact.from(Id.Namespace.SYSTEM, "wordcount", "1.0.0");
artifactRepository.addArtifact(systemId, systemArtifact, new HashSet<ArtifactRange>());
// test get /artifacts
Set<ArtifactSummary> expectedArtifacts = Sets.newHashSet(new ArtifactSummary("wordcount", "1.0.0", ArtifactScope.SYSTEM));
Set<ArtifactSummary> actualArtifacts = getArtifacts(Id.Namespace.DEFAULT);
Assert.assertEquals(expectedArtifacts, actualArtifacts);
// test get /artifacts?scope=system
expectedArtifacts = Sets.newHashSet(new ArtifactSummary("wordcount", "1.0.0", ArtifactScope.SYSTEM));
actualArtifacts = getArtifacts(Id.Namespace.DEFAULT, ArtifactScope.SYSTEM);
Assert.assertEquals(expectedArtifacts, actualArtifacts);
// test get /artifacts?scope=user
expectedArtifacts = Sets.newHashSet();
actualArtifacts = getArtifacts(Id.Namespace.DEFAULT, ArtifactScope.USER);
Assert.assertEquals(expectedArtifacts, actualArtifacts);
// test get /artifacts/wordcount?scope=user
expectedArtifacts = null;
actualArtifacts = getArtifacts(Id.Namespace.DEFAULT, "wordcount", ArtifactScope.USER);
Assert.assertEquals(expectedArtifacts, actualArtifacts);
// test get /artifacts/wordcount?scope=system
expectedArtifacts = Sets.newHashSet(new ArtifactSummary("wordcount", "1.0.0", ArtifactScope.SYSTEM));
actualArtifacts = getArtifacts(Id.Namespace.DEFAULT, "wordcount", ArtifactScope.SYSTEM);
Assert.assertEquals(expectedArtifacts, actualArtifacts);
// test get /artifacts/wordcount/versions/1.0.0?scope=user
ArtifactInfo actualInfo = getArtifact(defaultId, ArtifactScope.USER);
Assert.assertEquals(null, actualInfo);
// test get /artifacts/wordcount/versions/1.0.0?scope=system
actualInfo = getArtifact(defaultId, ArtifactScope.SYSTEM);
Assert.assertEquals("wordcount", actualInfo.getName());
Assert.assertEquals("1.0.0", actualInfo.getVersion());
// test delete /default/artifacts/wordcount/versions/1.0.0
deleteArtifact(defaultId, 404);
// test delete /system/artifacts/wordcount/versions/1.0.0
deleteArtifact(systemId, 200);
}
Aggregations