Skip to content

Commit

Permalink
Add 'template' action
Browse files Browse the repository at this point in the history
  • Loading branch information
andyone committed Oct 30, 2023
1 parent 3c3f1b8 commit 844fdd8
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 0 deletions.
68 changes: 68 additions & 0 deletions COOKBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* [Common](#common)
* [`exit`](#exit)
* [`wait`](#wait)
* [`template`](#template)
* [Input/Output](#inputoutput)
* [`expect`](#expect)
* [`print`](#print)
Expand Down Expand Up @@ -490,6 +491,71 @@ command "echo 'ABCD'" "Simple echo command"

<a href="#"><img src="https://gh.kaos.st/separator.svg"/></a>

##### `template`

Creates a file from a template. If file already exists, it will be rewritten with the same UID, GID and mode.

_Note that 'template' action will not automatically backup the destination file if it already exists (use `backup` and `backup-restore` actions to preserve the original file). Also, the created file will remain after tests execution if it was created outside the working directory._

You can use the following methods in your templates:

- `Var "name"` - get variable value;
- `Is "name" "value"` - compare variable value.

Simple example:

```
# Sysconfig for postgresql service
PG_ENGINE=""
PG_POSTMASTER=""
{{ if not .Is "data_dir" "" }}
PG_DATA="{{ .Var "data_dir" }}/db"
{{ else }}
PG_DATA=""
{{end}}
PG_LOG=""
PG_UPLOG=""
PG_SOCKET_DIR=""
TIMEOUT=""
DISABLE_AUTO_NUMA=""
```

**Syntax:** `template <source> <dest> [file-mode]`

**Arguments:**

* `source` - Path to template file (_String_)
* `dest` - Destination path (_String_)
* `file-mode` - Destination file mode (_Integer_) [Optional | 644]

**Negative form:** No

**Example:**

```yang
command "-" "Create configuration file"
template app.template /etc/myapp.conf
```

```yang
command "-" "Create configuration file"
template app.template /etc/myapp.conf 640
```

```yang
command "-" "Replace configuration file"
backup /etc/myapp.conf
template app.template /etc/myapp.conf 640
...
command "-" "Restore original configuration file"
backup-restore /etc/myapp.conf
```

<a href="#"><img src="https://gh.kaos.st/separator.svg"/></a>

#### Input/Output

Be aware that the output store limited to 2 Mb of data for each stream (`stdout` _and_ `stderr`). So if command generates lots of output data, it better to use `expect` action to working with the output.
Expand Down Expand Up @@ -563,6 +629,8 @@ command "echo 'ABCD'" "Simple echo command"
wait-output 10.0
```

<a href="#"><img src="https://gh.kaos.st/separator.svg"/></a>

##### `output-match`

Checks output with given [regular expression](https://en.wikipedia.org/wiki/Regular_expression).
Expand Down
114 changes: 114 additions & 0 deletions action/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package action

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2023 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import (
"fmt"
"os"
"strconv"
"text/template"

"github.com/essentialkaos/bibop/recipe"
)

// ////////////////////////////////////////////////////////////////////////////////// //

// varWrapper is a recipe wrapper for accessing variables
type varWrapper struct {
r *recipe.Recipe
}

// ////////////////////////////////////////////////////////////////////////////////// //

// Template is action processor for "template"
func Template(action *recipe.Action) error {
mode := uint64(0644)
source, err := action.GetS(0)

if err != nil {
return err
}

dest, err := action.GetS(1)

if err != nil {
return err
}

isSafePath, err := checkPathSafety(action.Command.Recipe, source)

if err != nil {
return err
}

if !isSafePath {
return fmt.Errorf("Action uses unsafe path (%s)", source)
}

isSafePath, err = checkPathSafety(action.Command.Recipe, dest)

if err != nil {
return err
}

if !isSafePath {
return fmt.Errorf("Action uses unsafe path (%s)", dest)
}

if action.Has(2) {
modeStr, _ := action.GetS(1)
mode, err = strconv.ParseUint(modeStr, 8, 32)

if err != nil {
return err
}
}

tmplData, err := os.ReadFile(source)

if err != nil {
fmt.Errorf("Can't read template %q: %v", source, err)
}

tmpl, err := template.New("").Parse(string(tmplData))

if err != nil {
return fmt.Errorf("Can't parse template %q: %v", source, err)
}

fd, err := os.OpenFile(dest, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.FileMode(mode))

if err != nil {
return fmt.Errorf("Can't save template data into %q: %v", dest, err)
}

defer fd.Close()

vw := &varWrapper{action.Command.Recipe}
err = tmpl.Execute(fd, vw)

if err != nil {
return fmt.Errorf("Can't render template %q: %v", source, err)
}

return nil
}

// ////////////////////////////////////////////////////////////////////////////////// //

// Var returns variable value
func (vw *varWrapper) Var(name string) string {
return vw.r.GetVariable(name, true)
}

// Is compares variable value
func (vw *varWrapper) Is(name, value string) bool {
return vw.r.GetVariable(name, true) == value
}

// ////////////////////////////////////////////////////////////////////////////////// //
1 change: 1 addition & 0 deletions cli/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ var handlers = map[string]action.Handler{
recipe.ACTION_LIB_EXPORTED: action.LibExported,
recipe.ACTION_PYTHON2_PACKAGE: action.Python2Package,
recipe.ACTION_PYTHON3_PACKAGE: action.Python3Package,
recipe.ACTION_TEMPLATE: action.Template,
}

var temp *tmp.Temp
Expand Down
4 changes: 4 additions & 0 deletions recipe/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ const (

ACTION_PYTHON2_PACKAGE = "python2-package"
ACTION_PYTHON3_PACKAGE = "python3-package"

ACTION_TEMPLATE = "template"
)

// ////////////////////////////////////////////////////////////////////////////////// //
Expand Down Expand Up @@ -217,4 +219,6 @@ var Tokens = []TokenInfo{

{ACTION_PYTHON2_PACKAGE, 1, 1, false, false},
{ACTION_PYTHON3_PACKAGE, 1, 1, false, false},

{ACTION_TEMPLATE, 2, 3, false, false},
}

0 comments on commit 844fdd8

Please sign in to comment.