Skip to content

Commit 8e57bcb

Browse files
committed
(ref) #26: adds more tests
1 parent c1e9bb5 commit 8e57bcb

14 files changed

Lines changed: 244 additions & 21 deletions

File tree

cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,6 @@ func resolveContext() {
155155

156156
func createRenderingEngine() {
157157
if projectCfg != nil {
158-
renderingEngine = render.NewRenderingEngine(projectCfg)
158+
renderingEngine = render.NewRenderingEngine(projectCfg, fs, fs)
159159
}
160160
}

docs/readme.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,12 @@ DATABASE_PASSWORD={{.Secrets.databasePassword}}
119119
You can have custom renderTargets to render files. For example `env` or `k8s`. You can than add multiple files to a renderTargets.
120120

121121
````bash
122-
# always render .env.dist to .env
122+
# always render empty.dist to .env
123123
# uses the targetName: env
124-
git secrets add file .env.dist .env -t env
124+
git secrets add file empty.dist .env -t env
125125

126126
# now execute the rendering process
127-
# this renders the .env.dist file to .env and fills out all variables using the default context
127+
# this renders the empty.dist file to .env and fills out all variables using the default context
128128
# targetName: env
129129
git secrets render env
130130

pkg/config/const/const_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package config_const

pkg/config/generic/repository_secret.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ func (s *Secret) Decode() (string, error) {
121121
return s.OriginContext.DecodeValue(s.EncodedValue)
122122
}
123123

124-
// DecodeSecrets decodes the secrets of the current context and puts them into a map[string]string
125-
func (c *Repository) DecodeSecrets() (SecretsMap, error) {
124+
// GetSecretsMapDecoded decodes the secrets of the current context and puts them into a map[string]string
125+
func (c *Repository) GetSecretsMapDecoded() (SecretsMap, error) {
126126

127127
// create the secrets map
128128
secretsMap := make(SecretsMap)
File renamed without changes.

pkg/render/render.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
config_generic "github.com/benammann/git-secrets/pkg/config/generic"
7+
"github.com/spf13/afero"
78
"html/template"
89
"io"
910
"os"
@@ -12,6 +13,8 @@ import (
1213

1314
type RenderingEngine struct {
1415
repository *config_generic.Repository
16+
fsIn afero.Fs
17+
fsOut afero.Fs
1518
}
1619

1720
type RenderingContext struct {
@@ -21,21 +24,23 @@ type RenderingContext struct {
2124
Configs config_generic.ConfigMap
2225
}
2326

24-
func NewRenderingEngine(repository *config_generic.Repository) *RenderingEngine {
27+
func NewRenderingEngine(repository *config_generic.Repository, fsIn afero.Fs, fsOut afero.Fs) *RenderingEngine {
2528
return &RenderingEngine{
2629
repository: repository,
30+
fsIn: fsIn,
31+
fsOut: fsOut,
2732
}
2833
}
2934

30-
// createTemplate creates a new template
31-
func (e *RenderingEngine) createTemplate(fileIn string) (*template.Template, error) {
32-
return createNewTemplate(fileIn)
35+
func (e *RenderingEngine) createTemplate(fileIn string) (*template.Template, error) {
36+
return createTemplate(e.fsIn, fileIn)
3337
}
3438

39+
// CreateRenderingContext creates the context which is used in the templates
3540
func (e *RenderingEngine) CreateRenderingContext(fileToRender *config_generic.FileToRender) (*RenderingContext, error) {
3641

3742
// decode the secrets
38-
secretsMap, errSecrets := e.repository.DecodeSecrets()
43+
secretsMap, errSecrets := e.repository.GetSecretsMapDecoded()
3944
if errSecrets != nil {
4045
return nil, fmt.Errorf("could not create context secrets: %s", errSecrets.Error())
4146
}
@@ -69,7 +74,7 @@ func (e *RenderingEngine) RenderFile(fileToRender *config_generic.FileToRender)
6974
func (e *RenderingEngine) WriteFile(fileToRender *config_generic.FileToRender) (usedContext *RenderingContext, err error) {
7075

7176
// open the file
72-
fsFileOut, errFsFile := os.OpenFile(fileToRender.FileOut, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
77+
fsFileOut, errFsFile := e.fsOut.OpenFile(fileToRender.FileOut, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
7378
if fsFileOut != nil {
7479
defer fsFileOut.Close()
7580
}

pkg/render/render_template.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@ package render
22

33
import (
44
"encoding/base64"
5+
"github.com/spf13/afero"
56
"github.com/tcnksm/go-gitconfig"
67
"html/template"
7-
"log"
8+
"io/fs"
89
)
910

11+
type AferoConvFs struct {
12+
aferoFs afero.Fs
13+
}
14+
15+
func (ac AferoConvFs) Open(name string) (fs.File, error) {
16+
return ac.aferoFs.Open(name)
17+
}
18+
1019
// getTemplateFunctions are added to the template and can be executed
1120
func getTemplateFunctions() template.FuncMap {
1221
return template.FuncMap{
@@ -27,23 +36,26 @@ func templateFunctionGitConfig(args ...interface{}) interface{} {
2736
if err != nil {
2837
globalVal, errGlobal := gitconfig.Global(args[0].(string))
2938
if errGlobal != nil {
30-
log.Fatalf("the key %s does not exist locally or globally", args[0].(string))
39+
return ""
3140
}
3241
return globalVal
3342
}
3443
return val
3544
}
3645

37-
// createNewTemplate creates a new template engine with all the extensions based on the file name
38-
func createNewTemplate(pathToFile string) (*template.Template, error) {
46+
func createTemplate(fs afero.Fs, pathToFile string) (*template.Template, error) {
3947

4048
// create the new engine with file base name
4149
tpl := template.New("")
4250

4351
// add the template functions
4452
tpl.Funcs(getTemplateFunctions())
4553

46-
tpl, err := tpl.ParseFiles(pathToFile)
54+
tpl, err := tpl.ParseFS(AferoConvFs{aferoFs: fs}, pathToFile)
55+
56+
if err != nil {
57+
return nil, err
58+
}
4759

4860
return tpl, err
49-
}
61+
}

pkg/render/render_test.go

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package render
2+
3+
import (
4+
"bytes"
5+
"embed"
6+
"encoding/json"
7+
"fmt"
8+
config_generic "github.com/benammann/git-secrets/pkg/config/generic"
9+
global_config "github.com/benammann/git-secrets/pkg/config/global"
10+
"github.com/spf13/afero"
11+
"github.com/stretchr/testify/assert"
12+
"testing"
13+
)
14+
15+
const GlobalSecretKey = "gitSecretsTest"
16+
const GlobalSecretValue = "eeSaoghoh8oi9leed7hai4looK3jae1N"
17+
18+
const FileRenderTestDefault = "render-test-default.json"
19+
20+
//go:embed test_fs
21+
var testFiles embed.FS
22+
var testFileAfero = &afero.FromIOFS{
23+
FS: testFiles,
24+
}
25+
26+
type TestRenderFunctions struct {
27+
Base64Encode string `json:"base64Encode"`
28+
}
29+
30+
type TestRenderContext struct {
31+
RenderContext *RenderingContext `json:"context"`
32+
TestFunctions *TestRenderFunctions `json:"functions"`
33+
}
34+
35+
func createTestRepository(fileName string, selectedContextName string) (*config_generic.Repository, error) {
36+
fileName = fmt.Sprintf("test_fs/%s", fileName)
37+
globalConfig := global_config.NewGlobalConfigProvider(global_config.NewMemoryStorageProvider())
38+
_ = globalConfig.SetSecret(GlobalSecretKey, GlobalSecretValue, false)
39+
mergeGlobalSecrets := make(map[string]string)
40+
repository, errParse := config_generic.ParseRepository(afero.FromIOFS{
41+
FS: testFiles,
42+
}, fileName, globalConfig, mergeGlobalSecrets)
43+
if errParse != nil {
44+
return nil, fmt.Errorf("could not parse: %s", errParse.Error())
45+
}
46+
_, errSetContext := repository.SetSelectedContext(selectedContextName)
47+
if errSetContext != nil {
48+
return nil, fmt.Errorf("could not set context: %s", errSetContext.Error())
49+
}
50+
return repository, nil
51+
}
52+
53+
func initRepository(t *testing.T, fileName string, selectedContextName string) (*config_generic.Repository, *RenderingEngine) {
54+
repo, errParse := createTestRepository(fileName, selectedContextName)
55+
assert.NotNil(t, repo)
56+
assert.NoError(t, errParse)
57+
return repo, NewRenderingEngine(repo, testFileAfero, testFileAfero)
58+
}
59+
60+
func TestNewRenderingEngine(t *testing.T) {
61+
_, engine := initRepository(t, FileRenderTestDefault, "default")
62+
assert.NotNil(t, engine)
63+
}
64+
65+
func TestRenderingEngine_CreateRenderingContext(t *testing.T) {
66+
repo, engine := initRepository(t, FileRenderTestDefault, "default")
67+
assert.NotNil(t, engine)
68+
69+
file := &config_generic.FileToRender{
70+
FileIn: "fileIn",
71+
FileOut: "fileOut",
72+
}
73+
74+
dbPassword := repo.GetCurrentSecret("databasePassword")
75+
dbPasswordVal, errDecode := dbPassword.Decode()
76+
assert.NoError(t, errDecode)
77+
78+
ctx, err := engine.CreateRenderingContext(file)
79+
assert.NoError(t, err)
80+
assert.Equal(t, "default", ctx.ContextName)
81+
assert.Equal(t, dbPasswordVal, ctx.Secrets["databasePassword"])
82+
assert.Equal(t, "3306", ctx.Configs["databasePort"])
83+
}
84+
85+
func TestRenderingEngine_ExecuteTemplate(t *testing.T) {
86+
_, engine := initRepository(t, FileRenderTestDefault, "default")
87+
fileToRender := &config_generic.FileToRender{
88+
FileIn: "test_fs/templates/render-context.json",
89+
}
90+
91+
var bytesOut bytes.Buffer
92+
usedContext, errExecute := engine.ExecuteTemplate(fileToRender, &bytesOut)
93+
assert.NoError(t, errExecute)
94+
assert.NotNil(t, usedContext)
95+
96+
var renderedFileDecoded TestRenderContext
97+
errDecode := json.Unmarshal(bytesOut.Bytes(), &renderedFileDecoded)
98+
assert.NoError(t, errDecode)
99+
assert.NotNil(t, renderedFileDecoded.RenderContext)
100+
101+
renderContext := renderedFileDecoded.RenderContext
102+
assert.Equal(t, "default", usedContext.ContextName)
103+
assert.Equal(t, usedContext.ContextName, renderContext.ContextName)
104+
assert.Equal(t, usedContext.File.FileIn, renderContext.File.FileIn)
105+
assert.Equal(t, usedContext.File.FileOut, renderContext.File.FileOut)
106+
assert.Equal(t, "3306", usedContext.Configs["databasePort"])
107+
assert.Equal(t, usedContext.Secrets["databasePort"], renderContext.Secrets["databasePort"])
108+
assert.Equal(t, "em8toheGhieh0Thu1ahz9Lou2ucheeh6", usedContext.Secrets["databasePassword"])
109+
assert.Equal(t, usedContext.Secrets["databasePassword"], renderContext.Secrets["databasePassword"])
110+
111+
}
112+
113+
func TestRenderingEngine_RenderFile(t *testing.T) {
114+
_, engine := initRepository(t, FileRenderTestDefault, "default")
115+
fileToRender := &config_generic.FileToRender{
116+
FileIn: "test_fs/templates/render-context.json",
117+
}
118+
_, fileContents, err := engine.RenderFile(fileToRender)
119+
assert.NoError(t, err)
120+
assert.NotEqual(t, "", fileContents)
121+
}
122+
123+
func TestRenderingEngine_WriteFile(t *testing.T) {
124+
_, engine := initRepository(t, FileRenderTestDefault, "default")
125+
fileToRender := &config_generic.FileToRender{
126+
FileIn: "test_fs/templates/render-context.json",
127+
FileOut: "render-context.json",
128+
}
129+
engine.fsOut = afero.NewMemMapFs()
130+
_, err := engine.WriteFile(fileToRender)
131+
assert.NoError(t, err)
132+
133+
fileExists, errExists := afero.Exists(engine.fsOut, fileToRender.FileOut)
134+
assert.NoError(t, errExists)
135+
assert.True(t, fileExists)
136+
137+
}
138+
139+
func TestRenderingEngine_createTemplate(t *testing.T) {
140+
fs := afero.FromIOFS{FS: testFiles}
141+
142+
t.Run("create template for existing file", func(t *testing.T) {
143+
tpl, err := createTemplate(fs, "test_fs/templates/render-context.json")
144+
assert.NoError(t, err)
145+
assert.NotNil(t, tpl)
146+
})
147+
148+
t.Run("fail if file not exists", func(t *testing.T) {
149+
tpl, err := createTemplate(fs, "test_fs/templates/missing-file")
150+
assert.Error(t, err)
151+
assert.Nil(t, tpl)
152+
})
153+
154+
155+
}

pkg/render/test_fs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
out/*
2+
!out/.gitkeep

0 commit comments

Comments
 (0)