Automated delivery of an ICN plug-in for continuous delivery

Agile is in vogue. Chances are good that your boss asked you to set up a build server to build your plug-ins and deliver them. At some point you’ll ask yourself, how do I automatically refresh the plugin on my environment, meaning without going to the ICN desktop and click the load button.

Here are 4 options, there might be more of course:

  1. Copy the jar and restart the whole web server (all of then if cluster). This reloads the plug-ins from their jars but that’s not conceivable for a production platform.
  2. Copy the jar and restart the ICN application on the web server. This also reloads the plug-ins. It’s better but still not conceivable for a production environment, we don;t want any interruption.
  3. Use Selenium and write a procedure to open the admin desktop, go to your plug-in, click the Load button and save. This is actually good, there is no interruption, just a bit boring to write and not easy to integrate to a build server (requires Selenium, running the browser…).
  4. Fake the behavior of going to the admin desktop and clicking load by calling the ICN rest api. This is what I’m going to develop here.

How does it work, the basics


First, you need to understand what’s going on at the network level when using ICN.

ICN is a one-page application, this means everything is ajax calls under the cover. Basically it uses the ICN JavaScript model to do things on the server. The way the JavaScript model works, it actually calls a REST webservice on the server, URL usually starts by:

/navigator/jaxrs/

This is not documented. The only way to understand how it works is to either use wireshark to analyze all network communications, or easier, use browser development tools (firebug, chrome dev tool…) and look at the network tab and see what’s going on. You will see it is actually POST HTTP requests. It posts URL encoded data and receive a secured JSON response.

Login

Of course, that couldn’t be as easy as calling an URL, you need to be authenticated. To do this we need to understand how authentication works in ICN. ICN uses a 2 ways authentication, based on cookies AND and on a security_token header. The logon page actually asks you to set these cookies (JSESSIONID and LtpaToken, only JSESSIONID is useful here) and give you a security_token in the body of the answer (as JSON). From now on, you will have to communicate the cookies for all requests you’re gonna make, and add the header “security_token“. Let’s analyze this together. Using curl, call the logon webservice the same way the login page is doing. I’ll help you, the POST parameters are:

ICN_network_logonSo let’s do the same thing with curl and see what is the response.

curl -X POST -v -d "desktop=authors&userid=P8Admin&password=F0rmation" http://basil:9080/navigator/jaxrs/logon
* Adding handle: conn: 0x1f7eb60
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x1f7eb60) send_pipe: 1, recv_pipe: 0
* About to connect() to basil port 9080 (#0)
*   Trying 192.168.56.101...
* Connected to basil (192.168.56.101) port 9080 (#0)
> POST /navigator/jaxrs/logon HTTP/1.1
> User-Agent: curl/7.33.0
> Host: basil:9080
> Accept: */*
> Content-Length: 49
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 49 out of 49 bytes
> HTTP/1.1 200 OK
> X-Powered-By: Servlet/3.0
> Strict-Transport-Security: max-age=7776000; includeSubdomains
> Cache-Control: no-cache
> Content-Type: text/plain; charset=UTF-8
> Content-Language: en-US
> Set-Cookie: JSESSIONID=0000oP3og9jckDfnB5RhaJgSkPR:-1; Path=/
> Set-Cookie: JSESSIONID=00001b3dg3oDh56UGQlpLUiV-B6:-1; Path=/
> Set-Cookie: JSESSIONID=0000_Gy2x3by2Q2reF511L_sOfY:-1; Path=/
> Set-Cookie: LtpaToken2=QLc4uwzWpcOwuHY3LlTpz2M8bm7/zWGyI+lD98RV9o5knfPl1mzytLFR6iUUn2Gixn2xY6bjUjTG7mtQc/DeiaomSxs/6p3G1D1emy46ctsnBNv9tvjH5GE6DAruQzOfSqNkRWGPzwEa6VpX7xBd5tKKCnIsjosGJj36YCvXGQo94nPdPrW0aWIUoIO3WMyFjagD2JNZhPhzX2jNVC+GSe05E9+4bKoDx1+mZ3FryKopZwaPeKI5/yxuBJLSTgldYxYs6Z0+3zek5kRroIVM3G3yfWhr6OqfhH+WaizOZzBOJ8KT9hMo0RYF/i3Ct2DE0q2af7wFlltonji8lL4yotv3Uo99SfmCPCxpUqTxNlf5f8rE4RimIAu/YZc9lAWokK7UZ38X9sBZM0VeecFx8z3kLfQ4RBpb/ppW3k7DS1W9+FwD0RYuP6JPMMHtoyWt3cVrdZ10r8DxSZbmtMIwOyIqBUTZFRRyuHAj9zN19HX9K205QH+efWFUnQGH0/f/fOdkYlj0glcp2JkoH8MHffruU4lYPFfYosXu5PFxSYai/6yRxUeKWLVMeooKyMaLSuqdrQmDhUjXdsT6D4oy/QMgIYjlMsBuF52CYm3bqc=; Path=/
> Transfer-Encoding: chunked
> Date: Wed, 29 Jul 2015 12:02:42 GMT
* Server WebSphere Application Server/8.0 is not blacklisted
> Server: WebSphere Application Server/8.0
> Expires: Thu, 01 Dec 1994 16:00:00 GMT
> {}&&{ "servers": [{ "entryTemplateSupported": true, "supportsDownloadCount": true, "priv_addItem": true, "repositoryId": "RCHOS2", "useSSO": false, "priv_addUnifiedSearch": false, "connected": true, "privFindUsersAndGroups": true, "searchTemplateSupported": true, "priv_workflow": true, "textSearchType": "", "priv_addTeamspaceTemplate": true, "adminLayout": { "featureClass": "ecm.widget.layout.AdminPane", "separator": false, "iconUrl": "adminLaunchIcon", "name": "Administration", "id": "ecmClientAdmin", "popupWindowClass": null, "featureTooltip": "" }, "priv_addSearch": true, "user_displayname": "P8Admin", "id": "RCHOS2", "objectStoreId": "{250AEFD6-4B95-4C34-947C-639E32BD63AD}", "supportsRecommendation": true, "objectStore": "TARGETOS", "syncEnabled": true, "userID": "P8Admin", "priv_addDoc": true, "capabilityComment": "documentonly", "recordType": "Plain", "objectStoreDisplayName": "TARGETOS", "priv_addModifyTeamRoles": true, "externalUser": false, "supportsTag": true, "priv_addTeamspace": true, "privAddEntryTemplate": true, "admin_user": true, "domainId": "{54F6D3E9-4F13-4295-B24F-81D316E81CBF}" }], "messagesEncoded": true, "containers": { "userID": "P8Admin", "connected": true, "desktop": "authors" }, "userid": "P8Admin", "taskSecurityRoles": { "isTaskAdmin": false, "isTaskUser": true, "isTaskAuditor": false }, "user_displayname": "P8Admin", "security_token": "-6597029755727235969", "messages": [{ "adminResponse": null, "moreInformation": null, "explanation": null, "number": "0", "userResponse": null, "text": "P8Adminlogged in." }] }* Connection #0 to host basil left intact

This is interested, because we can see that by calling the logon webservice, ICN actually asks us to set 3 cookies (4 but we don’t care about the LtpaToken to reload the plugin), and gives us a security_token. We don’t know yet how to use it but that might come handy later. Also, as you can see, the JSON is secured using a prefix {}&&, so it can’t be used crossed-domain via jsonp. We will have to remove this so tools can parse the json.

So what we want to do at this point, is call the URL and store the cookies, and also store the security token somewhere.

On windows, you can do the following cmd file:

You will need an utility call jq to parse the json and curl if not downloaded yet.

@echo off
rem Logon and store the cookies in a cookies store
curl -X POST -k -c cookies.txt -o output.txt -d "desktop=authors&userid=P8Admin&password=F0rmation" https://basil:9443/navigator/jaxrs/logon
rem Remove the json prefix
(For /f "tokens=2,* delims={" %%i in (output.txt) do echo {%%i{%%j)> outputNoPrefix.txt
rem Parse the json to get the security token
for /f %%i in ('jq -r .security_token outputNoPrefix.txt') do set token=%%i

On unix/linux, no need to install any extra tool:

#Logon and store the cookies in a cookies store
curl -X POST -k -c cookies.txt -o output.txt -d "desktop=authors&userid=P8Admin&password=F0rmation" https://basil:9443/navigator/jaxrs/logon
#Extract the security_token
token=`grep -E -o "\"security_token\":\"-?[0-9]*\"" output.txt | grep -o -E "[-]?[0-9]*"`

Reload

Now that we are logged on, we have to simulate the click of the Load button, so let’s go back to our browser and see what’s going on at this moment:

ICN_reload_plugin

You can see we are giving as cookies the JSESSIONID and the LtpaToken, we can also see where is used the security_token given when logging on. Finally, we can see what parameters are passed in the POST request. Now that we have all information we need, let’s try to to the same using curl:

curl -X POST -v -b cookies.txt -H "security_token:%token%" -d "fileName=/workspace/testPlugin/testplugin.jar&desktop=authors" http://basil:9080/navigator/jaxrs/admin/loadPlugin
* Adding handle: conn: 0x1f6f3d0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x1f6f3d0) send_pipe: 1, recv_pipe: 0
* About to connect() to basil port 9080 (#0)
* Trying 192.168.56.101...
* Connected to basil (192.168.56.101) port 9080 (#0)
> POST /navigator/jaxrs/admin/loadPlugin HTTP/1.1
> User-Agent: curl/7.33.0
> Host: basil:9080
> Accept: */*
> Cookie: JSESSIONID=0000q7qfUV5TlcmcfY76ZRSlZB2:-1; LtpaToken2=3VwfC9WT9KUN7FkABSpKqkP83N6mPxqor+nbF+G/DSjlM6rP5vIyhcZGgbwojxrTgZlJUIjMiGba2t6SOWqHhdNcxhsUWXgZ/9LKmT/A4G9TzsDPCBgbHySzuZjVUinNOTLGveGSIDJBsDvnMmEf0XOgo3w1DdBQTJ/n+OBWGQgnal+ZIsoOdM/Y1Q09gk5AfSom/CfOGQ+tmpmrth6/m6AX2cx8m4wddn7b9zelZUvgNKC6I9dcyW9WrUeOTG0GMtHUa4jkUhLAgFJcHPCFHyvxdLGAm52H9GOTE3AU/MHKVXZfVqU5252jCfmDKmaeViXJQY6u0cTOgGG+34VoqPUTVUsLMXNLbdP6N4c7c+Cx1z8LT56qx54LHVVhvKk4UyC013Dh1a3+7pIj/ZePOjLQWI1UeLGgF9PWe1eiwY4ik8/Jjx8IXxHiS8dTbL97jkUwb02uyxpxdqyfBopq8FvBmptMApP6q00FByk9ppnaqgQU5lmfJzAh6dGESyfy8ZcHo4WADhsQrS99PwVHp+Vpjj4frdmtwcX9oET0l1sjcg5b5axxKsynEVVxok9fJ+bnPbqVN2K7U8T6ruqbp93MMaucTPZw81DQQVcMi9I=
> security_token:6057487502591606037
> Content-Length: 61
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 61 out of 61 bytes
> HTTP/1.1 200 OK
> X-Powered-By: Servlet/3.0
> Strict-Transport-Security: max-age=7776000; includeSubdomains
> Cache-Control: no-cache
> Content-Type: text/plain; charset=UTF-8
> Content-Language: en-US
> Transfer-Encoding: chunked
> Date: Mon, 22 Feb 2016 23:03:22 GMT
* Server WebSphere Application Server/8.0 is not blacklisted
> Server: WebSphere Application Server/8.0
>
{}&&{"viewerDefs":[],"dependencies":[],"layouts":[],"cssFileName":"TestPlugin.css","name":"testPlugin 3","script":"TestPlugin.js","repositoryTypes":[],"openActions":[],"configClass":"testPluginDojo.ConfigurationPane","debugCssFileName":"TestPlugin.css","version":"1.0.2","id":"TestPlugin","dojoModule":"testPluginDojo","features":[],"actions":[{"global":false,"actionModelClass":"testPluginDojo\/TestAction","pluginId":null,"label":"TestAction","action":"","serverTypes":"p8","icon":"","id":"TestAction","privilegeName":"","widgetFunction":null,"widgetType":null,"iconClass":"","multiDoc":false}],"debugScript":"TestPlugin.js"}* Connection #0 to host basil left intact

It worked, ICN returned the plug-in configuration. We can see that our cookies have been sent and the header set, which authenticates us. We will actually need the information from this output later the the proper command will save it to a file:

curl -X POST -b cookies.txt -H "security_token:%token%" -o load.txt -d "fileName=/workspace/testPlugin/testplugin.jar&desktop=authors" http://basil:9080/navigator/jaxrs/admin/loadPlugin

Save

The load operation actually loads the new plugin. Actions, services, features and so on will now be the new version from your latest plugin’s version. However, by doing only the Load operation, the plugins UI does not get updated and that leads to a strange behavior, so let’s do the Save operation as if we were clicking the Save button after the relaod. By providing the right values, the plugins view will be correct.

First, let’s do the same, click the Save button and inspect what is going on:

ICN_save_plugin

So the save button actually calls the configuration url with the plugin id, and a json object providing again some plugin information. Let’s reproduce with curl, we will need some information from the load operation, that’s why we kept the file. We can also remove some useless information, especially the ordering (in the json), which we don’t have and that will force us to all the list url.

 

rem Remove the prefix in the load.txt file
(For /f "tokens=2,* delims={" %%i in (load.txt) do echo {%%i{%%j) > loadNoPrefix.txt
rem Get a few information from the load response
for /f %%i in ('jq -r .id loadNoPrefix.txt') do set id=%%i
for /f %%i in ('jq -r .configClass loadNoPrefix.txt') do set configClass=%%i
for /f %%i in ('jq -r .name loadNoPrefix.txt') do set name=%%i
for /f %%i in ('jq -r .version loadNoPrefix.txt') do set version=%%i
rem Then proceed to the save using our information
curl -X POST -v -b cookies.txt -H "security_token:%token%"  -d "action=update&id=%id%&configuration=PluginConfig&desktop=authors&json_post={\"enabled\":true,\"filename\":\"/workspace/testPlugin/testplugin.jar\",\"version\":\"%version%\",\"dependencies\":[],\"name\":\"%name%\",\"id\":\"%id%\",\"configClass\":\"%configClass%\"}" http://basil:9080/navigator/jaxrs/admin/configuration

* Adding handle: conn: 0x83f650
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x83f650) send_pipe: 1, recv_pipe: 0
* About to connect() to basil port 9080 (#0)
*   Trying 192.168.56.101...
* Connected to basil (192.168.56.101) port 9080 (#0)
> POST /navigator/jaxrs/admin/configuration HTTP/1.1
> User-Agent: curl/7.33.0
> Host: basil:9080
> Accept: */*
> Cookie: JSESSIONID=0000q7qfUV5TlcmcfY76ZRSlZB2:-1; LtpaToken2=3VwfC9WT9KUN7FkABSpKqkP83N6mPxqor+nbF+G/DSjlM6rP5vIyhcZGgbwojxrTgZlJUIjMiGba2t6SOWqHhdNcxhsUWXgZ/9LKmT/A4G9TzsDPCBgbHySzuZjVUinNOTLGveGSIDJBsDvnMmEf0XOgo3w1DdBQTJ/n+OBWGQgnal+ZIsoOdM/Y1Q09gk5AfSom/CfOGQ+tmpmrth6/m6AX2cx8m4wddn7b9zelZUvgNKC6I9dcyW9WrUeOTG0GMtHUa4jkUhLAgFJcHPCFHyvxdLGAm52H9GOTE3AU/MHKVXZfVqU5252jCfmDKmaeViXJQY6u0cTOgGG+34VoqPUTVUsLMXNLbdP6N4c7c+Cx1z8LT56qx54LHVVhvKk4UyC013Dh1a3+7pIj/ZePOjLQWI1UeLGgF9PWe1eiwY4ik8/Jjx8IXxHiS8dTbL97jkUwb02uyxpxdqyfBopq8FvBmptMApP6q00FByk9ppnaqgQU5lmfJzAh6dGESyfy8ZcHo4WADhsQrS99PwVHp+Vpjj4frdmtwcX9oET0l1sjcg5b5axxKsynEVVxok9fJ+bnPbqVN2K7U8T6ruqbp93MMaucTPZw81DQQVcMi9I=
> security_token:6057487502591606037
> Content-Length: 270
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 270 out of 270 bytes
> HTTP/1.1 200 OK
> X-Powered-By: Servlet/3.0
> Strict-Transport-Security: max-age=7776000; includeSubdomains
> Cache-Control: no-cache
> Content-Type: text/plain; charset=UTF-8
> Content-Language: en-US
> Transfer-Encoding: chunked
> Date: Mon, 22 Feb 2016 23:36:03 GMT
* Server WebSphere Application Server/8.0 is not blacklisted
> Server: WebSphere Application Server/8.0
>
{}&&{"messagesEncoded":true,"configuration":{"enabled":true,"classname":"com.ibm.testplugin.TestPlugin","ordering":6,"configClass":"testPluginDojo.ConfigurationPane","configuration":"","filename":"\/workspace\/testPlugin\/testplugin.jar","version":"1.0.2","dependencies":[],"id":"TestPlugin","name":"testPlugin"},"messages":[{"adminResponse":null,"moreInformation":null,"explanation":null,"number":"0","userResponse":null,"text":"The configuration was updated."}]}* Connection #0 to host basil left intact

This will save the configuration. This is the last step of our 3-step process: login, reload and save.

Summary

To summarize all the process, this is a 3-step process, we log in, then using our secuirty_token and cookies, we reload the plugin, then finally, using a few information provided by the response we got when reloading, we save the configuration.

Here is the global script to do this in one step:

@echo off
rem Logon and store the cookies in a cookies store
curl -X POST -k -c cookies.txt -o output.txt -d "desktop=authors&userid=P8Admin&password=F0rmation" https://basil:9443/navigator/jaxrs/logon
rem Remove the json prefix
(For /f "tokens=2,* delims={" %%i in (output.txt) do echo {%%i{%%j) > outputNoPrefix.txt
rem Parse the json to get the security token
for /f %%i in ('jq -r .security_token outputNoPrefix.txt') do set token=%%i
rem Reload the plugin
curl -X POST -k -b cookies.txt -H "security_token:%token%" -o load.txt -d "fileName=/workspace/testPlugin/testplugin.jar&desktop=authors" https://basil:9443/navigator/jaxrs/admin/loadPlugin
rem Remove the json prefix from the load response
(For /f "tokens=2,* delims={" %%i in (load.txt) do echo {%%i{%%j) > loadNoPrefix.txt
rem Get a few information from the load response
for /f %%i in ('jq -r .id loadNoPrefix.txt') do set id=%%i
for /f %%i in ('jq -r .configClass loadNoPrefix.txt') do set configClass=%%i
for /f %%i in ('jq -r .name loadNoPrefix.txt') do set name=%%i
for /f %%i in ('jq -r .version loadNoPrefix.txt') do set version=%%i
rem Then proceed to the save using our information
curl -X POST -v -b cookies.txt -H "security_token:%token%" -d "action=update&id=%id%&configuration=PluginConfig&desktop=authors&json_post={\"enabled\":true,\"filename\":\"/workspace/testPlugin/testplugin.jar\",\"version\":\"%version%\",\"dependencies\":[],\"name\":\"%name%\",\"id\":\"%id%\",\"configClass\":\"%configClass%\"}" http://basil:9080/navigator/jaxrs/admin/configuration

On linux/unix:

#Logon and store the cookies in a cookies store
curl -X POST -k -c cookies.txt -o output.txt -d "desktop=authors&userid=P8Admin&password=F0rmation" https://basil:9443/navigator/jaxrs/logon
#Extract the security_token
token=`grep -E -o "\"security_token\":\"-?[0-9]*\"" output.txt | grep -o -E "[-]?[0-9]*"`
# Reload the plugin
curl -X POST -k -b cookies.txt -H "security_token:$token" -o load.txt -d "fileName=/workspace/testPlugin/testplugin.jar&desktop=authors" https://basil:9443/navigator/jaxrs/admin/loadPlugin
# Get a few information from the load response
version=grep -E -o "\"version\":\"[0-9]+\.[0-9]+\.[0-9]+\"" loadPlugin.txt | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+"
id=grep -E -o "\"id\":\"[a-zA-Z0-9]+\"" loadPlugin.txt | grep -E -o ":\"[a-zA-Z0-9]+\"" | grep -E -o "[a-zA-Z0-9]+"
configClass=grep -E -o "\"configClass\":\"[a-zA-Z0-9]+\.[a-zA-Z0-9]+\"" loadPlugin.txt | grep -o -E "[a-zA-Z0-9]+\.[a-zA-Z0-9]+"
name=grep -E -o "\"name\":\"[a-zA-Z0-9]+\"" loadPlugin.txt | grep -E -o ":\"[a-zA-Z0-9]+\"" | grep -E -o "[a-zA-Z0-9]+"
# Then proceed to the save using our information
curl -X POST -v -b cookies.txt -H "security_token:$token" -d "action=update&id=$id&configuration=PluginConfig&desktop=authors&json_post={\"enabled\":true,\"filename\":\"/workspace/testPlugin/testplugin.jar\",\"version\":\"$version\",\"dependencies\":[],\"name\":\"$name\",\"id\":\"$id\",\"configClass\":\"$configClass\"}" http://basil:9080/navigator/jaxrs/admin/configuration

 

Bonus: Jenkins plug-in

For those of you who don’t want to bother with writing a batch task for their build, here is a Jenkins plug-in taking care of it for you. Just install this plug-in in Manage Jenkins > Manage Plugins > Advanced > Upload Plugin and then, in your project, add a build step and set the URL, username, password, desktop’s id and location of the file on the server. You need to copy the plug-in’s jar first though (with a scp task or something else).

ICN_jenkins_plugin

 

Output should look like this:

ICN_jenkins_plugin3

8 thoughts on “Automated delivery of an ICN plug-in for continuous delivery

  1. Romain

    Great script, but only the plugin view is updated, not the “Plug-ins” main view (so we need to access the “Plug-ins” view, then the plugin configuration to see the version). You can do it automatically by executing the following lines:

    Getting informations from loadPlugin.txt

    VERSION=grep -E -o "\"version\":\"[0-9]+\.[0-9]+\.[0-9]+\"" loadPlugin.txt | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+"
    ID=grep -E -o "\"id\":\"[a-zA-Z0-9]+\"" loadPlugin.txt | grep -E -o ":\"[a-zA-Z0-9]+\"" | grep -E -o "[a-zA-Z0-9]+"
    CONFIGCLASS=grep -E -o "\"configClass\":\"[a-zA-Z0-9]+\.[a-zA-Z0-9]+\"" loadPlugin.txt | grep -o -E "[a-zA-Z0-9]+\.[a-zA-Z0-9]+"
    NAME=grep -E -o "\"name\":\"[a-zA-Z0-9]+\"" loadPlugin.txt | grep -E -o ":\"[a-zA-Z0-9]+\"" | grep -E -o "[a-zA-Z0-9]+"
    PLUGIN_PATH=echo $PLUGIN_DIRECTORY/$PLUGIN | sed s,/,%2F,g

    curl -X POST -k -b cookies.txt -H “security_token:$TOKEN” -d “action=list&id=navigator&type=plugins&sorted=true&configuration=ApplicationConfig&login_desktop=admin&application=navigator&desktop=admin” $ICN_COMPLETE_URL/jaxrs/admin/configuration >> $LOG_FILE 2>> $LOG_ERR_FILE > listPlugin.txt

    Getting plugin order, needed by /configuration call

    ORDER=grep -E -o "\"id\":\"$ID\".*\"ordering\":[0-9]+," listPlugin.txt | grep -o -E "ordering\":[0-9]+," | grep -o -E "[0-9]+"

    Refreshing the Plug-ins view


    curl -X POST -k -b cookies.txt -H "security_token:$TOKEN" -d "action=update&id=$ID&configuration=PluginConfig&login_desktop=admin&application=navigator&json_post={"id":"$ID","enabled":true,"dependencies":[],"classname":"","name":"$NAME","filename":"$PLUGIN_PATH","ordering":$ORDER,"configuration":null,"version":"$VERSION","configClass":"$CONFIGCLASS"}&desktop=admin" $ICN_COMPLETE_URL/jaxrs/admin/configuration >> $LOG_FILE 2>> $LOG_ERR_FILE

    With that, the main view will be up-to-date 🙂

    Reply
    1. Guillaume Post author

      Hi Romain,

      It took me 6 months but I’m finally answering. Also I think I haven’t wished you an happy new year yet so happy new year. Hope I can see you this year. To reply to your comment, I agree and disagree with you 😉 Because doing only the loadPlugin does reload the plugin, even if this is a different location from what’s currently set, and new Java classes and JavaScript will be used, which is all I cared for at the time I wrote this. So it does the job (try to change something in a different jar and reload and you will notice the changes).

      However, I agree with you that it does not change the UI, which leads to confusion and strange behavior. Basically, as you said, the specific plugin view will be correct (version/name/actions/…) but the main plugin view won’t (wrong version and name).

      Anyway, let’s do this properly and also save the configuration after loading the new plugin.

      What you did works great, I did it on my side to see if I was ending with the same solution and I do so nice work. I’ll update the post with this information. I might try to simplify this a bit if I can, this order thing bothers me so I’ll see if we can do without it :).

      See you.

      Reply
  2. Tilo

    Hi, you can review what ICM is doing to load plugins.

    First load Plugin manual to know the values and read the values:
    http://ICNserver:9081/navigator/jaxrs/admin/configuration?action=list&application=navigator&configuration=ApplicationConfig&desktop=admin&id=navigator&securityTopic=plugins.plugins&sorted=truetype=plugins&userid=AdminTilo%40dom.com&security_token=-1321312312

    Second load JAR
    jaxrs/admin/loadPlugin?application=navigator&desktop=admin&fileName=__patch_to_jar_URLencoded&securityTopic=plugins.plugins&userid=AdminTilo%40mcom.com&security_token=-1321312312″

    No load with the required values from the previous “load”

    http://ICNserver:9081/navigator/jaxrs/admin/configuration?action=add&application=
    navigator&configuration=PluginConfig&desktop=admin&id=ICAPlugin&json_post={
    “id”: “ICAPlugin”,
    “name”: “IBM Watson Content Analytics”,
    “configuration”: “{\”validateCert\”:\”false\”,\”server\”:\”http://someserver\”,\”adminServer\”:\”http://someAdminse
    rver\”,\”adminToken\”:\”tiloToken123\”}”,
    “filename”: “C:\IBM\ECMClient\plugins\icaplugin.jar”,
    “version”: “3.5.0.2”,
    “configClass”: “ica.ConfigurationPane”,
    “enabled”: “true”
    }&securityTopic=plugins.plugins&update_list_configuration=ApplicationConfig&update_list_id=navigator&update_list_type=pl
    ugins&userid=AdminTilo%40Dom.com&security_token=-1321312312

    Also see here my request for more documentation info.
    https://www.ibm.com/developerworks/community/forums/html/topic?id=4966f796-c084-474f-b5b2-0533414cbf78

    Reply
  3. Pluto

    Hi, Thanks for the post and it is very informative. I have downloaded the “reloader.hpi” from your above post, installed it in Jenkins, added a build step with required details however, I am getting the below error when trying to build. Your inputs and help is appreciated.

    Connecting to ICN as XYZ…KO
    A JSONObject text must begin with ‘{‘ at character 0org.json.JSONException: A JSONObject text must begin with ‘{‘ at character 0
    at org.json.JSONTokener.syntaxError(JSONTokener.java:410)
    at org.json.JSONObject.(JSONObject.java:179)
    at org.json.JSONObject.(JSONObject.java:402)
    at org.gdelory.jenkins.plugins.icn.reloader.HelloWorldBuilder.logon(HelloWorldBuilder.java:136)
    at org.gdelory.jenkins.plugins.icn.reloader.HelloWorldBuilder.perform(HelloWorldBuilder.java:104)
    at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:770)
    at hudson.model.Build$BuildExecution.build(Build.java:199)
    at hudson.model.Build$BuildExecution.doRun(Build.java:160)
    at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:533)
    at hudson.model.Run.execute(Run.java:1745)
    at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
    at hudson.model.ResourceController.execute(ResourceController.java:89)
    at hudson.model.Executor.run(Executor.java:240)
    Login response was:
    Build step ‘Refresh plug-in in ICN’ marked build as failure
    Finished: FAILURE

    Reply
    1. Guillaume Post author

      Hi Pluto,

      Sorry for the delay, I was travelling out of the country for a while.

      It looks like the answer is empty. Are you sure your Jenkins can connect to ICN? Is your ICN running fine? Are all the login details correct, especially the url? Maybe you can try using curl to test it the step by step and see why the Jenkins plugin is failing. Sorry but I can’t really say more without more details, but there is something wrong with your connection to ICN.

      Reply
  4. Prashanth Kayampady

    This will work only for ICN with application managed authentication. If ICN is setup for form based / BASIC / SSO authentication, the scripts need to be changed a bit I guess.

    Reply
  5. David

    I realize this is an old post – but very helpful. I am stuck on the save portion of the script. In my pwd I do not have a loadPlugin.txt, and can’t find where you had it created. Also on the line version=grep -E -o, I have the error:

    -bash: -E: command not found.

    If you still monitor this, do you have any suggestions?

    Reply

Leave a Reply to David Cancel reply