3

i'm trying to pass command line arguments in my Spring Boot Yarn application and am having difficulties. i understand that i can set these in the yml document spring.yarn.appmaster.launchcontext.arguments but how can it from the command line? like java -jar MyYarnApp.jar {arg0} {arg1} and get access to it from my @YarnContainer?

i've discovered that @YarnProperties maps to spring.yarn.appmaster.launchcontext.arguments but i want to set them from the command line, not in the yml

incomplete-co.de
  • 2,137
  • 18
  • 23

1 Answers1

5

You are pretty close on this when you found spring.yarn.client.launchcontext.arguments and spring.yarn.appmaster.launchcontext.arguments. We don't have settings which would automatically pass all command-line arguments from a client into an appmaster which would then pass them into a container launch context. Not sure if we even want to do that because you surely want to be on control what happens with YARN container launch context. User using a client could then potentially pass a rogue arguments along a food chain.

Having said that, lets see what we can do with our Simple Single Project YARN Application Guide.

We still need to use those launch context arguments to define our command line parameters to basically map how things are passed from a client into an appmaster into a container.

What I added in application.yml:

spring:
    yarn:
        client:
            launchcontext:
                arguments:
                    --my.appmaster.arg1: ${my.client.arg1:notset1}
        appmaster:
            launchcontext:
                arguments:
                    --my.container.arg1: ${my.appmaster.arg1:notset2}

Modified HelloPojo in Application class:

@YarnComponent
@Profile("container")
public static class HelloPojo {

    private static final Log log = LogFactory.getLog(HelloPojo.class);

    @Autowired
    private Configuration configuration;

    @Value("${my.container.arg1}")
    private String arg1;

    @OnContainerStart
    public void onStart() throws Exception {
        log.info("Hello from HelloPojo");
        log.info("Container arg1 value is " + arg1);
        log.info("About to list from hdfs root content");

        FsShell shell = new FsShell(configuration);
        for (FileStatus s : shell.ls(false, "/")) {
            log.info(s);
        }
        shell.close();
    }

}

Notice how I added arg1 and used @Value to map it with my.container.arg1. We can either use @ConfigurationProperties or @Value which are normal Spring and Spring Boot functionalities and there's more in Boot's reference docs how to use those.

You could then modify AppIT unit test:

ApplicationInfo info = submitApplicationAndWait(Application.class, new String[]{"--my.client.arg1=arg1value"});

and run build with tests

./gradlew clean build

or just build it without running test:

./gradlew clean build -x test

and then submit into a real hadoop cluster with your my.client.arg1.

java -jar build/libs/gs-yarn-basic-single-0.1.0.jar --my.client.arg1=arg1value

Either way you see arg1value logged in container logs:

[2014-07-18 08:49:09.802] boot - 2003  INFO [main] --- ContainerLauncherRunner: Running YarnContainer with parameters [--spring.profiles.active=container,--my.container.arg1=arg1value]
[2014-07-18 08:49:09.806] boot - 2003  INFO [main] --- Application$HelloPojo: Container arg1 value is arg1value

Using format ${my.client.arg1:notset1} also allows you to automatically define a default value notset1 if my.client.arg1 is omitted by user. We're working on Spring Application Context here orchestrated by Spring Boot so all the goodies from there are in your disposal

If you need more precise control of those user facing arguments(using args4j, jopt, etc) then you'd need to have a separate code/jar for client/appmaster/container order to create a custom client main method. All the other Spring YARN getting started guides are pretty much using multi-project builds so look at those. For example if you just want to have first and second argument value without having a need to use full --my.client.arg1=arg1value on a command line.

Let us know if this works for you and if you have any other ideas to make things simpler.

Janne Valkealahti
  • 2,552
  • 1
  • 14
  • 12