feat: implement strategic merge machine config patching

This format is much easier to understand when compared to JSON patches,
it allows for more patch validation, and it should provide better user
experience.

This just implements the config merge, but it doesn't yet hook it up to
any CLI utility, so no user-facing docs.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
Andrey Smirnov 2022-06-29 21:29:03 +04:00
parent c2a5126088
commit 4f044e4664
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
15 changed files with 1150 additions and 11 deletions

View File

@ -168,8 +168,14 @@ type structType struct {
node *ast.StructType
}
func collectStructs(node ast.Node) []*structType {
type aliasType struct {
fieldType string
fieldTypeRef string
}
func collectStructs(node ast.Node) ([]*structType, map[string]aliasType) {
structs := []*structType{}
aliases := map[string]aliasType{}
collectStructs := func(n ast.Node) bool {
g, ok := n.(*ast.GenDecl)
@ -177,11 +183,17 @@ func collectStructs(node ast.Node) []*structType {
return true
}
isAlias := false
if g.Doc != nil {
for _, comment := range g.Doc.List {
if strings.Contains(comment.Text, "docgen:nodoc") {
return true
}
if strings.Contains(comment.Text, "docgen:alias") {
isAlias = true
}
}
}
@ -197,6 +209,13 @@ func collectStructs(node ast.Node) []*structType {
x, ok := t.Type.(*ast.StructType)
if !ok {
if isAlias {
aliases[t.Name.Name] = aliasType{
fieldType: formatFieldType(t.Type),
fieldTypeRef: getFieldType(t.Type),
}
}
return true
}
@ -225,7 +244,7 @@ func collectStructs(node ast.Node) []*structType {
ast.Inspect(node, collectStructs)
return structs
return structs, aliases
}
func parseComment(comment []byte) *Text {
@ -307,7 +326,7 @@ func escape(value string) string {
return strings.TrimSpace(value)
}
func collectFields(s *structType) (fields []*Field) {
func collectFields(s *structType, aliases map[string]aliasType) (fields []*Field) {
fields = []*Field{}
for _, f := range s.node.Fields.List {
@ -333,8 +352,17 @@ func collectFields(s *structType) (fields []*Field) {
}
fieldType := formatFieldType(f.Type)
if alias, ok := aliases[fieldType]; ok {
fieldType = alias.fieldType
}
fieldTypeRef := getFieldType(f.Type)
if alias, ok := aliases[fieldTypeRef]; ok {
fieldTypeRef = alias.fieldTypeRef
}
tag := reflect.StructTag(strings.Trim(f.Tag.Value, "`"))
yamlTag := tag.Get("yaml")
yamlTag = strings.Split(yamlTag, ",")[0]
@ -405,8 +433,6 @@ func processFile(inputFile, outputFile, typeName string) {
log.Fatal(err)
}
var structs []*structType
packageName := node.Name.Name
tokenFile := fset.File(node.Pos())
@ -416,7 +442,7 @@ func processFile(inputFile, outputFile, typeName string) {
fmt.Printf("parsing file in package %q: %s\n", packageName, tokenFile.Name())
structs = append(structs, collectStructs(node)...)
structs, aliases := collectStructs(node)
if len(structs) == 0 {
log.Fatalf("failed to find types that could be documented in %s", abs)
@ -433,7 +459,7 @@ func processFile(inputFile, outputFile, typeName string) {
for _, s := range structs {
fmt.Printf("generating docs for type: %q\n", s.name)
fields := collectFields(s)
fields := collectFields(s, aliases)
s := &Struct{
Name: s.name,

View File

@ -0,0 +1,170 @@
// 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 merge
import (
"fmt"
"reflect"
"strings"
)
// Merge two config trees together.
//
// Data in the left is replaced with data in the right unless it's zero value.
//
// This function is not supposed to be a generic merge function.
// It is specifically fine-tuned to merge Talos machine configuration.
//
// Rules:
// - if it is a simple value (int, float, string, etc.), it's merged into the left unless it's zero value, but boolean false is always merged.
// - if it is a pointer, merged dereferencing the pointer unless the right is nil
// - if it is a slice, merged by concatenating the right to the left.
// - if the `merge:"replace"` struct tag is defined, a slice is replaced with the value of the right (unless it's zero value.)
// - slices of `[]byte` are always replaced
// - if it is a map, for each key value is merged recursively.
// - if it is a struct, merge is performed for each field of the struct.
// - if the type implements 'merger' interface, Merge function is called to handle the merge process.
// - merger interface should be implemented on the pointer to the type.
func Merge(left, right interface{}) error {
return merge(reflect.ValueOf(left), reflect.ValueOf(right), false)
}
type merger interface {
Merge(other interface{}) error
}
var (
zeroValue reflect.Value
mergerType = reflect.TypeOf((*merger)(nil)).Elem()
)
//nolint:gocyclo,cyclop
func merge(vl, vr reflect.Value, replace bool) error {
tl, tr := vl.Type(), vr.Type()
if tl != tr {
return fmt.Errorf("merge type mismatch left %v right %v", tl, tr)
}
if reflect.PointerTo(tl).Implements(mergerType) {
return vl.Addr().Interface().(merger).Merge(vr.Interface())
}
switch tl.Kind() { //nolint:exhaustive
case reflect.Pointer:
if vr.IsZero() {
return nil
}
if vl.IsZero() {
vl.Set(vr)
return nil
}
return merge(vl.Elem(), vr.Elem(), replace)
case reflect.Slice:
if vr.IsZero() {
return nil
}
if !vl.CanSet() {
return fmt.Errorf("merge not possible, left %v is not settable", vl)
}
if replace || tl.Elem().Kind() == reflect.Uint8 {
vl.Set(vr)
return nil
}
if vl.IsNil() && vr.Len() == 0 {
vl.Set(reflect.MakeSlice(tl, 0, 0))
} else {
vl.Set(reflect.AppendSlice(reflect.MakeSlice(tl, 0, 0), reflect.AppendSlice(vl, vr)))
}
case reflect.Map:
if vr.IsZero() {
return nil
}
if replace {
vl.Set(vr)
return nil
}
if vl.IsNil() {
vl.Set(reflect.MakeMap(tl))
}
for _, k := range vr.MapKeys() {
if vl.MapIndex(k) != zeroValue {
v := reflect.New(tl.Elem()).Elem()
v.Set(vl.MapIndex(k))
if err := merge(v, vr.MapIndex(k), false); err != nil {
return err
}
vl.SetMapIndex(k, v)
} else {
vl.SetMapIndex(k, vr.MapIndex(k))
}
}
case reflect.Struct:
if replace {
vl.Set(vr)
return nil
}
for i := 0; i < tl.NumField(); i++ {
var replace bool
structTag := tl.Field(i).Tag.Get("merge")
for _, value := range strings.Split(structTag, ",") {
if value == "replace" {
replace = true
}
}
fl := vl.FieldByIndex(tl.Field(i).Index)
fr := vr.FieldByIndex(tr.Field(i).Index)
if err := merge(fl, fr, replace); err != nil {
return fmt.Errorf("merge field %v.%v: %v", tl, tl.Field(i).Name, err)
}
}
case
reflect.String,
reflect.Int,
reflect.Uint,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64,
reflect.Float32,
reflect.Float64,
reflect.Bool:
if !vl.CanSet() {
return fmt.Errorf("merge not possible, left %v is not settable", vl)
}
if tl.Kind() != reflect.Bool && vr.IsZero() {
return nil
}
vl.Set(vr)
default:
return fmt.Errorf("merge not implemented for %v", tl.Kind())
}
return nil
}

View File

@ -0,0 +1,254 @@
// 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 merge_test
import (
"fmt"
"sort"
"testing"
"github.com/siderolabs/go-pointer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/talos-systems/talos/pkg/machinery/config/merge"
)
type Config struct {
A string
B int
C *bool
Slice []Struct
ReplacedSlice []string `merge:"replace"`
Map map[string]Struct
CustomSlice CustomSlice
}
type Struct struct {
DA bool
DB *int
}
type CustomSlice []string
func (s *CustomSlice) Merge(other interface{}) error {
otherSlice, ok := other.(CustomSlice)
if !ok {
return fmt.Errorf("other is not CustomSlice: %v", other)
}
*s = append(*s, otherSlice...)
sort.Strings(*s)
return nil
}
func TestMerge(t *testing.T) {
for _, tt := range []struct {
name string
left, right Config
expected Config
}{
{
name: "zero",
},
{
name: "partial merge",
left: Config{
A: "a",
B: 3,
C: pointer.To(true),
Slice: []Struct{
{
DA: true,
DB: pointer.To(1),
},
},
Map: map[string]Struct{
"a": {
DA: true,
},
"b": {
DB: pointer.To(2),
},
},
},
right: Config{
A: "aa",
B: 4,
Slice: []Struct{
{
DA: false,
DB: pointer.To(2),
},
},
Map: map[string]Struct{
"a": {
DB: pointer.To(3),
},
"b": {
DA: true,
DB: pointer.To(5),
},
"c": {
DB: pointer.To(4),
},
},
},
expected: Config{
A: "aa",
B: 4,
C: pointer.To(true),
Slice: []Struct{
{
DA: true,
DB: pointer.To(1),
},
{
DA: false,
DB: pointer.To(2),
},
},
Map: map[string]Struct{
"a": {
DB: pointer.To(3),
},
"b": {
DA: true,
DB: pointer.To(5),
},
"c": {
DB: pointer.To(4),
},
},
},
},
{
name: "merge with zero",
left: Config{
A: "a",
B: 3,
C: pointer.To(true),
Slice: []Struct{
{
DA: false,
DB: pointer.To(2),
},
},
Map: map[string]Struct{
"a": {
DA: true,
},
"b": {
DB: pointer.To(2),
},
},
},
right: Config{},
expected: Config{
A: "a",
B: 3,
C: pointer.To(true),
Slice: []Struct{
{
DA: false,
DB: pointer.To(2),
},
},
Map: map[string]Struct{
"a": {
DA: true,
},
"b": {
DB: pointer.To(2),
},
},
},
},
{
name: "merge from zero",
left: Config{},
right: Config{
A: "a",
B: 3,
C: pointer.To(true),
Slice: []Struct{
{
DA: false,
DB: pointer.To(2),
},
},
Map: map[string]Struct{
"a": {
DA: true,
},
"b": {
DB: pointer.To(2),
},
},
},
expected: Config{
A: "a",
B: 3,
C: pointer.To(true),
Slice: []Struct{
{
DA: false,
DB: pointer.To(2),
},
},
Map: map[string]Struct{
"a": {
DA: true,
},
"b": {
DB: pointer.To(2),
},
},
},
},
{
name: "replace slice",
left: Config{
ReplacedSlice: []string{"a", "b"},
},
right: Config{
ReplacedSlice: []string{"c", "d"},
},
expected: Config{
ReplacedSlice: []string{"c", "d"},
},
},
{
name: "zero slice",
left: Config{},
right: Config{
Slice: []Struct{},
},
expected: Config{
Slice: []Struct{},
},
},
{
name: "custom slice",
left: Config{
CustomSlice: []string{"a", "c"},
},
right: Config{
CustomSlice: []string{"b", "d"},
},
expected: Config{
CustomSlice: []string{"a", "b", "c", "d"},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
err := merge.Merge(&tt.left, &tt.right)
require.NoError(t, err)
assert.Equal(t, tt.expected, tt.left)
})
}
}

View File

@ -0,0 +1,86 @@
version: v1alpha1
debug: false
persist: true
machine:
type: controlplane
token: u8ei4i.iymakyzguuqaw30r
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBMENmN3VtOHV6akE4ZkRlY3FySElXakFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdOakk1TVRNME9ERXhXaGNOTXpJd05qSTJNVE0wT0RFeFdqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUR2dk1ESFdSY2xtRHdtOGRkNUZDV0w0djJQSlFnMkZ0bDBtCklLd1MwYjFObzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5TZGU2ZG9JZDFjckdLVwpxek1YbG80dStoVjRNQVVHQXl0bGNBTkJBR0c3aEQ3Z2FJckhnTnhKYjByOGVDdkozMS96eHQraW8wQlVoSi9FCnBvUkVxaWxOV1RHUDViSDRMcERqU2ZIOE1UcGdiZWhkZTRJUGxnRW5iR3VVYmdzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJR2NZL0ZIU2lsNUhJTzlrcTNKZVBGbFdLNDJLZG9MOUwxYXBLZm1tdVJZaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
certSANs: []
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.24.2
network:
interfaces:
- interface: eth0
addresses:
- 10.3.5.7/24
mtu: 0
dhcp: false
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.1.0-alpha.2-105-g2deff6b6e
bootloader: true
wipe: true
features:
rbac: false
env:
http_proxy: http://127.0.0.1:3128/
cluster:
id: GGsG0g9PKDxVr1mV1hT929fu9lmC0MlTHfOkN63GJuQ=
secret: se0RJPQ6v2aN0ExMc7yE4L5fMuK/N9wuyGr57R0MskI=
controlPlane:
endpoint: https://10.0.0.1/
clusterName: foo
network:
dnsDomain: cluster.local
podSubnets: ["10.0.0.0/24"]
serviceSubnets: ["192.168.0.0/24", "ff:08::/64"]
token: 4pcl58.l0i5cv8h9k3k1az8
aescbcEncryptionSecret: A3U0/d6dmFeEO2/M6zQRWj9TqmhvOsM/RV8ZuxeIpXg=
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVU1UcVNRYlR4a2Iwb2gxdnEyRVdRekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXlNRFl5T1RFek5EZ3hNVm9YRFRNeU1EWXlOakV6TkRneApNVm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCTTZvTVUvcGJuY043SUI3OC9NMTVkMHBFRDVvK3FaWEZFUmJsd1VxUzJXUmplM0d3S2RDYWpXZjM2YUcKbHR5RWFJUlNzZnNISU4vZm45SFNWL08zUTR5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU5SjNqTHJmY2Z5TmlmNnBJampxVUlWdUQrbTR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVE1QVnR5TnMKRW5Mc1k1dXVOajdLcldVcFFQNTRyaVJ3WVZueGZOeStQRzRDSVFDUm5sR3k0bTExZFc5RjBJWVFmQUoweUZKRQpXRHRsT3QraEJaZzczWXR6N0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU1IeFZuVGFXdlFjNTNBTnlWMjhYVmltTW83U24zWnRhbTFGa2JwQjFmczNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFenFneFQrbHVkdzNzZ0h2ejh6WGwzU2tRUG1qNnBsY1VSRnVYQlNwTFpaR043Y2JBcDBKcQpOWi9mcG9hVzNJUm9oRkt4K3djZzM5K2YwZEpYODdkRGpBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
aggregatorCA:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUlwbllnQVl3UTlWYUthNXI3K1Y1bW93Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU1qQTJNamt4TXpRNE1URmFGdzB6TWpBMk1qWXhNelE0TVRGYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVJINXpHY1M5NVZ4bjl4T1hOVXg5ai9PVytHTkkxcFREU1FRc3V0S0NtakhKRHN2VTNKCmFTa1NVWmxzSVpYbWkxZXhlTHRZeS9TN202M0JMaUZnUTFYMm8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGSDZ1Uk1IVUFBaXJwRUU1SkhQS3ZrT3g2RUljTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRQ0FBems2YjBrK0VNTkZBbzVaTHo0bElqQmtFZnZwWDdsaGtBclM4MjZmcWdJaEFJeUI5OVNJVkFuYkFONlAKeFlSaWFqNS81R1d2OTFiT0pZQ2N0Y2tGL294YwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5YS0M4YkkxbTBVd0NWb0NWQlZERndtL3lqaWdQUVNrdGV0MVAra0pjWU9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUitjeG5FdmVWY1ovY1RselZNZlkvemx2aGpTTmFVdzBrRUxMclNncG94eVE3TDFOeVdrcApFbEdaYkNHVjVvdFhzWGk3V012MHU1dXR3UzRoWUVOVjlnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
apiServer:
image: k8s.gcr.io/kube-apiserver:v1.24.2
certSANs:
- 127.0.0.1
disablePodSecurityPolicy: true
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
controllerManager:
image: k8s.gcr.io/kube-controller-manager:v1.24.2
proxy:
image: k8s.gcr.io/kube-proxy:v1.24.2
scheduler:
image: k8s.gcr.io/kube-scheduler:v1.24.2
discovery:
enabled: true
registries:
kubernetes:
disabled: true
service: {}
etcd:
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNTZ0F3SUJBZ0lSQU9jRytGVk5EYTI0SXJ1YnA5QVRTVkl3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TWpBMk1qa3hNelE0TVRGYUZ3MHpNakEyTWpZeE16UTRNVEZhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRa2pRd3puYmF4ClFyOUVyOG51TUQyUEdEUHBRak1nNGc5czMzeW1GMnpCQWZhMGlta2RMK0hCRkZhaDZ4OHNNVnFsOWJIZEFyRWIKcjVjUFdEeUpRUkxmbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkl3VmNlNHhrNjI0ClZseVcvaHVwek40U2FZZGVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnphUzkyMExjK1dlOEpjNkk4dm9LWlQKZXJ3NDlMQ0o0VGpaeUwwVzl5RzdBaUI5QWRlOWNVa1AwSitDelZIdUVVU3NmVjBENFg4N0RyM3lUbGV0NHVVSQpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxqUCtiL1FnckZqTlh6WCswZWNQTU8xc1MvYzM4NUFObWFFU3VIbENSR0hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkkwTU01MjJzVUsvUksvSjdqQTlqeGd6NlVJeklPSVBiTjk4cGhkc3dRSDJ0SXBwSFMvaAp3UlJXb2VzZkxERmFwZld4M1FLeEc2K1hEMWc4aVVFUzN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,79 @@
version: v1alpha1
debug: false
persist: true
machine:
type: controlplane
token: u8ei4i.iymakyzguuqaw30r
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBMENmN3VtOHV6akE4ZkRlY3FySElXakFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdOakk1TVRNME9ERXhXaGNOTXpJd05qSTJNVE0wT0RFeFdqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUR2dk1ESFdSY2xtRHdtOGRkNUZDV0w0djJQSlFnMkZ0bDBtCklLd1MwYjFObzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5TZGU2ZG9JZDFjckdLVwpxek1YbG80dStoVjRNQVVHQXl0bGNBTkJBR0c3aEQ3Z2FJckhnTnhKYjByOGVDdkozMS96eHQraW8wQlVoSi9FCnBvUkVxaWxOV1RHUDViSDRMcERqU2ZIOE1UcGdiZWhkZTRJUGxnRW5iR3VVYmdzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJR2NZL0ZIU2lsNUhJTzlrcTNKZVBGbFdLNDJLZG9MOUwxYXBLZm1tdVJZaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
certSANs: []
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.24.2
network: {}
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.1.0-alpha.2-105-g2deff6b6e
bootloader: true
wipe: false
features:
rbac: true
cluster:
id: GGsG0g9PKDxVr1mV1hT929fu9lmC0MlTHfOkN63GJuQ=
secret: se0RJPQ6v2aN0ExMc7yE4L5fMuK/N9wuyGr57R0MskI=
controlPlane:
endpoint: https://127.0.0.1:6643/
clusterName: foo
network:
dnsDomain: cluster.local
podSubnets:
- 10.244.0.0/16
serviceSubnets:
- 10.96.0.0/12
token: 4pcl58.l0i5cv8h9k3k1az8
aescbcEncryptionSecret: A3U0/d6dmFeEO2/M6zQRWj9TqmhvOsM/RV8ZuxeIpXg=
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVU1UcVNRYlR4a2Iwb2gxdnEyRVdRekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXlNRFl5T1RFek5EZ3hNVm9YRFRNeU1EWXlOakV6TkRneApNVm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCTTZvTVUvcGJuY043SUI3OC9NMTVkMHBFRDVvK3FaWEZFUmJsd1VxUzJXUmplM0d3S2RDYWpXZjM2YUcKbHR5RWFJUlNzZnNISU4vZm45SFNWL08zUTR5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU5SjNqTHJmY2Z5TmlmNnBJampxVUlWdUQrbTR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVE1QVnR5TnMKRW5Mc1k1dXVOajdLcldVcFFQNTRyaVJ3WVZueGZOeStQRzRDSVFDUm5sR3k0bTExZFc5RjBJWVFmQUoweUZKRQpXRHRsT3QraEJaZzczWXR6N0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU1IeFZuVGFXdlFjNTNBTnlWMjhYVmltTW83U24zWnRhbTFGa2JwQjFmczNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFenFneFQrbHVkdzNzZ0h2ejh6WGwzU2tRUG1qNnBsY1VSRnVYQlNwTFpaR043Y2JBcDBKcQpOWi9mcG9hVzNJUm9oRkt4K3djZzM5K2YwZEpYODdkRGpBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
aggregatorCA:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUlwbllnQVl3UTlWYUthNXI3K1Y1bW93Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU1qQTJNamt4TXpRNE1URmFGdzB6TWpBMk1qWXhNelE0TVRGYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVJINXpHY1M5NVZ4bjl4T1hOVXg5ai9PVytHTkkxcFREU1FRc3V0S0NtakhKRHN2VTNKCmFTa1NVWmxzSVpYbWkxZXhlTHRZeS9TN202M0JMaUZnUTFYMm8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGSDZ1Uk1IVUFBaXJwRUU1SkhQS3ZrT3g2RUljTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRQ0FBems2YjBrK0VNTkZBbzVaTHo0bElqQmtFZnZwWDdsaGtBclM4MjZmcWdJaEFJeUI5OVNJVkFuYkFONlAKeFlSaWFqNS81R1d2OTFiT0pZQ2N0Y2tGL294YwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5YS0M4YkkxbTBVd0NWb0NWQlZERndtL3lqaWdQUVNrdGV0MVAra0pjWU9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUitjeG5FdmVWY1ovY1RselZNZlkvemx2aGpTTmFVdzBrRUxMclNncG94eVE3TDFOeVdrcApFbEdaYkNHVjVvdFhzWGk3V012MHU1dXR3UzRoWUVOVjlnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
apiServer:
image: k8s.gcr.io/kube-apiserver:v1.24.2
certSANs:
- 127.0.0.1
disablePodSecurityPolicy: true
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
controllerManager:
image: k8s.gcr.io/kube-controller-manager:v1.24.2
proxy:
image: k8s.gcr.io/kube-proxy:v1.24.2
scheduler:
image: k8s.gcr.io/kube-scheduler:v1.24.2
discovery:
enabled: true
registries:
kubernetes: {}
service: {}
etcd:
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNTZ0F3SUJBZ0lSQU9jRytGVk5EYTI0SXJ1YnA5QVRTVkl3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TWpBMk1qa3hNelE0TVRGYUZ3MHpNakEyTWpZeE16UTRNVEZhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRa2pRd3puYmF4ClFyOUVyOG51TUQyUEdEUHBRak1nNGc5czMzeW1GMnpCQWZhMGlta2RMK0hCRkZhaDZ4OHNNVnFsOWJIZEFyRWIKcjVjUFdEeUpRUkxmbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkl3VmNlNHhrNjI0ClZseVcvaHVwek40U2FZZGVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnphUzkyMExjK1dlOEpjNkk4dm9LWlQKZXJ3NDlMQ0o0VGpaeUwwVzl5RzdBaUI5QWRlOWNVa1AwSitDelZIdUVVU3NmVjBENFg4N0RyM3lUbGV0NHVVSQpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxqUCtiL1FnckZqTlh6WCswZWNQTU8xc1MvYzM4NUFObWFFU3VIbENSR0hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkkwTU01MjJzVUsvUksvSjdqQTlqeGd6NlVJeklPSVBiTjk4cGhkc3dRSDJ0SXBwSFMvaAp3UlJXb2VzZkxERmFwZld4M1FLeEc2K1hEMWc4aVVFUzN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,25 @@
machine:
network:
interfaces:
- interface: eth0
addresses:
- 10.3.5.7/24
dhcp: false
features:
rbac: false
env:
http_proxy: http://127.0.0.1:3128/
install:
wipe: true
cluster:
controlPlane:
endpoint: https://10.0.0.1
discovery:
registries:
kubernetes:
disabled: true
network:
podSubnets: ["10.0.0.0/24"]
serviceSubnets: ["192.168.0.0/24", "ff:08::/64"]
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,79 @@
version: v1alpha1
debug: false
persist: true
machine:
type: controlplane
token: u8ei4i.iymakyzguuqaw30r
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBMENmN3VtOHV6akE4ZkRlY3FySElXakFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdOakk1TVRNME9ERXhXaGNOTXpJd05qSTJNVE0wT0RFeFdqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUR2dk1ESFdSY2xtRHdtOGRkNUZDV0w0djJQSlFnMkZ0bDBtCklLd1MwYjFObzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5TZGU2ZG9JZDFjckdLVwpxek1YbG80dStoVjRNQVVHQXl0bGNBTkJBR0c3aEQ3Z2FJckhnTnhKYjByOGVDdkozMS96eHQraW8wQlVoSi9FCnBvUkVxaWxOV1RHUDViSDRMcERqU2ZIOE1UcGdiZWhkZTRJUGxnRW5iR3VVYmdzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJR2NZL0ZIU2lsNUhJTzlrcTNKZVBGbFdLNDJLZG9MOUwxYXBLZm1tdVJZaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
certSANs: []
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.24.2
network: {}
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.1.0-alpha.2-105-g2deff6b6e
bootloader: true
wipe: false
features:
rbac: true
cluster:
id: GGsG0g9PKDxVr1mV1hT929fu9lmC0MlTHfOkN63GJuQ=
secret: se0RJPQ6v2aN0ExMc7yE4L5fMuK/N9wuyGr57R0MskI=
controlPlane:
endpoint: https://127.0.0.1:6643/
clusterName: foo
network:
dnsDomain: cluster.local
podSubnets:
- 10.244.0.0/16
serviceSubnets:
- 10.96.0.0/12
token: 4pcl58.l0i5cv8h9k3k1az8
aescbcEncryptionSecret: A3U0/d6dmFeEO2/M6zQRWj9TqmhvOsM/RV8ZuxeIpXg=
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVU1UcVNRYlR4a2Iwb2gxdnEyRVdRekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXlNRFl5T1RFek5EZ3hNVm9YRFRNeU1EWXlOakV6TkRneApNVm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCTTZvTVUvcGJuY043SUI3OC9NMTVkMHBFRDVvK3FaWEZFUmJsd1VxUzJXUmplM0d3S2RDYWpXZjM2YUcKbHR5RWFJUlNzZnNISU4vZm45SFNWL08zUTR5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU5SjNqTHJmY2Z5TmlmNnBJampxVUlWdUQrbTR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVE1QVnR5TnMKRW5Mc1k1dXVOajdLcldVcFFQNTRyaVJ3WVZueGZOeStQRzRDSVFDUm5sR3k0bTExZFc5RjBJWVFmQUoweUZKRQpXRHRsT3QraEJaZzczWXR6N0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU1IeFZuVGFXdlFjNTNBTnlWMjhYVmltTW83U24zWnRhbTFGa2JwQjFmczNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFenFneFQrbHVkdzNzZ0h2ejh6WGwzU2tRUG1qNnBsY1VSRnVYQlNwTFpaR043Y2JBcDBKcQpOWi9mcG9hVzNJUm9oRkt4K3djZzM5K2YwZEpYODdkRGpBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
aggregatorCA:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUlwbllnQVl3UTlWYUthNXI3K1Y1bW93Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU1qQTJNamt4TXpRNE1URmFGdzB6TWpBMk1qWXhNelE0TVRGYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVJINXpHY1M5NVZ4bjl4T1hOVXg5ai9PVytHTkkxcFREU1FRc3V0S0NtakhKRHN2VTNKCmFTa1NVWmxzSVpYbWkxZXhlTHRZeS9TN202M0JMaUZnUTFYMm8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGSDZ1Uk1IVUFBaXJwRUU1SkhQS3ZrT3g2RUljTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRQ0FBems2YjBrK0VNTkZBbzVaTHo0bElqQmtFZnZwWDdsaGtBclM4MjZmcWdJaEFJeUI5OVNJVkFuYkFONlAKeFlSaWFqNS81R1d2OTFiT0pZQ2N0Y2tGL294YwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5YS0M4YkkxbTBVd0NWb0NWQlZERndtL3lqaWdQUVNrdGV0MVAra0pjWU9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUitjeG5FdmVWY1ovY1RselZNZlkvemx2aGpTTmFVdzBrRUxMclNncG94eVE3TDFOeVdrcApFbEdaYkNHVjVvdFhzWGk3V012MHU1dXR3UzRoWUVOVjlnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
apiServer:
image: k8s.gcr.io/kube-apiserver:v1.24.2
certSANs:
- 127.0.0.1
disablePodSecurityPolicy: true
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
controllerManager:
image: k8s.gcr.io/kube-controller-manager:v1.24.2
proxy:
image: k8s.gcr.io/kube-proxy:v1.24.2
scheduler:
image: k8s.gcr.io/kube-scheduler:v1.24.2
discovery:
enabled: true
registries:
kubernetes: {}
service: {}
etcd:
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNTZ0F3SUJBZ0lSQU9jRytGVk5EYTI0SXJ1YnA5QVRTVkl3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TWpBMk1qa3hNelE0TVRGYUZ3MHpNakEyTWpZeE16UTRNVEZhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRa2pRd3puYmF4ClFyOUVyOG51TUQyUEdEUHBRak1nNGc5czMzeW1GMnpCQWZhMGlta2RMK0hCRkZhaDZ4OHNNVnFsOWJIZEFyRWIKcjVjUFdEeUpRUkxmbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkl3VmNlNHhrNjI0ClZseVcvaHVwek40U2FZZGVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnphUzkyMExjK1dlOEpjNkk4dm9LWlQKZXJ3NDlMQ0o0VGpaeUwwVzl5RzdBaUI5QWRlOWNVa1AwSitDelZIdUVVU3NmVjBENFg4N0RyM3lUbGV0NHVVSQpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxqUCtiL1FnckZqTlh6WCswZWNQTU8xc1MvYzM4NUFObWFFU3VIbENSR0hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkkwTU01MjJzVUsvUksvSjdqQTlqeGd6NlVJeklPSVBiTjk4cGhkc3dRSDJ0SXBwSFMvaAp3UlJXb2VzZkxERmFwZld4M1FLeEc2K1hEMWc4aVVFUzN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,2 @@
version: v1alpha1
machine: {}

View File

@ -0,0 +1,79 @@
version: v1alpha1
debug: false
persist: true
machine:
type: controlplane
token: u8ei4i.iymakyzguuqaw30r
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBMENmN3VtOHV6akE4ZkRlY3FySElXakFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdOakk1TVRNME9ERXhXaGNOTXpJd05qSTJNVE0wT0RFeFdqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUR2dk1ESFdSY2xtRHdtOGRkNUZDV0w0djJQSlFnMkZ0bDBtCklLd1MwYjFObzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5TZGU2ZG9JZDFjckdLVwpxek1YbG80dStoVjRNQVVHQXl0bGNBTkJBR0c3aEQ3Z2FJckhnTnhKYjByOGVDdkozMS96eHQraW8wQlVoSi9FCnBvUkVxaWxOV1RHUDViSDRMcERqU2ZIOE1UcGdiZWhkZTRJUGxnRW5iR3VVYmdzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJR2NZL0ZIU2lsNUhJTzlrcTNKZVBGbFdLNDJLZG9MOUwxYXBLZm1tdVJZaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
certSANs: []
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.24.2
network: {}
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.1.0-alpha.2-105-g2deff6b6e
bootloader: true
wipe: false
features:
rbac: true
cluster:
id: GGsG0g9PKDxVr1mV1hT929fu9lmC0MlTHfOkN63GJuQ=
secret: se0RJPQ6v2aN0ExMc7yE4L5fMuK/N9wuyGr57R0MskI=
controlPlane:
endpoint: https://127.0.0.1:6643/
clusterName: foo
network:
dnsDomain: cluster.local
podSubnets:
- 10.244.0.0/16
serviceSubnets:
- 10.96.0.0/12
token: 4pcl58.l0i5cv8h9k3k1az8
aescbcEncryptionSecret: A3U0/d6dmFeEO2/M6zQRWj9TqmhvOsM/RV8ZuxeIpXg=
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVU1UcVNRYlR4a2Iwb2gxdnEyRVdRekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXlNRFl5T1RFek5EZ3hNVm9YRFRNeU1EWXlOakV6TkRneApNVm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCTTZvTVUvcGJuY043SUI3OC9NMTVkMHBFRDVvK3FaWEZFUmJsd1VxUzJXUmplM0d3S2RDYWpXZjM2YUcKbHR5RWFJUlNzZnNISU4vZm45SFNWL08zUTR5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU5SjNqTHJmY2Z5TmlmNnBJampxVUlWdUQrbTR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVE1QVnR5TnMKRW5Mc1k1dXVOajdLcldVcFFQNTRyaVJ3WVZueGZOeStQRzRDSVFDUm5sR3k0bTExZFc5RjBJWVFmQUoweUZKRQpXRHRsT3QraEJaZzczWXR6N0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU1IeFZuVGFXdlFjNTNBTnlWMjhYVmltTW83U24zWnRhbTFGa2JwQjFmczNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFenFneFQrbHVkdzNzZ0h2ejh6WGwzU2tRUG1qNnBsY1VSRnVYQlNwTFpaR043Y2JBcDBKcQpOWi9mcG9hVzNJUm9oRkt4K3djZzM5K2YwZEpYODdkRGpBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
aggregatorCA:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUlwbllnQVl3UTlWYUthNXI3K1Y1bW93Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU1qQTJNamt4TXpRNE1URmFGdzB6TWpBMk1qWXhNelE0TVRGYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVJINXpHY1M5NVZ4bjl4T1hOVXg5ai9PVytHTkkxcFREU1FRc3V0S0NtakhKRHN2VTNKCmFTa1NVWmxzSVpYbWkxZXhlTHRZeS9TN202M0JMaUZnUTFYMm8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGSDZ1Uk1IVUFBaXJwRUU1SkhQS3ZrT3g2RUljTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRQ0FBems2YjBrK0VNTkZBbzVaTHo0bElqQmtFZnZwWDdsaGtBclM4MjZmcWdJaEFJeUI5OVNJVkFuYkFONlAKeFlSaWFqNS81R1d2OTFiT0pZQ2N0Y2tGL294YwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5YS0M4YkkxbTBVd0NWb0NWQlZERndtL3lqaWdQUVNrdGV0MVAra0pjWU9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUitjeG5FdmVWY1ovY1RselZNZlkvemx2aGpTTmFVdzBrRUxMclNncG94eVE3TDFOeVdrcApFbEdaYkNHVjVvdFhzWGk3V012MHU1dXR3UzRoWUVOVjlnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
apiServer:
image: k8s.gcr.io/kube-apiserver:v1.24.2
certSANs:
- 127.0.0.1
disablePodSecurityPolicy: true
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
controllerManager:
image: k8s.gcr.io/kube-controller-manager:v1.24.2
proxy:
image: k8s.gcr.io/kube-proxy:v1.24.2
scheduler:
image: k8s.gcr.io/kube-scheduler:v1.24.2
discovery:
enabled: true
registries:
kubernetes: {}
service: {}
etcd:
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNTZ0F3SUJBZ0lSQU9jRytGVk5EYTI0SXJ1YnA5QVRTVkl3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TWpBMk1qa3hNelE0TVRGYUZ3MHpNakEyTWpZeE16UTRNVEZhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRa2pRd3puYmF4ClFyOUVyOG51TUQyUEdEUHBRak1nNGc5czMzeW1GMnpCQWZhMGlta2RMK0hCRkZhaDZ4OHNNVnFsOWJIZEFyRWIKcjVjUFdEeUpRUkxmbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkl3VmNlNHhrNjI0ClZseVcvaHVwek40U2FZZGVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnphUzkyMExjK1dlOEpjNkk4dm9LWlQKZXJ3NDlMQ0o0VGpaeUwwVzl5RzdBaUI5QWRlOWNVa1AwSitDelZIdUVVU3NmVjBENFg4N0RyM3lUbGV0NHVVSQpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxqUCtiL1FnckZqTlh6WCswZWNQTU8xc1MvYzM4NUFObWFFU3VIbENSR0hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkkwTU01MjJzVUsvUksvSjdqQTlqeGd6NlVJeklPSVBiTjk4cGhkc3dRSDJ0SXBwSFMvaAp3UlJXb2VzZkxERmFwZld4M1FLeEc2K1hEMWc4aVVFUzN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,96 @@
version: v1alpha1
debug: false
persist: true
machine:
type: controlplane
token: u8ei4i.iymakyzguuqaw30r
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBMENmN3VtOHV6akE4ZkRlY3FySElXakFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdOakk1TVRNME9ERXhXaGNOTXpJd05qSTJNVE0wT0RFeFdqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUR2dk1ESFdSY2xtRHdtOGRkNUZDV0w0djJQSlFnMkZ0bDBtCklLd1MwYjFObzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5TZGU2ZG9JZDFjckdLVwpxek1YbG80dStoVjRNQVVHQXl0bGNBTkJBR0c3aEQ3Z2FJckhnTnhKYjByOGVDdkozMS96eHQraW8wQlVoSi9FCnBvUkVxaWxOV1RHUDViSDRMcERqU2ZIOE1UcGdiZWhkZTRJUGxnRW5iR3VVYmdzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJR2NZL0ZIU2lsNUhJTzlrcTNKZVBGbFdLNDJLZG9MOUwxYXBLZm1tdVJZaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
certSANs: []
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.24.2
network:
hostname:
interfaces:
- interface: eth0
addresses:
- 172.20.0.2/24
dhcp: true
vip:
ip: 10.3.5.7
- deviceSelector:
driver: macvtap
dhcp: false
routes:
- network: 10.3.4.0/24
gateway: 10.3.4.1
- interface: eth1
addresses:
- "192.168.0.1/24"
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.1.0-alpha.2-105-g2deff6b6e
bootloader: true
wipe: false
features:
rbac: true
cluster:
id: GGsG0g9PKDxVr1mV1hT929fu9lmC0MlTHfOkN63GJuQ=
secret: se0RJPQ6v2aN0ExMc7yE4L5fMuK/N9wuyGr57R0MskI=
controlPlane:
endpoint: https://127.0.0.1:6643/
clusterName: foo
network:
dnsDomain: cluster.local
podSubnets:
- 10.244.0.0/16
serviceSubnets:
- 10.96.0.0/12
token: 4pcl58.l0i5cv8h9k3k1az8
aescbcEncryptionSecret: A3U0/d6dmFeEO2/M6zQRWj9TqmhvOsM/RV8ZuxeIpXg=
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVU1UcVNRYlR4a2Iwb2gxdnEyRVdRekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXlNRFl5T1RFek5EZ3hNVm9YRFRNeU1EWXlOakV6TkRneApNVm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCTTZvTVUvcGJuY043SUI3OC9NMTVkMHBFRDVvK3FaWEZFUmJsd1VxUzJXUmplM0d3S2RDYWpXZjM2YUcKbHR5RWFJUlNzZnNISU4vZm45SFNWL08zUTR5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU5SjNqTHJmY2Z5TmlmNnBJampxVUlWdUQrbTR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVE1QVnR5TnMKRW5Mc1k1dXVOajdLcldVcFFQNTRyaVJ3WVZueGZOeStQRzRDSVFDUm5sR3k0bTExZFc5RjBJWVFmQUoweUZKRQpXRHRsT3QraEJaZzczWXR6N0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU1IeFZuVGFXdlFjNTNBTnlWMjhYVmltTW83U24zWnRhbTFGa2JwQjFmczNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFenFneFQrbHVkdzNzZ0h2ejh6WGwzU2tRUG1qNnBsY1VSRnVYQlNwTFpaR043Y2JBcDBKcQpOWi9mcG9hVzNJUm9oRkt4K3djZzM5K2YwZEpYODdkRGpBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
aggregatorCA:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUlwbllnQVl3UTlWYUthNXI3K1Y1bW93Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU1qQTJNamt4TXpRNE1URmFGdzB6TWpBMk1qWXhNelE0TVRGYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVJINXpHY1M5NVZ4bjl4T1hOVXg5ai9PVytHTkkxcFREU1FRc3V0S0NtakhKRHN2VTNKCmFTa1NVWmxzSVpYbWkxZXhlTHRZeS9TN202M0JMaUZnUTFYMm8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGSDZ1Uk1IVUFBaXJwRUU1SkhQS3ZrT3g2RUljTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRQ0FBems2YjBrK0VNTkZBbzVaTHo0bElqQmtFZnZwWDdsaGtBclM4MjZmcWdJaEFJeUI5OVNJVkFuYkFONlAKeFlSaWFqNS81R1d2OTFiT0pZQ2N0Y2tGL294YwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5YS0M4YkkxbTBVd0NWb0NWQlZERndtL3lqaWdQUVNrdGV0MVAra0pjWU9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUitjeG5FdmVWY1ovY1RselZNZlkvemx2aGpTTmFVdzBrRUxMclNncG94eVE3TDFOeVdrcApFbEdaYkNHVjVvdFhzWGk3V012MHU1dXR3UzRoWUVOVjlnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
apiServer:
image: k8s.gcr.io/kube-apiserver:v1.24.2
certSANs:
- 127.0.0.1
disablePodSecurityPolicy: true
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
controllerManager:
image: k8s.gcr.io/kube-controller-manager:v1.24.2
proxy:
image: k8s.gcr.io/kube-proxy:v1.24.2
scheduler:
image: k8s.gcr.io/kube-scheduler:v1.24.2
discovery:
enabled: true
registries:
kubernetes: {}
service: {}
etcd:
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNTZ0F3SUJBZ0lSQU9jRytGVk5EYTI0SXJ1YnA5QVRTVkl3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TWpBMk1qa3hNelE0TVRGYUZ3MHpNakEyTWpZeE16UTRNVEZhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRa2pRd3puYmF4ClFyOUVyOG51TUQyUEdEUHBRak1nNGc5czMzeW1GMnpCQWZhMGlta2RMK0hCRkZhaDZ4OHNNVnFsOWJIZEFyRWIKcjVjUFdEeUpRUkxmbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkl3VmNlNHhrNjI0ClZseVcvaHVwek40U2FZZGVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnphUzkyMExjK1dlOEpjNkk4dm9LWlQKZXJ3NDlMQ0o0VGpaeUwwVzl5RzdBaUI5QWRlOWNVa1AwSitDelZIdUVVU3NmVjBENFg4N0RyM3lUbGV0NHVVSQpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxqUCtiL1FnckZqTlh6WCswZWNQTU8xc1MvYzM4NUFObWFFU3VIbENSR0hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkkwTU01MjJzVUsvUksvSjdqQTlqeGd6NlVJeklPSVBiTjk4cGhkc3dRSDJ0SXBwSFMvaAp3UlJXb2VzZkxERmFwZld4M1FLeEc2K1hEMWc4aVVFUzN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,88 @@
version: v1alpha1
debug: false
persist: true
machine:
type: controlplane
token: u8ei4i.iymakyzguuqaw30r
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQekNCOHFBREFnRUNBaEVBMENmN3VtOHV6akE4ZkRlY3FySElXakFGQmdNclpYQXdFREVPTUF3R0ExVUUKQ2hNRmRHRnNiM013SGhjTk1qSXdOakk1TVRNME9ERXhXaGNOTXpJd05qSTJNVE0wT0RFeFdqQVFNUTR3REFZRApWUVFLRXdWMFlXeHZjekFxTUFVR0F5dGxjQU1oQUR2dk1ESFdSY2xtRHdtOGRkNUZDV0w0djJQSlFnMkZ0bDBtCklLd1MwYjFObzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRk5TZGU2ZG9JZDFjckdLVwpxek1YbG80dStoVjRNQVVHQXl0bGNBTkJBR0c3aEQ3Z2FJckhnTnhKYjByOGVDdkozMS96eHQraW8wQlVoSi9FCnBvUkVxaWxOV1RHUDViSDRMcERqU2ZIOE1UcGdiZWhkZTRJUGxnRW5iR3VVYmdzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJR2NZL0ZIU2lsNUhJTzlrcTNKZVBGbFdLNDJLZG9MOUwxYXBLZm1tdVJZaAotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K
certSANs: []
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.24.2
network:
hostname:
interfaces:
- interface: eth0
addresses:
- 172.20.0.2/24
dhcp: true
- deviceSelector:
driver: macvtap
dhcp: false
install:
disk: /dev/sda
image: ghcr.io/siderolabs/installer:v1.1.0-alpha.2-105-g2deff6b6e
bootloader: true
wipe: false
features:
rbac: true
cluster:
id: GGsG0g9PKDxVr1mV1hT929fu9lmC0MlTHfOkN63GJuQ=
secret: se0RJPQ6v2aN0ExMc7yE4L5fMuK/N9wuyGr57R0MskI=
controlPlane:
endpoint: https://127.0.0.1:6643/
clusterName: foo
network:
dnsDomain: cluster.local
podSubnets:
- 10.244.0.0/16
serviceSubnets:
- 10.96.0.0/12
token: 4pcl58.l0i5cv8h9k3k1az8
aescbcEncryptionSecret: A3U0/d6dmFeEO2/M6zQRWj9TqmhvOsM/RV8ZuxeIpXg=
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRVU1UcVNRYlR4a2Iwb2gxdnEyRVdRekFLQmdncWhrak9QUVFEQWpBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXlNRFl5T1RFek5EZ3hNVm9YRFRNeU1EWXlOakV6TkRneApNVm93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCTTZvTVUvcGJuY043SUI3OC9NMTVkMHBFRDVvK3FaWEZFUmJsd1VxUzJXUmplM0d3S2RDYWpXZjM2YUcKbHR5RWFJUlNzZnNISU4vZm45SFNWL08zUTR5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVU5SjNqTHJmY2Z5TmlmNnBJampxVUlWdUQrbTR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVE1QVnR5TnMKRW5Mc1k1dXVOajdLcldVcFFQNTRyaVJ3WVZueGZOeStQRzRDSVFDUm5sR3k0bTExZFc5RjBJWVFmQUoweUZKRQpXRHRsT3QraEJaZzczWXR6N0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU1IeFZuVGFXdlFjNTNBTnlWMjhYVmltTW83U24zWnRhbTFGa2JwQjFmczNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFenFneFQrbHVkdzNzZ0h2ejh6WGwzU2tRUG1qNnBsY1VSRnVYQlNwTFpaR043Y2JBcDBKcQpOWi9mcG9hVzNJUm9oRkt4K3djZzM5K2YwZEpYODdkRGpBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
aggregatorCA:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZVENDQVFhZ0F3SUJBZ0lSQUlwbllnQVl3UTlWYUthNXI3K1Y1bW93Q2dZSUtvWkl6ajBFQXdJd0FEQWUKRncweU1qQTJNamt4TXpRNE1URmFGdzB6TWpBMk1qWXhNelE0TVRGYU1BQXdXVEFUQmdjcWhrak9QUUlCQmdncQpoa2pPUFFNQkJ3TkNBQVJINXpHY1M5NVZ4bjl4T1hOVXg5ai9PVytHTkkxcFREU1FRc3V0S0NtakhKRHN2VTNKCmFTa1NVWmxzSVpYbWkxZXhlTHRZeS9TN202M0JMaUZnUTFYMm8yRXdYekFPQmdOVkhROEJBZjhFQkFNQ0FvUXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BOEdBMVVkRXdFQi93UUZNQU1CQWY4dwpIUVlEVlIwT0JCWUVGSDZ1Uk1IVUFBaXJwRUU1SkhQS3ZrT3g2RUljTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCklRQ0FBems2YjBrK0VNTkZBbzVaTHo0bElqQmtFZnZwWDdsaGtBclM4MjZmcWdJaEFJeUI5OVNJVkFuYkFONlAKeFlSaWFqNS81R1d2OTFiT0pZQ2N0Y2tGL294YwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5YS0M4YkkxbTBVd0NWb0NWQlZERndtL3lqaWdQUVNrdGV0MVAra0pjWU9vQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUitjeG5FdmVWY1ovY1RselZNZlkvemx2aGpTTmFVdzBrRUxMclNncG94eVE3TDFOeVdrcApFbEdaYkNHVjVvdFhzWGk3V012MHU1dXR3UzRoWUVOVjlnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
serviceAccount:
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUd6VlpnLzlmdityQW9DNmZmRmRRZzdKMzk0ZFMxc3p2cmFTRklBZVJsV0lvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVjYwUVgwN0hOVCtIbjJRNkJaQ1BPeVNqMExqS2FvMDM2TUJqMG5PMFFKNVVnZkhhaDVMUwp3QzRLajMwNU52bmZ4bnNnUnI5MWUrbjJreDMxTnJIaFF3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
apiServer:
image: k8s.gcr.io/kube-apiserver:v1.24.2
certSANs:
- 127.0.0.1
disablePodSecurityPolicy: true
admissionControl:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
defaults:
audit: restricted
audit-version: latest
enforce: baseline
enforce-version: latest
warn: restricted
warn-version: latest
exemptions:
namespaces:
- kube-system
runtimeClasses: []
usernames: []
kind: PodSecurityConfiguration
controllerManager:
image: k8s.gcr.io/kube-controller-manager:v1.24.2
proxy:
image: k8s.gcr.io/kube-proxy:v1.24.2
scheduler:
image: k8s.gcr.io/kube-scheduler:v1.24.2
discovery:
enabled: true
registries:
kubernetes: {}
service: {}
etcd:
ca:
crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNTZ0F3SUJBZ0lSQU9jRytGVk5EYTI0SXJ1YnA5QVRTVkl3Q2dZSUtvWkl6ajBFQXdJd0R6RU4KTUFzR0ExVUVDaE1FWlhSalpEQWVGdzB5TWpBMk1qa3hNelE0TVRGYUZ3MHpNakEyTWpZeE16UTRNVEZhTUE4eApEVEFMQmdOVkJBb1RCR1YwWTJRd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRa2pRd3puYmF4ClFyOUVyOG51TUQyUEdEUHBRak1nNGc5czMzeW1GMnpCQWZhMGlta2RMK0hCRkZhaDZ4OHNNVnFsOWJIZEFyRWIKcjVjUFdEeUpRUkxmbzJFd1h6QU9CZ05WSFE4QkFmOEVCQU1DQW9Rd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSApBd0VHQ0NzR0FRVUZCd01DTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFRkl3VmNlNHhrNjI0ClZseVcvaHVwek40U2FZZGVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRnphUzkyMExjK1dlOEpjNkk4dm9LWlQKZXJ3NDlMQ0o0VGpaeUwwVzl5RzdBaUI5QWRlOWNVa1AwSitDelZIdUVVU3NmVjBENFg4N0RyM3lUbGV0NHVVSQpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxqUCtiL1FnckZqTlh6WCswZWNQTU8xc1MvYzM4NUFObWFFU3VIbENSR0hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkkwTU01MjJzVUsvUksvSjdqQTlqeGd6NlVJeklPSVBiTjk4cGhkc3dRSDJ0SXBwSFMvaAp3UlJXb2VzZkxERmFwZld4M1FLeEc2K1hEMWc4aVVFUzN3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View File

@ -0,0 +1,14 @@
machine:
network:
interfaces:
- interface: eth1
addresses:
- "192.168.0.1/24"
- interface: eth0
vip:
ip: 10.3.5.7
- deviceSelector:
driver: macvtap
routes:
- network: 10.3.4.0/24
gateway: 10.3.4.1

View File

@ -0,0 +1,62 @@
// 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 v1alpha1_test
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/config/configloader"
"github.com/talos-systems/talos/pkg/machinery/config/encoder"
"github.com/talos-systems/talos/pkg/machinery/config/merge"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
)
func TestStrategicMergePatch(t *testing.T) {
t.Parallel()
entries, err := os.ReadDir("testdata/strategic")
require.NoError(t, err)
for _, entry := range entries {
if !entry.IsDir() {
continue
}
t.Run(entry.Name(), testMerge(filepath.Join("testdata/strategic", entry.Name())))
}
}
func load(t *testing.T, path string) config.Provider {
provider, err := configloader.NewFromFile(path)
require.NoError(t, err)
return provider.Raw().(config.Provider)
}
func testMerge(path string) func(t *testing.T) {
return func(t *testing.T) {
t.Parallel()
left := load(t, filepath.Join(path, "left.yaml"))
right := load(t, filepath.Join(path, "right.yaml"))
expected := load(t, filepath.Join(path, "expected.yaml"))
result := left.(*v1alpha1.Config).DeepCopy()
err := merge.Merge(result, right)
require.NoError(t, err)
marshaled, err := result.EncodeString(encoder.WithComments(encoder.CommentsDisabled))
require.NoError(t, err)
assert.Equal(t, expected, result, "got:\n%v", marshaled)
}
}

View File

@ -34,6 +34,7 @@ import (
yaml "gopkg.in/yaml.v3"
"github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/config/merge"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
@ -1056,7 +1057,7 @@ type NetworkConfig struct {
// This can be further tuned through this configuration parameter.
// examples:
// - value: machineNetworkConfigExample.NetworkInterfaces
NetworkInterfaces []*Device `yaml:"interfaces,omitempty"`
NetworkInterfaces NetworkDeviceList `yaml:"interfaces,omitempty"`
// description: |
// Used to statically set the nameservers for the machine.
// Defaults to `1.1.1.1` and `8.8.8.8`
@ -1085,6 +1086,58 @@ type NetworkConfig struct {
NetworkDisableSearchDomain *bool `yaml:"disableSearchDomain,omitempty"`
}
// NetworkDeviceList is a list of *Device structures with overridden merge process.
//
//docgen:alias
type NetworkDeviceList []*Device
// Merge the network interface configuration intelligently.
func (devices *NetworkDeviceList) Merge(other interface{}) error {
otherDevices, ok := other.(NetworkDeviceList)
if !ok {
return fmt.Errorf("unexpected type for device merge %T", other)
}
for _, device := range otherDevices {
if err := devices.mergeDevice(device); err != nil {
return err
}
}
return nil
}
func (devices *NetworkDeviceList) mergeDevice(device *Device) error {
var existing *Device
switch {
case device.DeviceInterface != "":
for _, d := range *devices {
if d.DeviceInterface == device.DeviceInterface {
existing = d
break
}
}
case device.DeviceSelector != nil:
for _, d := range *devices {
if d.DeviceSelector != nil && *d.DeviceSelector == *device.DeviceSelector {
existing = d
break
}
}
}
if existing != nil {
return merge.Merge(existing, device)
}
*devices = append(*devices, device)
return nil
}
// InstallConfig represents the installation options for preparing a node.
type InstallConfig struct {
// description: |
@ -1572,13 +1625,13 @@ type ClusterNetworkConfig struct {
// examples:
// - value: >
// []string{"10.244.0.0/16"}
PodSubnet []string `yaml:"podSubnets"`
PodSubnet []string `yaml:"podSubnets" merge:"replace"`
// description: |
// The service subnet CIDR.
// examples:
// - value: >
// []string{"10.96.0.0/12"}
ServiceSubnet []string `yaml:"serviceSubnets"`
ServiceSubnet []string `yaml:"serviceSubnets" merge:"replace"`
}
// CNIConfig represents the CNI configuration options.

View File

@ -1396,7 +1396,7 @@ func (in *NetworkConfig) DeepCopyInto(out *NetworkConfig) {
*out = *in
if in.NetworkInterfaces != nil {
in, out := &in.NetworkInterfaces, &out.NetworkInterfaces
*out = make([]*Device, len(*in))
*out = make(NetworkDeviceList, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
@ -1444,6 +1444,32 @@ func (in *NetworkConfig) DeepCopy() *NetworkConfig {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in NetworkDeviceList) DeepCopyInto(out *NetworkDeviceList) {
{
in := &in
*out = make(NetworkDeviceList, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(Device)
(*in).DeepCopyInto(*out)
}
}
return
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDeviceList.
func (in NetworkDeviceList) DeepCopy() NetworkDeviceList {
if in == nil {
return nil
}
out := new(NetworkDeviceList)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NetworkDeviceSelector) DeepCopyInto(out *NetworkDeviceSelector) {
*out = *in