use of io.cdap.cdap.api.artifact.ArtifactSummary in project cdap by cdapio.
the class UpdateAppCommand method perform.
@Override
public void perform(Arguments arguments, PrintStream output) throws Exception {
String appName = arguments.get(ArgumentName.APP.toString());
ApplicationId appId = cliConfig.getCurrentNamespace().app(appName);
String artifactName = arguments.get(ArgumentName.ARTIFACT_NAME.toString());
String artifactVersion = arguments.get(ArgumentName.ARTIFACT_VERSION.toString());
ArtifactScope artifactScope = ArtifactScope.valueOf(arguments.get(ArgumentName.SCOPE.toString()).toUpperCase());
ArtifactSummary artifact = new ArtifactSummary(artifactName, artifactVersion, artifactScope);
JsonObject config = new JsonObject();
String configPath = arguments.getOptional(ArgumentName.APP_CONFIG_FILE.toString());
if (configPath != null) {
File configFile = resolver.resolvePathToFile(configPath);
try (FileReader reader = new FileReader(configFile)) {
AppRequest<JsonObject> appRequest = GSON.fromJson(reader, CONFIG_TYPE);
config = appRequest.getConfig();
}
}
AppRequest<JsonObject> appRequest = new AppRequest<>(artifact, config);
applicationClient.update(appId, appRequest);
output.println("Successfully updated application");
}
use of io.cdap.cdap.api.artifact.ArtifactSummary in project cdap by cdapio.
the class DefaultPreviewRunner method startPreview.
@Override
public Future<PreviewRequest> startPreview(PreviewRequest previewRequest) throws Exception {
ProgramId programId = previewRequest.getProgram();
long submitTimeMillis = RunIds.getTime(programId.getApplication(), TimeUnit.MILLISECONDS);
previewStarted(programId);
AppRequest<?> request = previewRequest.getAppRequest();
if (request == null) {
// This shouldn't happen
throw new IllegalStateException("Preview request shouldn't have an empty application request");
}
ArtifactSummary artifactSummary = request.getArtifact();
ApplicationId preview = programId.getParent();
try {
namespaceAdmin.create(new NamespaceMeta.Builder().setName(programId.getNamespaceId()).build());
} catch (NamespaceAlreadyExistsException e) {
LOG.debug("Namespace {} already exists.", programId.getNamespaceId());
}
DataTracerFactoryProvider.setDataTracerFactory(preview, dataTracerFactory);
String config = request.getConfig() == null ? null : GSON.toJson(request.getConfig());
PreviewConfig previewConfig = previewRequest.getAppRequest().getPreview();
PreferencesDetail preferences = preferencesFetcher.get(programId, true);
Map<String, String> userProps = new HashMap<>(preferences.getProperties());
if (previewConfig != null) {
userProps.putAll(previewConfig.getRuntimeArgs());
}
try {
LOG.debug("Deploying preview application for {}", programId);
applicationLifecycleService.deployApp(preview.getParent(), preview.getApplication(), preview.getVersion(), artifactSummary, config, NOOP_PROGRAM_TERMINATOR, null, request.canUpdateSchedules(), true, userProps);
} catch (Exception e) {
PreviewStatus previewStatus = new PreviewStatus(PreviewStatus.Status.DEPLOY_FAILED, submitTimeMillis, new BasicThrowable(e), null, null);
previewTerminated(programId, previewStatus);
throw e;
}
LOG.debug("Starting preview for {}", programId);
ProgramController controller = programLifecycleService.start(programId, userProps, false, true);
long startTimeMillis = System.currentTimeMillis();
AtomicBoolean timeout = new AtomicBoolean();
CompletableFuture<PreviewRequest> resultFuture = new CompletableFuture<>();
controller.addListener(new AbstractListener() {
@Override
public void init(ProgramController.State currentState, @Nullable Throwable cause) {
switch(currentState) {
case STARTING:
case ALIVE:
case STOPPING:
setStatus(programId, new PreviewStatus(PreviewStatus.Status.RUNNING, submitTimeMillis, null, startTimeMillis, null));
break;
case COMPLETED:
terminated(PreviewStatus.Status.COMPLETED, null);
break;
case KILLED:
terminated(PreviewStatus.Status.KILLED, null);
break;
case ERROR:
terminated(PreviewStatus.Status.RUN_FAILED, cause);
break;
}
}
@Override
public void completed() {
terminated(PreviewStatus.Status.COMPLETED, null);
}
@Override
public void killed() {
terminated(timeout.get() ? PreviewStatus.Status.KILLED_BY_TIMER : PreviewStatus.Status.KILLED, null);
}
@Override
public void error(Throwable cause) {
terminated(PreviewStatus.Status.RUN_FAILED, cause);
}
/**
* Handle termination of program run.
*
* @param status the termination status
* @param failureCause if the program was terminated due to error, this carries the failure cause
*/
private void terminated(PreviewStatus.Status status, @Nullable Throwable failureCause) {
PreviewStatus previewStatus = new PreviewStatus(status, submitTimeMillis, failureCause == null ? null : new BasicThrowable(failureCause), startTimeMillis, System.currentTimeMillis());
previewTerminated(programId, previewStatus);
if (failureCause == null) {
resultFuture.complete(previewRequest);
} else {
resultFuture.completeExceptionally(failureCause);
}
}
}, Threads.SAME_THREAD_EXECUTOR);
trackPreviewTimeout(previewRequest, timeout, resultFuture);
PreviewMessage message = new PreviewMessage(PreviewMessage.Type.PROGRAM_RUN_ID, programId.getParent(), GSON.toJsonTree(controller.getProgramRunId()));
previewDataPublisher.publish(programId.getParent(), message);
return resultFuture;
}
use of io.cdap.cdap.api.artifact.ArtifactSummary in project cdap by cdapio.
the class ApplicationLifecycleService method updateApp.
/**
* Update an existing application. An application's configuration and artifact version can be updated.
*
* @param appId the id of the application to update
* @param appRequest the request to update the application, including new config and artifact
* @param programTerminator a program terminator that will stop programs that are removed when updating an app.
* For example, if an update removes a flow, the terminator defines how to stop that flow.
* @return information about the deployed application
* @throws ApplicationNotFoundException if the specified application does not exist
* @throws ArtifactNotFoundException if the requested artifact does not exist
* @throws InvalidArtifactException if the specified artifact is invalid. For example, if the artifact name changed,
* if the version is an invalid version, or the artifact contains no app classes
* @throws Exception if there was an exception during the deployment pipeline. This exception will often wrap
* the actual exception
*/
public ApplicationWithPrograms updateApp(ApplicationId appId, AppRequest appRequest, ProgramTerminator programTerminator) throws Exception {
// Check if the current user has admin privileges on it before updating.
accessEnforcer.enforce(appId, authenticationContext.getPrincipal(), StandardPermission.UPDATE);
// check that app exists
ApplicationSpecification currentSpec = store.getApplication(appId);
if (currentSpec == null) {
throw new ApplicationNotFoundException(appId);
}
ArtifactId currentArtifact = currentSpec.getArtifactId();
// if no artifact is given, use the current one.
ArtifactId newArtifactId = currentArtifact;
// otherwise, check requested artifact is valid and use it
ArtifactSummary requestedArtifact = appRequest.getArtifact();
if (requestedArtifact != null) {
// cannot change artifact name, only artifact version.
if (!currentArtifact.getName().equals(requestedArtifact.getName())) {
throw new InvalidArtifactException(String.format(" Only artifact version updates are allowed. Cannot change from artifact '%s' to '%s'.", currentArtifact.getName(), requestedArtifact.getName()));
}
if (!currentArtifact.getScope().equals(requestedArtifact.getScope())) {
throw new InvalidArtifactException("Only artifact version updates are allowed. " + "Cannot change from a non-system artifact to a system artifact or vice versa.");
}
// check requested artifact version is valid
ArtifactVersion requestedVersion = new ArtifactVersion(requestedArtifact.getVersion());
if (requestedVersion.getVersion() == null) {
throw new InvalidArtifactException(String.format("Requested artifact version '%s' is invalid", requestedArtifact.getVersion()));
}
newArtifactId = new ArtifactId(currentArtifact.getName(), requestedVersion, currentArtifact.getScope());
}
// ownerAdmin.getImpersonationPrincipal will give the owner which will be impersonated for the application
// irrespective of the version
SecurityUtil.verifyOwnerPrincipal(appId, appRequest.getOwnerPrincipal(), ownerAdmin);
Object requestedConfigObj = appRequest.getConfig();
// if config is null, use the previous config. Shouldn't use a static GSON since the request Config object can
// be a user class, otherwise there will be ClassLoader leakage.
String requestedConfigStr = requestedConfigObj == null ? currentSpec.getConfiguration() : new Gson().toJson(requestedConfigObj);
Id.Artifact artifactId = Id.Artifact.fromEntityId(Artifacts.toProtoArtifactId(appId.getParent(), newArtifactId));
return deployApp(appId.getParent(), appId.getApplication(), null, artifactId, requestedConfigStr, programTerminator, ownerAdmin.getOwner(appId), appRequest.canUpdateSchedules());
}
use of io.cdap.cdap.api.artifact.ArtifactSummary in project cdap by cdapio.
the class ApplicationLifecycleService method upgradeApplication.
/**
* Upgrades an existing application by upgrading application artifact versions and plugin artifact versions.
*
* @param appId the id of the application to upgrade.
* @param allowedArtifactScopes artifact scopes allowed while looking for latest artifacts for upgrade.
* @param allowSnapshot whether to consider snapshot version of artifacts or not for upgrade.
* @throws IllegalStateException if something unexpected happened during upgrade.
* @throws IOException if there was an IO error during initializing application class from artifact.
* @throws JsonIOException if there was an error in serializing or deserializing app config.
* @throws UnsupportedOperationException if application does not support upgrade operation.
* @throws InvalidArtifactException if candidate application artifact is invalid for upgrade purpose.
* @throws NotFoundException if any object related to upgrade is not found like application/artifact.
* @throws Exception if there was an exception during the upgrade of application. This exception will often wrap
* the actual exception
*/
public void upgradeApplication(ApplicationId appId, Set<ArtifactScope> allowedArtifactScopes, boolean allowSnapshot) throws Exception {
// Check if the current user has admin privileges on it before updating.
accessEnforcer.enforce(appId, authenticationContext.getPrincipal(), StandardPermission.UPDATE);
// check that app exists
ApplicationSpecification currentSpec = store.getApplication(appId);
if (currentSpec == null) {
LOG.info("Application {} not found for upgrade.", appId);
throw new NotFoundException(appId);
}
ArtifactId currentArtifact = currentSpec.getArtifactId();
ArtifactSummary candidateArtifact = getLatestAppArtifactForUpgrade(appId, currentArtifact, allowedArtifactScopes, allowSnapshot);
ArtifactVersion candidateArtifactVersion = new ArtifactVersion(candidateArtifact.getVersion());
// Current artifact should not have higher version than candidate artifact.
if (currentArtifact.getVersion().compareTo(candidateArtifactVersion) > 0) {
String error = String.format("The current artifact has a version higher %s than any existing artifact.", currentArtifact.getVersion());
throw new InvalidArtifactException(error);
}
ArtifactId newArtifactId = new ArtifactId(candidateArtifact.getName(), candidateArtifactVersion, candidateArtifact.getScope());
Id.Artifact newArtifact = Id.Artifact.fromEntityId(Artifacts.toProtoArtifactId(appId.getParent(), newArtifactId));
ArtifactDetail newArtifactDetail = artifactRepository.getArtifact(newArtifact);
updateApplicationInternal(appId, currentSpec.getConfiguration(), programId -> {
}, newArtifactDetail, Collections.singletonList(ApplicationConfigUpdateAction.UPGRADE_ARTIFACT), allowedArtifactScopes, allowSnapshot, ownerAdmin.getOwner(appId), false);
}
use of io.cdap.cdap.api.artifact.ArtifactSummary in project cdap by cdapio.
the class SystemArtifactsAuthorizationTest method testAuthorizationForSystemArtifacts.
@Test
public void testAuthorizationForSystemArtifacts() throws Exception {
artifactRepository.addSystemArtifacts();
// alice should not be able to refresh system artifacts because she does not have admin privileges on namespace
// system
SecurityRequestContext.setUserId(ALICE.getName());
try {
artifactRepository.addSystemArtifacts();
Assert.fail("Adding system artifacts should have failed because alice does not have admin privileges on " + "the namespace system.");
} catch (UnauthorizedException expected) {
// expected
}
// grant alice admin privileges on the CDAP system namespace
Authorizable authorizable = Authorizable.fromEntityId(NamespaceId.SYSTEM, EntityType.ARTIFACT);
accessController.grant(authorizable, ALICE, Collections.singleton(StandardPermission.CREATE));
Assert.assertEquals(Collections.singleton(new GrantedPermission(authorizable, StandardPermission.CREATE)), accessController.listGrants(ALICE));
// refreshing system artifacts should succeed now
artifactRepository.addSystemArtifacts();
SecurityRequestContext.setUserId("bob");
// deleting a system artifact should fail because bob does not have admin privileges on the artifact
try {
artifactRepository.deleteArtifact(Id.Artifact.fromEntityId(SYSTEM_ARTIFACT));
Assert.fail("Deleting a system artifact should have failed because alice does not have admin privileges on " + "the artifact.");
} catch (UnauthorizedException expected) {
// expected
}
// grant alice admin privileges on test namespace
SecurityRequestContext.setUserId(ALICE.getName());
NamespaceId namespaceId = new NamespaceId("test");
accessController.grant(Authorizable.fromEntityId(namespaceId), ALICE, EnumSet.allOf(StandardPermission.class));
accessController.grant(Authorizable.fromEntityId(namespaceId, EntityType.ARTIFACT), ALICE, EnumSet.of(StandardPermission.LIST));
namespaceAdmin.create(new NamespaceMeta.Builder().setName(namespaceId.getNamespace()).build());
// test that system artifacts are available to everyone
List<ArtifactSummary> artifacts = artifactRepository.getArtifactSummaries(namespaceId, true);
Assert.assertEquals(1, artifacts.size());
ArtifactSummary artifactSummary = artifacts.get(0);
Assert.assertEquals(SYSTEM_ARTIFACT.getArtifact(), artifactSummary.getName());
Assert.assertEquals(SYSTEM_ARTIFACT.getVersion(), artifactSummary.getVersion());
Assert.assertEquals(SYSTEM_ARTIFACT.getNamespace(), artifactSummary.getScope().name().toLowerCase());
// test the getArtifact API
ArtifactDetail artifactDetail = artifactRepository.getArtifact(Id.Artifact.fromEntityId(SYSTEM_ARTIFACT));
io.cdap.cdap.api.artifact.ArtifactId artifactId = artifactDetail.getDescriptor().getArtifactId();
Assert.assertEquals(SYSTEM_ARTIFACT.getArtifact(), artifactId.getName());
Assert.assertEquals(SYSTEM_ARTIFACT.getVersion(), artifactId.getVersion().getVersion());
Assert.assertEquals(SYSTEM_ARTIFACT.getNamespace(), artifactId.getScope().name().toLowerCase());
namespaceAdmin.delete(namespaceId);
// enforce on the system artifact should fail in unit test, since we do not have auto-grant now
try {
accessController.enforce(SYSTEM_ARTIFACT, ALICE, EnumSet.allOf(StandardPermission.class));
Assert.fail();
} catch (UnauthorizedException e) {
// expected
}
try {
artifactRepository.deleteArtifact(Id.Artifact.fromEntityId(SYSTEM_ARTIFACT));
Assert.fail();
} catch (UnauthorizedException e) {
// expected
}
// deleting system artifact should succeed if alice has DELETE on the artifact
accessController.grant(Authorizable.fromEntityId(SYSTEM_ARTIFACT), ALICE, EnumSet.of(StandardPermission.DELETE));
artifactRepository.deleteArtifact(Id.Artifact.fromEntityId(SYSTEM_ARTIFACT));
// clean up privilege
accessController.revoke(Authorizable.fromEntityId(SYSTEM_ARTIFACT));
accessController.revoke(Authorizable.fromEntityId(NamespaceId.SYSTEM, EntityType.ARTIFACT));
accessController.revoke(Authorizable.fromEntityId(namespaceId, EntityType.ARTIFACT));
accessController.revoke(Authorizable.fromEntityId(namespaceId));
}
Aggregations