mirror of
				https://github.com/siderolabs/talos.git
				synced 2025-10-31 00:11:36 +01:00 
			
		
		
		
	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>
		
			
				
	
	
		
			110 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			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)
 | |
| 		})
 | |
| 	}
 | |
| }
 |