Working with URL parameters in custom Kibana plugin - elastic-stack

I am working on a custom plugin to Kibana (7.5.2). The plugin is of type 'app'. I would like to be able to pass parameters to this plugin in order to pre-load some data from Elasticsearch. I.e., I need to provide users with some specific URLs containing parameters that will be used by the plugin to show only a relevant portion of data.
My problem is that I was not able to find sufficient documentation on this and I do not know what the correct approach should be. I will try to summarize what I know/have done so far:
I have read the official resources on plugin development
I am aware of the fact that _g and _a URL parameters are used to pass state in Kibana applications. However, a) I am not sure if this is the correct approach in my case and b) I also failed to find any information on how my plugin should access the data from these parameters.
I checked the sources of other known plugins, but again, failed to find any clues.
I am able to inject some configuration values using injectUiAppVars in the init method of my plugin (index.js) and retrieve these values in my app (main.js):
index.js:
export default function (kibana) {
return new kibana.Plugin({
require: ['elasticsearch'],
name: ...,
uiExports: {
...
},
...
init(server, options) { // eslint-disable-line no-unused-vars
server.injectUiAppVars('logviewer', async () => {
var kibana_vars = await server.getInjectedUiAppVars('kibana');
var aggregated_vars = { ...kibana_vars, ...{ mycustomparameter: "some value" } }
return aggregated_vars
});
...
}
});
}
main.js
import chrome from 'ui/chrome';
. . .
const mycustomparameter = chrome.getInjected('mycustomparameter');
Providing that I manage to obtain parameters from URL, this would allow me to pass them to my app (via mycustomparameter), but again, I am not sure if this approach is correct.
I tried to get some help via the Elastic forum, but did not receive any answer yet.
My questions
1. Is there any source of information on this particular topic? I am aware of the fact that the plugin API changes frequently, hence I do not expect to find an extensive documentation. Maybe a good example?
Am I completely off course with the way I am trying to achieve it?
Thanks for reading this, any help would be much appreciated!

Related

How to restrict returned Wordpress REST-API fields when using WP-API Node Module

If I call this Wordpress blog url in a browser
<root...>wp-json/wp/v2/posts?per_page=5&fields=id,link,title
I get back JSON and the result is restricted to 3 fields
So how can I do this when using the node js wp-api module?
I would like something similar to .fields([]) but there is nothing in the docs, can find nothing in the module code.
TypeError: wpapi.posts(...).perPage(...).fields is not a function
Or something like .filter({})
TypeError: wpapi.posts(...).perPage(...).filter is not a function
But I think this might be connected with another Wordpress plugin that's required.
wpapi.posts()
.perPage(5)
.fields(['id','link','title'])
.search( 'search-term' ) //= (search in title or content)
.filter({
category_name: 'islands',
fields: [ 'id','link','title' ]
})
.get(function (err, data) {
..... etc.
TypeError: wpapi.posts(...).perPage(...).fields is not a function
Can anyone point me in the right direction? Thanks
It appears wp-api node module does not allow this.
So I uninstalled it and am now using axios along with standard text urls.
This worked for me:
wpapi.posts().param('_fields', 'id,title,content').get()
The node-wpapi documentation seems to suggest say that perPage() and functions like it are convenience functions that call param(props, value).
wpapi.posts().param('_fields', ['id','title','content']).get()
also seems to work but the first option gives a resulting request url that looks more like the format the Wordpress REST API Handbook uses

Sails v1 new machine-based actions and custom responses

I'm in the middle of upgrading our API from Sails v0.12 -> v1, which was prompted by the use of self-validating machines for controller actions. After finally getting through a ton of headache replacing deprecated code, I've landed in a rough spot...
With v0.12 (rather, with the older "req, res" controller style), one could use custom response handlers across the board. I've taken advantage of this, and have request logging at the end of all our response types (with some additional sugaring of data). This was done to log all requests in the database, so we can get insights into what our production servers are doing (because they are load-balanced, having a central place to view this is a must, and this was an easy route to take).
So now, my problem is moving forward with "Actions2" machine-style actions. How does one use these custom response types in these things? Are we being forced to repeat ourselves in our exists? I can't find any good documentation to help guide this process, nor can I find a consistent way to "hook" into the end of a response using machines as actions. I can't find any documentation on what kind of options machines can give to Sails.
#Nelson yes, I understand that, but at the time, that isn't what I wanted at all. I wanted all of the benefits of Actions2.
EDIT: While the original, crossed-out comment below does still work, the prefered way to use Actions2 and the custom responses folder paradigm, is to do something similar to the following in an Actions2 file:
module.exports = {
friendlyName: 'Human-friendly name of function',
description: 'Long description of function and what it does.',
inputs: {
userCommand: {
type: 'string',
required: true,
description: 'Long, human-readable description of the input'
}
},
exits: {
success: {
responseType: 'chatbotResponse'
}
},
fn: async function(inputs, exits){
// do some crazy stuff with the inputs, which has already been validated.
return exits.success('Woot');
}
}
This ultimately will route through the responses/chatbotResponse.js, which looks something similar to this:
module.exports = async function chatbotResponse(data){
let res = this.res,
req = this.req;
if (!data) {
data = 'Something didn\'t go as planned...';
}
// how to call a Node Machine style helper with named inputs
await sails.helpers.finalizeRequestLog.with({req: req, res: res, body: {plainString: data}});
return res.json(data);
};
ORIGINAL:
As it turns out, in the Actions2 function, you just need to add the env param async function(inputs, exists, env). The env will give you access to the req and res. So, if you have custom responses, that perform special tasks (like request logging), you can just use return await env.res.customResponse('Hurray, you made a successful call!');

IPython Javascript client API

Does IPython provide a Javascript client API for interfacing to a kernel server?
I had a look at https://ipython.org/ipython-doc/dev/development/messaging.html which explains the wire protocol between a front-end and a kernel.
I would be interested in finding out how the current web client communicates with a kernel and in particular how I could leverage JavaScript in order to programmatically create new notebooks from my own custom web client
Thanks
See https://gist.github.com/disarticulate/d06069ff3e71cf828e5329beab8cb084
There you can see a nice example:
// a very basic output handling
var handle_output = function (data) {console.log(data);}
//callbacks is an object whose so special, it appears to only have been documented in
//the source code, as no only google found me a link.
//callbacks.iopub.output is used to get the data from execute
var callbacks = {
iopub : {
output : handle_output,
}
}
//execute anything you want; if a string value is returned
//you can print it out and pass it to the callbacks
//(or do other things, no idea, it's poorly documented online
//(read the source F12->static/notebook/js/services/kernels/kernel.js)
//kernel.js/Kernel.prototype.execute
var kernel = IPython.notebook.kernel;
kernel.execute("print(json.dumps(python_dict))",callbacks)
You can see the definition going to in /static/services/kernels/kernel.js

Ember-cli , how do i change rest call on fly in the rest adapter

Im working on ember-cli, how do i change rest call on fly in the rest adapter. If i use path params not query params?for example:
export default DS.RESTAdapter.extend({
namespace:'res/v1/users/id',
pathForType: function() {
return Ember.String.underscore("friends");},});
Based on the user selection from dropdown we get the "id", using the id I need to get user friends from the database.
Could you please suggest a better way to do. My aapplication supports pathparams not the query params
To customize the URL, override the buildURL method in your adapter.
The tricky part is to access related records from the adapter. For example, you request friends for a given user. You work in a friend adapter, but you need to know the user's id to include it in the URL.
For that purpose, use the record property on the snapshot argument of the buildURL method.
Alternatively, you might want to override some of buildURL's underlying methods such as urlForFindQuery, depending on how you request your model from the store. With a find.query(), you will retrieve the id of the user from the query.
If this does not help you, please respond with the way you're trying to fetch friends from the store.
I have created a variable in enviroment.js 'userId'. When ever i select a user
i set config.userId in the controller to the corresponding Id.
config.userId=this.get('selectedUser');
In pathforType of adapter I used this varible
pathForType: function() {
return Ember.String.underscore(config.userId+"/friends");
}
you just need to add an import statement
import config from '../config/environment';
Please suggest me if anyone get to know better way. Thanks all for your responses
buildURL() only takes the type imo. so you have to pass some more jazz.
i did something along the lines of the following in the application adapter
$ ember generate adapter application
app/adapters/application.js
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
findQuery: function(store, type, query) {
var urlQuery = query.theshityouwant;
var reply = this.ajax(this.buildURL(type.typeKey + '/' + urlQuery), 'GET', { headers: all});
return reply;
},
})
});

Angular JS: Full example of GET/POST/DELETE/PUT client for a REST/CRUD backend?

I've implemented a REST/CRUD backend by following this article as an example: http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/ . I have MongoDB running locally, I'm not using MongoLabs.
I've followed the Google tutorial that uses ngResource and a Factory pattern and I have query (GET all items), get an item (GET), create an item (POST), and delete an item (DELETE) working. I'm having difficulty implementing PUT the way the backend API wants it -- a PUT to a URL that includes the id (.../foo/) and also includes the updated data.
I have this bit of code to define my services:
angular.module('realmenServices', ['ngResource']).
factory('RealMen', function($resource){
return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method:'PUT'},
remove: {method:'DELETE'}
});
I call the method from this controller code:
$scope.change = function() {
RealMen.update({entryId: $scope.entryId}, function() {
$location.path('/');
});
}
but when I call the update function, the URL does not include the ID value: it's only "/realmen", not "/realmen/ID".
I've tried various solutions involving adding a "RealMen.prototype.update", but still cannot get the entryId to show up on the URL. (It also looks like I'll have to build the JSON holding just the DB field values myself -- the POST operation does it for me automatically when creating a new entry, but there doesn't seem to be a data structure that only contains the field values when I'm viewing/editing a single entry).
Is there an example client app that uses all four verbs in the expected RESTful way?
I've also seen references to Restangular and another solution that overrides $save so that it can issue either a POST or PUT (http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/). This technology seems to be changing so rapidly that there doesn't seem to be a good reference solution that folks can use as an example.
I'm the creator of Restangular.
You can take a look at this CRUD example to see how you can PUT/POST/GET elements without all that URL configuration and $resource configuration that you need to do. Besides it, you can then use nested resources without any configuration :).
Check out this plunkr example:
http://plnkr.co/edit/d6yDka?p=preview
You could also see the README and check the documentation here https://github.com/mgonto/restangular
If you need some feature that's not there, just create an issue. I usually add features asked within a week, as I also use this library for all my AngularJS projects :)
Hope it helps!
Because your update uses PUT method, {entryId: $scope.entryId} is considered as data, to tell angular generate from the PUT data, you need to add params: {entryId: '#entryId'} when you define your update, which means
return $resource('http://localhost\\:3000/realmen/:entryId', {}, {
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method:'PUT', params: {entryId: '#entryId'}},
remove: {method:'DELETE'}
});
Fix: Was missing a closing curly brace on the update line.
You can implement this way
$resource('http://localhost\\:3000/realmen/:entryId', {entryId: '#entryId'}, {
UPDATE: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId' },
ACTION: {method: 'PUT', url: 'http://localhost\\:3000/realmen/:entryId/action' }
})
RealMen.query() //GET /realmen/
RealMen.save({entryId: 1},{post data}) // POST /realmen/1
RealMen.delete({entryId: 1}) //DELETE /realmen/1
//any optional method
RealMen.UPDATE({entryId:1}, {post data}) // PUT /realmen/1
//query string
RealMen.query({name:'john'}) //GET /realmen?name=john
Documentation:
https://docs.angularjs.org/api/ngResource/service/$resource
Hope it helps