Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d6d204e
Add Handlebars template validation and corresponding tests
teresaromero Nov 28, 2025
ea6d4bd
add validator test cases with bad packages
teresaromero Nov 28, 2025
67389f6
Add validation for Handlebars template files in input and integration…
teresaromero Nov 28, 2025
97a32b2
Refactor Handlebars definition specifications for clarity and consist…
teresaromero Nov 28, 2025
f5854ea
Update changelog with link
teresaromero Nov 28, 2025
32ebc29
Fix variable naming for handlebars template validation error
teresaromero Nov 28, 2025
e76c19a
Fix syntax error in sql_query definition across multiple Handlebars t…
teresaromero Nov 28, 2025
49c9c5a
Reorder import statements for consistency in validate_hbs_templates.go
teresaromero Nov 28, 2025
86281bb
update compliace gomod
teresaromero Nov 28, 2025
3e48130
Refactor Handlebars validation logic to include linked files
teresaromero Nov 28, 2025
32ab54d
Add bad integration Handlebars templates with linked files
teresaromero Nov 28, 2025
bc7eee5
Reorder import statements for consistency in validate_hbs_templates_t…
teresaromero Nov 28, 2025
0f1ae93
use path instead of filepath
teresaromero Dec 1, 2025
d4898fe
Replace filepath.Join with path.Join in TestValidateHandlebarsFiles f…
teresaromero Dec 1, 2025
d6ee0cd
fix validateHandlebarsEntry to read file content from filesystem or a…
teresaromero Dec 1, 2025
ab1a541
Reorder logrus dependency in go.mod for consistency
teresaromero Dec 3, 2025
0d298e7
Improve error messages in Handlebars validation for clarity
teresaromero Dec 3, 2025
e699759
Add link to Fleet implementation link for available Handlebars helper…
teresaromero Dec 3, 2025
31644e8
Refactor Handlebars validation to return structured errors and update…
teresaromero Dec 3, 2025
62679a5
Merge branch 'main' of github.com:elastic/package-spec into 21-handle…
teresaromero Dec 3, 2025
17b18db
append errors instead of return
teresaromero Dec 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions code/go/internal/validator/semantic/validate_hbs_templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package semantic

import (
"errors"
"io/fs"
"os"
"path"

"github.com/mailgun/raymond/v2"

"github.com/elastic/package-spec/v3/code/go/internal/fspath"
"github.com/elastic/package-spec/v3/code/go/internal/linkedfiles"
"github.com/elastic/package-spec/v3/code/go/pkg/specerrors"
)

var (
errInvalidHandlebarsTemplate = errors.New("invalid handlebars template")
)

// ValidateHandlebarsFiles validates all Handlebars (.hbs) files in the package filesystem.
// It returns a list of validation errors if any Handlebars files are invalid.
// hbs are located in both the package root and data stream directories under the agent folder.
func ValidateHandlebarsFiles(fsys fspath.FS) specerrors.ValidationErrors {
var errs specerrors.ValidationErrors

// template files are placed at /agent/input directory or
// at the datastream /agent/stream directory
inputDir := path.Join("agent", "input")
if inputErrs := validateTemplateDir(fsys, inputDir); inputErrs != nil {
errs = append(errs, inputErrs...)
}

datastreamEntries, err := fs.ReadDir(fsys, "data_stream")
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return specerrors.ValidationErrors{
specerrors.NewStructuredErrorf("error reading data_stream directory: %w", err),
}
}
for _, dsEntry := range datastreamEntries {
if !dsEntry.IsDir() {
continue
}
streamDir := path.Join("data_stream", dsEntry.Name(), "agent", "stream")
dsErrs := validateTemplateDir(fsys, streamDir)
if dsErrs != nil {
errs = append(errs, dsErrs...)
}
}

return errs
}

// validateTemplateDir validates all Handlebars files in the given directory.
func validateTemplateDir(fsys fspath.FS, dir string) specerrors.ValidationErrors {
entries, err := fs.ReadDir(fsys, dir)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return specerrors.ValidationErrors{
specerrors.NewStructuredErrorf("error trying to read :%s", dir),
}
}
var errs specerrors.ValidationErrors
for _, entry := range entries {
if path.Ext(entry.Name()) == ".hbs" {
err := validateHandlebarsEntry(fsys, dir, entry.Name())
if err != nil {
errs = append(errs, specerrors.NewStructuredErrorf("%w: error validating %s: %w", errInvalidHandlebarsTemplate, path.Join(dir, entry.Name()), err))
}
continue
}
if path.Ext(entry.Name()) == ".link" {
linkFilePath := path.Join(dir, entry.Name())
linkFile, err := linkedfiles.NewLinkedFile(fsys.Path(linkFilePath))
if err != nil {
errs = append(errs, specerrors.NewStructuredErrorf("error reading linked file %s: %w", linkFilePath, err))
continue
}
err = validateHandlebarsEntry(fsys, dir, linkFile.IncludedFilePath)
if err != nil {
errs = append(errs, specerrors.NewStructuredErrorf("%w: error validating %s: %w", errInvalidHandlebarsTemplate, path.Join(dir, linkFile.IncludedFilePath), err))
}
}
}
return errs
}

// validateHandlebarsEntry validates a single Handlebars file located at filePath.
// it parses the file using the raymond library to check for syntax errors.
func validateHandlebarsEntry(fsys fspath.FS, dir, entryName string) error {
if entryName == "" {
return nil
}

var content []byte
var err error

// First try to read from filesystem (works for regular files and files within zip)
filePath := path.Join(dir, entryName)
if content, err = fs.ReadFile(fsys, filePath); err != nil {
// If fs.ReadFile fails (likely due to linked file path outside filesystem boundary),
// fall back to absolute path approach like linkedfiles.FS does
absolutePath := fsys.Path(filePath)
if content, err = os.ReadFile(absolutePath); err != nil {
return err
}
Comment on lines +103 to +108
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the comment, is this already done by the linkedfiles.FS ? If so, maybe it could be removed from here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this refers to the logic at getLinkedFileChecksum where the file content is read to get the checksum. If the file is not within fsys fs.ReadFile fails, as is not in its scope. If this happens, we use os.ReadFile (like in getLinkedFileChecksum) to read the file with the absolute path of it

}

// Parse from content string instead of file path
_, err = raymond.Parse(string(content))
return err
}
125 changes: 125 additions & 0 deletions code/go/internal/validator/semantic/validate_hbs_templates_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package semantic

import (
"os"
"path"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/elastic/package-spec/v3/code/go/internal/fspath"
)

func TestValidateTemplateDir(t *testing.T) {
t.Run("empty directory", func(t *testing.T) {
tmpDir := t.TempDir()
pkgDir := path.Join(tmpDir, "package")
err := os.MkdirAll(pkgDir, 0o755)
require.NoError(t, err)

templateDir := path.Join(pkgDir, "agent", "input")
err = os.MkdirAll(templateDir, 0o755)
require.NoError(t, err)

fsys := fspath.DirFS(pkgDir)
errs := validateTemplateDir(fsys, path.Join("agent", "input"))
require.Empty(t, errs)

})
t.Run("valid handlebars file", func(t *testing.T) {
tmpDir := t.TempDir()
pkgDir := path.Join(tmpDir, "package")
err := os.MkdirAll(pkgDir, 0o755)
require.NoError(t, err)

templateDir := path.Join(pkgDir, "agent", "input")
err = os.MkdirAll(templateDir, 0o755)
require.NoError(t, err)
hbsFilePath := path.Join(templateDir, "template.hbs")
hbsContent := `{{#if condition}}Valid Handlebars{{/if}}`
err = os.WriteFile(hbsFilePath, []byte(hbsContent), 0o644)
require.NoError(t, err)

fsys := fspath.DirFS(pkgDir)
errs := validateTemplateDir(fsys, path.Join("agent", "input"))
require.Empty(t, errs)
})
t.Run("invalid handlebars file", func(t *testing.T) {
tmpDir := t.TempDir()
pkgDir := path.Join(tmpDir, "package")
err := os.MkdirAll(pkgDir, 0o755)
require.NoError(t, err)

templateDir := path.Join(pkgDir, "agent", "input")
err = os.MkdirAll(templateDir, 0o755)
require.NoError(t, err)
hbsFilePath := path.Join(templateDir, "template.hbs")
hbsContent := `{{#if condition}}Valid Handlebars`
err = os.WriteFile(hbsFilePath, []byte(hbsContent), 0o644)
require.NoError(t, err)

fsys := fspath.DirFS(pkgDir)
errs := validateTemplateDir(fsys, path.Join("agent", "input"))
require.NotEmpty(t, errs)
assert.Len(t, errs, 1)
})
t.Run("valid linked handlebars file", func(t *testing.T) {
tmpDir := t.TempDir()
pkgDir := path.Join(tmpDir, "package")
err := os.MkdirAll(pkgDir, 0o755)
require.NoError(t, err)

pkgDirLinked := path.Join(tmpDir, "linked")
err = os.MkdirAll(pkgDirLinked, 0o755)
require.NoError(t, err)
linkedHbsFilePath := path.Join(pkgDirLinked, "linked_template.hbs")
linkedHbsContent := `{{#if condition}}Valid Linked Handlebars{{/if}}`
err = os.WriteFile(linkedHbsFilePath, []byte(linkedHbsContent), 0o644)
require.NoError(t, err)

templateDir := path.Join(pkgDir, "agent", "input")
err = os.MkdirAll(templateDir, 0o755)
require.NoError(t, err)
hbsFilePath := path.Join(templateDir, "template.hbs.link")
hbsContent := `../../../linked/linked_template.hbs`
err = os.WriteFile(hbsFilePath, []byte(hbsContent), 0o644)
require.NoError(t, err)

fsys := fspath.DirFS(pkgDir)
errs := validateTemplateDir(fsys, path.Join("agent", "input"))
require.Empty(t, errs)

})
t.Run("invalid linked handlebars file", func(t *testing.T) {
tmpDir := t.TempDir()
pkgDir := path.Join(tmpDir, "package")
err := os.MkdirAll(pkgDir, 0o755)
require.NoError(t, err)

pkgDirLinked := path.Join(tmpDir, "linked")
err = os.MkdirAll(pkgDirLinked, 0o755)
require.NoError(t, err)
linkedHbsFilePath := path.Join(pkgDirLinked, "linked_template.hbs")
linkedHbsContent := `{{#if condition}}Valid Linked Handlebars`
err = os.WriteFile(linkedHbsFilePath, []byte(linkedHbsContent), 0o644)
require.NoError(t, err)

templateDir := path.Join(pkgDir, "agent", "input")
err = os.MkdirAll(templateDir, 0o755)
require.NoError(t, err)
hbsFilePath := path.Join(templateDir, "template.hbs.link")
hbsContent := `../../../linked/linked_template.hbs`
err = os.WriteFile(hbsFilePath, []byte(hbsContent), 0o644)
require.NoError(t, err)

fsys := fspath.DirFS(pkgDir)
errs := validateTemplateDir(fsys, path.Join("agent", "input"))
require.NotEmpty(t, errs)
assert.Len(t, errs, 1)
})
}
1 change: 1 addition & 0 deletions code/go/internal/validator/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ func (s Spec) rules(pkgType string, rootSpec spectypes.ItemSpec) validationRules
{fn: semantic.ValidateInputPackagesPolicyTemplates, types: []string{"input"}},
{fn: semantic.ValidateMinimumAgentVersion},
{fn: semantic.ValidateIntegrationPolicyTemplates, types: []string{"integration"}},
{fn: semantic.ValidateHandlebarsFiles, types: []string{"integration", "input"}},
}

var validationRules validationRules
Expand Down
23 changes: 23 additions & 0 deletions code/go/pkg/validator/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,29 @@ func TestLinksAreBlocked(t *testing.T) {
t.Error("links should not be allowed in package")
}

func TestValidateHandlebarsFiles(t *testing.T) {
tests := map[string]string{
"bad_input_hbs": "invalid handlebars template: error validating agent/input/input.yml.hbs: Parse error on line 10:\nExpecting OpenEndBlock, got: 'EOF'",
"bad_integration_hbs": "invalid handlebars template: error validating data_stream/foo/agent/stream/filestream.yml.hbs: Parse error on line 43:\nExpecting OpenEndBlock, got: 'EOF'",
"bad_integration_hbs_linked": "invalid handlebars template: error validating ../bad_integration_hbs/data_stream/foo/agent/stream/filestream.yml.hbs: Parse error on line 43:\nExpecting OpenEndBlock, got: 'EOF'",
}

for pkgName, expectedErrorMessage := range tests {
t.Run(pkgName, func(t *testing.T) {
errs := ValidateFromPath(path.Join("..", "..", "..", "..", "test", "packages", pkgName))
require.Error(t, errs)
vErrs, ok := errs.(specerrors.ValidationErrors)
require.True(t, ok)

var errMessages []string
for _, vErr := range vErrs {
errMessages = append(errMessages, vErr.Error())
}
require.Contains(t, errMessages, expectedErrorMessage)
})
}
}

func requireErrorMessage(t *testing.T, pkgName string, invalidItemsPerFolder map[string][]string, expectedErrorMessage string) {
pkgRootPath := filepath.Join("..", "..", "..", "..", "test", "packages", pkgName)

Expand Down
2 changes: 2 additions & 0 deletions compliance/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ require (
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magefile/mage v1.15.0 // indirect
github.com/mailgun/raymond/v2 v2.0.48 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
Expand Down Expand Up @@ -145,6 +146,7 @@ require (
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/cobra v1.10.1 // indirect
Expand Down
8 changes: 8 additions & 0 deletions compliance/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
Expand Down Expand Up @@ -337,6 +339,9 @@ github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnj
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
Expand All @@ -354,6 +359,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down Expand Up @@ -456,6 +462,7 @@ golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -464,6 +471,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/evanphx/json-patch/v5 v5.9.11
github.com/go-viper/mapstructure/v2 v2.4.0
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901
github.com/mailgun/raymond/v2 v2.0.48
github.com/otiai10/copy v1.14.1
github.com/stretchr/testify v1.11.1
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415
Expand All @@ -39,6 +40,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/otiai10/mint v1.6.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand All @@ -58,10 +60,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
Expand All @@ -86,6 +92,7 @@ golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
Expand All @@ -106,6 +113,9 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/gotestsum v1.13.0 h1:+Lh454O9mu9AMG1APV4o0y7oDYKyik/3kBOiCqiEpRo=
Expand Down
Loading