talos/pkg/machinery/config/configloader/configloader_test.go
Andrey Smirnov 6be5a13d5d
feat: implement machine config documents for event and log streaming
Fixes #7228

Add some changes to make Talos accept partial machine configuration
without main v1alpha1 config.

With this change, it's possible to connect a machine already running
with machine configuration (v1alpha1), the following patch will connect
to a local SideroLink endpoint:

```yaml
apiVersion: v1alpha1
kind: SideroLinkConfig
apiUrl: grpc://172.20.0.1:4000/?jointoken=foo
---
apiVersion: v1alpha1
kind: KmsgLogConfig
name: apiSink
url: tcp://[fdae:41e4:649b:9303::1]:4001/
---
apiVersion: v1alpha1
kind: EventSinkConfig
endpoint: "[fdae:41e4:649b:9303::1]:8080"
```

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
2023-07-01 00:22:44 +04:00

110 lines
2.3 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package configloader_test
import (
"os"
"path/filepath"
"reflect"
"testing"
"github.com/stretchr/testify/require"
"github.com/siderolabs/talos/pkg/machinery/config/configloader"
)
// callMethods calls obj's "getter" methods recursively and fails on panic.
//
//nolint:gocyclo
func callMethods(t testing.TB, obj reflect.Value, chain ...string) {
t.Helper()
if obj.Kind() == reflect.Interface && obj.IsNil() {
return
}
typ := obj.Type()
for i := 0; i < obj.NumMethod(); i++ {
method := obj.Method(i)
if method.Type().NumIn() != 0 {
continue
}
methodName := typ.Method(i).Name
nextChain := make([]string, len(chain)+1)
copy(nextChain, chain)
nextChain[len(nextChain)-1] = methodName
// t.Log(nextChain)
// skip known broken methods
switch methodName {
case "GetRSAKey", "GetEd25519Key", "GetECDSAKey", "GetCert", "GetKey":
fallthrough
case "MarshalYAML":
fallthrough
case "Doc":
fallthrough
case "Endpoint":
// t.Logf("Skipping %v", nextChain)
continue
}
var resS []reflect.Value
require.NotPanics(t, func() { resS = method.Call(nil) }, "Method chain: %v", nextChain)
if len(resS) == 0 {
continue
}
res := resS[0]
// skip result if it has the same type
// to avoid infinite recursion on methods like DeepCopy
if res.Type() == typ {
continue
}
callMethods(t, res, nextChain...)
}
}
func testConfigLoaderBytes(t testing.TB, b []byte, failOnError bool) {
t.Helper()
p, err := configloader.NewFromBytes(b)
if err != nil {
if failOnError {
t.Fatalf("Failed to load: %s.", err)
} else {
t.Skipf("Failed to load, skipping: %s.", err)
}
}
callMethods(t, reflect.ValueOf(p))
}
// TODO(aleksi): maybe remove once Go 1.18 is out; see https://github.com/golang/go/issues/47413
func TestConfigLoader(t *testing.T) {
t.Parallel()
files, err := filepath.Glob(filepath.Join("testdata", "*.test"))
require.NoError(t, err)
for _, file := range files {
file := file
t.Run(file, func(t *testing.T) {
t.Parallel()
b, err := os.ReadFile(file)
require.NoError(t, err)
testConfigLoaderBytes(t, b, true)
})
}
}