mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-02 22:34:56 -04:00
cli: state file validation (#2523)
* re-use `ReadFromFile` in `CreateOrRead` Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * [wip]: add constraints Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * [wip] error formatting Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * wip Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * formatted error messages Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * state file validation Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * linter fixes Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * allow overriding the constraints Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * dont validate on read Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * add pre-create constraints Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * [wip] Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * finish pre-init validation test Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * finish post-init validation Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * use state file validation in CLI Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * fix apply tests Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * Update internal/validation/errors.go Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> * use transformator for tests * tidy * use empty check directly Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * Update cli/internal/state/state.go Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> * Update cli/internal/state/state.go Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> * Update cli/internal/state/state.go Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> * Update cli/internal/state/state.go Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> * conditional validation per CSP Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * tidy Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * fix rebase Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * add default case Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> * validate state-file as last input Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> --------- Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com> Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>
This commit is contained in:
parent
eaec73cca4
commit
744a605602
21 changed files with 1779 additions and 247 deletions
290
internal/validation/constraints_test.go
Normal file
290
internal/validation/constraints_test.go
Normal file
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIPAddress(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
ip string
|
||||
wantErr bool
|
||||
}{
|
||||
"valid ipv4": {
|
||||
ip: "127.0.0.1",
|
||||
},
|
||||
"valid ipv6": {
|
||||
ip: "2001:db8::68",
|
||||
},
|
||||
"invalid": {
|
||||
ip: "invalid",
|
||||
wantErr: true,
|
||||
},
|
||||
"empty": {
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := IPAddress(tc.ip).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCIDR(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
cidr string
|
||||
wantErr bool
|
||||
}{
|
||||
"valid ipv4": {
|
||||
cidr: "192.0.2.0/24",
|
||||
},
|
||||
"valid ipv6": {
|
||||
cidr: "2001:db8::/32",
|
||||
},
|
||||
"invalid": {
|
||||
cidr: "invalid",
|
||||
wantErr: true,
|
||||
},
|
||||
"empty": {
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := CIDR(tc.cidr).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNSName(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
dnsName string
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
dnsName: "example.com",
|
||||
},
|
||||
"invalid": {
|
||||
dnsName: "invalid",
|
||||
wantErr: true,
|
||||
},
|
||||
"empty": {
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := DNSName(tc.dnsName).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptySlice(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
s []any
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
s: []any{},
|
||||
},
|
||||
"nil": {
|
||||
s: nil,
|
||||
},
|
||||
"invalid": {
|
||||
s: []any{1},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := EmptySlice(tc.s).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotEmptySlice(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
s []any
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
s: []any{1},
|
||||
},
|
||||
"invalid": {
|
||||
s: []any{},
|
||||
wantErr: true,
|
||||
},
|
||||
"nil": {
|
||||
s: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := NotEmptySlice(tc.s).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
c := func(i int, s string) *Constraint {
|
||||
return Equal(s, "abc")
|
||||
}
|
||||
testCases := map[string]struct {
|
||||
s []string
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
s: []string{"abc", "abc", "abc"},
|
||||
},
|
||||
"nil": {
|
||||
s: nil,
|
||||
},
|
||||
"empty": {
|
||||
s: []string{},
|
||||
},
|
||||
"all are invalid": {
|
||||
s: []string{"def", "lol"},
|
||||
wantErr: true,
|
||||
},
|
||||
"one is invalid": {
|
||||
s: []string{"abc", "def"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := All(tc.s, c).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotEqual(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
a any
|
||||
b any
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
a: "abc",
|
||||
b: "def",
|
||||
},
|
||||
"invalid": {
|
||||
a: "abc",
|
||||
b: "abc",
|
||||
wantErr: true,
|
||||
},
|
||||
"empty": {
|
||||
wantErr: true,
|
||||
},
|
||||
"one empty": {
|
||||
a: "abc",
|
||||
b: "",
|
||||
},
|
||||
"one nil": {
|
||||
a: "abc",
|
||||
b: nil,
|
||||
},
|
||||
"both nil": {
|
||||
a: nil,
|
||||
b: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := NotEqual(tc.a, tc.b).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIfNotNil(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
a *int
|
||||
c func() *Constraint
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
a: new(int),
|
||||
c: func() *Constraint {
|
||||
return &Constraint{
|
||||
Satisfied: func() *TreeError {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"nil": {
|
||||
a: nil,
|
||||
c: func() *Constraint {
|
||||
return &Constraint{
|
||||
Satisfied: func() *TreeError {
|
||||
t.Fatal("should not be called")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := IfNotNil(tc.a, tc.c).Satisfied()
|
||||
if tc.wantErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue