feat: remove ApplyDynamicConfig

This means that Talos no longer tries to change the machine
configuration on the fly.

Certificate SANs are already handled automatically by COSI controllers,
so the only remaining part is the platform's hostname which was written
back to machine configuration.

In the follow-up PRs we'll provide better interface for platforms to
provide network-related data.

Fixes #4597

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
Andrey Smirnov 2021-12-24 14:40:19 +03:00
parent 3623da136b
commit d5a82b37eb
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
6 changed files with 0 additions and 207 deletions

View File

@ -133,11 +133,6 @@ func (s *Server) ApplyConfiguration(ctx context.Context, in *machine.ApplyConfig
return nil, err return nil, err
} }
err = cfgProvider.ApplyDynamicConfig(ctx, s.Controller.Runtime().State().Platform())
if err != nil {
return nil, err
}
// --immediate // --immediate
if in.Immediate { if in.Immediate {
if err = s.Controller.Runtime().CanApplyImmediate(cfgProvider); err != nil { if err = s.Controller.Runtime().CanApplyImmediate(cfgProvider); err != nil {

View File

@ -292,7 +292,6 @@ func (o *Openstack) Hostname(ctx context.Context) (hostname []byte, err error) {
download.WithErrorOnEmptyResponse(errors.ErrNoHostname)) download.WithErrorOnEmptyResponse(errors.ErrNoHostname))
if err != nil { if err != nil {
// Platform cannot support this endpoint, or return timeout. // Platform cannot support this endpoint, or return timeout.
// ApplyDynamicConfig can crash in this situation.
log.Printf("failed to fetch hostname, ignored: %s", err) log.Printf("failed to fetch hostname, ignored: %s", err)
return nil, nil return nil, nil

View File

@ -471,15 +471,6 @@ func LoadConfig(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFu
// SaveConfig represents the SaveConfig task. // SaveConfig represents the SaveConfig task.
func SaveConfig(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) { func SaveConfig(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) { return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
if err = r.Config().ApplyDynamicConfig(ctx, r.State().Platform()); err != nil {
return err
}
err = r.State().V1Alpha2().SetConfig(r.Config())
if err != nil {
return err
}
var b []byte var b []byte
b, err = r.Config().Bytes() b, err = r.Config().Bytes()

View File

@ -5,7 +5,6 @@
package config package config
import ( import (
"context"
"crypto/tls" "crypto/tls"
"net" "net"
"net/url" "net/url"
@ -28,7 +27,6 @@ type Provider interface {
Cluster() ClusterConfig Cluster() ClusterConfig
// Validate checks configuration and returns warnings and fatal errors (as multierror). // Validate checks configuration and returns warnings and fatal errors (as multierror).
Validate(RuntimeMode, ...ValidationOption) ([]string, error) Validate(RuntimeMode, ...ValidationOption) ([]string, error)
ApplyDynamicConfig(context.Context, DynamicConfigProvider) error
String(encoderOptions ...encoder.Option) (string, error) String(encoderOptions ...encoder.Option) (string, error)
Bytes(encoderOptions ...encoder.Option) ([]byte, error) Bytes(encoderOptions ...encoder.Option) ([]byte, error)
} }

View File

@ -5,12 +5,9 @@
package v1alpha1 package v1alpha1
import ( import (
"context"
"crypto/tls" "crypto/tls"
stdx509 "crypto/x509" stdx509 "crypto/x509"
"fmt" "fmt"
"log"
"net"
"os" "os"
"strings" "strings"
"time" "time"
@ -78,79 +75,6 @@ func (c *Config) Bytes(options ...encoder.Option) ([]byte, error) {
return encoder.NewEncoder(c, options...).Encode() return encoder.NewEncoder(c, options...).Encode()
} }
// ApplyDynamicConfig implements the config.Provider interface.
//nolint:gocyclo
func (c *Config) ApplyDynamicConfig(ctx context.Context, dynamicProvider config.DynamicConfigProvider) error {
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
if c.MachineConfig == nil {
c.MachineConfig = &MachineConfig{}
}
hostname, err := dynamicProvider.Hostname(ctx)
if err != nil {
return err
}
if hostname != nil {
if c.MachineConfig.MachineNetwork == nil {
c.MachineConfig.MachineNetwork = &NetworkConfig{}
}
c.MachineConfig.MachineNetwork.NetworkHostname = string(hostname)
}
addrs, err := dynamicProvider.ExternalIPs(ctx)
if err != nil {
// TODO: use passed logger instead of the global one
log.Printf("certificates will be created without external IPs: %v", err)
}
if c.MachineConfig.MachineNetwork != nil {
addrs = append(addrs, addressesFromMachineNetworkConfig(c.MachineConfig.MachineNetwork)...)
}
existingSANs := map[string]bool{}
for _, addr := range c.MachineConfig.MachineCertSANs {
existingSANs[addr] = true
}
sans := make([]string, 0, len(addrs))
for i, addr := range addrs {
sans = append(sans, addr.String())
if existingSANs[sans[i]] {
continue
}
c.MachineConfig.MachineCertSANs = append(c.MachineConfig.MachineCertSANs, sans[i])
}
if c.ClusterConfig == nil {
c.ClusterConfig = &ClusterConfig{}
}
if c.ClusterConfig.APIServerConfig == nil {
c.ClusterConfig.APIServerConfig = &APIServerConfig{}
}
existingCertSANs := map[string]bool{}
for _, certSAN := range c.ClusterConfig.APIServerConfig.CertSANs {
existingCertSANs[certSAN] = true
}
for _, certSAN := range sans {
if existingCertSANs[certSAN] {
continue
}
c.ClusterConfig.APIServerConfig.CertSANs = append(c.ClusterConfig.APIServerConfig.CertSANs, certSAN)
}
return nil
}
// Install implements the config.Provider interface. // Install implements the config.Provider interface.
func (m *MachineConfig) Install() config.Install { func (m *MachineConfig) Install() config.Install {
if m.MachineInstall == nil { if m.MachineInstall == nil {
@ -1278,27 +1202,3 @@ func (v VolumeMountConfig) ReadOnly() bool {
func (u *UdevConfig) Rules() []string { func (u *UdevConfig) Rules() []string {
return u.UdevRules return u.UdevRules
} }
func addressesFromMachineNetworkConfig(nc *NetworkConfig) []net.IP {
var addresses []net.IP
for _, networkConfig := range nc.NetworkInterfaces {
if networkConfig.VIPConfig() != nil {
sharedIP := net.ParseIP(networkConfig.VIPConfig().IP())
if sharedIP != nil {
addresses = append(addresses, sharedIP)
}
for _, vlan := range networkConfig.Vlans() {
if vlan.VIPConfig() != nil {
sharedIP := net.ParseIP(vlan.VIPConfig().IP())
if sharedIP != nil {
addresses = append(addresses, sharedIP)
}
}
}
}
}
return addresses
}

View File

@ -5,104 +5,14 @@
package v1alpha1_test package v1alpha1_test
import ( import (
"context"
"net"
"testing" "testing"
"github.com/stretchr/testify/assert" "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"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1" "github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/bundle"
"github.com/talos-systems/talos/pkg/machinery/constants"
) )
type dynamicConfigProvider struct {
externalIPs []net.IP
}
// Hostname implements DynamicConfigProvider.
func (cp *dynamicConfigProvider) Hostname(ctx context.Context) ([]byte, error) {
return []byte("talos-default-master-1"), nil
}
// ExternalIPs implements DynamicConfigProvider.
func (cp *dynamicConfigProvider) ExternalIPs(ctx context.Context) ([]net.IP, error) {
return cp.externalIPs, nil
}
// TestApplyDynamicConfig check ApplyDynamicConfig works and is idempotent.
func TestApplyDynamicConfig(t *testing.T) {
b, err := bundle.NewConfigBundle(
bundle.WithInputOptions(
&bundle.InputOptions{
ClusterName: "talos-default",
Endpoint: "10.5.0.1",
KubeVersion: constants.DefaultKubernetesVersion,
},
),
)
require.NoError(t, err)
config := b.ControlPlane()
ctx := context.Background()
provider := &dynamicConfigProvider{
externalIPs: []net.IP{
net.ParseIP("10.2.0.3"),
net.ParseIP("10.10.1.2"),
},
}
err = config.ApplyDynamicConfig(ctx, provider)
require.NoError(t, err)
c, ok := config.(*v1alpha1.Config)
require.True(t, ok)
require.Equal(t, "talos-default-master-1", c.Machine().Network().Hostname())
require.Equal(t, []string{"10.2.0.3", "10.10.1.2"}, c.MachineConfig.CertSANs())
provider.externalIPs = []net.IP{
net.ParseIP("10.2.0.3"),
net.ParseIP("10.10.1.2"),
}
provider = &dynamicConfigProvider{
externalIPs: []net.IP{
net.ParseIP("10.2.0.3"),
net.ParseIP("10.10.1.2"),
net.ParseIP("10.10.1.3"),
},
}
err = config.ApplyDynamicConfig(ctx, provider)
require.NoError(t, err)
require.Equal(t, []string{"10.2.0.3", "10.10.1.2", "10.10.1.3"}, c.MachineConfig.CertSANs())
require.Equal(t, []string{"10.2.0.3", "10.10.1.2", "10.10.1.3"}, c.ClusterConfig.CertSANs())
c.MachineConfig.MachineNetwork.NetworkInterfaces = append(c.MachineConfig.MachineNetwork.NetworkInterfaces, &v1alpha1.Device{
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
SharedIP: "192.168.88.77",
},
DeviceVlans: []*v1alpha1.Vlan{
{
VlanID: 100,
VlanVIP: &v1alpha1.DeviceVIPConfig{
SharedIP: "192.168.88.66",
},
},
},
})
err = config.ApplyDynamicConfig(ctx, provider)
require.NoError(t, err)
require.Equal(t, []string{"10.2.0.3", "10.10.1.2", "10.10.1.3", "192.168.88.77", "192.168.88.66"}, c.MachineConfig.CertSANs())
}
func TestInterfaces(t *testing.T) { func TestInterfaces(t *testing.T) {
t.Parallel() t.Parallel()