This is an old revision of the document!
Yet another method of reading the JSON-RPC interface.
The example below reads the result of the latest softwareAudit and displays it as a table. Information about installed sw products are merged in.
All needed files (.html, .js, .css) should be hosted below /usr/share/opsiconfd/static/AngularExample folder thus avoiding cross scripting complaints of modern browsers.
The location would then read https://opsi:4447/AngularExample.
configed will currently answer /rpc? requests with Encoding “deflate”, but will anounce it as “gzip”. This issue is known and a patch is mentioned in the forums.
Most requests require a logon, some even special rights. The script user should be member of a new group opsireader and the acl.conf file should be prepended with appropriate lines:
getProducts_.* : sys_group(opsireader); sys_group(opsiadmin); opsi_depotserver; self; opsi_client productOnClient_get.* : sys_group(opsireader); sys_group(opsiadmin); opsi_depotserver;self; opsi_client auditSoftwareOnClient_get.* : sys_group(opsireader); sys_group(opsiadmin); opsi_depotserver; self; opsi_client product_get.* : sys_group(opsireader); sys_group(opsiadmin); opsi_depotserver; self; opsi_client
/usr/share/opsiconfd/static/AngularExample ├ index.html ├ swinv.js └ swinv.css
Where all other is loaded from..
<!DOCTYPE html> <html ng-app="opsi-swinv"> <head> <link rel="stylesheet" type="text/css" href="swinv.css" > <script type="text/javascript" src="angular.js"></script> <!-- chenge to angular-min for production --> <!-- script type="text/javascript" src="angular-resource.js"></script --> <script type="text/javascript" src="swinv.js"></script> <script type="text/javascript" src="swpattern.js"></script> </head> <body ng-controller="swinvController as sw"> <div class="swlist"> <input id="inputId" ng-model="sw.clientId"></input> <button ng-click="sw.refresh(sw.clientId)">refresh list</button> <table border > <tr><th>Name</th><th>Version</th><th>Lizenz</th><th>Installationsgrund</th></tr> <tr ng-repeat="swp in sw.products" ng-show="sw.nonMS(swp.name)"> <td>{{swp.name}} </td> <td> {{swp.version}}</td> <td>{{sw.reason(swp.name)}}</td> <td class={{sw.csswarn(swp.name)}}><span ng-show="!sw.isOpsi(swp.name)">{{sw.reason(swp.name)}} </span>{{sw.opsiProdId(swp.name)}}</td> </tr> </table> <br/><label><input type="checkbox" ng-model="sw.showopsiinstalled" />installed OPSI products on this client <span>({{sw.clientId}})</span></label> <div ng-show="sw.showopsiinstalled"> <table border> <tr><th>OpsiProduct</th></tr> <tr ng-repeat="inst in sw.installed"> <td>{{inst}}</td> </tr> </table> </div> <br/><label><input type="checkbox" ng-model="sw.showallprods" />available products</label> <table ng-show="sw.showallprods" border width="100%"> <tr><th>productInfo</th><th>productId</th><th>...............................................</th></tr> <tr ng-repeat="prod in sw.productinfos"> <td>{{prod.productId}}</td> <td>{{prod.name}}</td> <td></td> </tr> </table> </div> </body> </html>
swinv.js The AngularJS mimic..
(function(){
var app = angular.module('opsi-swinv', []);
app.controller('swinvController',function($http,$filter){
this.showallprods=0;
this.showopsiinstalled=0;
baseurl='/rpc';
logonurl='https://testerMemberOfGroupopsireader:unGuessablePassword@'+window.location.host+'/rpc';
this.clientId="defaultclient.domain.local";
this.auditParams={'id':'jsonrpc','method':'auditSoftwareOnClient_getObjects','params':[]};
this.auditParams.params.push([]);
this.auditParams.params.push({"clientId":"defaultclient.domain.local"});
opsiURL=baseurl+"?"+$filter('json')(this.auditParams);
me=this;
me['installed']=[];
me['productinfos']=[];
this.jsonParmDns=function(){
this.search=window.location.search;
if (this.search.match(/dns/)){ // we believe in barcode like {"dns":"<clientId>"}
var qsearch=decodeURIComponent(this.search).match(/{.+dns.+:.+}/);
var jsonsearch=decodeURIComponent(qsearch); // get the json
return angular.fromJson(jsonsearch).dns;
// return JSON.parse(jsonsearch).dns;
}
return null;
};
this.opsicall=function(field,method,arg){
Params={'id':'1','method':method,'params':[]};
if(arg)Params.params[0]=arg;
$http.post(baseurl,Params)
.success(function(response,stat,head,conf){
// alert("success: "+$filter('json')(response));
me.opsires="success: "+method;
me.opsiconf=conf;
if(response.error)
alert(response.error.message);
else
me[field]=response.result;
})
.error(function(err,stat,head,conf){
me.opsires="error";
alert("err: "+(err)+stat+head+$filter('json')(conf));
me.opsistat=stat;
me.opsihead=head;
me.opsiconf=conf;
});
};
this.logon=function(){
$http.post(logonurl,this.logonParams)
.success(function(response){
// alert("success: "+$filter('json')(response));
// call after logon success
me.getproductinfos();
me.refresh(me.clientId);
})
.error(function(response){
alert("err: "+(response));
});
};
this.getprods=function(id){
this.opsires="calling.. "+id;
if(id)this.auditParams.params[1].clientId=id;
$http.post(baseurl,this.auditParams)
.success(function(response,stat,head,conf){
// alert("success: "+response);
if(response.error)alert(response.error.message);
me.products=response.result;
me.opsistat=stat;
me.opsihead=head;
me.opsiconf=conf;
})
.error(function(err,stat,head,conf){
me.opsires="error";
alert("err: "+(err)+stat+head+$filter('json')(conf));
me.opsistat=stat;
me.opsihead=head;
me.opsiconf=conf;
});
};
// get products on Client with id
this.getinstalled=function(id){
this.opsicall('installed','getInstalledLocalBootProductIds_list',id);
};
// get all available OPSi products
this.getproductinfos=function(){
this.opsicall('productinfos','getProducts_listOfHashes');
};
this.logon();
this.clientId=this.jsonParmDns();
// this.getproductinfos();
this.refresh=function(id){
if(null != id){
this.getprods(id);
this.getinstalled(id);
}
};
this.nonMS=function(name){
// return true;
if(name.match(/AddressBook/)) return false;
if(name.match(/^Connection Manager/)) return false;
if(name.match(/^DirectDrawEx/)) return false;
if(name.match(/^DXM_Runtime/)) return false;
if(name.match(/^Fontcore/)) return false;
if(name.match(/KB[0-9]+/)) return false;
if(name.match(/Microsoft/)) return false;
if(name.match(/^MPlayer2/)) return false;
if(name.match(/^Outlook/)) return false;
if(name.match(/^[iI][Ee]/)) return false;
if(name.match(/^Windows/)) return false;
if(name.match(/^MobileOptionPack/)) return false;
if(name.match(/^SchedulingAgent/)) return false;
if(name.match(/^WIC/)) return false;
return true;
}
this.pattern=swpattern;
this.reason=function(name){
for(p in this.pattern){
if(name.match(p))
return this.pattern[p];
}
};
// guess the corresponding OPSI productId from the Windows Product name
this.opsiProdId=function(name){
for(i=0; i<this.productinfos.length;i++){
p=this.productinfos[i];
if(p.name && name.match(p.name)||name.match(p.productId))
return p.productId;
}
return null;
};
// convenience: is this an OPSI product?
this.isOpsi=function(name){
return (null != this.opsiProdId(name));
};
// mark rows w/o reason/license
this.csswarn=function(name){
if(this.isOpsi(name) || this.reason(name))
return "ng-binding";
else
return "warn";
};
});
var swpattern={'^Audacity':'OpenSource',
'^Java':'Oracle',
'^Mozilla ':'Mozilla Public',
'^OpenOff':'OpenSource',
'^Google':'Google Public',
'^Adobe Flash':'Adobe Public',
'^OpenSSL':'OpenSource',
'^Python':'OpenSource'
};
})();