enable-openshift-ci: full example using openshift-java-client

Version 2

    This wiki entry will show you a complete example using the openshift-java-client. The openshift-java-client is a java library that allows you talk to the OpenShift PaaS programmatically.

    This article will develop a command line tool in java, that takes a project on your disk and sets up a jenkins build for it on OpenShift.

    The example is hosted on github at https://github.com/adietish/enable-openshift-ci and you may freely reuse, redistribute or modify the code since it's licensed under the Eclipse Public License.

    Requirements

    • your project is required to build with maven and has to be committed to a git repository
    • you need an account on OpenShift. (If you have no account yet, you would have to signup first)
    • you need 3 free application slots (given that you have a default quota of 3 applications, you shall have no application in your account).
    • you need to have git available on your command-line (enable-openshift-ci is using it to deploy)

    Usage

    -p     the project (folder) that we will enable CI for
    -pw   the OpenShift password
    -u     the OpenShift user
    

     

    You have to tell enable-openshift-ci where it will find your project (-p), what's your OpenShift user (-u) and what password you are using (-pw).

    An exemplary call using the jar would look the following:

     

    java -jar target/enable-openshift-ci-0.0.1-SNAPSHOT-jar-with-dependencies.jar -p <PATH_TO_PROJECT> -a test -u <USER> -pw <PASSWORT>
    

     

    Calling it using maven would look like this:

    mvn test -Du=<USER> -Dpw=<PASSWORD> -Dp=<PATH_TO_PROJECT>
    

     

    Enable-openshift-ci will log into your OpenShift account, create a domain (if needed), an application for your project and a jenkins application. It will then add the remote application git repo to your local project. You will then be ready to merge the remote content to your local project, add the openshift profile to your pom and push your project upstream. This will trigger the jenkins build.

    Implementation

    Build setup

    First of all enable-openshift-ci requires the openshift-java-client. The client library is available as artifact from maven central. Enable-openshift-ci is a maven project, we can therefore add the openshift-java-client to its classpath by simply using the following snippet in the it's pom:

    <dependency>
         <groupId>com.openshift</groupId>
         <artifactId>openshift-java-client</artifactId>
         <version>2.0.0</version>
    </dependency>
    

    A few classes

    • Main: Bootstrapping
    • Parameters: Parses, validates and holds the command line parameters
    • OpenShiftCI: Creates the OpenShift CI, pushes your project to it

     

    Parameters: Talk to me via command line parameters

    To keep the example simple, we will stick to a GUI-less programm, that you control by command-line arguments. The Parameters class holds all parameters that were given at the command line. It will check them for validity and offer them for further processing.

    What's important in this context is that the Parameters class will ensure that your project exists, that it is a maven project and that it is shared with a git repository.

    OpenShiftCI: I want my CI instance!

    The OpenShiftCI class is where it all happens. It will connect to your OpenShift account, create your Jenkins instance and push your project to it. The create() method looks like this:

     

    IUser user = createUser();
    IDomain domain = getOrCreateDomain(user);
    IApplication application = getOrCreateApplication(project.getName(), domain);
    IApplication jenkinsApplication = getOrCreateJenkins(domain);
    waitForApplication(jenkinsApplication);
    waitForApplication(application);
    embedJenkinsClient(application);
    deployToOpenShift(application);
    System.out.println("Done.");
    

    Let's get in touch with OpenShift

    Before enable-openshift-ci can manipulate resources on OpenShift, it has to connect to it. It asks the OpenShiftConnectionFactory for a new connection.

    The first required parameter is the url of the OpenShift PaaS. You may either hard code it or ask the OpenShift configuration for it:

    new OpenShiftConfiguration().getLibraServer()
    

    The connection factory also asks for a meaningful client id. We will use "enable-openshift-ci".

    Last but not least, you also have to give it your OpenShift credentials.

    String openshiftServer = new OpenShiftConfiguration().getLibraServer();
    IOpenShiftConnection connection = new OpenShiftConnectionFactory().getConnection("enable-openshift-ci", "<user>", "<password>", openshiftServer);
    

     

    Once you have your connection you can get your user instance which will allow you to create your the domain and the applications:

    IUser user = connection.getUser();
    

    Now I need a domain

    All resources on OpenShift are bound to a domain. We therefore have to make sure we have a domain in a first step, we either get the existing one or create a new one in getOrCreateDomain():

    IDomain domain = user.getDefaultDomain();
    if (domain == null) {
      domain = user.createDomain("openshiftci");
    

     

    In case we create a new domain, we have to make sure that OpenShift has our ssh-key. The ssh-key is required as soon as you deal with an OpenShift git-repository, the application logs etc (not when manipulating resources). To keep things simple, we will stick to the default ssh-key id_rsa.pub and add it to OpenShift in case it's not present yet. When adding the key, we will use a unique name which is the current time in millisecons in this simplified example:

    ISSHPublicKey key = new SSHPublicKey(SSH_PUBLIC_KEY);
    IOpenShiftSSHKey addedKey = user.getSSHKeyByPublicKey(key.getPublicKey());
    if (addedKey == null) {
              user.putSSHKey(String.valueOf(System.currentTimeMillis()), key);
    }
    

    Let's get an application for my project

    Now that we have a domain, we are ready to create an application for our project.

    Our tool uses an constant name for the new project. It therefore checks if this application already exists:

    IApplication application = domain.getApplicationByName("openshiftci");
    

     

    If there's no such application, it will create a new one:

    IApplication application = domain.createApplication(name, ICartridge.JBOSSAS_7);

     

    If it already exists, getOrCreateApplication() will check if it's a jbossas-7 application, since we are dealing with a maven aka java project.

    ICartridge.JBOSSAS_7.equals(application.getCartridge())
    

    OpenShift, gimme my CI instance!

    We now created an application that OpenShift builds whenever we push to it's git repository. The build is executed within the git push. To have a jenkins CI instance doing that work, we have to add a jenkins application and connect both.

     

    getOrCreateJenkins() first checks if there are any jenkins applications within your domain:

    List<IApplication> jenkinsApplications = domain.getApplicationsByCartridge(ICartridge.JENKINS_14);
    if(jenkinsApplications.isEmpty()) {
    
       ...
    

     

    If it spots an jenkins instance, it will leave this step alone, it wont create another jenkins application. If there's none yet, it will create a new one and print it's url and credentials:

    IApplication jenkins = domain.createApplication(DEFAULT_JENKINS_NAME, ICartridge.JENKINS_14);
    System.out.println(jenkins.getCreationLog());
    

     

    We now have to make sure both applications are reachable. We will eventually wait for them to become ready:

    Future<Boolean> applicationAccessible = application.waitForAccessibleAsync(WAIT_TIMEOUT);
    if (!applicationAccessible.get()) {
       ...
    

     

    Once they are both ready, we can connect both and add the jenkins cartridge to our project application. Doing this tells OpenShift to build the project application within in the jenkins application.

    The embedded cartridge offers a creation log, that shows at what url the jenkins jobs may be reached at.

     

    IEmbeddedCartridge jenkinsClient = application.addEmbeddableCartridge(IEmbeddableCartridge.JENKINS_14);
    System.out.println(jenkinsClient.getCreationLog());
    

     

    We're almost there

    Enable-openshift-ci will now last but not least add the git repository of your application as remote to your local project repository. It will use the git command line to "git add remote":

    exec("git remote add openshift -f " + application.getGitUrl());
    


    To now have your project built on OpenShift, you'll have to make sure your pom has an openshift profile:

    <profile>
        <!-- When built in OpenShift the 'openshift' profile will be used when invoking mvn. -->
        <!-- Use this profile for any OpenShift specific customization your app will need. -->
        <!-- By default that is to put the resulting archive into the 'deployments' folder. -->
        <!-- http://maven.apache.org/guides/mini/guide-building-for-different-environments.html -->
        <id>openshift</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.1.1</version>
                    <configuration>
                        <outputDirectory>deployments</outputDirectory>
                        <warName>ROOT</warName>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
    

     

    You'll then simply merge the remote repo into you local repo and push it upstream. You'll do something like this:

    git add .
    git commit -a -m 'deploying to openshift'
    git merge openshift/master -s recursive -X ours
    git push openshift HEAD
    

     

    Pushing your project upstream will now trigger a jenkins build.

     

    We're there, you now have a utility that will setup a jenkins for your project. We discussed all steps involved.