mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Swagger: Show k8s APIs (#78091)
This commit is contained in:
parent
e4d41e878f
commit
b8e8d84ef7
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -467,7 +467,6 @@ cypress.config.js @grafana/grafana-frontend-platform
|
|||||||
/public/test/ @grafana/grafana-frontend-platform
|
/public/test/ @grafana/grafana-frontend-platform
|
||||||
/public/test/helpers/alertingRuleEditor.tsx @grafana/alerting-frontend
|
/public/test/helpers/alertingRuleEditor.tsx @grafana/alerting-frontend
|
||||||
/public/views/ @grafana/grafana-frontend-platform
|
/public/views/ @grafana/grafana-frontend-platform
|
||||||
/public/views/openapi3.html @grafana/backend-platform
|
|
||||||
/public/views/swagger.html @grafana/backend-platform
|
/public/views/swagger.html @grafana/backend-platform
|
||||||
|
|
||||||
/public/app/features/explore/Logs/ @grafana/observability-logs
|
/public/app/features/explore/Logs/ @grafana/observability-logs
|
||||||
|
@ -27,7 +27,7 @@ Since version 8.4, HTTP API details are [specified](https://editor.swagger.io/?u
|
|||||||
|
|
||||||
Starting from version 9.1, there is also a [OpenAPI v3 specification](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/public/openapi3.json) (generated by the v2 one).
|
Starting from version 9.1, there is also a [OpenAPI v3 specification](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/public/openapi3.json) (generated by the v2 one).
|
||||||
|
|
||||||
Users can browser and try out both via the Swagger UI editor (served by the grafana server) by navigating to `/swagger-ui` and `/openapi3` respectively.
|
Users can browser and try out both via the Swagger UI editor (served by the grafana server) by navigating to `/swagger`.
|
||||||
|
|
||||||
## Authenticating API requests
|
## Authenticating API requests
|
||||||
|
|
||||||
|
@ -79,4 +79,4 @@ make swagger-clean && make openapi3-gen
|
|||||||
|
|
||||||
They can observe its output into the `public/api-merged.json` and `public/openapi3.json` files.
|
They can observe its output into the `public/api-merged.json` and `public/openapi3.json` files.
|
||||||
|
|
||||||
Finally, they can browser and try out both the OpenAPI v2 and v3 via the Swagger UI editor (served by the grafana server) by navigating to `/swagger-ui` and `/openapi3` respectively.
|
Finally, they can browser and try out both the OpenAPI v2 and v3 via the Swagger UI editor (served by the grafana server) by navigating to `/swagger`.
|
||||||
|
@ -213,8 +213,8 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
// expose plugin file system assets
|
// expose plugin file system assets
|
||||||
r.Get("/public/plugins/:pluginId/*", hs.getPluginAssets)
|
r.Get("/public/plugins/:pluginId/*", hs.getPluginAssets)
|
||||||
|
|
||||||
r.Get("/swagger-ui", swaggerUI)
|
// add swagger support
|
||||||
r.Get("/openapi3", openapi3)
|
registerSwaggerUI(r)
|
||||||
|
|
||||||
if hs.Features.IsEnabledGlobally(featuremgmt.FlagClientTokenRotation) {
|
if hs.Features.IsEnabledGlobally(featuremgmt.FlagClientTokenRotation) {
|
||||||
r.Post("/api/user/auth-tokens/rotate", routing.Wrap(hs.RotateUserAuthToken))
|
r.Post("/api/user/auth-tokens/rotate", routing.Wrap(hs.RotateUserAuthToken))
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func openapi3(c *contextmodel.ReqContext) {
|
|
||||||
data := map[string]any{
|
|
||||||
"Nonce": c.RequestNonce,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add CSP for unpkg.com to allow loading of Swagger UI assets
|
|
||||||
if existingCSP := c.Resp.Header().Get("Content-Security-Policy"); existingCSP != "" {
|
|
||||||
newCSP := strings.Replace(existingCSP, "style-src", "style-src https://unpkg.com/", 1)
|
|
||||||
c.Resp.Header().Set("Content-Security-Policy", newCSP)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "openapi3", data)
|
|
||||||
}
|
|
@ -4,19 +4,31 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func swaggerUI(c *contextmodel.ReqContext) {
|
func registerSwaggerUI(r routing.RouteRegister) {
|
||||||
data := map[string]any{
|
// Deprecated
|
||||||
"Nonce": c.RequestNonce,
|
r.Get("/swagger-ui", func(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
http.Redirect(w, r, "swagger", http.StatusMovedPermanently)
|
||||||
|
})
|
||||||
|
// Deprecated
|
||||||
|
r.Get("/openapi3", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Redirect(w, r, "swagger?show=v3", http.StatusMovedPermanently)
|
||||||
|
})
|
||||||
|
|
||||||
// Add CSP for unpkg.com to allow loading of Swagger UI assets
|
r.Get("/swagger", func(c *contextmodel.ReqContext) {
|
||||||
if existingCSP := c.Resp.Header().Get("Content-Security-Policy"); existingCSP != "" {
|
data := map[string]any{
|
||||||
newCSP := strings.Replace(existingCSP, "style-src", "style-src https://unpkg.com/", 1)
|
"Nonce": c.RequestNonce,
|
||||||
c.Resp.Header().Set("Content-Security-Policy", newCSP)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "swagger", data)
|
// Add CSP for unpkg.com to allow loading of Swagger UI assets
|
||||||
|
if existingCSP := c.Resp.Header().Get("Content-Security-Policy"); existingCSP != "" {
|
||||||
|
newCSP := strings.Replace(existingCSP, "style-src", "style-src https://unpkg.com/", 1)
|
||||||
|
c.Resp.Header().Set("Content-Security-Policy", newCSP)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "swagger", data)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Swagger UI</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui.css" integrity="sha384-pzdBB6iZwPIzBHgXle+9cgvKuMgtWNrBopXkjrWnKCi3m4uJsPPdLQ4IPMqRDirS" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
|
||||||
<style>
|
|
||||||
html
|
|
||||||
{
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: -moz-scrollbars-vertical;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after
|
|
||||||
{
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body
|
|
||||||
{
|
|
||||||
margin:0;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="swagger-ui"></div>
|
|
||||||
|
|
||||||
<script nonce="[[.Nonce]]" src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-bundle.js" charset="UTF-8" integrity="sha384-BGJ5JzR5LEl4ETmxXXlZtXtMWj3uQ9jj9/OHe3yrn5rrtAyLOz1SyyzwMfuwZgPc" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
||||||
<script nonce="[[.Nonce]]" src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-standalone-preset.js" charset="UTF-8" integrity="sha384-AWSfISmlS8fS336GXRkpL0Uv6EbCpsFfXDUwmklhbb3SctGSuvXWBcbjERjgf/e4" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
||||||
<script nonce="[[.Nonce]]">
|
|
||||||
window.onload = function() {
|
|
||||||
// Begin Swagger UI call region
|
|
||||||
const ui = SwaggerUIBundle({
|
|
||||||
url: "/public/openapi3.json",
|
|
||||||
dom_id: '#swagger-ui',
|
|
||||||
deepLinking: true,
|
|
||||||
presets: [
|
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout",
|
|
||||||
filter: true,
|
|
||||||
tagsSorter: "alpha",
|
|
||||||
tryItOutEnabled: true
|
|
||||||
});
|
|
||||||
// End Swagger UI call region
|
|
||||||
|
|
||||||
window.ui = ui;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,15 +1,21 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
<!-- HTML for static distribution bundle build -->
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<title>Swagger UI</title>
|
<title>Swagger UI</title>
|
||||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui.css" integrity="sha384-pzdBB6iZwPIzBHgXle+9cgvKuMgtWNrBopXkjrWnKCi3m4uJsPPdLQ4IPMqRDirS" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
<link
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
rel="stylesheet"
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
type="text/css"
|
||||||
|
href="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui.css"
|
||||||
|
integrity="sha384-pzdBB6iZwPIzBHgXle+9cgvKuMgtWNrBopXkjrWnKCi3m4uJsPPdLQ4IPMqRDirS"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>
|
||||||
|
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
|
||||||
<style>
|
<style>
|
||||||
html
|
html {
|
||||||
{
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: -moz-scrollbars-vertical;
|
overflow: -moz-scrollbars-vertical;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
@ -17,47 +23,85 @@
|
|||||||
|
|
||||||
*,
|
*,
|
||||||
*:before,
|
*:before,
|
||||||
*:after
|
*:after {
|
||||||
{
|
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
body
|
body {
|
||||||
{
|
margin: 0;
|
||||||
margin:0;
|
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topbar-wrapper img {
|
||||||
|
content: url('public/img/grafana_icon.svg');
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="swagger-ui"></div>
|
<div id="swagger-ui"></div>
|
||||||
|
|
||||||
<script nonce="[[.Nonce]]" src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-bundle.js" charset="UTF-8" integrity="sha384-BGJ5JzR5LEl4ETmxXXlZtXtMWj3uQ9jj9/OHe3yrn5rrtAyLOz1SyyzwMfuwZgPc" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
<script
|
||||||
<script nonce="[[.Nonce]]" src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-standalone-preset.js" charset="UTF-8" integrity="sha384-AWSfISmlS8fS336GXRkpL0Uv6EbCpsFfXDUwmklhbb3SctGSuvXWBcbjERjgf/e4" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
nonce="[[.Nonce]]"
|
||||||
|
src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-bundle.js"
|
||||||
|
charset="UTF-8"
|
||||||
|
integrity="sha384-BGJ5JzR5LEl4ETmxXXlZtXtMWj3uQ9jj9/OHe3yrn5rrtAyLOz1SyyzwMfuwZgPc"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
nonce="[[.Nonce]]"
|
||||||
|
src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-standalone-preset.js"
|
||||||
|
charset="UTF-8"
|
||||||
|
integrity="sha384-AWSfISmlS8fS336GXRkpL0Uv6EbCpsFfXDUwmklhbb3SctGSuvXWBcbjERjgf/e4"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
<script nonce="[[.Nonce]]">
|
<script nonce="[[.Nonce]]">
|
||||||
window.onload = function() {
|
window.onload = async function () {
|
||||||
// Begin Swagger UI call region
|
// the trailing slash breaks relative URL loading
|
||||||
const ui = SwaggerUIBundle({
|
if (window.location.pathname.endsWith('/')) {
|
||||||
url: "/public/api-merged.json",
|
const idx = window.location.href.lastIndexOf('/');
|
||||||
dom_id: '#swagger-ui',
|
window.location.href = window.location.href.substring(0, idx);
|
||||||
deepLinking: true,
|
return;
|
||||||
presets: [
|
}
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout",
|
|
||||||
filter: true,
|
|
||||||
tagsSorter: "alpha",
|
|
||||||
tryItOutEnabled: true
|
|
||||||
});
|
|
||||||
// End Swagger UI call region
|
|
||||||
|
|
||||||
window.ui = ui;
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
};
|
const v2 = { name: 'Grafana API (OpenAPI v2)', url: 'public/api-merged.json' };
|
||||||
</script>
|
const v3 = { name: 'Grafana API (OpenAPI v3)', url: 'public/openapi3.json' };
|
||||||
|
const urls = urlParams.get('show') == 'v3' ? [v3, v2] : [v2, v3];
|
||||||
|
try {
|
||||||
|
const rsp = await fetch('openapi/v3');
|
||||||
|
const apis = await rsp.json();
|
||||||
|
for (const [key, value] of Object.entries(apis.paths)) {
|
||||||
|
const parts = key.split('/');
|
||||||
|
if (parts.length == 3) {
|
||||||
|
urls.push({
|
||||||
|
name: `${parts[1]}/${parts[2]}`,
|
||||||
|
url: value.serverRelativeURL.substring(1), // remove initial slash
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
urls.push({ name: 'Grafana apps (OpenAPI v2)', url: 'openapi/v2' });
|
||||||
|
} catch (err) {
|
||||||
|
// console.warn('Error loading k8s apis', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin Swagger UI call region
|
||||||
|
const ui = SwaggerUIBundle({
|
||||||
|
urls,
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
deepLinking: true,
|
||||||
|
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
|
||||||
|
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
|
||||||
|
layout: 'StandaloneLayout',
|
||||||
|
filter: true,
|
||||||
|
tagsSorter: 'alpha',
|
||||||
|
tryItOutEnabled: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
window.ui = ui;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user