import kibana dashboards and visualization using groovy

Kibana is a the official visualization tool for elasticsearch. But sooner or later, you want it or not, you'll need to migrate your kibana dashboard and visualizations.

Kibana already offer a tool to do this, using the export/import buttons, but I've two issues with this approachL
1- If the index does not yet exist, you can't import your visualizations
2- If you like automating things, this is not the best way for you, since you need to map each visualization to the index.

I like always automating things using scripts or automation tools, That's why I've wrote a small groovy script, that handle importing all the visualizations and dashboards from an old kibana instance. It uses elasticsearch api to create new dashboards/visualizations from the source of the old ones:

  @Grab('io.github.http-builder-ng:http-builder-ng-okhttp:1.0.2')
  import static groovyx.net.http.HttpBuilder.configure
  import static groovy.json.JsonOutput.toJson
  import groovy.transform.Field
  import groovy.json.*

  @Field String ES_HOST = "YOUR_ES_URL"
  Field String EXPORT_FILE = "YOUR_EXPORTED_DATA"
  def jsonSlurper = new JsonSlurper()
  def reader = new BufferedReader(new InputStreamReader(new FileInputStream(EXPORT_FILE),"UTF-8"))
  data = jsonSlurper.parse(reader)
  println '**** looking for indices ****'
  def map = indecesMap(data, jsonSlurper)
  map.each{ k, v -> println "History of changes => Old: ${k}, New: ${v}" }
  println '**** Importing dashboards and visualizations ****'
  data.each{
    if(it._type == "dashboard")
    addDashboard(it, map, jsonSlurper)
    else{
    addVisualization(it, map, jsonSlurper)
  }
  println '**** All done! ****'
  }

  void addDashboard(Object item, Map map, JsonSlurper js) {
    handleRequest('/.kibana/dashboard/' + item._id, toJson(item._source))
  }

  void addVisualization(Object item, Map map, JsonSlurper js) {
    handleRequest('/.kibana/visualization/' + item._id, toJson(item._source))
  }

  Map indecesMap(Object indices, JsonSlurper jsonSlurper){
    def indecesMap = [:];
    indices.each{
      def index = getIndexOfVisualisation(jsonSlurper, it._source)
      if(it._type == 'visualization' && index != null && !indecesMap.containsKey(index)){
        def newIndex = System.console().readLine "index ${index} found, do you wanna replace it ? (press enter to keep it! )"
        indecesMap.put(index, (newIndex == '')? index : newIndex)
      }
    }

    return indecesMap;
  }

  String getIndexOfVisualisation(JsonSlurper js, Object item){
    def meta = item.kibanaSavedObjectMeta.searchSourceJSON
    if(meta != null)
    return js.parseText(meta).index
    else
    println item._id
  }

  void handleRequest(String uri, String data){
    def posts = configure {
      request.uri = ES_HOST
      request.uri.path = uri
      request.contentType = 'application/json'
      // Replacing space with - bacause the request return 406
      request.body = data.replace(" - ", "-").replace(" ", "-")
      }.put()
    }

The code is also available on github. Please feel free to comment below or rise a github issue if you've any suggestion ;)