blueprint: add representation of Directories and Files customization
Extend the Blueprint customizations with the representation for custom Directories and Files specified by the user. Implement custom Unmarshalers for TOML and JSON. These ensure that all user-provided values are validated before use and also handle the fact that user and group ownership for directories and files can be specifies as a string or as an integer. Implement helper functions for converting the Blueprint-specific types for these customizations to their internal representation from `fsnode` package. Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This commit is contained in:
parent
26e6983320
commit
c1991b3d51
3 changed files with 1098 additions and 0 deletions
797
internal/blueprint/fsnode_customizations_test.go
Normal file
797
internal/blueprint/fsnode_customizations_test.go
Normal file
|
|
@ -0,0 +1,797 @@
|
|||
package blueprint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/fsnode"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDirectoryCustomizationToFsNodeDirectory(t *testing.T) {
|
||||
ensureDirCreation := func(dir *fsnode.Directory, err error) *fsnode.Directory {
|
||||
t.Helper()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, dir)
|
||||
return dir
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Dir DirectoryCustomization
|
||||
WantDir *fsnode.Directory
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
Name: "empty",
|
||||
Dir: DirectoryCustomization{},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-only",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
},
|
||||
WantDir: ensureDirCreation(fsnode.NewDirectory("/etc/dir", nil, nil, nil, false)),
|
||||
},
|
||||
{
|
||||
Name: "path-invalid",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "etc/dir",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-mode",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
Mode: "0700",
|
||||
},
|
||||
WantDir: ensureDirCreation(fsnode.NewDirectory("/etc/dir", common.ToPtr(os.FileMode(0700)), nil, nil, false)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-mode-no-leading-zero",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
Mode: "700",
|
||||
},
|
||||
WantDir: ensureDirCreation(fsnode.NewDirectory("/etc/dir", common.ToPtr(os.FileMode(0700)), nil, nil, false)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-mode-invalid",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
Mode: "12345",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-user-group-string",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
User: "root",
|
||||
Group: "root",
|
||||
},
|
||||
WantDir: ensureDirCreation(fsnode.NewDirectory("/etc/dir", nil, "root", "root", false)),
|
||||
},
|
||||
{
|
||||
Name: "path-user-group-int64",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
User: int64(0),
|
||||
Group: int64(0),
|
||||
},
|
||||
WantDir: ensureDirCreation(fsnode.NewDirectory("/etc/dir", nil, int64(0), int64(0), false)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-user-invalid-string",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
User: "r@@t",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-user-invalid-int64",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
User: -1,
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-group-invalid-string",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
Group: "r@@t",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-group-invalid-int64",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
Group: -1,
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-ensure-parent-dirs",
|
||||
Dir: DirectoryCustomization{
|
||||
Path: "/etc/dir",
|
||||
EnsureParents: true,
|
||||
},
|
||||
WantDir: ensureDirCreation(fsnode.NewDirectory("/etc/dir", nil, nil, nil, true)),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
dir, err := tc.Dir.ToFsNodeDirectory()
|
||||
if tc.Error {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, dir)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, tc.WantDir, dir)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirectoryCustomizationUnmarshalTOML(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
TOML string
|
||||
Want []DirectoryCustomization
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
Name: "directory-with-path",
|
||||
TOML: `
|
||||
name = "test"
|
||||
description = "Test"
|
||||
version = "0.0.0"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir"
|
||||
`,
|
||||
Want: []DirectoryCustomization{
|
||||
{
|
||||
Path: "/etc/dir",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "multiple-directories",
|
||||
TOML: `
|
||||
name = "test"
|
||||
description = "Test"
|
||||
version = "0.0.0"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir1"
|
||||
mode = "0700"
|
||||
user = "root"
|
||||
group = "root"
|
||||
ensure_parents = true
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir2"
|
||||
mode = "0755"
|
||||
user = 0
|
||||
group = 0
|
||||
ensure_parents = true
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir3"
|
||||
`,
|
||||
Want: []DirectoryCustomization{
|
||||
{
|
||||
Path: "/etc/dir1",
|
||||
Mode: "0700",
|
||||
User: "root",
|
||||
Group: "root",
|
||||
EnsureParents: true,
|
||||
},
|
||||
{
|
||||
Path: "/etc/dir2",
|
||||
Mode: "0755",
|
||||
User: int64(0),
|
||||
Group: int64(0),
|
||||
EnsureParents: true,
|
||||
},
|
||||
{
|
||||
Path: "/etc/dir3",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid-directories",
|
||||
TOML: `
|
||||
name = "test"
|
||||
description = "Test"
|
||||
version = "0.0.0"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/../dir1"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir2"
|
||||
mode = "12345"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir3"
|
||||
user = "r@@t"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir4"
|
||||
group = "r@@t"
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir5"
|
||||
user = -1
|
||||
|
||||
[[customizations.directories]]
|
||||
path = "/etc/dir6"
|
||||
group = -1
|
||||
|
||||
|
||||
[[customizations.directories]]
|
||||
`,
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
var blueprint Blueprint
|
||||
err := toml.Unmarshal([]byte(tc.TOML), &blueprint)
|
||||
if tc.Error {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blueprint.Customizations)
|
||||
assert.Len(t, blueprint.Customizations.Directories, len(tc.Want))
|
||||
assert.EqualValues(t, tc.Want, blueprint.Customizations.GetDirectories())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirectoryCustomizationUnmarshalJSON(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
JSON string
|
||||
Want []DirectoryCustomization
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
Name: "directory-with-path",
|
||||
JSON: `
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Test",
|
||||
"version": "0.0.0",
|
||||
"customizations": {
|
||||
"directories": [
|
||||
{
|
||||
"path": "/etc/dir"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Want: []DirectoryCustomization{
|
||||
{
|
||||
Path: "/etc/dir",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "multiple-directories",
|
||||
JSON: `
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Test",
|
||||
"version": "0.0.0",
|
||||
"customizations": {
|
||||
"directories": [
|
||||
{
|
||||
"path": "/etc/dir1",
|
||||
"mode": "0700",
|
||||
"user": "root",
|
||||
"group": "root",
|
||||
"ensure_parents": true
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir2",
|
||||
"mode": "0755",
|
||||
"user": 0,
|
||||
"group": 0,
|
||||
"ensure_parents": true
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Want: []DirectoryCustomization{
|
||||
{
|
||||
Path: "/etc/dir1",
|
||||
Mode: "0700",
|
||||
User: "root",
|
||||
Group: "root",
|
||||
EnsureParents: true,
|
||||
},
|
||||
{
|
||||
Path: "/etc/dir2",
|
||||
Mode: "0755",
|
||||
User: int64(0),
|
||||
Group: int64(0),
|
||||
EnsureParents: true,
|
||||
},
|
||||
{
|
||||
Path: "/etc/dir3",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid-directories",
|
||||
JSON: `
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Test",
|
||||
"version": "0.0.0",
|
||||
"customizations": {
|
||||
"directories": [
|
||||
{
|
||||
"path": "/etc/../dir1"
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir2",
|
||||
"mode": "12345"
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir3",
|
||||
"user": "r@@t"
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir4",
|
||||
"group": "r@@t"
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir5",
|
||||
"user": -1
|
||||
},
|
||||
{
|
||||
"path": "/etc/dir6",
|
||||
"group": -1
|
||||
}
|
||||
{}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
var blueprint Blueprint
|
||||
err := json.Unmarshal([]byte(tc.JSON), &blueprint)
|
||||
if tc.Error {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blueprint.Customizations)
|
||||
assert.Len(t, blueprint.Customizations.Directories, len(tc.Want))
|
||||
assert.EqualValues(t, tc.Want, blueprint.Customizations.GetDirectories())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFileCustomizationToFsNodeFile(t *testing.T) {
|
||||
ensureFileCreation := func(file *fsnode.File, err error) *fsnode.File {
|
||||
t.Helper()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, file)
|
||||
return file
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
Name string
|
||||
File FileCustomization
|
||||
Want *fsnode.File
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
Name: "empty",
|
||||
File: FileCustomization{},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-only",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", nil, nil, nil, nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-invalid",
|
||||
File: FileCustomization{
|
||||
Path: "../etc/file",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-mode",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Mode: "0700",
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", common.ToPtr(os.FileMode(0700)), nil, nil, nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-mode-no-leading-zero",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Mode: "700",
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", common.ToPtr(os.FileMode(0700)), nil, nil, nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-mode-invalid",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Mode: "12345",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-user-group-string",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
User: "root",
|
||||
Group: "root",
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", nil, "root", "root", nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-user-group-int64",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
User: int64(0),
|
||||
Group: int64(0),
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", nil, int64(0), int64(0), nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-user-invalid-string",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
User: "r@@t",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-user-invalid-int64",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
User: int64(-1),
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-group-string",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Group: "root",
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", nil, nil, "root", nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-group-int64",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Group: int64(0),
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", nil, nil, int64(0), nil)),
|
||||
},
|
||||
{
|
||||
Name: "path-and-group-invalid-string",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Group: "r@@t",
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-group-invalid-int64",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Group: int64(-1),
|
||||
},
|
||||
Error: true,
|
||||
},
|
||||
{
|
||||
Name: "path-and-data",
|
||||
File: FileCustomization{
|
||||
Path: "/etc/file",
|
||||
Data: "hello world",
|
||||
},
|
||||
Want: ensureFileCreation(fsnode.NewFile("/etc/file", nil, nil, nil, []byte("hello world"))),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
file, err := tc.File.ToFsNodeFile()
|
||||
if tc.Error {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, file)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, tc.Want, file)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileCustomizationUnmarshalTOML(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
TOML string
|
||||
Want []FileCustomization
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
Name: "file-with-path",
|
||||
TOML: `
|
||||
name = "test"
|
||||
description = "Test"
|
||||
version = "0.0.0"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file"
|
||||
`,
|
||||
Want: []FileCustomization{
|
||||
{
|
||||
Path: "/etc/file",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "multiple-files",
|
||||
TOML: `
|
||||
name = "test"
|
||||
description = "Test"
|
||||
version = "0.0.0"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file1"
|
||||
mode = "0600"
|
||||
user = "root"
|
||||
group = "root"
|
||||
data = "hello world"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file2"
|
||||
mode = "0644"
|
||||
data = "hello world 2"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file3"
|
||||
user = 0
|
||||
group = 0
|
||||
data = "hello world 3"
|
||||
`,
|
||||
Want: []FileCustomization{
|
||||
{
|
||||
Path: "/etc/file1",
|
||||
Mode: "0600",
|
||||
User: "root",
|
||||
Group: "root",
|
||||
Data: "hello world",
|
||||
},
|
||||
{
|
||||
Path: "/etc/file2",
|
||||
Mode: "0644",
|
||||
Data: "hello world 2",
|
||||
},
|
||||
{
|
||||
Path: "/etc/file3",
|
||||
User: int64(0),
|
||||
Group: int64(0),
|
||||
Data: "hello world 3",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid-files",
|
||||
TOML: `
|
||||
name = "test"
|
||||
description = "Test"
|
||||
version = "0.0.0"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/../file1"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file2"
|
||||
mode = "12345"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file3"
|
||||
user = "r@@t"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file4"
|
||||
group = "r@@t"
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file5"
|
||||
user = -1
|
||||
|
||||
[[customizations.files]]
|
||||
path = "/etc/file6"
|
||||
group = -1
|
||||
`,
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
var blueprint Blueprint
|
||||
err := toml.Unmarshal([]byte(tc.TOML), &blueprint)
|
||||
if tc.Error {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blueprint.Customizations)
|
||||
assert.Len(t, blueprint.Customizations.Files, len(tc.Want))
|
||||
assert.EqualValues(t, tc.Want, blueprint.Customizations.Files)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileCustomizationUnmarshalJSON(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
JSON string
|
||||
Want []FileCustomization
|
||||
Error bool
|
||||
}{
|
||||
{
|
||||
Name: "file-with-path",
|
||||
JSON: `
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Test",
|
||||
"version": "0.0.0",
|
||||
"customizations": {
|
||||
"files": [
|
||||
{
|
||||
"path": "/etc/file"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Want: []FileCustomization{
|
||||
{
|
||||
Path: "/etc/file",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "multiple-files",
|
||||
JSON: `
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Test",
|
||||
"version": "0.0.0",
|
||||
"customizations": {
|
||||
"files": [
|
||||
{
|
||||
"path": "/etc/file1",
|
||||
"mode": "0600",
|
||||
"user": "root",
|
||||
"group": "root",
|
||||
"data": "hello world"
|
||||
},
|
||||
{
|
||||
"path": "/etc/file2",
|
||||
"mode": "0644",
|
||||
"data": "hello world 2"
|
||||
},
|
||||
{
|
||||
"path": "/etc/file3",
|
||||
"user": 0,
|
||||
"group": 0,
|
||||
"data": "hello world 3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Want: []FileCustomization{
|
||||
{
|
||||
Path: "/etc/file1",
|
||||
Mode: "0600",
|
||||
User: "root",
|
||||
Group: "root",
|
||||
Data: "hello world",
|
||||
},
|
||||
{
|
||||
Path: "/etc/file2",
|
||||
Mode: "0644",
|
||||
Data: "hello world 2",
|
||||
},
|
||||
{
|
||||
Path: "/etc/file3",
|
||||
User: int64(0),
|
||||
Group: int64(0),
|
||||
Data: "hello world 3",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "invalid-files",
|
||||
JSON: `
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Test",
|
||||
"version": "0.0.0",
|
||||
"customizations": {
|
||||
"files": [
|
||||
{
|
||||
"path": "/etc/../file1"
|
||||
},
|
||||
{
|
||||
"path": "/etc/file2",
|
||||
"mode": "12345"
|
||||
},
|
||||
{
|
||||
"path": "/etc/file3",
|
||||
"user": "r@@t"
|
||||
},
|
||||
{
|
||||
"path": "/etc/file4",
|
||||
"group": "r@@t"
|
||||
},
|
||||
{
|
||||
"path": "/etc/file5",
|
||||
"user": -1
|
||||
},
|
||||
{
|
||||
"path": "/etc/file6",
|
||||
"group": -1
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
var blueprint Blueprint
|
||||
err := json.Unmarshal([]byte(tc.JSON), &blueprint)
|
||||
if tc.Error {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blueprint.Customizations)
|
||||
assert.Len(t, blueprint.Customizations.Files, len(tc.Want))
|
||||
assert.EqualValues(t, tc.Want, blueprint.Customizations.Files)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue