mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Rendering: Add PDFRendering capability (#84438)
* Rendering: Add PDFRendering capability * fix tests
This commit is contained in:
parent
d3571c399a
commit
58170d4141
@ -3,6 +3,7 @@ package rendering
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
)
|
)
|
||||||
@ -17,7 +18,8 @@ type CapabilityName string
|
|||||||
const (
|
const (
|
||||||
ScalingDownImages CapabilityName = "ScalingDownImages"
|
ScalingDownImages CapabilityName = "ScalingDownImages"
|
||||||
FullHeightImages CapabilityName = "FullHeightImages"
|
FullHeightImages CapabilityName = "FullHeightImages"
|
||||||
SvgSanitization CapabilityName = "SvgSanitization"
|
SVGSanitization CapabilityName = "SvgSanitization"
|
||||||
|
PDFRendering CapabilityName = "PdfRendering"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrUnknownCapability = errors.New("unknown capability")
|
var ErrUnknownCapability = errors.New("unknown capability")
|
||||||
@ -55,3 +57,16 @@ func (rs *RenderingService) HasCapability(ctx context.Context, capability Capabi
|
|||||||
|
|
||||||
return CapabilitySupportRequestResult{IsSupported: compiledSemverConstraint.Check(compiledImageRendererVersion), SemverConstraint: semverConstraint}, nil
|
return CapabilitySupportRequestResult{IsSupported: compiledSemverConstraint.Check(compiledImageRendererVersion), SemverConstraint: semverConstraint}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rs *RenderingService) IsCapabilitySupported(ctx context.Context, capabilityName CapabilityName) error {
|
||||||
|
capability, err := rs.HasCapability(ctx, capabilityName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !capability.IsSupported {
|
||||||
|
return fmt.Errorf("%s unsupported, requires image renderer version: %s", capabilityName, capability.SemverConstraint)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -14,8 +14,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var netTransport = &http.Transport{
|
var netTransport = &http.Transport{
|
||||||
@ -40,10 +38,6 @@ var (
|
|||||||
|
|
||||||
func (rs *RenderingService) renderViaHTTP(ctx context.Context, renderType RenderType, renderKey string, opts Opts) (*RenderResult, error) {
|
func (rs *RenderingService) renderViaHTTP(ctx context.Context, renderType RenderType, renderKey string, opts Opts) (*RenderResult, error) {
|
||||||
if renderType == RenderPDF {
|
if renderType == RenderPDF {
|
||||||
if !rs.features.IsEnabled(ctx, featuremgmt.FlagNewPDFRendering) {
|
|
||||||
return nil, fmt.Errorf("feature 'newPDFRendering' disabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.Encoding = "pdf"
|
opts.Encoding = "pdf"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,7 @@ type Service interface {
|
|||||||
RenderErrorImage(theme models.Theme, error error) (*RenderResult, error)
|
RenderErrorImage(theme models.Theme, error error) (*RenderResult, error)
|
||||||
GetRenderUser(ctx context.Context, key string) (*RenderUser, bool)
|
GetRenderUser(ctx context.Context, key string) (*RenderUser, bool)
|
||||||
HasCapability(ctx context.Context, capability CapabilityName) (CapabilitySupportRequestResult, error)
|
HasCapability(ctx context.Context, capability CapabilityName) (CapabilitySupportRequestResult, error)
|
||||||
|
IsCapabilitySupported(ctx context.Context, capability CapabilityName) error
|
||||||
CreateRenderingSession(ctx context.Context, authOpts AuthOpts, sessionOpts SessionOpts) (Session, error)
|
CreateRenderingSession(ctx context.Context, authOpts AuthOpts, sessionOpts SessionOpts) (Session, error)
|
||||||
SanitizeSVG(ctx context.Context, req *SanitizeSVGRequest) (*SanitizeSVGResponse, error)
|
SanitizeSVG(ctx context.Context, req *SanitizeSVGRequest) (*SanitizeSVGResponse, error)
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,20 @@ func (mr *MockServiceMockRecorder) HasCapability(ctx, capability interface{}) *g
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasCapability", reflect.TypeOf((*MockService)(nil).HasCapability), ctx, capability)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasCapability", reflect.TypeOf((*MockService)(nil).HasCapability), ctx, capability)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCapabilitySupported mocks base method.
|
||||||
|
func (m *MockService) IsCapabilitySupported(ctx context.Context, capability CapabilityName) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "IsCapabilitySupported", ctx, capability)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCapabilitySupported indicates an expected call of IsCapabilitySupported.
|
||||||
|
func (mr *MockServiceMockRecorder) IsCapabilitySupported(ctx, capability interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCapabilitySupported", reflect.TypeOf((*MockService)(nil).IsCapabilitySupported), ctx, capability)
|
||||||
|
}
|
||||||
|
|
||||||
// IsAvailable mocks base method.
|
// IsAvailable mocks base method.
|
||||||
func (m *MockService) IsAvailable(ctx context.Context) bool {
|
func (m *MockService) IsAvailable(ctx context.Context) bool {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -6,15 +6,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rs *RenderingService) renderViaPlugin(ctx context.Context, renderType RenderType, renderKey string, opts Opts) (*RenderResult, error) {
|
func (rs *RenderingService) renderViaPlugin(ctx context.Context, renderType RenderType, renderKey string, opts Opts) (*RenderResult, error) {
|
||||||
if renderType == RenderPDF {
|
if renderType == RenderPDF {
|
||||||
if !rs.features.IsEnabled(ctx, featuremgmt.FlagNewPDFRendering) {
|
|
||||||
return nil, fmt.Errorf("feature 'newPDFRendering' disabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.Encoding = "pdf"
|
opts.Encoding = "pdf"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +125,13 @@ func ProvideService(cfg *setting.Cfg, features *featuremgmt.FeatureManager, remo
|
|||||||
semverConstraint: ">= 3.4.0",
|
semverConstraint: ">= 3.4.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: SvgSanitization,
|
name: SVGSanitization,
|
||||||
semverConstraint: ">= 3.5.0",
|
semverConstraint: ">= 3.5.0",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: PDFRendering,
|
||||||
|
semverConstraint: ">= 3.10.0",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Cfg: cfg,
|
Cfg: cfg,
|
||||||
features: features,
|
features: features,
|
||||||
@ -292,6 +296,16 @@ func (rs *RenderingService) render(ctx context.Context, renderType RenderType, o
|
|||||||
return rs.renderUnavailableImage(), nil
|
return rs.renderUnavailableImage(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if renderType == RenderPDF || opts.Encoding == "pdf" {
|
||||||
|
if !rs.features.IsEnabled(ctx, featuremgmt.FlagNewPDFRendering) {
|
||||||
|
return nil, fmt.Errorf("feature 'newPDFRendering' disabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rs.IsCapabilitySupported(ctx, PDFRendering); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rs.log.Info("Rendering", "path", opts.Path)
|
rs.log.Info("Rendering", "path", opts.Path)
|
||||||
if math.IsInf(opts.DeviceScaleFactor, 0) || math.IsNaN(opts.DeviceScaleFactor) || opts.DeviceScaleFactor == 0 {
|
if math.IsInf(opts.DeviceScaleFactor, 0) || math.IsNaN(opts.DeviceScaleFactor) || opts.DeviceScaleFactor == 0 {
|
||||||
opts.DeviceScaleFactor = 1
|
opts.DeviceScaleFactor = 1
|
||||||
@ -327,7 +341,7 @@ func (rs *RenderingService) RenderCSV(ctx context.Context, opts CSVOpts, session
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RenderingService) SanitizeSVG(ctx context.Context, req *SanitizeSVGRequest) (*SanitizeSVGResponse, error) {
|
func (rs *RenderingService) SanitizeSVG(ctx context.Context, req *SanitizeSVGRequest) (*SanitizeSVGResponse, error) {
|
||||||
capability, err := rs.HasCapability(ctx, SvgSanitization)
|
capability, err := rs.HasCapability(ctx, SVGSanitization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user