new attribute interpreter for commands (#7)

This commit is contained in:
Julien Neuhart
2018-05-16 10:55:08 +02:00
committed by GitHub
parent faec55dd01
commit 5100693789
15 changed files with 102 additions and 25 deletions

View File

@@ -17,12 +17,15 @@ commands:
# Unlike others commands' templates, you have access to FilesPaths instead of FilePath: it gathers all PDF files which should be merged. # Unlike others commands' templates, you have access to FilesPaths instead of FilePath: it gathers all PDF files which should be merged.
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
# The command template: you have access to FilePath and ResultFilePath variables. # The command template: you have access to FilePath and ResultFilePath variables.
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
# The binary which will call the command.
interpreter: "/bin/sh -c"
# Duration in seconds after which the command will be killed if it has not finished. # Duration in seconds after which the command will be killed if it has not finished.
timeout: 30 timeout: 30
# Files with the following extensions will be converted by the current command. # Files with the following extensions will be converted by the current command.
@@ -30,12 +33,14 @@ commands:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -8,18 +8,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,22 +5,27 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 0 timeout: 0
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 0 timeout: 0
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 0 timeout: 0
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 0 timeout: 0
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 0 timeout: 0
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -5,18 +5,22 @@ logs:
commands: commands:
merge: merge:
template: "pdftk {{ range $filePath := FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" template: "pdftk {{ range $filePath := FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
conversions: conversions:
- template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}" - template: "markdown-pdf {{ .FilePath }} -o {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".md" - ".md"
- template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" - template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}"
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".html" - ".html"
- ".htm" - ".htm"
- template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" - template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\""
interpreter: "/bin/sh -c"
timeout: 30 timeout: 30
extensions: extensions:
- ".doc" - ".doc"

View File

@@ -8,6 +8,7 @@ package config
import ( import (
"fmt" "fmt"
"strings"
"text/template" "text/template"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@@ -29,6 +30,8 @@ type (
Command struct { Command struct {
// Template is the data-driven template of the command. // Template is the data-driven template of the command.
Template *template.Template Template *template.Template
// The binary which will call the command.
Interpreter []string
// Timeout is the duration in seconds after which the command's process will be killed // Timeout is the duration in seconds after which the command's process will be killed
// if it does not finish before. // if it does not finish before.
Timeout int Timeout int
@@ -123,15 +126,29 @@ func GetLogsFormatter() logrus.Formatter {
return config.logsFormatter return config.logsFormatter
} }
type interpreterEmptyError struct {
command string
}
const interpreterEmptyErrorMessage = "the interepreter for command %s should not be empty"
func (e *interpreterEmptyError) Error() string {
return fmt.Sprintf(interpreterEmptyErrorMessage, e.command)
}
// NewCommand instantiates a Command. If the given command string // NewCommand instantiates a Command. If the given command string
// is not a valid template, throws an error. // is not a valid template, throws an error.
func NewCommand(command string, timeout int) (*Command, error) { func NewCommand(command string, interpreter string, timeout int) (*Command, error) {
t, err := template.New(command).Parse(command) t, err := template.New(command).Parse(command)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Command{t, timeout}, nil if interpreter == "" {
return nil, &interpreterEmptyError{command}
}
return &Command{t, strings.Fields(interpreter), timeout}, nil
} }
type fileExtensionAlreadyUsedError struct { type fileExtensionAlreadyUsedError struct {
@@ -140,7 +157,7 @@ type fileExtensionAlreadyUsedError struct {
existingCommand *Command existingCommand *Command
} }
const fileExtensionAlreadyUsedErrorMessage = "file extension '%s' from command '%s' is already used by command '%s'" const fileExtensionAlreadyUsedErrorMessage = "file extension %s from command %s is already used by command %s"
func (e *fileExtensionAlreadyUsedError) Error() string { func (e *fileExtensionAlreadyUsedError) Error() string {
return fmt.Sprintf(fileExtensionAlreadyUsedErrorMessage, e.extension, e.command.Template.Name(), e.existingCommand.Template.Name()) return fmt.Sprintf(fileExtensionAlreadyUsedErrorMessage, e.extension, e.command.Template.Name(), e.existingCommand.Template.Name())
@@ -167,7 +184,7 @@ type noCommandFoundForFileExtensionError struct {
extension string extension string
} }
const noCommandFoundForFileExtensionErrorMessage = "no command found for file extension '%s'" const noCommandFoundForFileExtensionErrorMessage = "no command found for file extension %s"
func (e *noCommandFoundForFileExtensionError) Error() string { func (e *noCommandFoundForFileExtensionError) Error() string {
return fmt.Sprintf(noCommandFoundForFileExtensionErrorMessage, e.extension) return fmt.Sprintf(noCommandFoundForFileExtensionErrorMessage, e.extension)

View File

@@ -99,26 +99,39 @@ func TestGetLogsFormatter(t *testing.T) {
} }
} }
func TestInterpreterEmptyError(t *testing.T) {
err := &interpreterEmptyError{"echo hello world"}
expected := fmt.Sprintf(interpreterEmptyErrorMessage, err.command)
if err.Error() != expected {
t.Errorf("Error returned a wrong message: got '%s' want '%s'", err.Error(), expected)
}
}
func TestNewCommand(t *testing.T) { func TestNewCommand(t *testing.T) {
var cmd string var cmd string
// case 1: uses a wrong command template. // case 1: uses a wrong command template.
cmd = "pdftk {{ range $filePath := FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" cmd = "pdftk {{ range $filePath := FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
if _, err := NewCommand(cmd, 0); err == nil { if _, err := NewCommand(cmd, "/bin/sh -c", 0); err == nil {
t.Errorf("Command should not have been instantiated by using '%s' as command template", cmd) t.Errorf("Command should not have been instantiated by using '%s' as command template", cmd)
} }
// case 2: uses a correct command template. // case 2: uses a correct command template.
cmd = "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" cmd = "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}"
if _, err := NewCommand(cmd, 0); err != nil { if _, err := NewCommand(cmd, "/bin/sh -c", 0); err != nil {
t.Errorf("Command should have been instantiated by using '%s' as command template", cmd) t.Errorf("Command should have been instantiated by using '%s' as command template", cmd)
} }
// case 3: uses an empty interpreter.
if _, err := NewCommand(cmd, "", 0); err == nil {
t.Error("Command should not have been instantiated by using an empty interpreter")
}
} }
func TestFileExtensionAlreadyUsedError(t *testing.T) { func TestFileExtensionAlreadyUsedError(t *testing.T) {
ext := ".pdf" ext := ".pdf"
cmd1, _ := NewCommand("echo", 0) cmd1, _ := NewCommand("echo", "/bin/sh -c", 0)
cmd2, _ := NewCommand("echo", 0) cmd2, _ := NewCommand("echo", "/bin/sh -c", 0)
err := &fileExtensionAlreadyUsedError{ext, cmd1, cmd2} err := &fileExtensionAlreadyUsedError{ext, cmd1, cmd2}
expected := fmt.Sprintf(fileExtensionAlreadyUsedErrorMessage, err.extension, err.command.Template.Name(), err.existingCommand.Template.Name()) expected := fmt.Sprintf(fileExtensionAlreadyUsedErrorMessage, err.extension, err.command.Template.Name(), err.existingCommand.Template.Name())
@@ -129,7 +142,7 @@ func TestFileExtensionAlreadyUsedError(t *testing.T) {
func TestWithCommand(t *testing.T) { func TestWithCommand(t *testing.T) {
ext := ".pdf" ext := ".pdf"
cmd, _ := NewCommand("echo", 0) cmd, _ := NewCommand("echo", "/bin/sh -c", 0)
// case 1: uses a command with a file extension not already referenced. // case 1: uses a command with a file extension not already referenced.
if err := WithCommand(ext, cmd); err != nil { if err := WithCommand(ext, cmd); err != nil {
@@ -154,7 +167,7 @@ func TestNoCommandFoundForFileExtensionError(t *testing.T) {
func TestGetCommand(t *testing.T) { func TestGetCommand(t *testing.T) {
Reset() Reset()
ext := ".pdf" ext := ".pdf"
cmd, _ := NewCommand("echo", 0) cmd, _ := NewCommand("echo", "/bin/sh -c", 0)
WithCommand(ext, cmd) WithCommand(ext, cmd)
// case 1: uses a file extension which has a command associated. // case 1: uses a file extension which has a command associated.

View File

@@ -24,7 +24,7 @@ func ParseFile(configurationFilePath string) error {
} }
// handles merge command first... // handles merge command first...
cmd, err := NewCommand(fileConfig.Commands.Merge.Template, fileConfig.Commands.Merge.Timeout) cmd, err := NewCommand(fileConfig.Commands.Merge.Template, fileConfig.Commands.Merge.Interpreter, fileConfig.Commands.Merge.Timeout)
if err != nil { if err != nil {
return err return err
} }
@@ -33,7 +33,7 @@ func ParseFile(configurationFilePath string) error {
// ...then conversion commands! // ...then conversion commands!
for _, command := range fileConfig.Commands.Conversions { for _, command := range fileConfig.Commands.Conversions {
cmd, err := NewCommand(command.Template, command.Timeout) cmd, err := NewCommand(command.Template, command.Interpreter, command.Timeout)
if err != nil { if err != nil {
return err return err
} }
@@ -64,15 +64,17 @@ type (
// mergeCommand gathers all data regarding the... merge command. // mergeCommand gathers all data regarding the... merge command.
mergeCommand struct { mergeCommand struct {
Template string `yaml:"template"` Template string `yaml:"template"`
Timeout int `yaml:"timeout"` Interpreter string `yaml:"interpreter"`
Timeout int `yaml:"timeout"`
} }
// conversionCommand gathers all data regarding a conversion command. // conversionCommand gathers all data regarding a conversion command.
conversionCommand struct { conversionCommand struct {
Template string `yaml:"template"` Template string `yaml:"template"`
Timeout int `yaml:"timeout"` Interpreter string `yaml:"interpreter"`
Extensions []string `yaml:"extensions"` Timeout int `yaml:"timeout"`
Extensions []string `yaml:"extensions"`
} }
) )

View File

@@ -24,7 +24,7 @@ type commandTimeoutError struct {
timeout int timeout int
} }
const commandTimeoutErrorMessage = "the command '%s' has reached the %d second(s) timeout" const commandTimeoutErrorMessage = "the command %s has reached the %d second(s) timeout"
func (e *commandTimeoutError) Error() string { func (e *commandTimeoutError) Error() string {
return fmt.Sprintf(commandTimeoutErrorMessage, e.command, e.timeout) return fmt.Sprintf(commandTimeoutErrorMessage, e.command, e.timeout)
@@ -32,11 +32,13 @@ func (e *commandTimeoutError) Error() string {
// run runs the given command. If timeout is reached or // run runs the given command. If timeout is reached or
// something bad happened, returns an error. // something bad happened, returns an error.
func (r *runner) run(command string, timeout int) error { func (r *runner) run(command string, interpreter []string, timeout int) error {
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock() defer r.mu.Unlock()
cmd := exec.Command("/bin/sh", "-c", command) binary := interpreter[0]
parameters := append(interpreter[1:], command)
cmd := exec.Command(binary, parameters...)
logger.Debugf("executing command %s", cmd.Args) logger.Debugf("executing command %s", cmd.Args)
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
@@ -85,7 +87,7 @@ func Unconv(workingDir string, file *gfile.File) (string, error) {
return "", err return "", err
} }
err = forest.run(data.String(), cmd.Timeout) err = forest.run(data.String(), cmd.Interpreter, cmd.Timeout)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -114,7 +116,7 @@ func Merge(workingDir string, filesPaths []string) (string, error) {
return "", err return "", err
} }
err = forest.run(data.String(), cmd.Timeout) err = forest.run(data.String(), cmd.Interpreter, cmd.Timeout)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"testing" "testing"
"github.com/thecodingmachine/gotenberg/app/config" "github.com/thecodingmachine/gotenberg/app/config"
@@ -42,19 +43,19 @@ func TestRun(t *testing.T) {
// case 1: uses a simple command. // case 1: uses a simple command.
cmd = "echo Hello world" cmd = "echo Hello world"
if err := forest.run(cmd, 30); err != nil { if err := forest.run(cmd, strings.Fields("/bin/sh -c"), 30); err != nil {
t.Errorf("Command '%s' should have worked", cmd) t.Errorf("Command '%s' should have worked", cmd)
} }
// case 2: uses a simple command but with an unsuitable timeout. // case 2: uses a simple command but with an unsuitable timeout.
cmd = "sleep 5" cmd = "sleep 5"
if err := forest.run(cmd, 0); err == nil { if err := forest.run(cmd, strings.Fields("/bin/sh -c"), 0); err == nil {
t.Errorf("Command '%s' should not have worked", cmd) t.Errorf("Command '%s' should not have worked", cmd)
} }
// case 3: uses a broken command. // case 3: uses a broken command.
cmd = "helloworld" cmd = "helloworld"
if err := forest.run(cmd, 30); err == nil { if err := forest.run(cmd, strings.Fields("/bin/sh -c"), 30); err == nil {
t.Errorf("Command '%s' should not have worked", cmd) t.Errorf("Command '%s' should not have worked", cmd)
} }
} }