From 95f440eaa06d2a558fc828c11b451b6aed8d5855 Mon Sep 17 00:00:00 2001 From: Alexey Palazhchenko Date: Mon, 27 Sep 2021 14:59:32 +0000 Subject: [PATCH] test: add fuzz test for configloader That PR contains an example of how fuzz tests can be written with Go 1.18. It also fixes a few panics with invalid configs. Signed-off-by: Alexey Palazhchenko --- .../configloader/configloader_fuzz_test.go | 37 ++ .../config/configloader/configloader_test.go | 108 ++++-- .../configloader/testdata/controlplane.test | 339 ++++++++++++++++ .../config/configloader/testdata/empty1.test | 1 + .../config/configloader/testdata/empty2.test | 1 + .../config/configloader/testdata/worker.test | 364 ++++++++++++++++++ .../types/v1alpha1/v1alpha1_clusterconfig.go | 6 +- .../types/v1alpha1/v1alpha1_provider.go | 8 + 8 files changed, 836 insertions(+), 28 deletions(-) create mode 100644 pkg/machinery/config/configloader/configloader_fuzz_test.go create mode 100644 pkg/machinery/config/configloader/testdata/controlplane.test create mode 100644 pkg/machinery/config/configloader/testdata/empty1.test create mode 100644 pkg/machinery/config/configloader/testdata/empty2.test create mode 100644 pkg/machinery/config/configloader/testdata/worker.test diff --git a/pkg/machinery/config/configloader/configloader_fuzz_test.go b/pkg/machinery/config/configloader/configloader_fuzz_test.go new file mode 100644 index 000000000..f418bfd5a --- /dev/null +++ b/pkg/machinery/config/configloader/configloader_fuzz_test.go @@ -0,0 +1,37 @@ +// 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/. + +//go:build go1.18 +// +build go1.18 + +package configloader_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func FuzzConfigLoader(f *testing.F) { + files, err := filepath.Glob(filepath.Join("testdata", "*.test")) + require.NoError(f, err) + + for _, file := range files { + b, err := os.ReadFile(file) + require.NoError(f, err) + f.Add(b) + } + + f.Add([]byte(": \xea")) + f.Add([]byte(nil)) + f.Add([]byte("")) + + f.Fuzz(func(t *testing.T, b []byte) { + t.Parallel() + + testConfigLoaderBytes(t, b) + }) +} diff --git a/pkg/machinery/config/configloader/configloader_test.go b/pkg/machinery/config/configloader/configloader_test.go index 90e85ad29..62ed02e2d 100644 --- a/pkg/machinery/config/configloader/configloader_test.go +++ b/pkg/machinery/config/configloader/configloader_test.go @@ -2,42 +2,96 @@ // 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/. -//nolint:testpackage -package configloader +package configloader_test import ( + "os" + "path/filepath" + "reflect" "testing" - "github.com/stretchr/testify/suite" + "github.com/stretchr/testify/require" + + "github.com/talos-systems/talos/pkg/machinery/config/configloader" ) -// docgen: nodoc -type Suite struct { - suite.Suite -} +// callMethods calls obj's "getter" methods recursively and fails on panic. +func callMethods(t testing.TB, obj reflect.Value, chain ...string) { + t.Helper() -func TestSuite(t *testing.T) { - suite.Run(t, new(Suite)) -} + typ := obj.Type() -func (suite *Suite) SetupSuite() {} + for i := 0; i < obj.NumMethod(); i++ { + method := obj.Method(i) -func (suite *Suite) TestNew() { - for _, tt := range []struct { - source []byte - expectedErr string - }{ - { - source: []byte(": \xea"), - expectedErr: "recovered: internal error: attempted to parse unknown event (please report): none", - }, - } { - _, err := newConfig(tt.source) - - if tt.expectedErr == "" { - suite.Require().NoError(err) - } else { - suite.Require().EqualError(err, tt.expectedErr) + 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 "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) { + t.Helper() + + p, err := configloader.NewFromBytes(b) + if err != nil { + 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) + }) } } diff --git a/pkg/machinery/config/configloader/testdata/controlplane.test b/pkg/machinery/config/configloader/testdata/controlplane.test new file mode 100644 index 000000000..f76140c89 --- /dev/null +++ b/pkg/machinery/config/configloader/testdata/controlplane.test @@ -0,0 +1,339 @@ +version: v1alpha1 # Indicates the schema used to decode the contents. +debug: false # Enable verbose logging to the console. +persist: true # Indicates whether to pull the machine config upon every boot. +# Provides machine specific configuration options. +machine: + type: controlplane # Defines the role of the machine within the cluster. + token: 7a10fa.izhckmwn5xmsjwi5 # The `token` is used by a machine to join the PKI of the cluster. + # The root certificate authority of the PKI. + ca: + crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJQakNCOGFBREFnRUNBaEFJazRNbkdRZ01HQmkrM3p6aHZsRlZNQVVHQXl0bGNEQVFNUTR3REFZRFZRUUsKRXdWMFlXeHZjekFlRncweU1UQTRNall4TWpBMU5USmFGdzB6TVRBNE1qUXhNakExTlRKYU1CQXhEakFNQmdOVgpCQW9UQlhSaGJHOXpNQ293QlFZREsyVndBeUVBUzFKbXZ3WFFjTTNJVWRQb1FvTk5jVzh2bzBBenVENUIwb1hoCk9sSnpUa2VqWVRCZk1BNEdBMVVkRHdFQi93UUVBd0lDaERBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUkKS3dZQkJRVUhBd0l3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVL25nVE5YaG9YbkFheU5WaQp3RUREQjdGdHgvQXdCUVlESzJWd0EwRUFuTS9EMFNsZVhBcFVoWlpXQkp0djd2NnhjTFl4ekRoWmd3eFIzODFHCmNjM21XS09MSHZvOENVQU85WmpqZGV4UCtLN1dyMjhxZUxuMWwxTG83SWZWQkE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + key: LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM0Q0FRQXdCUVlESzJWd0JDSUVJSkJpdHJaQ1VrMFl1YytsblpqZXFHeVl1MGQxTGpNV2Fvd2FQL2diaTIwQwotLS0tLUVORCBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0K + # Extra certificate subject alternative names for the machine's certificate. + certSANs: [] + # # Uncomment this to enable SANs. + # - 10.0.0.10 + # - 172.16.0.10 + # - 192.168.0.10 + + # Used to provide additional options to the kubelet. + kubelet: {} + # # The `image` field is an optional reference to an alternative kubelet image. + # image: ghcr.io/talos-systems/kubelet:v1.22.1 + + # # The `ClusterDNS` field is an optional reference to an alternative kubelet clusterDNS ip list. + # clusterDNS: + # - 10.96.0.10 + # - 169.254.2.53 + + # # The `extraArgs` field is used to provide additional flags to the kubelet. + # extraArgs: + # key: value + + # # The `extraMounts` field is used to add additional mounts to the kubelet container. + # extraMounts: + # - destination: /var/lib/example + # type: bind + # source: /var/lib/example + # options: + # - rshared + # - rw + + # Provides machine specific network configuration options. + network: {} + # # `interfaces` is used to define the network interface configuration. + # interfaces: + # - interface: eth0 # The interface name. + # # Assigns static IP addresses to the interface. + # addresses: + # - 192.168.2.0/24 + # # A list of routes associated with the interface. + # routes: + # - network: 0.0.0.0/0 # The route's network. + # gateway: 192.168.2.1 # The route's gateway. + # metric: 1024 # The optional metric for the route. + # mtu: 1500 # The interface's MTU. + # + # # # Bond specific options. + # # bond: + # # # The interfaces that make up the bond. + # # interfaces: + # # - eth0 + # # - eth1 + # # mode: 802.3ad # A bond option. + # # lacpRate: fast # A bond option. + + # # # Indicates if DHCP should be used to configure the interface. + # # dhcp: true + + # # # DHCP specific options. + # # dhcpOptions: + # # routeMetric: 1024 # The priority of all routes received via DHCP. + + # # # Wireguard specific configuration. + + # # # wireguard server example + # # wireguard: + # # privateKey: ABCDEF... # Specifies a private key configuration (base64 encoded). + # # listenPort: 51111 # Specifies a device's listening port. + # # # Specifies a list of peer configurations to apply to a device. + # # peers: + # # - publicKey: ABCDEF... # Specifies the public key of this peer. + # # endpoint: 192.168.1.3 # Specifies the endpoint of this peer entry. + # # # AllowedIPs specifies a list of allowed IP addresses in CIDR notation for this peer. + # # allowedIPs: + # # - 192.168.1.0/24 + # # # wireguard peer example + # # wireguard: + # # privateKey: ABCDEF... # Specifies a private key configuration (base64 encoded). + # # # Specifies a list of peer configurations to apply to a device. + # # peers: + # # - publicKey: ABCDEF... # Specifies the public key of this peer. + # # endpoint: 192.168.1.2 # Specifies the endpoint of this peer entry. + # # persistentKeepaliveInterval: 10s # Specifies the persistent keepalive interval for this peer. + # # # AllowedIPs specifies a list of allowed IP addresses in CIDR notation for this peer. + # # allowedIPs: + # # - 192.168.1.0/24 + + # # # Virtual (shared) IP address configuration. + # # vip: + # # ip: 172.16.199.55 # Specifies the IP address to be used. + + # # Used to statically set the nameservers for the machine. + # nameservers: + # - 8.8.8.8 + # - 1.1.1.1 + + # # Allows for extra entries to be added to the `/etc/hosts` file + # extraHostEntries: + # - ip: 192.168.1.100 # The IP of the host. + # # The host alias. + # aliases: + # - example + # - example.domain.tld + + # Used to provide instructions for installations. + install: + disk: /dev/sda # The disk used for installations. + image: ghcr.io/aleksi/installer:v0.12.0-alpha.1-20-g5f5ac12f1 # Allows for supplying the image used to perform the installation. + bootloader: true # Indicates if a bootloader should be installed. + wipe: false # Indicates if the installation disk should be wiped at installation time. + + # # Look up disk using disk attributes like model, size, serial and others. + # diskSelector: + # size: 4GB # Disk size. + # model: WDC* # Disk model `/sys/block//device/model`. + + # # Allows for supplying extra kernel args via the bootloader. + # extraKernelArgs: + # - talos.platform=metal + # - reboot=k + # Features describe individual Talos features that can be switched on or off. + features: + rbac: true # Enable role-based access control (RBAC). + + # # Used to partition, format and mount additional disks. + + # # MachineDisks list example. + # disks: + # - device: /dev/sdb # The name of the disk to use. + # # A list of partitions to create on the disk. + # partitions: + # - mountpoint: /var/mnt/extra # Where to mount the partition. + # + # # # The size of partition: either bytes or human readable representation. If `size:` is omitted, the partition is sized to occupy the full disk. + + # # # Human readable representation. + # # size: 100 MB + # # # Precise value in bytes. + # # size: 1073741824 + + # # Allows the addition of user specified files. + + # # MachineFiles usage example. + # files: + # - content: '...' # The contents of the file. + # permissions: 0o666 # The file's permissions in octal. + # path: /tmp/file.txt # The path of the file. + # op: append # The operation to use + + # # The `env` field allows for the addition of environment variables. + + # # Environment variables definition examples. + # env: + # GRPC_GO_LOG_SEVERITY_LEVEL: info + # GRPC_GO_LOG_VERBOSITY_LEVEL: "99" + # https_proxy: http://SERVER:PORT/ + # env: + # GRPC_GO_LOG_SEVERITY_LEVEL: error + # https_proxy: https://USERNAME:PASSWORD@SERVER:PORT/ + # env: + # https_proxy: http://DOMAIN\USERNAME:PASSWORD@SERVER:PORT/ + + # # Used to configure the machine's time settings. + + # # Example configuration for cloudflare ntp server. + # time: + # disabled: false # Indicates if the time service is disabled for the machine. + # # Specifies time (NTP) servers to use for setting the system time. + # servers: + # - time.cloudflare.com + + # # Used to configure the machine's sysctls. + + # # MachineSysctls usage example. + # sysctls: + # kernel.domainname: talos.dev + # net.ipv4.ip_forward: "0" + + # # Used to configure the machine's container image registry mirrors. + # registries: + # # Specifies mirror configuration for each registry. + # mirrors: + # ghcr.io: + # # List of endpoints (URLs) for registry mirrors to use. + # endpoints: + # - https://registry.insecure + # - https://ghcr.io/v2/ + # # Specifies TLS & auth configuration for HTTPS image registries. + # config: + # registry.insecure: + # # The TLS configuration for the registry. + # tls: + # insecureSkipVerify: true # Skip TLS server certificate verification (not recommended). + # + # # # Enable mutual TLS authentication with the registry. + # # clientIdentity: + # # crt: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSklla05DTUhGLi4u + # # key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u + # + # # # The auth configuration for this registry. + # # auth: + # # username: username # Optional registry authentication. + # # password: password # Optional registry authentication. + + # # Machine system disk encryption configuration. + # systemDiskEncryption: + # # Ephemeral partition encryption. + # ephemeral: + # provider: luks2 # Encryption provider to use for the encryption. + # # Defines the encryption keys generation and storage method. + # keys: + # - # Deterministically generated key from the node UUID and PartitionLabel. + # nodeID: {} + # slot: 0 # Key slot number for LUKS2 encryption. + # + # # # Cipher kind to use for the encryption. Depends on the encryption provider. + # # cipher: aes-xts-plain64 + + # # # Defines the encryption sector size. + # # blockSize: 4096 + + # # # Additional --perf parameters for the LUKS2 encryption. + # # options: + # # - no_read_workqueue + # # - no_write_workqueue +# Provides cluster specific configuration options. +cluster: + id: Ahg8OEr1t2urQH2wcG2_g0-t1Rtf-QRtA3uBCIe9S3w= # Globally unique identifier for this cluster. + secret: y1VWsecCqtdFYWP1xsxw7p2YZJ/Bdwa+H9NzXlIfEbY= # Shared secret of cluster. + # Provides control plane specific configuration options. + controlPlane: + endpoint: https://1.2.3.4:6443 # Endpoint is the canonical controlplane endpoint, which can be an IP address or a DNS hostname. + clusterName: test # Configures the cluster's name. + # Provides cluster specific network configuration options. + network: + dnsDomain: cluster.local # The domain used by Kubernetes DNS. + # The pod subnet CIDR. + podSubnets: + - 10.244.0.0/16 + # The service subnet CIDR. + serviceSubnets: + - 10.96.0.0/12 + + # # The CNI used. + # cni: + # name: custom # Name of CNI to use. + # # URLs containing manifests to apply for the CNI. + # urls: + # - https://raw.githubusercontent.com/cilium/cilium/v1.8/install/kubernetes/quick-install.yaml + token: y9pn8n.g7wi0m50e0wu9b9v # The [bootstrap token](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) used to join the cluster. + aescbcEncryptionSecret: /ZaQCnD11lrRRF2OH7ez96cpn99VWhD1AXdWbZwLQrc= # The key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/). + # The base64 encoded root certificate authority used by Kubernetes. + ca: + crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRRm1GY0ZiaUtCQ1dtazB5YVZUM1Z5ekFLQmdncWhrak9QUVFEQkRBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXhNRGd5TmpFeU1EVTFNbG9YRFRNeE1EZ3lOREV5TURVMQpNbG93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCQk1LTXBOZTkxanBmYWZxYlgzNDYyTEk1ZHBSRUpNdlY3U0t6YXZWWHRDa29oTFhpcHZMY3BiUkIyRm8KVGFzNURmSFc3Q2gwQng1S1RnOVRJelVrSGlpallUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVVrWG5oWUFkbXRDVG15aDVLOTNLTTA2Sk9aME13Q2dZSUtvWkl6ajBFQXdRRFNBQXdSUUlnQVZXYUkwQlUKUUt1MHRoRDNmSjBkaitqbEVxTW5nUGdQaXhJck1mdEdmU1FDSVFES3VIMWIvZzdRS1p1QmU3UEJocC9aZ2xrRgpRdTI5aHdJU0JjbE1aak9tK0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUFvV1BZTUluUThPYUVvb3NnZ2ozUE5XMzVwQ0tIZlFDNWg4TERNalI2dmNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFRXdveWsxNzNXT2w5cCtwdGZmanJZc2psMmxFUWt5OVh0SXJOcTlWZTBLU2lFdGVLbTh0eQpsdEVIWVdoTnF6a044ZGJzS0hRSEhrcE9EMU1qTlNRZUtBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= + # The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation. + aggregatorCA: + crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZRENDQVFXZ0F3SUJBZ0lRRnB2RkhrM1pOOGtQQkUyTElBN2FvekFLQmdncWhrak9QUVFEQkRBQU1CNFgKRFRJeE1EZ3lOakV5TURVMU1sb1hEVE14TURneU5ERXlNRFUxTWxvd0FEQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxRwpTTTQ5QXdFSEEwSUFCRDVDNGprWHhzVWhyb0ZwOGpzY0tkYndyaSsxWURMQm9NMDNlNTMxM2xsbUhEbWZ6dFh1CnNjdkQ2RTFyY0hHV3ljRlJmbEc0K2hVYWtrNHFUSUtRMEF5allUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWQKQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZApCZ05WSFE0RUZnUVU0VGJqMnUvMUhySU5PSVBPeGZnZHlGeUZwVDh3Q2dZSUtvWkl6ajBFQXdRRFNRQXdSZ0loCkFKRERJZ2lMRE91cHZxWDVVdy9UakJ3NFltRXYzZVRqSHprczRBN1gwNHdWQWlFQTg3Ulo4WjlUdmRIT3BJRHUKdjBEN1ArMFdnS3pCTWpKY05KQ012L1RLSkE0PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUMzUFNaMjZGekVoeEhzdGRMK1Y4Zk9vQS9WV3hsd3YzRWozVnBwaVpiaDVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFUGtMaU9SZkd4U0d1Z1dueU94d3AxdkN1TDdWZ01zR2d6VGQ3bmZYZVdXWWNPWi9PMWU2eAp5OFBvVFd0d2NaYkp3VkYrVWJqNkZScVNUaXBNZ3BEUURBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= + # The base64 encoded private key for service account token generation. + serviceAccount: + key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUF0eXJVdG53YmgxUk5wSThyUzdCbEl1OWhWdUFwQ2RxdXhSelVoVXJnSGdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFKzZmd3Y2RzJvdGdNWExHa0ErS1BKbVQ4ZDJISWx1aEdJVWw2NTgyYmprMVVCR3U1SWNpQwoyanRHYnpGSTEweTlOMlZJZDl5d05Mc3dGbjV4YWRyYy9BPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= + # API server specific configuration options. + apiServer: + # Extra certificate subject alternative names for the API server's certificate. + certSANs: + - 1.2.3.4 + + # # The container image used in the API server manifest. + # image: k8s.gcr.io/kube-apiserver:v1.22.1 + # Controller manager server specific configuration options. + controllerManager: {} + # # The container image used in the controller manager manifest. + # image: k8s.gcr.io/kube-controller-manager:v1.22.1 + + # Kube-proxy server-specific configuration options + proxy: {} + # # The container image used in the kube-proxy manifest. + # image: k8s.gcr.io/kube-proxy:v1.22.1 + + # Scheduler server specific configuration options. + scheduler: {} + # # The container image used in the scheduler manifest. + # image: k8s.gcr.io/kube-scheduler:v1.22.1 + + # Etcd specific configuration options. + etcd: + # The `ca` is the root certificate authority of the PKI. + ca: + crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNPZ0F3SUJBZ0lRQTV1QkpPTG1wL3RrbEVRS0FFV1RtakFLQmdncWhrak9QUVFEQkRBUE1RMHcKQ3dZRFZRUUtFd1JsZEdOa01CNFhEVEl4TURneU5qRXlNRFUxTWxvWERUTXhNRGd5TkRFeU1EVTFNbG93RHpFTgpNQXNHQTFVRUNoTUVaWFJqWkRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkdxeWR0MjZXRUpSCllyV1NJZkp3QnZHSTZTWENqcENvU1Z6U25jWDFYaUwvY2I0RFJINU5WQ3JuZU9EYjZRb3ZwUTFKaEE3RTR6RDAKTHB5dTE1TW1zM2VqWVRCZk1BNEdBMVVkRHdFQi93UUVBd0lDaERBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjRApBUVlJS3dZQkJRVUhBd0l3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVR0lwR3JsOFpqTHV5CkFOdzR4Y0RMSGxzZ0c1Z3dDZ1lJS29aSXpqMEVBd1FEU0FBd1JRSWhBT2dsQzlZbkIxZlE4cnNDZSsyY2pQR2MKODlUT0ZXMk10bEVFcWtYdm03cWpBaUE3a3JXRjVXMWxpMmtlVEV5cnZlYjZuajBGWGZRYi9MbERUQnh5YzJicwpNZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUg3V2JCd1pHdVZUUmZkdjZDR3JDUzEzYnR5Q2dGL3JyeUV2YkJ3d0hNYThvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFYXJKMjNicFlRbEZpdFpJaDhuQUc4WWpwSmNLT2tLaEpYTktkeGZWZUl2OXh2Z05FZmsxVQpLdWQ0NE52cENpK2xEVW1FRHNUak1QUXVuSzdYa3lhemR3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= + + # # The container image used to create the etcd service. + # image: gcr.io/etcd-development/etcd:v3.4.16 + # A list of urls that point to additional manifests. + extraManifests: [] + # - https://www.example.com/manifest1.yaml + # - https://www.example.com/manifest2.yaml + + # A list of inline Kubernetes manifests. + inlineManifests: [] + # - name: namespace-ci # Name of the manifest. + # contents: |- # Manifest contents as a string. + # apiVersion: v1 + # kind: Namespace + # metadata: + # name: ci + + + # # Core DNS specific configuration options. + # coreDNS: + # image: docker.io/coredns/coredns:1.8.4 # The `image` field is an override to the default coredns image. + + # # External cloud provider configuration. + # externalCloudProvider: + # enabled: true # Enable external cloud provider. + # # A list of urls that point to additional manifests for an external cloud provider. + # manifests: + # - https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml + # - https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml + + # # A map of key value pairs that will be added while fetching the extraManifests. + # extraManifestHeaders: + # Token: "1234567" + # X-ExtraInfo: info + + # # Settings for admin kubeconfig generation. + # adminKubeconfig: + # certLifetime: 1h0m0s # Admin kubeconfig certificate lifetime (default is 1 year). diff --git a/pkg/machinery/config/configloader/testdata/empty1.test b/pkg/machinery/config/configloader/testdata/empty1.test new file mode 100644 index 000000000..b9b48b40d --- /dev/null +++ b/pkg/machinery/config/configloader/testdata/empty1.test @@ -0,0 +1 @@ +machine: diff --git a/pkg/machinery/config/configloader/testdata/empty2.test b/pkg/machinery/config/configloader/testdata/empty2.test new file mode 100644 index 000000000..61c0be28d --- /dev/null +++ b/pkg/machinery/config/configloader/testdata/empty2.test @@ -0,0 +1 @@ +cluster: diff --git a/pkg/machinery/config/configloader/testdata/worker.test b/pkg/machinery/config/configloader/testdata/worker.test new file mode 100644 index 000000000..1060d2563 --- /dev/null +++ b/pkg/machinery/config/configloader/testdata/worker.test @@ -0,0 +1,364 @@ +--- +version: v1alpha1 # Indicates the schema used to decode the contents. +debug: false # Enable verbose logging to the console. +persist: true # Indicates whether to pull the machine config upon every boot. +# Provides machine specific configuration options. +machine: + type: worker # Defines the role of the machine within the cluster. + token: 7a10fa.izhckmwn5xmsjwi5 # The `token` is used by a machine to join the PKI of the cluster. + # Extra certificate subject alternative names for the machine's certificate. + certSANs: [] + # # Uncomment this to enable SANs. + # - 10.0.0.10 + # - 172.16.0.10 + # - 192.168.0.10 + + # Used to provide additional options to the kubelet. + kubelet: {} + # # The `image` field is an optional reference to an alternative kubelet image. + # image: ghcr.io/talos-systems/kubelet:v1.22.1 + + # # The `ClusterDNS` field is an optional reference to an alternative kubelet clusterDNS ip list. + # clusterDNS: + # - 10.96.0.10 + # - 169.254.2.53 + + # # The `extraArgs` field is used to provide additional flags to the kubelet. + # extraArgs: + # key: value + + # # The `extraMounts` field is used to add additional mounts to the kubelet container. + # extraMounts: + # - destination: /var/lib/example + # type: bind + # source: /var/lib/example + # options: + # - rshared + # - rw + + # Provides machine specific network configuration options. + network: {} + # # `interfaces` is used to define the network interface configuration. + # interfaces: + # - interface: eth0 # The interface name. + # # Assigns static IP addresses to the interface. + # addresses: + # - 192.168.2.0/24 + # # A list of routes associated with the interface. + # routes: + # - network: 0.0.0.0/0 # The route's network. + # gateway: 192.168.2.1 # The route's gateway. + # metric: 1024 # The optional metric for the route. + # mtu: 1500 # The interface's MTU. + # + # # # Bond specific options. + # # bond: + # # # The interfaces that make up the bond. + # # interfaces: + # # - eth0 + # # - eth1 + # # mode: 802.3ad # A bond option. + # # lacpRate: fast # A bond option. + + # # # Indicates if DHCP should be used to configure the interface. + # # dhcp: true + + # # # DHCP specific options. + # # dhcpOptions: + # # routeMetric: 1024 # The priority of all routes received via DHCP. + + # # # Wireguard specific configuration. + + # # # wireguard server example + # # wireguard: + # # privateKey: ABCDEF... # Specifies a private key configuration (base64 encoded). + # # listenPort: 51111 # Specifies a device's listening port. + # # # Specifies a list of peer configurations to apply to a device. + # # peers: + # # - publicKey: ABCDEF... # Specifies the public key of this peer. + # # endpoint: 192.168.1.3 # Specifies the endpoint of this peer entry. + # # # AllowedIPs specifies a list of allowed IP addresses in CIDR notation for this peer. + # # allowedIPs: + # # - 192.168.1.0/24 + # # # wireguard peer example + # # wireguard: + # # privateKey: ABCDEF... # Specifies a private key configuration (base64 encoded). + # # # Specifies a list of peer configurations to apply to a device. + # # peers: + # # - publicKey: ABCDEF... # Specifies the public key of this peer. + # # endpoint: 192.168.1.2 # Specifies the endpoint of this peer entry. + # # persistentKeepaliveInterval: 10s # Specifies the persistent keepalive interval for this peer. + # # # AllowedIPs specifies a list of allowed IP addresses in CIDR notation for this peer. + # # allowedIPs: + # # - 192.168.1.0/24 + + # # # Virtual (shared) IP address configuration. + # # vip: + # # ip: 172.16.199.55 # Specifies the IP address to be used. + + # # Used to statically set the nameservers for the machine. + # nameservers: + # - 8.8.8.8 + # - 1.1.1.1 + + # # Allows for extra entries to be added to the `/etc/hosts` file + # extraHostEntries: + # - ip: 192.168.1.100 # The IP of the host. + # # The host alias. + # aliases: + # - example + # - example.domain.tld + + # Used to provide instructions for installations. + install: + disk: /dev/sda # The disk used for installations. + image: ghcr.io/aleksi/installer:v0.12.0-alpha.1-20-g5f5ac12f1 # Allows for supplying the image used to perform the installation. + bootloader: true # Indicates if a bootloader should be installed. + wipe: false # Indicates if the installation disk should be wiped at installation time. + + # # Look up disk using disk attributes like model, size, serial and others. + # diskSelector: + # size: 4GB # Disk size. + # model: WDC* # Disk model `/sys/block//device/model`. + + # # Allows for supplying extra kernel args via the bootloader. + # extraKernelArgs: + # - talos.platform=metal + # - reboot=k + # Features describe individual Talos features that can be switched on or off. + features: + rbac: true # Enable role-based access control (RBAC). + + # # The root certificate authority of the PKI. + + # # machine CA example + # ca: + # crt: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSklla05DTUhGLi4u + # key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u + + # # Used to partition, format and mount additional disks. + + # # MachineDisks list example. + # disks: + # - device: /dev/sdb # The name of the disk to use. + # # A list of partitions to create on the disk. + # partitions: + # - mountpoint: /var/mnt/extra # Where to mount the partition. + # + # # # The size of partition: either bytes or human readable representation. If `size:` is omitted, the partition is sized to occupy the full disk. + + # # # Human readable representation. + # # size: 100 MB + # # # Precise value in bytes. + # # size: 1073741824 + + # # Allows the addition of user specified files. + + # # MachineFiles usage example. + # files: + # - content: '...' # The contents of the file. + # permissions: 0o666 # The file's permissions in octal. + # path: /tmp/file.txt # The path of the file. + # op: append # The operation to use + + # # The `env` field allows for the addition of environment variables. + + # # Environment variables definition examples. + # env: + # GRPC_GO_LOG_SEVERITY_LEVEL: info + # GRPC_GO_LOG_VERBOSITY_LEVEL: "99" + # https_proxy: http://SERVER:PORT/ + # env: + # GRPC_GO_LOG_SEVERITY_LEVEL: error + # https_proxy: https://USERNAME:PASSWORD@SERVER:PORT/ + # env: + # https_proxy: http://DOMAIN\USERNAME:PASSWORD@SERVER:PORT/ + + # # Used to configure the machine's time settings. + + # # Example configuration for cloudflare ntp server. + # time: + # disabled: false # Indicates if the time service is disabled for the machine. + # # Specifies time (NTP) servers to use for setting the system time. + # servers: + # - time.cloudflare.com + + # # Used to configure the machine's sysctls. + + # # MachineSysctls usage example. + # sysctls: + # kernel.domainname: talos.dev + # net.ipv4.ip_forward: "0" + + # # Used to configure the machine's container image registry mirrors. + # registries: + # # Specifies mirror configuration for each registry. + # mirrors: + # ghcr.io: + # # List of endpoints (URLs) for registry mirrors to use. + # endpoints: + # - https://registry.insecure + # - https://ghcr.io/v2/ + # # Specifies TLS & auth configuration for HTTPS image registries. + # config: + # registry.insecure: + # # The TLS configuration for the registry. + # tls: + # insecureSkipVerify: true # Skip TLS server certificate verification (not recommended). + # + # # # Enable mutual TLS authentication with the registry. + # # clientIdentity: + # # crt: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSklla05DTUhGLi4u + # # key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u + # + # # # The auth configuration for this registry. + # # auth: + # # username: username # Optional registry authentication. + # # password: password # Optional registry authentication. + + # # Machine system disk encryption configuration. + # systemDiskEncryption: + # # Ephemeral partition encryption. + # ephemeral: + # provider: luks2 # Encryption provider to use for the encryption. + # # Defines the encryption keys generation and storage method. + # keys: + # - # Deterministically generated key from the node UUID and PartitionLabel. + # nodeID: {} + # slot: 0 # Key slot number for LUKS2 encryption. + # + # # # Cipher kind to use for the encryption. Depends on the encryption provider. + # # cipher: aes-xts-plain64 + + # # # Defines the encryption sector size. + # # blockSize: 4096 + + # # # Additional --perf parameters for the LUKS2 encryption. + # # options: + # # - no_read_workqueue + # # - no_write_workqueue +# Provides cluster specific configuration options. +cluster: + id: Ahg8OEr1t2urQH2wcG2_g0-t1Rtf-QRtA3uBCIe9S3w= # Globally unique identifier for this cluster. + secret: y1VWsecCqtdFYWP1xsxw7p2YZJ/Bdwa+H9NzXlIfEbY= # Shared secret of cluster. + # Provides control plane specific configuration options. + controlPlane: + endpoint: https://1.2.3.4:6443 # Endpoint is the canonical controlplane endpoint, which can be an IP address or a DNS hostname. + # Provides cluster specific network configuration options. + network: + dnsDomain: cluster.local # The domain used by Kubernetes DNS. + # The pod subnet CIDR. + podSubnets: + - 10.244.0.0/16 + # The service subnet CIDR. + serviceSubnets: + - 10.96.0.0/12 + + # # The CNI used. + # cni: + # name: custom # Name of CNI to use. + # # URLs containing manifests to apply for the CNI. + # urls: + # - https://raw.githubusercontent.com/cilium/cilium/v1.8/install/kubernetes/quick-install.yaml + token: y9pn8n.g7wi0m50e0wu9b9v # The [bootstrap token](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) used to join the cluster. + aescbcEncryptionSecret: "" # The key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/). + # # Decryption secret example (do not use in production!). + # z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM= + + # The base64 encoded root certificate authority used by Kubernetes. + ca: + crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJpVENDQVMrZ0F3SUJBZ0lRRm1GY0ZiaUtCQ1dtazB5YVZUM1Z5ekFLQmdncWhrak9QUVFEQkRBVk1STXcKRVFZRFZRUUtFd3ByZFdKbGNtNWxkR1Z6TUI0WERUSXhNRGd5TmpFeU1EVTFNbG9YRFRNeE1EZ3lOREV5TURVMQpNbG93RlRFVE1CRUdBMVVFQ2hNS2EzVmlaWEp1WlhSbGN6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VICkEwSUFCQk1LTXBOZTkxanBmYWZxYlgzNDYyTEk1ZHBSRUpNdlY3U0t6YXZWWHRDa29oTFhpcHZMY3BiUkIyRm8KVGFzNURmSFc3Q2gwQng1S1RnOVRJelVrSGlpallUQmZNQTRHQTFVZER3RUIvd1FFQXdJQ2hEQWRCZ05WSFNVRQpGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFCkZnUVVrWG5oWUFkbXRDVG15aDVLOTNLTTA2Sk9aME13Q2dZSUtvWkl6ajBFQXdRRFNBQXdSUUlnQVZXYUkwQlUKUUt1MHRoRDNmSjBkaitqbEVxTW5nUGdQaXhJck1mdEdmU1FDSVFES3VIMWIvZzdRS1p1QmU3UEJocC9aZ2xrRgpRdTI5aHdJU0JjbE1aak9tK0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + key: "" + + # # The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation. + + # # AggregatorCA example. + # aggregatorCA: + # crt: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSklla05DTUhGLi4u + # key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u + + # # The base64 encoded private key for service account token generation. + + # # AggregatorCA example. + # serviceAccount: + # key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u + + # # API server specific configuration options. + # apiServer: + # image: k8s.gcr.io/kube-apiserver:v1.22.1 # The container image used in the API server manifest. + # # Extra arguments to supply to the API server. + # extraArgs: + # feature-gates: ServerSideApply=true + # http2-max-streams-per-connection: "32" + # # Extra certificate subject alternative names for the API server's certificate. + # certSANs: + # - 1.2.3.4 + # - 4.5.6.7 + + # # Controller manager server specific configuration options. + # controllerManager: + # image: k8s.gcr.io/kube-controller-manager:v1.22.1 # The container image used in the controller manager manifest. + # # Extra arguments to supply to the controller manager. + # extraArgs: + # feature-gates: ServerSideApply=true + + # # Kube-proxy server-specific configuration options + # proxy: + # image: k8s.gcr.io/kube-proxy:v1.22.1 # The container image used in the kube-proxy manifest. + # mode: ipvs # proxy mode of kube-proxy. + # # Extra arguments to supply to kube-proxy. + # extraArgs: + # proxy-mode: iptables + + # # Scheduler server specific configuration options. + # scheduler: + # image: k8s.gcr.io/kube-scheduler:v1.22.1 # The container image used in the scheduler manifest. + # # Extra arguments to supply to the scheduler. + # extraArgs: + # feature-gates: AllBeta=true + + # # Etcd specific configuration options. + # etcd: + # image: gcr.io/etcd-development/etcd:v3.4.16 # The container image used to create the etcd service. + # # The `ca` is the root certificate authority of the PKI. + # ca: + # crt: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSklla05DTUhGLi4u + # key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u + # # Extra arguments to supply to etcd. + # extraArgs: + # election-timeout: "5000" + + # # Core DNS specific configuration options. + # coreDNS: + # image: docker.io/coredns/coredns:1.8.4 # The `image` field is an override to the default coredns image. + + # # External cloud provider configuration. + # externalCloudProvider: + # enabled: true # Enable external cloud provider. + # # A list of urls that point to additional manifests for an external cloud provider. + # manifests: + # - https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml + # - https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml + + # # A list of urls that point to additional manifests. + # extraManifests: + # - https://www.example.com/manifest1.yaml + # - https://www.example.com/manifest2.yaml + + # # A map of key value pairs that will be added while fetching the extraManifests. + # extraManifestHeaders: + # Token: "1234567" + # X-ExtraInfo: info + + # # A list of inline Kubernetes manifests. + # inlineManifests: + # - name: namespace-ci # Name of the manifest. + # contents: |- # Manifest contents as a string. + # apiVersion: v1 + # kind: Namespace + # metadata: + # name: ci + + # # Settings for admin kubeconfig generation. + # adminKubeconfig: + # certLifetime: 1h0m0s # Admin kubeconfig certificate lifetime (default is 1 year). diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_clusterconfig.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_clusterconfig.go index 7a26e924b..857fc36ef 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_clusterconfig.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_clusterconfig.go @@ -73,6 +73,10 @@ func (c *ClusterConfig) Token() config.Token { // CertSANs implements the config.ClusterConfig interface. func (c *ClusterConfig) CertSANs() []string { + if c.APIServerConfig == nil { + return nil + } + return c.APIServerConfig.CertSANs } @@ -117,7 +121,7 @@ func (c *ClusterConfig) Network() config.ClusterNetwork { // LocalAPIServerPort implements the config.ClusterConfig interface. func (c *ClusterConfig) LocalAPIServerPort() int { - if c.ControlPlane.LocalAPIServerPort == 0 { + if c.ControlPlane == nil || c.ControlPlane.LocalAPIServerPort == 0 { return constants.DefaultControlPlanePort } diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go index dd899aced..e63b33f71 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go @@ -47,11 +47,19 @@ func (c *Config) Persist() bool { // Machine implements the config.Provider interface. func (c *Config) Machine() config.MachineConfig { + if c.MachineConfig == nil { + return &MachineConfig{} + } + return c.MachineConfig } // Cluster implements the config.Provider interface. func (c *Config) Cluster() config.ClusterConfig { + if c.ClusterConfig == nil { + return &ClusterConfig{} + } + return c.ClusterConfig }