mirror of
https://github.com/lingble/talos.git
synced 2025-11-27 11:23:46 +00:00
As this implements Go client for Talos API, it makes sense to publish it one the top level. Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
188 lines
4.7 KiB
Go
188 lines
4.7 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
yaml "gopkg.in/yaml.v2"
|
|
|
|
"github.com/talos-systems/talos/internal/pkg/runtime"
|
|
"github.com/talos-systems/talos/pkg/client/config"
|
|
"github.com/talos-systems/talos/pkg/config/machine"
|
|
"github.com/talos-systems/talos/pkg/config/types/v1alpha1"
|
|
"github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate"
|
|
)
|
|
|
|
// Content represents the raw config data.
|
|
type Content struct {
|
|
Version string `yaml:"version"`
|
|
|
|
data []byte
|
|
}
|
|
|
|
// NewConfigBundle returns a new bundle
|
|
// nolint: gocyclo
|
|
func NewConfigBundle(opts ...BundleOption) (*v1alpha1.ConfigBundle, error) {
|
|
options := DefaultBundleOptions()
|
|
|
|
for _, opt := range opts {
|
|
if err := opt(&options); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
bundle := &v1alpha1.ConfigBundle{}
|
|
|
|
// Configs already exist, we'll pull them in.
|
|
if options.ExistingConfigs != "" {
|
|
if options.InputOptions != nil {
|
|
return bundle, fmt.Errorf("both existing config path and input options specified")
|
|
}
|
|
|
|
// Pull existing machine configs of each type
|
|
for _, configType := range []machine.Type{machine.TypeInit, machine.TypeControlPlane, machine.TypeWorker} {
|
|
data, err := ioutil.ReadFile(filepath.Join(options.ExistingConfigs, strings.ToLower(configType.String())+".yaml"))
|
|
if err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
unmarshalledConfig := &v1alpha1.Config{}
|
|
if err := yaml.Unmarshal(data, unmarshalledConfig); err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
switch configType {
|
|
case machine.TypeInit:
|
|
bundle.InitCfg = unmarshalledConfig
|
|
case machine.TypeControlPlane:
|
|
bundle.ControlPlaneCfg = unmarshalledConfig
|
|
case machine.TypeWorker:
|
|
bundle.JoinCfg = unmarshalledConfig
|
|
}
|
|
}
|
|
|
|
// Pull existing talosconfig
|
|
talosConfig, err := ioutil.ReadFile(filepath.Join(options.ExistingConfigs, "talosconfig"))
|
|
if err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
bundle.TalosCfg = &config.Config{}
|
|
if err = yaml.Unmarshal(talosConfig, bundle.TalosCfg); err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
return bundle, nil
|
|
}
|
|
|
|
// Handle generating net-new configs
|
|
fmt.Println("generating PKI and tokens")
|
|
|
|
var input *generate.Input
|
|
|
|
input, err := generate.NewInput(
|
|
options.InputOptions.ClusterName,
|
|
options.InputOptions.Endpoint,
|
|
options.InputOptions.KubeVersion,
|
|
options.InputOptions.GenOptions...,
|
|
)
|
|
if err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
for _, configType := range []machine.Type{machine.TypeInit, machine.TypeControlPlane, machine.TypeWorker} {
|
|
var generatedConfig *v1alpha1.Config
|
|
|
|
generatedConfig, err = generate.Config(configType, input)
|
|
if err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
switch configType {
|
|
case machine.TypeInit:
|
|
bundle.InitCfg = generatedConfig
|
|
case machine.TypeControlPlane:
|
|
bundle.ControlPlaneCfg = generatedConfig
|
|
case machine.TypeWorker:
|
|
bundle.JoinCfg = generatedConfig
|
|
}
|
|
}
|
|
|
|
bundle.TalosCfg, err = generate.Talosconfig(input, options.InputOptions.GenOptions...)
|
|
if err != nil {
|
|
return bundle, err
|
|
}
|
|
|
|
return bundle, nil
|
|
}
|
|
|
|
// newConfig initializes and returns a Configurator.
|
|
func newConfig(c Content) (config runtime.Configurator, err error) {
|
|
switch c.Version {
|
|
case v1alpha1.Version:
|
|
config = &v1alpha1.Config{}
|
|
if err = yaml.Unmarshal(c.data, config); err != nil {
|
|
return config, fmt.Errorf("failed to parse version: %w", err)
|
|
}
|
|
|
|
return config, nil
|
|
default:
|
|
return nil, fmt.Errorf("unknown version: %q", c.Version)
|
|
}
|
|
}
|
|
|
|
// NewFromFile will take a filepath and attempt to parse a config file from it
|
|
func NewFromFile(filepath string) (runtime.Configurator, error) {
|
|
content, err := fromFile(filepath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newConfig(content)
|
|
}
|
|
|
|
// NewFromBytes will take a byteslice and attempt to parse a config file from it
|
|
func NewFromBytes(in []byte) (runtime.Configurator, error) {
|
|
content, err := fromBytes(in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newConfig(content)
|
|
}
|
|
|
|
// fromFile is a convenience function that reads the config from disk, and
|
|
// unmarshals it.
|
|
func fromFile(p string) (c Content, err error) {
|
|
b, err := ioutil.ReadFile(p)
|
|
if err != nil {
|
|
return c, fmt.Errorf("read config: %w", err)
|
|
}
|
|
|
|
return unmarshal(b)
|
|
}
|
|
|
|
// fromBytes is a convenience function that reads the config from a string, and
|
|
// unmarshals it.
|
|
func fromBytes(b []byte) (c Content, err error) {
|
|
return unmarshal(b)
|
|
}
|
|
|
|
func unmarshal(b []byte) (c Content, err error) {
|
|
c = Content{
|
|
data: b,
|
|
}
|
|
|
|
if err = yaml.Unmarshal(b, &c); err != nil {
|
|
return c, fmt.Errorf("failed to parse config: %s", err.Error())
|
|
}
|
|
|
|
return c, nil
|
|
}
|