Rendering: Remove deprecated plugin support (#118809)

This commit is contained in:
Matheus Macabu
2026-02-27 09:25:09 +01:00
committed by GitHub
parent e780d81f78
commit 67afc3a2c1
4 changed files with 3 additions and 194 deletions

View File

@@ -124,7 +124,7 @@ docker run -d -p 3000:3000 --name=grafana \
## Build a custom Grafana Docker image
In the Grafana GitHub repository, the `packaging/docker/custom/` folder includes a `Dockerfile` that you can use to build a custom Grafana image. The `Dockerfile` accepts `GRAFANA_VERSION`, `GF_INSTALL_PLUGINS`, and `GF_INSTALL_IMAGE_RENDERER_PLUGIN` as build arguments.
In the Grafana GitHub repository, the `packaging/docker/custom/` folder includes a `Dockerfile` that you can use to build a custom Grafana image. The `Dockerfile` accepts `GRAFANA_VERSION` and `GF_INSTALL_PLUGINS` as build arguments.
The `GRAFANA_VERSION` build argument must be a valid `grafana/grafana` Docker image tag. By default, Grafana builds an Alpine-based image. To build an Ubuntu-based image, append `-ubuntu` to the `GRAFANA_VERSION` build argument.
@@ -145,30 +145,6 @@ docker build \
docker run -d -p 3000:3000 --name=grafana grafana-custom
```
### Build Grafana with the Image Renderer plugin pre-installed
> **Note:** This feature is experimental.
Currently, the Grafana Image Renderer plugin requires dependencies that are not available in the Grafana Docker image (see [GitHub Issue#301](https://github.com/grafana/grafana-image-renderer/issues/301) for more details). However, you can create a customized Docker image using the `GF_INSTALL_IMAGE_RENDERER_PLUGIN` build argument as a solution. This will install the necessary dependencies for the Grafana Image Renderer plugin to run.
Example:
The following example shows how to build a customized Grafana Docker image that includes the Image Renderer plugin.
```bash
# go to the folder
cd packaging/docker/custom
# running the build command
docker build \
--build-arg "GRAFANA_VERSION=latest" \
--build-arg "GF_INSTALL_IMAGE_RENDERER_PLUGIN=true" \
-t grafana-custom .
# running the docker run command
docker run -d -p 3000:3000 --name=grafana grafana-custom
```
### Build a Grafana Docker image with pre-installed plugins
If you run multiple Grafana installations with the same plugins, you can save time by building a customized image that includes plugins available on the [Grafana Plugin download page](/grafana/plugins). When you build a customized image, Grafana doesn't have to install the plugins each time it starts, making the startup process more efficient.

View File

@@ -2,8 +2,6 @@ ARG GRAFANA_VERSION="latest"
FROM grafana/grafana:${GRAFANA_VERSION}
ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false"
ARG GF_GID="0"
ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins"
@@ -12,39 +10,10 @@ ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/chrome"
USER root
RUN mkdir -p "$GF_PATHS_PLUGINS" && \
chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" && \
if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \
if grep -i -q alpine /etc/issue; then \
apk add --no-cache udev ttf-opensans chromium && \
ln -s /usr/bin/chromium-browser "$GF_PLUGIN_RENDERING_CHROME_BIN"; \
else \
cd /tmp && \
curl -sLO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
DEBIAN_FRONTEND=noninteractive && \
apt-get update -q && \
apt-get install -q -y ./google-chrome-stable_current_amd64.deb && \
rm -rf /var/lib/apt/lists/* && \
rm ./google-chrome-stable_current_amd64.deb && \
ln -s /usr/bin/google-chrome "$GF_PLUGIN_RENDERING_CHROME_BIN"; \
fi \
fi
chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS"
USER grafana
RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \
if grep -i -q alpine /etc/issue; then \
grafana-cli \
--pluginsDir "$GF_PATHS_PLUGINS" \
--pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-alpine-x64-no-chromium.zip \
plugins install grafana-image-renderer; \
else \
grafana-cli \
--pluginsDir "$GF_PATHS_PLUGINS" \
--pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \
plugins install grafana-image-renderer; \
fi \
fi
ARG GF_INSTALL_PLUGINS=""
RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \

View File

@@ -1,117 +0,0 @@
package rendering
import (
"context"
"errors"
"fmt"
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
)
func (rs *RenderingService) renderViaPlugin(ctx context.Context, renderType RenderType, renderKey string, opts Opts) (*RenderResult, error) {
logger := rs.log.FromContext(ctx)
// gives plugin some additional time to timeout and return possible errors.
ctx, cancel := context.WithTimeout(ctx, getRequestTimeout(opts.TimeoutOpts))
defer cancel()
filePath, err := rs.getNewFilePath(renderType)
if err != nil {
return nil, err
}
headers := map[string]*pluginextensionv2.StringList{}
for k, values := range opts.Headers {
headers[k] = &pluginextensionv2.StringList{
Values: values,
}
}
req := &pluginextensionv2.RenderRequest{
Url: rs.getGrafanaCallbackURL(opts.Path),
Width: int32(opts.Width),
Height: int32(opts.Height),
DeviceScaleFactor: float32(opts.DeviceScaleFactor),
FilePath: filePath,
Timeout: int32(opts.Timeout.Seconds()),
RenderKey: renderKey,
Timezone: isoTimeOffsetToPosixTz(opts.Timezone),
Domain: rs.domain,
Headers: headers,
AuthToken: rs.Cfg.RendererAuthToken,
Encoding: string(renderType),
}
logger.Debug("Calling renderer plugin", "req", req)
rc, err := rs.plugin.Client()
if err != nil {
return nil, err
}
rsp, err := rc.Render(ctx, req)
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
logger.Error("Rendering timed out")
return nil, ErrTimeout
}
if err != nil {
return nil, err
}
if rsp.Error != "" {
return nil, fmt.Errorf("rendering failed: %s", rsp.Error)
}
return &RenderResult{FilePath: filePath}, err
}
func (rs *RenderingService) renderCSVViaPlugin(ctx context.Context, renderKey string, opts CSVOpts) (*RenderCSVResult, error) {
logger := rs.log.FromContext(ctx)
// gives plugin some additional time to timeout and return possible errors.
ctx, cancel := context.WithTimeout(ctx, getRequestTimeout(opts.TimeoutOpts))
defer cancel()
filePath, err := rs.getNewFilePath(RenderCSV)
if err != nil {
return nil, err
}
headers := map[string]*pluginextensionv2.StringList{}
for k, values := range opts.Headers {
headers[k] = &pluginextensionv2.StringList{
Values: values,
}
}
req := &pluginextensionv2.RenderCSVRequest{
Url: rs.getGrafanaCallbackURL(opts.Path),
FilePath: filePath,
RenderKey: renderKey,
Domain: rs.domain,
Timeout: int32(opts.Timeout.Seconds()),
Timezone: isoTimeOffsetToPosixTz(opts.Timezone),
Headers: headers,
AuthToken: rs.Cfg.RendererAuthToken,
}
logger.Debug("Calling renderer plugin", "req", req)
rc, err := rs.plugin.Client()
if err != nil {
return nil, err
}
rsp, err := rc.RenderCSV(ctx, req)
if err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
logger.Error("Rendering timed out")
return nil, ErrTimeout
}
return nil, err
}
if rsp.Error != "" {
return nil, fmt.Errorf("rendering failed: %s", rsp.Error)
}
return &RenderCSVResult{FilePath: filePath, FileName: rsp.FileName}, nil
}

View File

@@ -34,7 +34,6 @@ var _ Service = (*RenderingService)(nil)
type RenderingService struct {
log log.Logger
plugin Plugin
renderAction renderFunc
renderCSVAction renderCSVFunc
domain string
@@ -42,7 +41,6 @@ type RenderingService struct {
version string
versionMutex sync.RWMutex
capabilities []Capability
pluginAvailable bool
rendererCallbackURL string
netClient *http.Client
@@ -126,8 +124,6 @@ func ProvideService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, remot
}
}
_, exists := rm.Renderer(context.Background())
netTransport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
@@ -176,7 +172,6 @@ func ProvideService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, remot
RendererPluginManager: rm,
log: logger,
domain: domain,
pluginAvailable: exists,
rendererCallbackURL: rendererCallbackURL,
netClient: netClient,
}
@@ -219,20 +214,6 @@ func (rs *RenderingService) Run(ctx context.Context) error {
}
}
if rp, exists := rs.RendererPluginManager.Renderer(ctx); exists {
rs.log = rs.log.New("renderer", "plugin")
rs.plugin = rp
if err := rs.plugin.Start(ctx); err != nil {
return err
}
rs.version = rp.Version()
rs.renderAction = rs.renderViaPlugin
rs.renderCSVAction = rs.renderCSVViaPlugin
<-ctx.Done()
return nil
}
rs.log.Debug("No image renderer found/installed. " +
"For image rendering support please use the Grafana Image Renderer remote rendering service. " +
"Read more at https://grafana.com/docs/grafana/latest/administration/image_rendering/")
@@ -246,7 +227,7 @@ func (rs *RenderingService) remoteAvailable() bool {
}
func (rs *RenderingService) IsAvailable(ctx context.Context) bool {
return rs.remoteAvailable() || rs.pluginAvailable
return rs.remoteAvailable()
}
func (rs *RenderingService) Version() string {