Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
(GH-342) Implement CheckConfig in private processor
Browse files Browse the repository at this point in the history
Prior to this commit, functional logic for validating a config file
lived not in the private processor (pct_config_processor) but in the
private build package as a private function.

This commit adds the CheckConfig function to the private processor
as a public function so that the private processor becomes a valid
implementation of the ConfigProcessorI interface.

It slightly refactors the implementation from the build package in
this transfer, as the logic for reading a configuration file is
already defined in a private function for the private processor. It
also ensures that the full path to the configuration file being checked
is returned in any error messages; the prior implementation only
specified 'pct-config.yml' which is neither generic for use in other
libraries/tools, nor specific if the caller is pointing to a config
anywhere but in the current working directory.

This commit **does not** replace any upstream package usage to point
to the new function, it **only** makes the private processor a valid
implementation of the ConfigProcessorI interface.
  • Loading branch information
michaeltlombardi committed Feb 11, 2022
1 parent 19aaa80 commit 2e1b426
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
26 changes: 26 additions & 0 deletions internal/pkg/pct_config_processor/pct_config_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ func (p *PctConfigProcessor) ProcessConfig(sourceDir, targetDir string, force bo
return namespacedPath, nil
}

func (p *PctConfigProcessor) CheckConfig(configFile string) error {
info, err := p.readConfig(configFile)
if err != nil {
return err
}

msg := fmt.Sprintf("The following attributes are missing in %s:\n", configFile)
orig := msg
// These parts are essential for build and deployment.

if info.Template.Id == "" {
msg = msg + " * id\n"
}
if info.Template.Author == "" {
msg = msg + " * author\n"
}
if info.Template.Version == "" {
msg = msg + " * version\n"
}
if msg != orig {
return fmt.Errorf(msg)
}

return nil
}

func (p *PctConfigProcessor) readConfig(configFile string) (info pct.PuppetContentTemplateInfo, err error) {
fileBytes, err := p.AFS.ReadFile(configFile)
if err != nil {
Expand Down
125 changes: 125 additions & 0 deletions internal/pkg/pct_config_processor/pct_config_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pct_config_processor_test

import (
"path/filepath"
"regexp"
"testing"

"github.com/puppetlabs/pdkgo/internal/pkg/pct_config_processor"
Expand Down Expand Up @@ -100,3 +101,127 @@ template:
}

}

type CheckConfigTest struct {
name string
mockConfigFile bool
configFilePath string
configFileYaml string
errorMsg string
}

func TestPctConfigProcessor_CheckConfig(t *testing.T) {
type args struct {
configFile string
}
tests := []CheckConfigTest{
{
name: "When config not found",
mockConfigFile: false,
configFilePath: "my/missing/pct-config.yml",
errorMsg: "file does not exist",
},
{
name: "When config valid",
mockConfigFile: true,
configFilePath: "my/valid/pct-config.yml",

configFileYaml: `---
template:
id: test-template
author: test-user
version: 0.1.0
`,
errorMsg: "",
},
{
name: "When config invalid",
mockConfigFile: true,
configFilePath: "my/invalid/pct-config.yml",
// This is invalid because it starts with tabs which the parses errors on
configFileYaml: `---
foo: bar
`,
errorMsg: "parsing config: yaml",
},
{
name: "When config missing author",
mockConfigFile: true,
configFilePath: "my/missing/author/pct-config.yml",

configFileYaml: `---
template:
id: test-template
version: 0.1.0
`,
errorMsg: `The following attributes are missing in .+:\s+\* author`,
},
{
name: "When config missing id",
mockConfigFile: true,
configFilePath: "my/missing/id/pct-config.yml",

configFileYaml: `---
template:
author: test-user
version: 0.1.0
`,
errorMsg: `The following attributes are missing in .+:\s+\* id`,
},
{
name: "When config missing version",
mockConfigFile: true,
configFilePath: "my/missing/version/pct-config.yml",

configFileYaml: `---
template:
author: test-user
id: test-template
`,
errorMsg: `The following attributes are missing in .+:\s+\* version`,
},
{
name: "When config missing author, id, and version",
mockConfigFile: true,
configFilePath: "my/missing/version/pct-config.yml",

configFileYaml: `---
template:
`,
errorMsg: `The following attributes are missing in .+:\s+\* id\s+\* author\s+\* version`,
},
{
name: "When config missing template key",
mockConfigFile: true,
configFilePath: "my/missing/version/pct-config.yml",

configFileYaml: `---
foo: bar
`,
errorMsg: `The following attributes are missing in .+:\s+\* id\s+\* author\s+\* version`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fs := afero.NewMemMapFs()
afs := &afero.Afero{Fs: fs}

if tt.mockConfigFile {
dir := filepath.Dir(tt.configFilePath)
afs.Mkdir(dir, 0750) //nolint:gosec,errcheck // this result is not used in a secure application
config, _ := afs.Create(tt.configFilePath) //nolint:gosec,errcheck // this result is not used in a secure application
config.Write([]byte(tt.configFileYaml)) //nolint:errcheck
}

configProcessor := pct_config_processor.PctConfigProcessor{AFS: afs}

err := configProcessor.CheckConfig(tt.configFilePath)

if tt.errorMsg != "" && err != nil {
assert.Regexp(t, regexp.MustCompile(tt.errorMsg), err.Error())
} else {
assert.NoError(t, err)
}
})
}
}

0 comments on commit 2e1b426

Please sign in to comment.