Grafana dashboard: Grafana Dashboard Exporter/Importer
Description: One button, which will export all Grafana dashboards and download them as a zip file + importer.

One button, which will export all dashboards and download them as a zip file with folder structure. Only Grafana API and html/css/js are used. Internet connection is required, because some js libraries are downloaded from CDN.

GitHub repo: [Grafana Utils](https://github.com/monitoringartist/grafana-utils)

Note:

Grafana 6+ users: The text panel does no longer by default allow unsantizied HTML, which is required to run custom Javascript code in the dashboard. To enable unsafe Javascript execution in text panels enable the settings disable_sanitize_html under the section [panels] in your Grafana ini file, or set env variable GF_PANELS_DISABLE_SANITIZE_HTML=true.

{
  "__inputs": [],
  "__requires": [
    {
      "type": "grafana",
      "id": "grafana",
      "name": "Grafana",
      "version": "5.0.0"
    },
    {
      "type": "panel",
      "id": "text",
      "name": "Text",
      "version": "5.0.0"
    }
  ],
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": "-- Grafana --",
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "type": "dashboard"
      }
    ]
  },
  "description": "One button, which will export all Grafana dashboards and download them as a zip file + importer.",
  "editable": false,
  "gnetId": 5837,
  "graphTooltip": 0,
  "id": null,
  "links": [],
  "panels": [
    {
      "content": "<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js'></script>\n<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.min.js'></script>\n<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js'></script>\n\n<script type='text/javascript'>\nfunction resetMessage () {\n    $(\"#result\")\n    .removeClass()\n    .text(\"\");\n    $(\"#apiresult2\")\n    .removeClass()\n    .text(\"\");\n}\nfunction showMessage(text, id) {\n    resetMessage();\n    $(id)\n    .addClass(\"alert alert-success\")\n    .text(text);\n}\nfunction showError(text, id) {\n    resetMessage();\n    $(id)\n    .addClass(\"alert alert-danger\")\n    .text(text);\n}\nfunction updatePercent(percent) {\n    $(\"#progress_bar\").removeClass(\"hide\")\n    .find(\".progress-bar\")\n    .attr(\"aria-valuenow\", percent)\n    .css({\n        width : percent + \"%\"\n    });\n}\n\nfunction urlToPromise(url) {\n    return new Promise(function(resolve, reject) {\n        JSZipUtils.getBinaryContent(url, function (err, data) {\n            if(err) {\n                reject(err);\n            } else {\n                resolve(data);\n            }\n        });\n    });\n}\n\nvar $form = $(\"#download_form\").on(\"submit\", function () {\n\n    resetMessage();\n    showMessage(\"Starting export ...\", \"#result\");\n    if(!JSZip.support.blob) {\n      showError(\"Sorry, this Grafana dashboard works only with a recent browser !\");\n      return;\n    }\n    var Promise = window.Promise;\n    if (!Promise) {\n      Promise = JSZip.external.Promise;\n    }\n\n    var zip = new JSZip();\n\n    // get all dashboards\n    $.ajax({\n        type: 'GET',\n        url: '/api/search',\n        data: 'query=&type=dash-db',\n        dataType: 'json',\n        async: false,\n        success: function (data) {\n            $.each(data, function(index, el) {\n              if ('folderTitle' in el) {\n                zipname = el.folderTitle.replace(/[:/]{1}/g,\"-\") + '/' + el.title.replace(/[:/]{1}/g,\"-\") + '.json';\n              } else {\n                zipname = el.title.replace(/[:/]{1}/g,\"-\") + '.json';\n              }\n              zip.file(zipname, urlToPromise(\"/api/dashboards/uid/\" + el.uid), {binary:true});\n            });\n        }\n    });\n\n    // when everything has been downloaded, we can trigger the dl\n    zip.generateAsync({type:\"blob\"}, function updateCallback(metadata) {\n        var msg = \"Exporting: \" + metadata.percent.toFixed(2) + \" %\";\n        if(metadata.currentFile) {\n            msg += \", processing dashboard: \" + metadata.currentFile;\n        }\n        showMessage(msg, \"#result\");\n        updatePercent(metadata.percent|0);\n    })\n    .then(function callback(blob) {\n        filename = \"grafana-dashboards-\" + new Date().getTime() + \".zip\";\n        saveAs(blob, filename);\n        showMessage(\"Done!\", \"#result\");\n    }, function (e) {\n        showError(e);\n    });\n\n    return false;\n});\n</script>\n\n<form action=\"#\" id=\"download_form\">\n    <button type=\"submit\" class=\"btn btn-primary\"><i class=\"fa fa-save\"></i> Download all dashboards</button>\n    <br/><br/>\n</form>\n\n<div class=\"progress hide\" id=\"progress_bar\">\n    <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width: 0%;\">\n    </div>\n</div>\n\n<p class=\"hide\" id=\"result\"></p>",
      "gridPos": {
        "h": 4,
        "w": 24,
        "x": 0,
        "y": 0
      },
      "id": 2,
      "links": [],
      "mode": "html",
      "title": "Grafana Dashboard Exporter",
      "transparent": true,
      "type": "text"
    },
    {
      "content": "<form>\n  <div class=\"gf-form-group\">\n    Content of one dashboard json file:\n    <textarea class=\"gf-form-input\" id=\"inputdata2\" name=\"inputdata2\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" style=\"height: 100px; width: 100%;\" wrap=\"off\"></textarea>\n    <br>\n    \n    <div class=\"gf-form-inline\">\n        <div class=\"gf-form max-width-12\">\n           <button type=\"submit\" class=\"btn btn-primary\" onClick=\"importDashboard(); return false;\"><i class=\"fa fa-upload\"></i> Import dasboard</button>\n        </div>\n        <!-- gf-form-switch class=\"gf-form\" label=\"Force Dashboard Overwrite\" checked=\"ctrl.current.isDefault\" switch-class=\"max-width-6\">\n        <label for=\"check-113\" class=\"gf-form-label width-16 pointer\" ng-show=\"ctrl.label\">\n          Force Dashboard Overwrite (TODO)\n        </label>\n        <div class=\"gf-form-switch max-width-6\" ng-if=\"ctrl.show\">\n          <input id=\"check-113\" ng-model=\"ctrl.checked\" ng-change=\"ctrl.internalOnChange()\" class=\"ng-pristine ng-untouched ng-valid ng-empty\" type=\"checkbox\">\n          <label for=\"check-113\" data-on=\"Yes\" data-off=\"No\"></label>\n        </div>\n        </gf-form-switch -->\n    </div>\n    <br/><br/>\n    <div id=\"apiresult2\"></div>\n  </div>\n</form>\n\n<script type=\"text/javascript\">\nfunction importDashboard() {\n  showMessage(\"Starting import ...\", \"#apiresult2\");\n  if ($('#inputdata2').val().trim() === \"\") {\n    showError(\"Error: empty input\", \"#apiresult2\");\n    return;\n  }\n  try {\n      postdata = JSON.parse($('#inputdata2').val());\n  } catch(e) {\n      showError(\"Error: JSON parser - \" + e, \"#apiresult2\");\n      return;\n  }\n  postdata[\"overwrite\"] = true;\n  \n  $.ajax({\n    type: 'POST',\n    url: \"/api/dashboards/db\",\n    data: JSON.stringify(postdata),\n    contentType: \"application/json\",\n    dataType: \"json\",\n    processData: false,\n    async: false,\n    success: function(data){\n      showMessage(\"API response: \" + JSON.stringify(data), \"#apiresult2\")\n    },\n    error: function(xhr, status, error) {\n      showMessage(\"request error: \" + error + status + xhr, \"#apiresult2\")\n    }\n  });\n}\n\n</script>",
      "gridPos": {
        "h": 8,
        "w": 24,
        "x": 0,
        "y": 4
      },
      "id": 9,
      "links": [],
      "mode": "html",
      "title": "Grafana Dashboard Importer",
      "transparent": true,
      "type": "text"
    },
    {
      "content": "<a style=\"float: right\" href=\"http://www.monitoringartist.com\" target=\"_blank\" title=\"Dashboard maintained by Monitoring Artist - DevOps / Docker / Kubernetes / AWS ECS / Google GCP / Zabbix / Zenoss / Terraform / Monitoring\"><img src=\"https://monitoringartist.github.io/monitoring-artist-logo-grafana.png\" height=\"30px\" /></a><a style=\"float: left\" target=\"_blank\" href=\"https://grafana.com/dashboards/5837\">Installed from Grafana.com dashboards</a>",
      "gridPos": {
        "h": 3,
        "w": 24,
        "x": 0,
        "y": 12
      },
      "id": 11,
      "links": [],
      "mode": "html",
      "title": "",
      "transparent": true,
      "type": "text"
    }
  ],
  "schemaVersion": 16,
  "style": "dark",
  "tags": [
    "monitoringartist"
  ],
  "templating": {
    "list": []
  },
  "time": {
    "from": "now-6h",
    "to": "now"
  },
  "timepicker": {
    "hidden": false,
    "refresh_intervals": [
      "5s",
      "10s",
      "30s",
      "1m",
      "5m",
      "15m",
      "30m",
      "1h",
      "2h",
      "1d"
    ],
    "time_options": [
      "5m",
      "15m",
      "1h",
      "6h",
      "12h",
      "24h",
      "2d",
      "7d",
      "30d"
    ]
  },
  "timezone": "",
  "title": "Grafana Dashboard Exporter/Importer",
  "uid": "ZyX4ZXtiz",
  "version": 5
}