Image Rendering: Remove PhantomJS support (#23460)

Removes all references and usage of PhantomJS #23375.
Remove direct link rendered image e2e smoke test for now.
Docker: Fix installing chrome in ubuntu custom docker image.
Improve handling of image renderer not available/installed #23593.
Add PhantomJS breaking change and upgrading notes.
Use grabpl v0.2.10.

Closes #13802

Co-authored-by: Kyle Brandt <kyle@grafana.com>
Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>
This commit is contained in:
Marcus Efraimsson
2020-04-15 22:17:41 +02:00
committed by GitHub
co-authored by Kyle Brandt Arve Knudsen Diana Payton
parent 0a1ab60b8c
commit 6e313e7d37
38 changed files with 107 additions and 478 deletions
+1
View File
@@ -32,6 +32,7 @@ type RenderResult struct {
type renderFunc func(ctx context.Context, renderKey string, options Opts) (*RenderResult, error)
type Service interface {
IsAvailable() bool
Render(ctx context.Context, opts Opts) (*RenderResult, error)
RenderErrorImage(error error) (*RenderResult, error)
GetRenderUser(key string) (*RenderUser, bool)
-129
View File
@@ -1,129 +0,0 @@
package rendering
import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/grafana/grafana/pkg/infra/log"
)
func (rs *RenderingService) renderViaPhantomJS(ctx context.Context, renderKey string, opts Opts) (*RenderResult, error) {
var executable = "phantomjs"
if runtime.GOOS == "windows" {
executable = executable + ".exe"
}
url := rs.getURL(opts.Path)
binPath, _ := filepath.Abs(filepath.Join(rs.Cfg.PhantomDir, executable))
if _, err := os.Stat(binPath); os.IsNotExist(err) {
rs.log.Error("executable not found", "executable", binPath)
return nil, ErrPhantomJSNotInstalled
}
scriptPath, _ := filepath.Abs(filepath.Join(rs.Cfg.PhantomDir, "render.js"))
pngPath, err := rs.getFilePathForNewImage()
if err != nil {
return nil, err
}
phantomDebugArg := "--debug=false"
if log.GetLogLevelFor("rendering") >= log.LvlDebug {
phantomDebugArg = "--debug=true"
}
cmdArgs := []string{
"--ignore-ssl-errors=true",
"--web-security=true",
"--local-url-access=false",
phantomDebugArg,
scriptPath,
fmt.Sprintf("url=%v", url),
fmt.Sprintf("width=%v", opts.Width),
fmt.Sprintf("height=%v", opts.Height),
fmt.Sprintf("png=%v", pngPath),
fmt.Sprintf("domain=%v", rs.domain),
fmt.Sprintf("timeout=%v", opts.Timeout.Seconds()),
fmt.Sprintf("renderKey=%v", renderKey),
}
if opts.Encoding != "" {
cmdArgs = append([]string{fmt.Sprintf("--output-encoding=%s", opts.Encoding)}, cmdArgs...)
}
// gives phantomjs some additional time to timeout and return possible errors.
commandCtx, cancel := context.WithTimeout(ctx, opts.Timeout+time.Second*2)
defer cancel()
cmd := exec.CommandContext(commandCtx, binPath, cmdArgs...)
cmd.Stderr = cmd.Stdout
timezone := ""
cmd.Env = os.Environ()
if opts.Timezone != "" {
timezone = isoTimeOffsetToPosixTz(opts.Timezone)
cmd.Env = appendEnviron(cmd.Env, "TZ", timezone)
}
// Added to disable usage of newer version of OPENSSL
// that seem to be incompatible with PhantomJS (used in Debian Buster)
if runtime.GOOS == "linux" {
disableNewOpenssl := "/etc/ssl"
cmd.Env = appendEnviron(cmd.Env, "OPENSSL_CONF", disableNewOpenssl)
}
rs.log.Debug("executing Phantomjs", "binPath", binPath, "cmdArgs", cmdArgs, "timezone", timezone)
out, err := cmd.Output()
if out != nil {
rs.log.Debug("Phantomjs output", "out", string(out))
}
if err != nil {
rs.log.Debug("Phantomjs error", "error", err)
}
// check for timeout first
if commandCtx.Err() == context.DeadlineExceeded {
rs.log.Info("Rendering timed out")
return nil, ErrTimeout
}
if err != nil {
rs.log.Error("Phantomjs exited with non zero exit code", "error", err)
return nil, err
}
rs.log.Debug("Image rendered", "path", pngPath)
return &RenderResult{FilePath: pngPath}, nil
}
func isoTimeOffsetToPosixTz(isoOffset string) string {
// invert offset
if strings.HasPrefix(isoOffset, "UTC+") {
return strings.Replace(isoOffset, "UTC+", "UTC-", 1)
}
if strings.HasPrefix(isoOffset, "UTC-") {
return strings.Replace(isoOffset, "UTC-", "UTC+", 1)
}
return isoOffset
}
func appendEnviron(baseEnviron []string, name string, value string) []string {
results := make([]string, 0)
prefix := fmt.Sprintf("%s=", name)
for _, v := range baseEnviron {
if !strings.HasPrefix(v, prefix) {
results = append(results, v)
}
}
return append(results, fmt.Sprintf("%s=%s", name, value))
}
+28 -17
View File
@@ -6,6 +6,7 @@ import (
"net/url"
"os"
"path/filepath"
"strings"
"time"
"github.com/grafana/grafana/pkg/infra/remotecache"
@@ -23,8 +24,6 @@ func init() {
registry.RegisterService(&RenderingService{})
}
var IsPhantomJSEnabled = false
const renderKeyPrefix = "render-%s"
type RenderUser struct {
@@ -76,30 +75,31 @@ func (rs *RenderingService) Run(ctx context.Context) error {
return nil
}
if plugins.Renderer == nil {
rs.log = rs.log.New("renderer", "phantomJS")
rs.log.Info("Backend rendering via phantomJS")
rs.log.Warn("phantomJS is deprecated and will be removed in a future release. " +
"You should consider migrating from phantomJS to grafana-image-renderer plugin. " +
"Read more at https://grafana.com/docs/grafana/latest/administration/image_rendering/")
rs.renderAction = rs.renderViaPhantomJS
IsPhantomJSEnabled = true
if plugins.Renderer != nil {
rs.log = rs.log.New("renderer", "plugin")
rs.pluginInfo = plugins.Renderer
if err := rs.startPlugin(ctx); err != nil {
return err
}
rs.renderAction = rs.renderViaPlugin
<-ctx.Done()
return nil
}
rs.log = rs.log.New("renderer", "plugin")
rs.pluginInfo = plugins.Renderer
rs.log.Debug("No image renderer found/installed. " +
"For image rendering support please install the grafana-image-renderer plugin. " +
"Read more at https://grafana.com/docs/grafana/latest/administration/image_rendering/")
if err := rs.startPlugin(ctx); err != nil {
return err
}
rs.renderAction = rs.renderViaPlugin
<-ctx.Done()
return nil
}
func (rs *RenderingService) IsAvailable() bool {
return rs.renderAction != nil
}
func (rs *RenderingService) RenderErrorImage(err error) (*RenderResult, error) {
imgUrl := "public/img/rendering_error.png"
@@ -209,3 +209,14 @@ func (rs *RenderingService) deleteRenderKey(key string) {
rs.log.Error("Failed to delete render key", "error", err)
}
}
func isoTimeOffsetToPosixTz(isoOffset string) string {
// invert offset
if strings.HasPrefix(isoOffset, "UTC+") {
return strings.Replace(isoOffset, "UTC+", "UTC-", 1)
}
if strings.HasPrefix(isoOffset, "UTC-") {
return strings.Replace(isoOffset, "UTC-", "UTC+", 1)
}
return isoOffset
}