use of io.cdap.cdap.app.program.Program in project cdap by caskdata.
the class DefaultRuntimeJob method run.
@Override
public void run(RuntimeJobEnvironment runtimeJobEnv) throws Exception {
// Setup process wide settings
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
// Get Program Options
ProgramOptions programOpts = readJsonFile(new File(DistributedProgramRunner.PROGRAM_OPTIONS_FILE_NAME), ProgramOptions.class);
ProgramRunId programRunId = programOpts.getProgramId().run(ProgramRunners.getRunId(programOpts));
ProgramId programId = programRunId.getParent();
Arguments systemArgs = programOpts.getArguments();
// Setup logging context for the program
LoggingContextAccessor.setLoggingContext(LoggingContextHelper.getLoggingContextWithRunId(programRunId, systemArgs.asMap()));
// Get the cluster launch type
Cluster cluster = GSON.fromJson(systemArgs.getOption(ProgramOptionConstants.CLUSTER), Cluster.class);
// Get App spec
ApplicationSpecification appSpec = readJsonFile(new File(DistributedProgramRunner.APP_SPEC_FILE_NAME), ApplicationSpecification.class);
ProgramDescriptor programDescriptor = new ProgramDescriptor(programId, appSpec);
// Create injector and get program runner
Injector injector = Guice.createInjector(createModules(runtimeJobEnv, createCConf(runtimeJobEnv, programOpts), programRunId, programOpts));
CConfiguration cConf = injector.getInstance(CConfiguration.class);
// Initialize log appender
LogAppenderInitializer logAppenderInitializer = injector.getInstance(LogAppenderInitializer.class);
logAppenderInitializer.initialize();
SystemArguments.setLogLevel(programOpts.getUserArguments(), logAppenderInitializer);
ProxySelector oldProxySelector = ProxySelector.getDefault();
RuntimeMonitors.setupMonitoring(injector, programOpts);
Deque<Service> coreServices = createCoreServices(injector, systemArgs, cluster);
startCoreServices(coreServices);
// regenerate app spec
ConfiguratorFactory configuratorFactory = injector.getInstance(ConfiguratorFactory.class);
try {
Map<String, String> systemArguments = new HashMap<>(programOpts.getArguments().asMap());
File pluginDir = new File(programOpts.getArguments().getOption(ProgramOptionConstants.PLUGIN_DIR, DistributedProgramRunner.PLUGIN_DIR));
// create a directory to store plugin artifacts for the regeneration of app spec to fetch plugin artifacts
DirUtils.mkdirs(pluginDir);
if (!programOpts.getArguments().hasOption(ProgramOptionConstants.PLUGIN_DIR)) {
systemArguments.put(ProgramOptionConstants.PLUGIN_DIR, DistributedProgramRunner.PLUGIN_DIR);
}
// remember the file names in the artifact folder before app regeneration
List<String> pluginFiles = DirUtils.listFiles(pluginDir, File::isFile).stream().map(File::getName).collect(Collectors.toList());
ApplicationSpecification generatedAppSpec = regenerateAppSpec(systemArguments, programOpts.getUserArguments().asMap(), programId, appSpec, programDescriptor, configuratorFactory);
appSpec = generatedAppSpec != null ? generatedAppSpec : appSpec;
programDescriptor = new ProgramDescriptor(programDescriptor.getProgramId(), appSpec);
List<String> pluginFilesAfter = DirUtils.listFiles(pluginDir, File::isFile).stream().map(File::getName).collect(Collectors.toList());
if (pluginFilesAfter.isEmpty()) {
systemArguments.remove(ProgramOptionConstants.PLUGIN_DIR);
}
// recreate it from the folders
if (!pluginFiles.equals(pluginFilesAfter)) {
systemArguments.remove(ProgramOptionConstants.PLUGIN_ARCHIVE);
}
// update program options
programOpts = new SimpleProgramOptions(programOpts.getProgramId(), new BasicArguments(systemArguments), programOpts.getUserArguments(), programOpts.isDebug());
} catch (Exception e) {
LOG.warn("Failed to regenerate the app spec for program {}, using the existing app spec", programId, e);
}
ProgramStateWriter programStateWriter = injector.getInstance(ProgramStateWriter.class);
CompletableFuture<ProgramController.State> programCompletion = new CompletableFuture<>();
try {
ProgramRunner programRunner = injector.getInstance(ProgramRunnerFactory.class).create(programId.getType());
// Create and run the program. The program files should be present in current working directory.
try (Program program = createProgram(cConf, programRunner, programDescriptor, programOpts)) {
ProgramController controller = programRunner.run(program, programOpts);
controllerFuture.complete(controller);
runtimeClientService.onProgramStopRequested(controller::stop);
controller.addListener(new AbstractListener() {
@Override
public void completed() {
programCompletion.complete(ProgramController.State.COMPLETED);
}
@Override
public void killed() {
// Write an extra state to make sure there is always a terminal state even
// if the program application run failed to write out the state.
programStateWriter.killed(programRunId);
programCompletion.complete(ProgramController.State.KILLED);
}
@Override
public void error(Throwable cause) {
// Write an extra state to make sure there is always a terminal state even
// if the program application run failed to write out the state.
programStateWriter.error(programRunId, cause);
programCompletion.completeExceptionally(cause);
}
}, Threads.SAME_THREAD_EXECUTOR);
if (stopRequested) {
controller.stop();
}
// Block on the completion
programCompletion.get();
} finally {
if (programRunner instanceof Closeable) {
Closeables.closeQuietly((Closeable) programRunner);
}
}
} catch (Throwable t) {
controllerFuture.completeExceptionally(t);
if (!programCompletion.isDone()) {
// We log here so that the logs would still send back to the program logs collection.
// Only log if the program completion is not done.
// Otherwise the program runner itself should have logged the error.
LOG.error("Failed to execute program {}", programRunId, t);
// If the program completion is not done, then this exception
// is due to systematic failure in which fail to run the program.
// We write out an extra error state for the program to make sure the program state get transited.
programStateWriter.error(programRunId, t);
}
throw t;
} finally {
stopCoreServices(coreServices, logAppenderInitializer);
ProxySelector.setDefault(oldProxySelector);
Authenticator.setDefault(null);
runCompletedLatch.countDown();
}
}
use of io.cdap.cdap.app.program.Program in project cdap by caskdata.
the class DistributedWorkflowProgramRunner method setupLaunchConfig.
@Override
protected void setupLaunchConfig(ProgramLaunchConfig launchConfig, Program program, ProgramOptions options, CConfiguration cConf, Configuration hConf, File tempDir) throws IOException {
WorkflowSpecification spec = program.getApplicationSpecification().getWorkflows().get(program.getName());
List<ClassAcceptor> acceptors = new ArrayList<>();
acceptors.add(launchConfig.getClassAcceptor());
// Only interested in MapReduce and Spark nodes.
// This is because CUSTOM_ACTION types are running inside the driver
Set<SchedulableProgramType> runnerTypes = EnumSet.of(SchedulableProgramType.MAPREDUCE, SchedulableProgramType.SPARK);
Iterable<ScheduleProgramInfo> programInfos = spec.getNodeIdMap().values().stream().filter(WorkflowActionNode.class::isInstance).map(WorkflowActionNode.class::cast).map(WorkflowActionNode::getProgram).filter(programInfo -> runnerTypes.contains(programInfo.getProgramType()))::iterator;
// Can't use Stream.forEach as we want to preserve the IOException being thrown
for (ScheduleProgramInfo programInfo : programInfos) {
ProgramType programType = ProgramType.valueOfSchedulableType(programInfo.getProgramType());
ProgramRunner runner = programRunnerFactory.create(programType);
try {
if (runner instanceof DistributedProgramRunner) {
// Call setupLaunchConfig with the corresponding program.
// Need to constructs a new ProgramOptions with the scope extracted for the given program
ProgramId programId = program.getId().getParent().program(programType, programInfo.getProgramName());
Map<String, String> programUserArgs = RuntimeArguments.extractScope(programId.getType().getScope(), programId.getProgram(), options.getUserArguments().asMap());
ProgramOptions programOptions = new SimpleProgramOptions(programId, options.getArguments(), new BasicArguments(programUserArgs));
((DistributedProgramRunner) runner).setupLaunchConfig(launchConfig, Programs.create(cConf, program, programId, runner), programOptions, cConf, hConf, tempDir);
acceptors.add(launchConfig.getClassAcceptor());
}
} finally {
if (runner instanceof Closeable) {
Closeables.closeQuietly((Closeable) runner);
}
}
}
// Set the class acceptor
launchConfig.setClassAcceptor(new AndClassAcceptor(acceptors));
// Find out the default resources requirements based on the programs inside the workflow
// At least gives the Workflow driver 768 mb of container memory
Map<String, Resources> runnablesResources = Maps.transformValues(launchConfig.getRunnables(), this::getResources);
Resources defaultResources = maxResources(new Resources(768), findDriverResources(spec.getNodes(), runnablesResources));
// Clear and set the runnable for the workflow driver.
launchConfig.clearRunnables();
// Extract scoped runtime arguments that only meant for the workflow but not for child nodes
Map<String, String> runtimeArgs = RuntimeArguments.extractScope("task", "workflow", options.getUserArguments().asMap());
launchConfig.addRunnable(spec.getName(), new WorkflowTwillRunnable(spec.getName()), 1, runtimeArgs, defaultResources, 0);
}
use of io.cdap.cdap.app.program.Program in project cdap by caskdata.
the class AbstractProgramRuntimeServiceTest method testScopingRuntimeArguments.
@Test
public void testScopingRuntimeArguments() throws Exception {
Map<ProgramId, Arguments> argumentsMap = new ConcurrentHashMap<>();
ProgramRunnerFactory runnerFactory = createProgramRunnerFactory(argumentsMap);
final Program program = createDummyProgram();
TestProgramRunDispatcher launchDispatcher = new TestProgramRunDispatcher(cConf, runnerFactory, program, null, null);
ProgramRunDispatcherFactory factory = new ProgramRunDispatcherFactory(cConf, launchDispatcher);
final ProgramRuntimeService runtimeService = new AbstractProgramRuntimeService(cConf, runnerFactory, new NoOpProgramStateWriter(), factory, false) {
@Override
public ProgramLiveInfo getLiveInfo(ProgramId programId) {
return new ProgramLiveInfo(programId, "runtime") {
};
}
};
runtimeService.startAndWait();
try {
try {
ProgramDescriptor descriptor = new ProgramDescriptor(program.getId(), null, NamespaceId.DEFAULT.artifact("test", "1.0"));
// Set of scopes to test
String programScope = program.getType().getScope();
String clusterName = "c1";
List<String> scopes = Arrays.asList("cluster.*.", "cluster." + clusterName + ".", "cluster." + clusterName + ".app.*.", "app.*.", "app." + program.getApplicationId() + ".", "app." + program.getApplicationId() + "." + programScope + ".*.", "app." + program.getApplicationId() + "." + programScope + "." + program.getName() + ".", programScope + ".*.", programScope + "." + program.getName() + ".", "");
for (String scope : scopes) {
ProgramOptions programOptions = new SimpleProgramOptions(program.getId(), new BasicArguments(Collections.singletonMap(Constants.CLUSTER_NAME, clusterName)), new BasicArguments(Collections.singletonMap(scope + "size", Integer.toString(scope.length()))));
final ProgramController controller = runtimeService.run(descriptor, programOptions, RunIds.generate()).getController();
Tasks.waitFor(ProgramController.State.COMPLETED, controller::getState, 5, TimeUnit.SECONDS, 100, TimeUnit.MILLISECONDS);
// Should get an argument
Arguments args = argumentsMap.get(program.getId());
Assert.assertNotNull(args);
Assert.assertEquals(scope.length(), Integer.parseInt(args.getOption("size")));
}
} finally {
runtimeService.stopAndWait();
}
} finally {
runtimeService.stopAndWait();
}
}
use of io.cdap.cdap.app.program.Program in project cdap by caskdata.
the class AbstractProgramRuntimeServiceTest method testTetheredRun.
@Test(timeout = 5000)
public void testTetheredRun() throws IOException, ExecutionException, InterruptedException, TimeoutException {
ProgramRunnerFactory runnerFactory = createProgramRunnerFactory();
Program program = createDummyProgram();
InMemoryDiscoveryService discoveryService = new InMemoryDiscoveryService();
RemoteClientFactory remoteClientFactory = new RemoteClientFactory(discoveryService, new DefaultInternalAuthenticator(new AuthenticationTestContext()));
LocationFactory locationFactory = new LocalLocationFactory(TEMP_FOLDER.newFolder());
InMemoryProgramRunDispatcher launchDispatcher = new TestProgramRunDispatcher(cConf, runnerFactory, program, locationFactory, remoteClientFactory, true);
ProgramRuntimeService runtimeService = new TestProgramRuntimeService(cConf, runnerFactory, null, launchDispatcher);
runtimeService.startAndWait();
try {
ProgramDescriptor descriptor = new ProgramDescriptor(program.getId(), null, NamespaceId.DEFAULT.artifact("test", "1.0"));
Arguments sysArgs = new BasicArguments(ImmutableMap.of(ProgramOptionConstants.PEER_NAME, "mypeer"));
Arguments userArgs = new BasicArguments(Collections.emptyMap());
ProgramController controller = runtimeService.run(descriptor, new SimpleProgramOptions(program.getId(), sysArgs, userArgs), RunIds.generate()).getController();
Tasks.waitFor(ProgramController.State.COMPLETED, controller::getState, 5, TimeUnit.SECONDS, 100, TimeUnit.MILLISECONDS);
} finally {
runtimeService.stopAndWait();
}
}
use of io.cdap.cdap.app.program.Program in project cdap by caskdata.
the class AppFabricTestHelper method submit.
/**
* Submits a program execution.
*
* @param app the application containing the program
* @param programClassName name of the program class
* @param userArgs runtime arguments
* @param folderSupplier a Supplier of temporary folder
* @return a {@link ProgramController} for controlling the program execution.
*/
public static ProgramController submit(ApplicationWithPrograms app, String programClassName, Arguments userArgs, Supplier<File> folderSupplier) throws Exception {
ProgramRunnerFactory runnerFactory = injector.getInstance(ProgramRunnerFactory.class);
ProgramRunner runner = null;
Program program = null;
for (ProgramDescriptor programDescriptor : app.getPrograms()) {
if (programDescriptor.getSpecification().getClassName().equals(programClassName)) {
runner = runnerFactory.create(programDescriptor.getProgramId().getType());
program = createProgram(programDescriptor, app.getArtifactLocation(), runner, folderSupplier);
break;
}
}
Assert.assertNotNull(program);
BasicArguments systemArgs = new BasicArguments(ImmutableMap.of(ProgramOptionConstants.RUN_ID, RunIds.generate().getId(), ProgramOptionConstants.HOST, InetAddress.getLoopbackAddress().getCanonicalHostName(), ProgramOptionConstants.ARTIFACT_ID, Joiner.on(":").join(app.getArtifactId().toIdParts())));
return runner.run(program, new SimpleProgramOptions(program.getId(), systemArgs, userArgs));
}
Aggregations