mirror of
https://github.com/siderolabs/talos.git
synced 2025-11-29 14:41:13 +01:00
feat: implement apply configuration without reboot
This allows config to be written to disk without being applied immediately. Small refactoring to extract common code paths. At first, I tried to implement this via the sequencer, but looks like it's too hard to get it right, as sequencer lacks context and config to be written is not applied to the runtime. Fixes #2828 Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
parent
2588e2960b
commit
9a32e34cb1
@ -61,7 +61,10 @@ service MachineService {
|
|||||||
// rpc applyConfiguration
|
// rpc applyConfiguration
|
||||||
// ApplyConfiguration describes a request to assert a new configuration upon a
|
// ApplyConfiguration describes a request to assert a new configuration upon a
|
||||||
// node.
|
// node.
|
||||||
message ApplyConfigurationRequest { bytes data = 1; }
|
message ApplyConfigurationRequest {
|
||||||
|
bytes data = 1;
|
||||||
|
bool no_reboot = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// ApplyConfigurationResponse describes the response to a configuration request.
|
// ApplyConfigurationResponse describes the response to a configuration request.
|
||||||
message ApplyConfiguration { common.Metadata metadata = 1; }
|
message ApplyConfiguration { common.Metadata metadata = 1; }
|
||||||
|
|||||||
@ -23,6 +23,7 @@ var applyConfigCmdFlags struct {
|
|||||||
filename string
|
filename string
|
||||||
insecure bool
|
insecure bool
|
||||||
interactive bool
|
interactive bool
|
||||||
|
noReboot bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyConfigCmd represents the applyConfiguration command.
|
// applyConfigCmd represents the applyConfiguration command.
|
||||||
@ -108,7 +109,8 @@ var applyConfigCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := c.ApplyConfiguration(ctx, &machineapi.ApplyConfigurationRequest{
|
if _, err := c.ApplyConfiguration(ctx, &machineapi.ApplyConfigurationRequest{
|
||||||
Data: cfgBytes,
|
Data: cfgBytes,
|
||||||
|
NoReboot: applyConfigCmdFlags.noReboot,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("error applying new configuration: %s", err)
|
return fmt.Errorf("error applying new configuration: %s", err)
|
||||||
}
|
}
|
||||||
@ -122,7 +124,8 @@ func init() {
|
|||||||
applyConfigCmd.Flags().StringVarP(&applyConfigCmdFlags.filename, "file", "f", "", "the filename of the updated configuration")
|
applyConfigCmd.Flags().StringVarP(&applyConfigCmdFlags.filename, "file", "f", "", "the filename of the updated configuration")
|
||||||
applyConfigCmd.Flags().BoolVarP(&applyConfigCmdFlags.insecure, "insecure", "i", false, "apply the config using the insecure (encrypted with no auth) maintenance service")
|
applyConfigCmd.Flags().BoolVarP(&applyConfigCmdFlags.insecure, "insecure", "i", false, "apply the config using the insecure (encrypted with no auth) maintenance service")
|
||||||
applyConfigCmd.Flags().StringSliceVar(&applyConfigCmdFlags.certFingerprints, "cert-fingerprint", nil, "list of server certificate fingeprints to accept (defaults to no check)")
|
applyConfigCmd.Flags().StringSliceVar(&applyConfigCmdFlags.certFingerprints, "cert-fingerprint", nil, "list of server certificate fingeprints to accept (defaults to no check)")
|
||||||
applyConfigCmd.Flags().BoolVarP(&applyConfigCmdFlags.interactive, "interactive", "", false, "apply the config using text based interactive mode")
|
applyConfigCmd.Flags().BoolVar(&applyConfigCmdFlags.interactive, "interactive", false, "apply the config using text based interactive mode")
|
||||||
|
applyConfigCmd.Flags().BoolVar(&applyConfigCmdFlags.noReboot, "no-reboot", false, "apply the config only after the reboot")
|
||||||
|
|
||||||
addCommand(applyConfigCmd)
|
addCommand(applyConfigCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -93,19 +94,42 @@ func (s *Server) Register(obj *grpc.Server) {
|
|||||||
|
|
||||||
// ApplyConfiguration implements machine.MachineService.
|
// ApplyConfiguration implements machine.MachineService.
|
||||||
func (s *Server) ApplyConfiguration(ctx context.Context, in *machine.ApplyConfigurationRequest) (reply *machine.ApplyConfigurationResponse, err error) {
|
func (s *Server) ApplyConfiguration(ctx context.Context, in *machine.ApplyConfigurationRequest) (reply *machine.ApplyConfigurationResponse, err error) {
|
||||||
if err = s.Controller.Runtime().SetConfig(in.GetData()); err != nil {
|
if !in.NoReboot {
|
||||||
return nil, err
|
if err = s.Controller.Runtime().SetConfig(in.GetData()); err != nil {
|
||||||
}
|
return nil, err
|
||||||
|
|
||||||
go func() {
|
|
||||||
if err = s.Controller.Run(runtime.SequenceApplyConfiguration, in); err != nil {
|
|
||||||
log.Println("apply configuration failed:", err)
|
|
||||||
|
|
||||||
if err != runtime.ErrLocked {
|
|
||||||
s.server.GracefulStop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
go func() {
|
||||||
|
if err = s.Controller.Run(runtime.SequenceApplyConfiguration, in); err != nil {
|
||||||
|
log.Println("apply configuration failed:", err)
|
||||||
|
|
||||||
|
if err != runtime.ErrLocked {
|
||||||
|
s.server.GracefulStop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
cfg, err := s.Controller.Runtime().ValidateConfig(in.GetData())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cfg.ApplyDynamicConfig(ctx, s.Controller.Runtime().State().Platform())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var b []byte
|
||||||
|
|
||||||
|
b, err = cfg.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ioutil.WriteFile(constants.ConfigPath, b, 0o600); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reply = &machine.ApplyConfigurationResponse{
|
reply = &machine.ApplyConfigurationResponse{
|
||||||
Messages: []*machine.ApplyConfiguration{
|
Messages: []*machine.ApplyConfiguration{
|
||||||
|
|||||||
@ -4,11 +4,14 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "github.com/talos-systems/talos/pkg/machinery/config"
|
import (
|
||||||
|
"github.com/talos-systems/talos/pkg/machinery/config"
|
||||||
|
)
|
||||||
|
|
||||||
// Runtime defines the runtime parameters.
|
// Runtime defines the runtime parameters.
|
||||||
type Runtime interface {
|
type Runtime interface {
|
||||||
Config() config.Provider
|
Config() config.Provider
|
||||||
|
ValidateConfig([]byte) (config.Provider, error)
|
||||||
SetConfig([]byte) error
|
SetConfig([]byte) error
|
||||||
State() State
|
State() State
|
||||||
Events() EventStream
|
Events() EventStream
|
||||||
|
|||||||
@ -35,15 +35,25 @@ func (r *Runtime) Config() config.Provider {
|
|||||||
return r.c
|
return r.c
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig implements the Runtime interface.
|
// ValidateConfig implements the Runtime interface.
|
||||||
func (r *Runtime) SetConfig(b []byte) error {
|
func (r *Runtime) ValidateConfig(b []byte) (config.Provider, error) {
|
||||||
cfg, err := configloader.NewFromBytes(b)
|
cfg, err := configloader.NewFromBytes(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse config: %w", err)
|
return nil, fmt.Errorf("failed to parse config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cfg.Validate(r.State().Platform().Mode()); err != nil {
|
if err := cfg.Validate(r.State().Platform().Mode()); err != nil {
|
||||||
return fmt.Errorf("failed to validate config: %w", err)
|
return nil, fmt.Errorf("failed to validate config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfig implements the Runtime interface.
|
||||||
|
func (r *Runtime) SetConfig(b []byte) error {
|
||||||
|
cfg, err := r.ValidateConfig(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.c = cfg
|
r.c = cfg
|
||||||
|
|||||||
@ -58,11 +58,12 @@ func (*Sequencer) ApplyConfiguration(r runtime.Runtime, req *machineapi.ApplyCon
|
|||||||
).Append(
|
).Append(
|
||||||
"unmountState",
|
"unmountState",
|
||||||
UnmountStatePartition,
|
UnmountStatePartition,
|
||||||
).AppendList(stopAllPhaselist(r)).
|
).AppendList(
|
||||||
Append(
|
stopAllPhaselist(r),
|
||||||
"reboot",
|
).Append(
|
||||||
Reboot,
|
"reboot",
|
||||||
)
|
Reboot,
|
||||||
|
)
|
||||||
|
|
||||||
return phases
|
return phases
|
||||||
}
|
}
|
||||||
|
|||||||
@ -485,31 +485,10 @@ 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) {
|
||||||
saveCtx, ctxCancel := context.WithTimeout(context.Background(), 30*time.Second)
|
if err = r.Config().ApplyDynamicConfig(ctx, r.State().Platform()); err != nil {
|
||||||
defer ctxCancel()
|
|
||||||
|
|
||||||
hostname, err := r.State().Platform().Hostname(saveCtx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostname != nil {
|
|
||||||
r.Config().Machine().Network().SetHostname(string(hostname))
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs, err := r.State().Platform().ExternalIPs(saveCtx)
|
|
||||||
if err != nil {
|
|
||||||
logger.Printf("certificates will be created without external IPs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sans := make([]string, 0, len(addrs))
|
|
||||||
for _, addr := range addrs {
|
|
||||||
sans = append(sans, addr.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Config().Machine().Security().SetCertSANs(sans)
|
|
||||||
r.Config().Cluster().SetCertSANs(sans)
|
|
||||||
|
|
||||||
var b []byte
|
var b []byte
|
||||||
|
|
||||||
b, err = r.Config().Bytes()
|
b, err = r.Config().Bytes()
|
||||||
|
|||||||
@ -49,6 +49,10 @@ func (s *Server) Register(obj *grpc.Server) {
|
|||||||
|
|
||||||
// ApplyConfiguration implements machine.MachineService.
|
// ApplyConfiguration implements machine.MachineService.
|
||||||
func (s *Server) ApplyConfiguration(ctx context.Context, in *machine.ApplyConfigurationRequest) (reply *machine.ApplyConfigurationResponse, err error) {
|
func (s *Server) ApplyConfiguration(ctx context.Context, in *machine.ApplyConfigurationRequest) (reply *machine.ApplyConfigurationResponse, err error) {
|
||||||
|
if in.NoReboot {
|
||||||
|
return nil, fmt.Errorf("apply configuration without reboot is not supported in maintenance mode")
|
||||||
|
}
|
||||||
|
|
||||||
cfgProvider, err := configloader.NewFromBytes(in.GetData())
|
cfgProvider, err := configloader.NewFromBytes(in.GetData())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse config: %w", err)
|
return nil, fmt.Errorf("failed to parse config: %w", err)
|
||||||
|
|||||||
@ -72,7 +72,7 @@ func (suite *NetworkdSuite) TestHostname() {
|
|||||||
suite.Assert().Equal(addr, net.ParseIP("192.168.0.10"))
|
suite.Assert().Equal(addr, net.ParseIP("192.168.0.10"))
|
||||||
|
|
||||||
// Static for computed hostname ( talos-ip )
|
// Static for computed hostname ( talos-ip )
|
||||||
sampleConfig.Machine().Network().SetHostname("")
|
sampleConfig.(*v1alpha1.Config).MachineConfig.MachineNetwork.NetworkHostname = ""
|
||||||
|
|
||||||
nwd, err = New(sampleConfig)
|
nwd, err = New(sampleConfig)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -83,7 +83,7 @@ func (suite *NetworkdSuite) TestHostname() {
|
|||||||
suite.Assert().Equal(addr, net.ParseIP("192.168.0.10"))
|
suite.Assert().Equal(addr, net.ParseIP("192.168.0.10"))
|
||||||
|
|
||||||
// Static for hostname too long
|
// Static for hostname too long
|
||||||
sampleConfig.Machine().Network().SetHostname("somereallyreallyreallylongstringthathasmorethan63charactersbecauseweneedtotestit")
|
sampleConfig.(*v1alpha1.Config).MachineConfig.MachineNetwork.NetworkHostname = "somereallyreallyreallylongstringthathasmorethan63charactersbecauseweneedtotestit"
|
||||||
|
|
||||||
nwd, err = New(sampleConfig)
|
nwd, err = New(sampleConfig)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -93,7 +93,7 @@ func (suite *NetworkdSuite) TestHostname() {
|
|||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
|
|
||||||
// Static for hostname vs domain name
|
// Static for hostname vs domain name
|
||||||
sampleConfig.Machine().Network().SetHostname("dadjokes.biz.dev.com.org.io")
|
sampleConfig.(*v1alpha1.Config).MachineConfig.MachineNetwork.NetworkHostname = "dadjokes.biz.dev.com.org.io"
|
||||||
|
|
||||||
nwd, err = New(sampleConfig)
|
nwd, err = New(sampleConfig)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|||||||
@ -40,6 +40,10 @@ const applyConfigTestSysctl = "net.ipv6.conf.all.accept_ra_mtu"
|
|||||||
|
|
||||||
const applyConfigTestSysctlVal = "1"
|
const applyConfigTestSysctlVal = "1"
|
||||||
|
|
||||||
|
const applyConfigNoRebootTestSysctl = "fs.file-max"
|
||||||
|
|
||||||
|
const applyConfigNoRebootTestSysctlVal = "500000"
|
||||||
|
|
||||||
const assertRebootedRebootTimeout = 10 * time.Minute
|
const assertRebootedRebootTimeout = 10 * time.Minute
|
||||||
|
|
||||||
// ApplyConfigSuite ...
|
// ApplyConfigSuite ...
|
||||||
@ -127,6 +131,52 @@ func (suite *ApplyConfigSuite) TestApply() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestApplyNoReboot verifies the apply config API without reboot.
|
||||||
|
func (suite *ApplyConfigSuite) TestApplyNoReboot() {
|
||||||
|
suite.WaitForBootDone(suite.ctx)
|
||||||
|
|
||||||
|
node := suite.RandomDiscoveredNode()
|
||||||
|
nodeCtx := client.WithNodes(suite.ctx, node)
|
||||||
|
|
||||||
|
provider, err := suite.readConfigFromNode(nodeCtx)
|
||||||
|
suite.Require().NoError(err, "failed to read existing config from node %q", node)
|
||||||
|
|
||||||
|
provider.Machine().Sysctls()[applyConfigNoRebootTestSysctl] = applyConfigNoRebootTestSysctlVal
|
||||||
|
|
||||||
|
cfgDataOut, err := provider.Bytes()
|
||||||
|
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
||||||
|
|
||||||
|
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
|
NoReboot: true,
|
||||||
|
Data: cfgDataOut,
|
||||||
|
})
|
||||||
|
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
||||||
|
|
||||||
|
// Verify configuration change
|
||||||
|
var newProvider config.Provider
|
||||||
|
|
||||||
|
newProvider, err = suite.readConfigFromNode(nodeCtx)
|
||||||
|
|
||||||
|
suite.Require().NoError(err, "failed to read updated configuration from node %q: %w", node)
|
||||||
|
|
||||||
|
suite.Assert().Equal(
|
||||||
|
newProvider.Machine().Sysctls()[applyConfigNoRebootTestSysctl],
|
||||||
|
applyConfigNoRebootTestSysctlVal,
|
||||||
|
)
|
||||||
|
|
||||||
|
// revert back
|
||||||
|
delete(provider.Machine().Sysctls(), applyConfigNoRebootTestSysctl)
|
||||||
|
|
||||||
|
cfgDataOut, err = provider.Bytes()
|
||||||
|
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
||||||
|
|
||||||
|
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
|
NoReboot: true,
|
||||||
|
Data: cfgDataOut,
|
||||||
|
})
|
||||||
|
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *ApplyConfigSuite) readConfigFromNode(nodeCtx context.Context) (config.Provider, error) {
|
func (suite *ApplyConfigSuite) readConfigFromNode(nodeCtx context.Context) (config.Provider, error) {
|
||||||
// Load the current node machine config
|
// Load the current node machine config
|
||||||
cfgData := new(bytes.Buffer)
|
cfgData := new(bytes.Buffer)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
16
pkg/machinery/config/dynamic.go
Normal file
16
pkg/machinery/config/dynamic.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// 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 config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DynamicConfigProvider provides additional configuration which is overlaid on top of existing configuration.
|
||||||
|
type DynamicConfigProvider interface {
|
||||||
|
Hostname(context.Context) ([]byte, error)
|
||||||
|
ExternalIPs(context.Context) ([]net.IP, error)
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -24,6 +25,7 @@ type Provider interface {
|
|||||||
Machine() MachineConfig
|
Machine() MachineConfig
|
||||||
Cluster() ClusterConfig
|
Cluster() ClusterConfig
|
||||||
Validate(RuntimeMode) error
|
Validate(RuntimeMode) error
|
||||||
|
ApplyDynamicConfig(context.Context, DynamicConfigProvider) error
|
||||||
String() (string, error)
|
String() (string, error)
|
||||||
Bytes() ([]byte, error)
|
Bytes() ([]byte, error)
|
||||||
}
|
}
|
||||||
@ -84,14 +86,12 @@ type Security interface {
|
|||||||
CA() *x509.PEMEncodedCertificateAndKey
|
CA() *x509.PEMEncodedCertificateAndKey
|
||||||
Token() string
|
Token() string
|
||||||
CertSANs() []string
|
CertSANs() []string
|
||||||
SetCertSANs([]string)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MachineNetwork defines the requirements for a config that pertains to network
|
// MachineNetwork defines the requirements for a config that pertains to network
|
||||||
// related options.
|
// related options.
|
||||||
type MachineNetwork interface {
|
type MachineNetwork interface {
|
||||||
Hostname() string
|
Hostname() string
|
||||||
SetHostname(string)
|
|
||||||
Resolvers() []string
|
Resolvers() []string
|
||||||
Devices() []Device
|
Devices() []Device
|
||||||
ExtraHosts() []ExtraHost
|
ExtraHosts() []ExtraHost
|
||||||
@ -230,7 +230,6 @@ type ClusterConfig interface {
|
|||||||
Endpoint() *url.URL
|
Endpoint() *url.URL
|
||||||
Token() Token
|
Token() Token
|
||||||
CertSANs() []string
|
CertSANs() []string
|
||||||
SetCertSANs([]string)
|
|
||||||
CA() *x509.PEMEncodedCertificateAndKey
|
CA() *x509.PEMEncodedCertificateAndKey
|
||||||
AESCBCEncryptionSecret() string
|
AESCBCEncryptionSecret() string
|
||||||
Config(machine.Type) (string, error)
|
Config(machine.Type) (string, error)
|
||||||
|
|||||||
@ -5,9 +5,11 @@
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
stdx509 "crypto/x509"
|
stdx509 "crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
@ -70,6 +72,53 @@ func (c *Config) Bytes() (res []byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyDynamicConfig implements the config.Provider interface.
|
||||||
|
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 {
|
||||||
|
log.Printf("certificates will be created without external IPs: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sans := make([]string, 0, len(addrs))
|
||||||
|
for _, addr := range addrs {
|
||||||
|
sans = append(sans, addr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
c.MachineConfig.MachineCertSANs = append(c.MachineConfig.MachineCertSANs, sans...)
|
||||||
|
|
||||||
|
if c.ClusterConfig == nil {
|
||||||
|
c.ClusterConfig = &ClusterConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ClusterConfig.APIServerConfig == nil {
|
||||||
|
c.ClusterConfig.APIServerConfig = &APIServerConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ClusterConfig.APIServerConfig.CertSANs = append(c.ClusterConfig.APIServerConfig.CertSANs, sans...)
|
||||||
|
|
||||||
|
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 {
|
||||||
@ -179,11 +228,6 @@ func (m *MachineConfig) CertSANs() []string {
|
|||||||
return m.MachineCertSANs
|
return m.MachineCertSANs
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCertSANs implements the config.Provider interface.
|
|
||||||
func (m *MachineConfig) SetCertSANs(sans []string) {
|
|
||||||
m.MachineCertSANs = append(m.MachineCertSANs, sans...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Registries implements the config.Provider interface.
|
// Registries implements the config.Provider interface.
|
||||||
func (m *MachineConfig) Registries() config.Registries {
|
func (m *MachineConfig) Registries() config.Registries {
|
||||||
return &m.MachineRegistries
|
return &m.MachineRegistries
|
||||||
@ -242,15 +286,6 @@ func (c *ClusterConfig) CertSANs() []string {
|
|||||||
return c.APIServerConfig.CertSANs
|
return c.APIServerConfig.CertSANs
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCertSANs implements the config.Provider interface.
|
|
||||||
func (c *ClusterConfig) SetCertSANs(sans []string) {
|
|
||||||
if c.APIServerConfig == nil {
|
|
||||||
c.APIServerConfig = &APIServerConfig{}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.APIServerConfig.CertSANs = append(c.APIServerConfig.CertSANs, sans...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CA implements the config.Provider interface.
|
// CA implements the config.Provider interface.
|
||||||
func (c *ClusterConfig) CA() *x509.PEMEncodedCertificateAndKey {
|
func (c *ClusterConfig) CA() *x509.PEMEncodedCertificateAndKey {
|
||||||
return c.ClusterCA
|
return c.ClusterCA
|
||||||
@ -641,11 +676,6 @@ func (n *NetworkConfig) Hostname() string {
|
|||||||
return n.NetworkHostname
|
return n.NetworkHostname
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHostname implements the config.Provider interface.
|
|
||||||
func (n *NetworkConfig) SetHostname(hostname string) {
|
|
||||||
n.NetworkHostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
// Devices implements the config.Provider interface.
|
// Devices implements the config.Provider interface.
|
||||||
func (n *NetworkConfig) Devices() []config.Device {
|
func (n *NetworkConfig) Devices() []config.Device {
|
||||||
interfaces := make([]config.Device, len(n.NetworkInterfaces))
|
interfaces := make([]config.Device, len(n.NetworkInterfaces))
|
||||||
|
|||||||
@ -344,6 +344,7 @@ node.
|
|||||||
| Field | Type | Label | Description |
|
| Field | Type | Label | Description |
|
||||||
| ----- | ---- | ----- | ----------- |
|
| ----- | ---- | ----- | ----------- |
|
||||||
| data | [bytes](#bytes) | | |
|
| data | [bytes](#bytes) | | |
|
||||||
|
| no_reboot | [bool](#bool) | | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ talosctl apply-config [flags]
|
|||||||
-h, --help help for apply-config
|
-h, --help help for apply-config
|
||||||
-i, --insecure apply the config using the insecure (encrypted with no auth) maintenance service
|
-i, --insecure apply the config using the insecure (encrypted with no auth) maintenance service
|
||||||
--interactive apply the config using text based interactive mode
|
--interactive apply the config using text based interactive mode
|
||||||
|
--no-reboot apply the config only after the reboot
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options inherited from parent commands
|
### Options inherited from parent commands
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user