Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FLINK-8333] [flip6] Separate deployment options from command options #5220

Closed
wants to merge 12 commits into from

Conversation

tillrohrmann
Copy link
Contributor

What is the purpose of the change

This commit separates the parsing of command options and deployment options into two
steps. This makes it easier to make the CustomCommandLines non-static.

Moreover, this commit moves the CliFrontend into the cli sub package.

This PR is based on #5219.

Brief change log

  • Move CliFrontend to org.apache.flink.client.cli
  • Decouple creation of RunOptions, ListOptions, etc. from CliFrontendParser

Verifying this change

This change is already covered by existing tests.

Does this pull request potentially affect one of the following parts:

  • Dependencies (does it add or upgrade a dependency): (no)
  • The public API, i.e., is any changed class annotated with @Public(Evolving): (no)
  • The serializers: (no)
  • The runtime per-record code paths (performance sensitive): (no)
  • Anything that affects deployment or recovery: JobManager (and its components), Checkpointing, Yarn/Mesos, ZooKeeper: (no)
  • The S3 file system connector: (no)

Documentation

  • Does this pull request introduce a new feature? (no)
  • If yes, how is the feature documented? (not applicable)

* @param program The program for which to create the client.
* @throws Exception
*/
protected ClusterClient createClient(
CommandLineOptions options,
CustomCommandLine<?> customCommandLine,
Copy link
Member

@GJL GJL Jan 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it really necessary to change the signature? It seems that the behavior is otherwise the same. Why not leave the line

CustomCommandLine<?> activeCommandLine = getActiveCustomCommandLine(options.getCommandLine());

inside this method.

Edit: Is it needed in a later commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was probably not necessary. Since this method will be removed anyway in a subsequent PR, I'll keep it as it is.

}
if (program != null) {
program.deleteExtractedLibraries();
program.deleteExtractedLibraries();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't run if createClient() fails. Before the client creation was inside the try block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Will change it.

catch (Exception e) {
return handleError(e);
}
jobId = new JobID(StringUtils.hexStringToByte(jobIdString));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception's message won't be super meaningful:

new JobID(StringUtils.hexStringToByte("dupa"));
java.lang.NumberFormatException: For input string: "du"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Will throw a more meaningful exception.

LOG.error("Error: The value for the Job ID is not a valid ID.");
System.out.println("Error: The value for the Job ID is not a valid ID.");
return 1;
throw new CliArgsException("The value for the JobID is not a valid ID: " + e.getMessage());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe log the input value as well

	try {
			new JobID(StringUtils.hexStringToByte("dea84ec368d886f1638c01447ec6951"));
		} catch (Exception e) {
			throw new CliArgsException("The value for the JobID is not a valid ID: " + e.getMessage());
		}

message is:

The value for the JobID is not a valid ID: Argument bytes must by an array of 16 bytes

Also, this piece of code is duplicated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will change it.

if (cleanedArgs.length >= 1) {
String jobIdString = cleanedArgs[0];
try {
jobId = new JobID(StringUtils.hexStringToByte(jobIdString));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well use JobID.fromHexString() and add a meaningful message in fromHexString that you propagate.

return triggerSavepoint(clusterClient, jobId, savepointDirectory);
}
} catch (Exception e) {
return handleError(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why catch exception here? It's already done in parseParameters(String[] args).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oversight from my side.

// Parse command line options
InfoOptions options;
try {
options = CliFrontendParser.parseInfoCommand(args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CliFrontendParser.parseInfoCommand() is no longer in use. Can be deleted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will remove it.

// expected
}

Mockito.verify(testFrontend.client, times(1)).stop(any(JobID.class));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are already mocking the behavior of the client with:

doThrow(new IllegalArgumentException("Test exception")).when(client).stop(any(JobID.class));

Therefore the test should fail in the absence of the exception, i.e., if stop is not called. I think this verify is not needed:

        @Test(expected = IllegalArgumentException.class)
	public void testUnknownJobId() throws Exception {
		// test unknown job Id
		JobID jid = new JobID();

		String[] parameters = {jid.toString()};
		StopTestCliFrontend testFrontend = new StopTestCliFrontend(true);

		testFrontend.stop(parameters);
		fail("Should have failed.");
	}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Will adapt it accordingly.

fail("Should have failed.");
}

@Test(expected = CliArgsException.class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Test could be stricter by asserting that the exception carries the expected message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I'm, however, not a super fan of testing for exception messages. If the message is changed then you don't see it directly.

/**
* Tests for the RUN command.
*/
public class CliFrontendRunTest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File is not recognized as moved by git 😢

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for that.

int retCode = testFrontend.cancel(parameters);
assertTrue(retCode == 0);
int retCode = testFrontend.cancel(parameters);
assertTrue(retCode == 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Code is copied but it's better to use assertEquals for proper failure reasons.

Copy link
Member

@GJL GJL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good to me. Thanks for your contribution @tillrohrmann. I have added some comments that you may want to address.

@tillrohrmann
Copy link
Contributor Author

Thanks a lot for your review @GJL. I've addressed your comments and rebased onto the preceding PR. Will merge it once Travis gives green light.

…lusterClient

Introduce YarnApplicationStatusMonitor which does the Yarn ApplicationStatus polling in
the FlinkYarnSessionCli. This decouples the YarnClusterClient from the actual communication
with Yarn and, thus, gives a better separation of concerns.
Moves the YarnClient from the YarnClusterClient to the AbstractYarnClusterDescriptor.
This makes the latter responsible for the lifecycle management of the client and gives
a better separation of concerns.
Move the savepoint disposal logic from the CliFrontend into the ClusterClient. This gives
a better separation of concerns and allows the CliFrontend to be used with different
ClusterClient implementations.
This commit separates the parsing of command options and deployment options into two
steps. This makes it easier to make the CustomCommandLines non-static.

Moreover, this commit moves the CliFrontend into the cli sub package.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants