use of co.cask.cdap.common.ConflictException in project cdap by caskdata.
the class AppLifecycleHttpHandler method updateApp.
/**
* Updates an existing application.
*/
@POST
@Path("/apps/{app-id}/update")
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void updateApp(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") final String namespaceId, @PathParam("app-id") final String appName) throws NotFoundException, BadRequestException, UnauthorizedException, IOException {
ApplicationId appId = validateApplicationId(namespaceId, appName);
AppRequest appRequest;
try (Reader reader = new InputStreamReader(new ChannelBufferInputStream(request.getContent()), Charsets.UTF_8)) {
appRequest = GSON.fromJson(reader, AppRequest.class);
} catch (IOException e) {
LOG.error("Error reading request to update app {} in namespace {}.", appName, namespaceId, e);
throw new IOException("Error reading request body.");
} catch (JsonSyntaxException e) {
throw new BadRequestException("Request body is invalid json: " + e.getMessage());
}
try {
applicationLifecycleService.updateApp(appId, appRequest, createProgramTerminator());
responder.sendString(HttpResponseStatus.OK, "Update complete.");
} catch (InvalidArtifactException e) {
throw new BadRequestException(e.getMessage());
} catch (ConflictException e) {
responder.sendString(HttpResponseStatus.CONFLICT, e.getMessage());
} catch (NotFoundException | UnauthorizedException e) {
throw e;
} catch (Exception e) {
// this is the same behavior as deploy app pipeline, but this is bad behavior. Error handling needs improvement.
LOG.error("Deploy failure", e);
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
}
}
use of co.cask.cdap.common.ConflictException in project cdap by caskdata.
the class TestFrameworkTestRun method testConcurrentRuns.
@Test
public void testConcurrentRuns() throws Exception {
ApplicationManager appManager = deployApplication(ConcurrentRunTestApp.class);
WorkerManager workerManager = appManager.getWorkerManager(ConcurrentRunTestApp.TestWorker.class.getSimpleName());
workerManager.start();
// Start another time should fail as worker doesn't support concurrent run.
try {
workerManager.start();
Assert.fail("Expected failure to start worker");
} catch (Exception e) {
Assert.assertTrue(Throwables.getRootCause(e) instanceof ConflictException);
}
workerManager.stop();
// Start the workflow
File tmpDir = TEMP_FOLDER.newFolder();
File actionFile = new File(tmpDir, "action.file");
Map<String, String> args = Collections.singletonMap("action.file", actionFile.getAbsolutePath());
WorkflowManager workflowManager = appManager.getWorkflowManager(ConcurrentRunTestApp.TestWorkflow.class.getSimpleName());
// Starts two runs, both should succeed
workflowManager.start(args);
workflowManager.start(args);
// Should get two active runs
workflowManager.waitForRuns(ProgramRunStatus.RUNNING, 2, 10L, TimeUnit.SECONDS);
// Touch the file to complete the workflow runs
Files.touch(actionFile);
workflowManager.waitForRuns(ProgramRunStatus.COMPLETED, 2, 10L, TimeUnit.SECONDS);
}
use of co.cask.cdap.common.ConflictException in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method startPrograms.
/**
* Starts all programs that are passed into the data. The data is an array of JSON objects
* where each object must contain the following three elements: appId, programType, and programId
* (flow name, service name, etc.). In additional, each object can contain an optional runtimeargs element,
* which is a map of arguments to start the program with.
* <p>
* Example input:
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1"},
* {"appId": "App1", "programType": "Mapreduce", "programId": "MapReduce2", "runtimeargs":{"arg1":"val1"}},
* {"appId": "App2", "programType": "Flow", "programId": "Flow1"}]
* </code></pre>
* </p><p>
* The response will be an array of JsonObjects each of which will contain the three input parameters
* as well as a "statusCode" field which maps to the status code for the data in that JsonObjects.
* </p><p>
* If an error occurs in the input (for the example above, App2 does not exist), then all JsonObjects for which the
* parameters have a valid status will have the status field but all JsonObjects for which the parameters do not have
* a valid status will have an error message and statusCode.
* </p><p>
* For example, if there is no App2 in the data above, then the response would be 200 OK with following possible data:
* </p>
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1", "statusCode": 200},
* {"appId": "App1", "programType": "Mapreduce", "programId": "Mapreduce2", "statusCode": 200},
* {"appId":"App2", "programType":"Flow", "programId":"Flow1", "statusCode":404, "error": "App: App2 not found"}]
* </code></pre>
*/
@POST
@Path("/start")
@AuditPolicy({ AuditDetail.REQUEST_BODY, AuditDetail.RESPONSE_BODY })
public void startPrograms(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
List<BatchProgramStart> programs = validateAndGetBatchInput(request, BATCH_STARTS_TYPE);
List<BatchProgramResult> output = new ArrayList<>(programs.size());
for (BatchProgramStart program : programs) {
ProgramId programId = new ProgramId(namespaceId, program.getAppId(), program.getProgramType(), program.getProgramId());
try {
ProgramController programController = lifecycleService.start(programId, program.getRuntimeargs(), false);
output.add(new BatchProgramResult(program, HttpResponseStatus.OK.getCode(), null, programController.getRunId().getId()));
} catch (NotFoundException e) {
output.add(new BatchProgramResult(program, HttpResponseStatus.NOT_FOUND.getCode(), e.getMessage()));
} catch (BadRequestException e) {
output.add(new BatchProgramResult(program, HttpResponseStatus.BAD_REQUEST.getCode(), e.getMessage()));
} catch (ConflictException e) {
output.add(new BatchProgramResult(program, HttpResponseStatus.CONFLICT.getCode(), e.getMessage()));
}
}
responder.sendJson(HttpResponseStatus.OK, output);
}
use of co.cask.cdap.common.ConflictException in project cdap by caskdata.
the class DatasetTypeService method deleteAll.
/**
* Deletes all {@link DatasetModuleMeta dataset modules} in the specified {@link NamespaceId namespace}.
*/
void deleteAll(NamespaceId namespaceId) throws Exception {
Principal principal = authenticationContext.getPrincipal();
authorizationEnforcer.enforce(namespaceId, principal, Action.ADMIN);
if (NamespaceId.SYSTEM.equals(namespaceId)) {
throw new UnauthorizedException(String.format("Cannot delete modules from '%s' namespace.", namespaceId));
}
ensureNamespaceExists(namespaceId);
// revoke all privileges on all modules
for (DatasetModuleMeta meta : typeManager.getModules(namespaceId)) {
privilegesManager.revoke(namespaceId.datasetModule(meta.getName()));
}
try {
typeManager.deleteModules(namespaceId);
} catch (DatasetModuleConflictException e) {
throw new ConflictException(e.getMessage(), e);
}
}
use of co.cask.cdap.common.ConflictException in project cdap by caskdata.
the class InMemoryDatasetOpExecutor method update.
@Override
public DatasetSpecification update(DatasetId datasetInstanceId, DatasetTypeMeta typeMeta, DatasetProperties props, DatasetSpecification existing) throws Exception {
DatasetType type = client.getDatasetType(typeMeta, null, new ConstantClassLoaderProvider());
if (type == null) {
throw new IllegalArgumentException("Dataset type cannot be instantiated for provided type meta: " + typeMeta);
}
try {
DatasetSpecification spec = type.reconfigure(datasetInstanceId.getEntityName(), props, existing);
DatasetAdmin admin = type.getAdmin(DatasetContext.from(datasetInstanceId.getNamespace()), spec);
if (admin instanceof Updatable) {
((Updatable) admin).update(existing);
} else {
admin.create();
}
if (spec.getDescription() == null && existing.getDescription() != null) {
spec.setDescription(existing.getDescription());
}
return spec;
} catch (IncompatibleUpdateException e) {
throw new ConflictException(e.getMessage());
}
}
Aggregations