1
// This Source Code Form is subject to the terms of the Mozilla Public
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
14
"github.com/aenix-io/talm/pkg/generated"
15
"github.com/spf13/cobra"
18
"github.com/siderolabs/talos/cmd/talosctl/cmd/mgmt/gen"
19
"github.com/siderolabs/talos/pkg/machinery/config"
20
"github.com/siderolabs/talos/pkg/machinery/config/generate"
21
"github.com/siderolabs/talos/pkg/machinery/config/generate/secrets"
24
var initCmdFlags struct {
30
// initCmd represents the `init` command.
31
var initCmd = &cobra.Command{
33
Short: "Initialize a new project and generate default values",
36
PreRunE: func(cmd *cobra.Command, args []string) error {
37
if !cmd.Flags().Changed("talos-version") {
38
initCmdFlags.talosVersion = Config.TemplateOptions.TalosVersion
42
RunE: func(cmd *cobra.Command, args []string) error {
44
secretsBundle *secrets.Bundle
45
versionContract *config.VersionContract
49
if initCmdFlags.talosVersion != "" {
50
versionContract, err = config.ParseContractFromVersion(initCmdFlags.talosVersion)
52
return fmt.Errorf("invalid talos-version: %w", err)
56
secretsBundle, err = secrets.NewBundle(secrets.NewFixedClock(time.Now()),
60
return fmt.Errorf("failed to create secrets bundle: %w", err)
62
var genOptions []generate.Option //nolint:prealloc
63
if !isValidPreset(initCmdFlags.preset) {
64
return fmt.Errorf("invalid preset: %s. Valid presets are: %s", initCmdFlags.preset, generated.AvailablePresets)
66
if initCmdFlags.talosVersion != "" {
67
var versionContract *config.VersionContract
69
versionContract, err = config.ParseContractFromVersion(initCmdFlags.talosVersion)
71
return fmt.Errorf("invalid talos-version: %w", err)
74
genOptions = append(genOptions, generate.WithVersionContract(versionContract))
76
genOptions = append(genOptions, generate.WithSecretsBundle(secretsBundle))
78
err = writeSecretsBundleToFile(secretsBundle)
83
// Clalculate cluster name from directory
84
absolutePath, err := filepath.Abs(Config.RootDir)
88
clusterName := filepath.Base(absolutePath)
90
configBundle, err := gen.GenerateConfigBundle(genOptions, clusterName, "https://192.168.0.1:6443", "", []string{}, []string{}, []string{})
91
configBundle.TalosConfig().Contexts[clusterName].Endpoints = []string{"127.0.0.1"}
96
data, err := yaml.Marshal(configBundle.TalosConfig())
98
return fmt.Errorf("failed to marshal config: %+v", err)
101
talosconfigFile := filepath.Join(Config.RootDir, "talosconfig")
102
if err = writeToDestination(data, talosconfigFile, 0o644); err != nil {
106
for path, content := range generated.PresetFiles {
107
parts := strings.SplitN(path, "/", 2)
108
chartName := parts[0]
109
// Write preset files
110
if chartName == initCmdFlags.preset {
111
file := filepath.Join(Config.RootDir, filepath.Join(parts[1:]...))
112
if parts[len(parts)-1] == "Chart.yaml" {
113
writeToDestination([]byte(fmt.Sprintf(content, clusterName, Config.InitOptions.Version)), file, 0o644)
115
err = writeToDestination([]byte(content), file, 0o644)
121
// Write library chart
122
if chartName == "talm" {
123
file := filepath.Join(Config.RootDir, filepath.Join("charts", path))
124
if parts[len(parts)-1] == "Chart.yaml" {
125
writeToDestination([]byte(fmt.Sprintf(content, "talm", Config.InitOptions.Version)), file, 0o644)
127
err = writeToDestination([]byte(content), file, 0o644)
140
func writeSecretsBundleToFile(bundle *secrets.Bundle) error {
141
bundleBytes, err := yaml.Marshal(bundle)
146
secretsFile := filepath.Join(Config.RootDir, "secrets.yaml")
147
if err = validateFileExists(secretsFile); err != nil {
151
return writeToDestination(bundleBytes, secretsFile, 0o644)
155
initCmd.Flags().StringVar(&initCmdFlags.talosVersion, "talos-version", "", "the desired Talos version to generate config for (backwards compatibility, e.g. v0.8)")
156
initCmd.Flags().StringVarP(&initCmdFlags.preset, "preset", "p", "generic", "specify preset to generate files")
157
initCmd.Flags().BoolVar(&initCmdFlags.force, "force", false, "will overwrite existing files")
162
func isValidPreset(preset string) bool {
163
for _, validPreset := range generated.AvailablePresets {
164
if preset == validPreset {
171
func validateFileExists(file string) error {
172
if !initCmdFlags.force {
173
if _, err := os.Stat(file); err == nil {
174
return fmt.Errorf("file %q already exists, use --force to overwrite", file)
181
func writeToDestination(data []byte, destination string, permissions os.FileMode) error {
182
if err := validateFileExists(destination); err != nil {
186
parentDir := filepath.Dir(destination)
188
// Create dir path, ignoring "already exists" messages
189
if err := os.MkdirAll(parentDir, os.ModePerm); err != nil {
190
return fmt.Errorf("failed to create output dir: %w", err)
193
err := os.WriteFile(destination, data, permissions)
195
fmt.Fprintf(os.Stderr, "Created %s\n", destination)