mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-03 19:51:16 +02:00
feat: split osctl
commands into Talos API and cluster management
This keeps backwards compatibility with `osctl` CLI binary with the exception of `osctl config generate` which was renamed to `osctl gen config` to avoid confusion with other `osctl config` commands which operate on client config, not Talos server config. Command implementation and helpers were split into subpackages for cleaner code and more visible boundaries. The resulting binary still combines commands from both sections into a single binary. Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
parent
a1350aa819
commit
0babc39653
@ -222,8 +222,9 @@ ARG SHA
|
||||
ARG TAG
|
||||
ARG ARTIFACTS
|
||||
ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version"
|
||||
ARG MGMT_HELPERS_PKG="github.com/talos-systems/talos/cmd/osctl/pkg/mgmt/helpers"
|
||||
WORKDIR /src/cmd/osctl
|
||||
RUN --mount=type=cache,target=/.cache/go-build GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X github.com/talos-systems/talos/cmd/osctl/pkg/helpers.ArtifactsPath=${ARTIFACTS}" -o /osctl-linux-amd64
|
||||
RUN --mount=type=cache,target=/.cache/go-build GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${MGMT_HELPERS_PKG}.ArtifactsPath=${ARTIFACTS}" -o /osctl-linux-amd64
|
||||
RUN chmod +x /osctl-linux-amd64
|
||||
|
||||
FROM scratch AS osctl-linux
|
||||
@ -234,8 +235,9 @@ ARG SHA
|
||||
ARG TAG
|
||||
ARG ARTIFACTS
|
||||
ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version"
|
||||
ARG MGMT_HELPERS_PKG="github.com/talos-systems/talos/cmd/osctl/pkg/mgmt/helpers"
|
||||
WORKDIR /src/cmd/osctl
|
||||
RUN --mount=type=cache,target=/.cache/go-build GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X github.com/talos-systems/talos/cmd/osctl/pkg/helpers.ArtifactsPath=${ARTIFACTS}" -o /osctl-darwin-amd64
|
||||
RUN --mount=type=cache,target=/.cache/go-build GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${MGMT_HELPERS_PKG}.ArtifactsPath=${ARTIFACTS}" -o /osctl-darwin-amd64
|
||||
RUN chmod +x /osctl-darwin-amd64
|
||||
|
||||
FROM scratch AS osctl-darwin
|
||||
@ -419,9 +421,10 @@ FROM base AS integration-test-provision-linux-build
|
||||
ARG SHA
|
||||
ARG TAG
|
||||
ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version"
|
||||
ARG MGMT_HELPERS_PKG="github.com/talos-systems/talos/cmd/osctl/pkg/mgmt/helpers"
|
||||
ARG ARTIFACTS
|
||||
RUN --mount=type=cache,target=/.cache/go-build GOOS=linux GOARCH=amd64 go test -c \
|
||||
-ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X github.com/talos-systems/talos/cmd/osctl/pkg/helpers.ArtifactsPath=${ARTIFACTS}" \
|
||||
-ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${MGMT_HELPERS_PKG}.ArtifactsPath=${ARTIFACTS}" \
|
||||
-tags integration,integration_provision \
|
||||
./internal/integration
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// completionCmd represents the completion command
|
||||
@ -52,7 +52,7 @@ osctl completion zsh > "${fpath[1]}/_osctl"`,
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
helpers.Should(cmd.Usage())
|
||||
cli.Should(cmd.Usage())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
@ -1,302 +0,0 @@
|
||||
// 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 cmd
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
clientconfig "github.com/talos-systems/talos/cmd/osctl/pkg/client/config"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
var (
|
||||
configVersion string
|
||||
dnsDomain string
|
||||
kubernetesVersion string
|
||||
installDisk string
|
||||
installImage string
|
||||
outputDir string
|
||||
)
|
||||
|
||||
// configCmd represents the config command.
|
||||
var configCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Manage the client configuration",
|
||||
Long: ``,
|
||||
}
|
||||
|
||||
// configEndpointCmd represents the config endpoint command.
|
||||
var configEndpointCmd = &cobra.Command{
|
||||
Use: "endpoint <endpoint>...",
|
||||
Aliases: []string{"endpoints"},
|
||||
Short: "Set the endpoint(s) for the current context",
|
||||
Long: ``,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := clientconfig.Open(talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
if c.Context == "" {
|
||||
return fmt.Errorf("no context is set")
|
||||
}
|
||||
|
||||
c.Contexts[c.Context].Endpoints = args
|
||||
if err := c.Save(talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configNodeCmd represents the config node command.
|
||||
var configNodeCmd = &cobra.Command{
|
||||
Use: "node <endpoint>...",
|
||||
Aliases: []string{"nodes"},
|
||||
Short: "Set the node(s) for the current context",
|
||||
Long: ``,
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := clientconfig.Open(talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
if c.Context == "" {
|
||||
return fmt.Errorf("no context is set")
|
||||
}
|
||||
|
||||
c.Contexts[c.Context].Nodes = args
|
||||
if err := c.Save(talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configContextCmd represents the configc context command.
|
||||
var configContextCmd = &cobra.Command{
|
||||
Use: "context <context>",
|
||||
Short: "Set the current context",
|
||||
Long: ``,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
context := args[0]
|
||||
|
||||
c, err := clientconfig.Open(talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
|
||||
c.Context = context
|
||||
|
||||
if err := c.Save(talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configAddCmd represents the config add command.
|
||||
var configAddCmd = &cobra.Command{
|
||||
Use: "add <context>",
|
||||
Short: "Add a new context",
|
||||
Long: ``,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
context := args[0]
|
||||
c, err := clientconfig.Open(talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
|
||||
caBytes, err := ioutil.ReadFile(ca)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading CA: %w", err)
|
||||
}
|
||||
|
||||
crtBytes, err := ioutil.ReadFile(crt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading certificate: %w", err)
|
||||
}
|
||||
|
||||
keyBytes, err := ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading key: %w", err)
|
||||
}
|
||||
|
||||
newContext := &clientconfig.Context{
|
||||
CA: base64.StdEncoding.EncodeToString(caBytes),
|
||||
Crt: base64.StdEncoding.EncodeToString(crtBytes),
|
||||
Key: base64.StdEncoding.EncodeToString(keyBytes),
|
||||
}
|
||||
|
||||
if c.Contexts == nil {
|
||||
c.Contexts = map[string]*clientconfig.Context{}
|
||||
}
|
||||
|
||||
c.Contexts[context] = newContext
|
||||
if err := c.Save(talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configGenerateCmd represents the config generate command.
|
||||
var configGenerateCmd = &cobra.Command{
|
||||
Use: "generate <cluster name> https://<load balancer IP or DNS name>",
|
||||
Short: "Generate a set of configuration files",
|
||||
Long: ``,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// Validate url input to ensure it has https:// scheme before we attempt to gen
|
||||
u, err := url.Parse(args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse load balancer IP or DNS name: %w", err)
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
return fmt.Errorf("no scheme specified for load balancer IP or DNS name\ntry \"https://<load balancer IP or DNS name>\"")
|
||||
}
|
||||
|
||||
switch configVersion {
|
||||
case "v1alpha1":
|
||||
return genV1Alpha1Config(args)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
//nolint: gocyclo
|
||||
func genV1Alpha1Config(args []string) error {
|
||||
// If output dir isn't specified, set to the current working dir
|
||||
var err error
|
||||
if outputDir == "" {
|
||||
outputDir, err = os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get working dir: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create dir path, ignoring "already exists" messages
|
||||
if err = os.MkdirAll(outputDir, os.ModePerm); err != nil && !os.IsExist(err) {
|
||||
return fmt.Errorf("failed to create output dir: %w", err)
|
||||
}
|
||||
|
||||
var genOptions []generate.GenOption //nolint: prealloc
|
||||
|
||||
for _, registryMirror := range registryMirrors {
|
||||
components := strings.SplitN(registryMirror, "=", 2)
|
||||
if len(components) != 2 {
|
||||
return fmt.Errorf("invalid registry mirror spec: %q", registryMirror)
|
||||
}
|
||||
|
||||
genOptions = append(genOptions, generate.WithRegistryMirror(components[0], components[1]))
|
||||
}
|
||||
|
||||
configBundle, err := config.NewConfigBundle(
|
||||
config.WithInputOptions(
|
||||
&config.InputOptions{
|
||||
ClusterName: args[0],
|
||||
Endpoint: args[1],
|
||||
KubeVersion: kubernetesVersion,
|
||||
GenOptions: append(genOptions,
|
||||
generate.WithInstallDisk(installDisk),
|
||||
generate.WithInstallImage(installImage),
|
||||
generate.WithAdditionalSubjectAltNames(additionalSANs),
|
||||
generate.WithDNSDomain(dnsDomain),
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate config bundle: %w", err)
|
||||
}
|
||||
|
||||
for _, t := range []machine.Type{machine.TypeInit, machine.TypeControlPlane, machine.TypeWorker} {
|
||||
name = strings.ToLower(t.String()) + ".yaml"
|
||||
fullFilePath := filepath.Join(outputDir, name)
|
||||
|
||||
var configString string
|
||||
|
||||
switch t {
|
||||
case machine.TypeInit:
|
||||
configString, err = configBundle.Init().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case machine.TypeControlPlane:
|
||||
configString, err = configBundle.ControlPlane().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case machine.TypeWorker:
|
||||
configString, err = configBundle.Join().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(fullFilePath, []byte(configString), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("created %s\n", fullFilePath)
|
||||
}
|
||||
|
||||
// We set the default endpoint to localhost for configs generated, with expectation user will tweak later
|
||||
configBundle.TalosConfig().Contexts[args[0]].Endpoints = []string{"127.0.0.1"}
|
||||
|
||||
data, err := yaml.Marshal(configBundle.TalosConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config: %+v", err)
|
||||
}
|
||||
|
||||
fullFilePath := filepath.Join(outputDir, "talosconfig")
|
||||
|
||||
if err = ioutil.WriteFile(fullFilePath, data, 0644); err != nil {
|
||||
return fmt.Errorf("%w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("created %s\n", fullFilePath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
configCmd.AddCommand(configContextCmd, configEndpointCmd, configNodeCmd, configAddCmd, configGenerateCmd)
|
||||
configAddCmd.Flags().StringVar(&ca, "ca", "", "the path to the CA certificate")
|
||||
configAddCmd.Flags().StringVar(&crt, "crt", "", "the path to the certificate")
|
||||
configAddCmd.Flags().StringVar(&key, "key", "", "the path to the key")
|
||||
configGenerateCmd.Flags().StringVar(&installDisk, "install-disk", "/dev/sda", "the disk to install to")
|
||||
configGenerateCmd.Flags().StringVar(&installImage, "install-image", defaultImage(constants.DefaultInstallerImageRepository), "the image used to perform an installation") // nolint: lll
|
||||
configGenerateCmd.Flags().StringSliceVar(&additionalSANs, "additional-sans", []string{}, "additional Subject-Alt-Names for the APIServer certificate")
|
||||
configGenerateCmd.Flags().StringVar(&dnsDomain, "dns-domain", "cluster.local", "the dns domain to use for cluster")
|
||||
configGenerateCmd.Flags().StringVar(&configVersion, "version", "v1alpha1", "the desired machine config version to generate")
|
||||
configGenerateCmd.Flags().StringVar(&kubernetesVersion, "kubernetes-version", constants.DefaultKubernetesVersion, "desired kubernetes version to run")
|
||||
configGenerateCmd.Flags().StringVarP(&outputDir, "output-dir", "o", "", "destination to output generated files")
|
||||
configGenerateCmd.Flags().StringSliceVar(®istryMirrors, "registry-mirror", []string{}, "list of registry mirrors to use in format: <registry host>=<mirror URL>")
|
||||
helpers.Should(configAddCmd.MarkFlagRequired("ca"))
|
||||
helpers.Should(configAddCmd.MarkFlagRequired("crt"))
|
||||
helpers.Should(configAddCmd.MarkFlagRequired("key"))
|
||||
rootCmd.AddCommand(configCmd)
|
||||
}
|
13
cmd/osctl/cmd/mgmt/cluster.go
Normal file
13
cmd/osctl/cmd/mgmt/cluster.go
Normal file
@ -0,0 +1,13 @@
|
||||
// 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 mgmt
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/cmd/osctl/cmd/mgmt/cluster"
|
||||
)
|
||||
|
||||
func init() {
|
||||
addCommand(cluster.Cmd)
|
||||
}
|
38
cmd/osctl/cmd/mgmt/cluster/cluster.go
Normal file
38
cmd/osctl/cmd/mgmt/cluster/cluster.go
Normal file
@ -0,0 +1,38 @@
|
||||
// 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 cluster implements "cluster" subcommands.
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
clientconfig "github.com/talos-systems/talos/cmd/osctl/pkg/client/config"
|
||||
)
|
||||
|
||||
// Cmd represents the cluster command
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "cluster",
|
||||
Short: "A collection of commands for managing local docker-based or firecracker-based clusters",
|
||||
Long: ``,
|
||||
}
|
||||
|
||||
var (
|
||||
provisioner string
|
||||
stateDir string
|
||||
clusterName string
|
||||
)
|
||||
|
||||
func init() {
|
||||
defaultStateDir, err := clientconfig.GetTalosDirectory()
|
||||
if err == nil {
|
||||
defaultStateDir = filepath.Join(defaultStateDir, "clusters")
|
||||
}
|
||||
|
||||
Cmd.PersistentFlags().StringVar(&provisioner, "provisioner", "docker", "Talos cluster provisioner to use")
|
||||
Cmd.PersistentFlags().StringVar(&stateDir, "state", defaultStateDir, "directory path to store cluster state")
|
||||
Cmd.PersistentFlags().StringVar(&clusterName, "name", "talos-default", "the name of the cluster")
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,22 +11,19 @@ import (
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
clientconfig "github.com/talos-systems/talos/cmd/osctl/pkg/client/config"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/mgmt/helpers"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/access"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/check"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/providers"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
@ -34,11 +31,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
provisioner string
|
||||
clusterName string
|
||||
talosconfig string
|
||||
nodeImage string
|
||||
nodeInstallImage string
|
||||
registryMirrors []string
|
||||
kubernetesVersion string
|
||||
nodeVmlinuxPath string
|
||||
nodeInitramfsPath string
|
||||
bootloaderEmulation bool
|
||||
@ -58,46 +55,16 @@ var (
|
||||
cniBinPath []string
|
||||
cniConfDir string
|
||||
cniCacheDir string
|
||||
stateDir string
|
||||
)
|
||||
|
||||
// clusterCmd represents the cluster command
|
||||
var clusterCmd = &cobra.Command{
|
||||
Use: "cluster",
|
||||
Short: "A collection of commands for managing local docker-based or firecracker-based clusters",
|
||||
Long: ``,
|
||||
}
|
||||
|
||||
// clusterUpCmd represents the cluster up command
|
||||
var clusterUpCmd = &cobra.Command{
|
||||
// createCmd represents the cluster up command
|
||||
var createCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Creates a local docker-based or firecracker-based kubernetes cluster",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return helpers.WithCLIContext(context.Background(), create)
|
||||
},
|
||||
}
|
||||
|
||||
// clusterDownCmd represents the cluster up command
|
||||
var clusterDownCmd = &cobra.Command{
|
||||
Use: "destroy",
|
||||
Short: "Destroys a local docker-based or firecracker-based kubernetes cluster",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return helpers.WithCLIContext(context.Background(), destroy)
|
||||
},
|
||||
}
|
||||
|
||||
// clusterShowCmd represents the cluster show command
|
||||
var clusterShowCmd = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "Shows info about a local provisioned kubernetes cluster",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return helpers.WithCLIContext(context.Background(), show)
|
||||
return cli.WithContext(context.Background(), create)
|
||||
},
|
||||
}
|
||||
|
||||
@ -305,87 +272,6 @@ func create(ctx context.Context) (err error) {
|
||||
return check.Wait(checkCtx, clusterAccess, check.DefaultClusterChecks(), check.StderrReporter())
|
||||
}
|
||||
|
||||
func destroy(ctx context.Context) error {
|
||||
provisioner, err := providers.Factory(ctx, provisioner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer provisioner.Close() //nolint: errcheck
|
||||
|
||||
cluster, err := provisioner.Reflect(ctx, clusterName, stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return provisioner.Destroy(ctx, cluster)
|
||||
}
|
||||
|
||||
func show(ctx context.Context) error {
|
||||
provisioner, err := providers.Factory(ctx, provisioner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer provisioner.Close() //nolint: errcheck
|
||||
|
||||
cluster, err := provisioner.Reflect(ctx, clusterName, stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
fmt.Fprintf(w, "PROVISIONER\t%s\n", cluster.Provisioner())
|
||||
fmt.Fprintf(w, "NAME\t%s\n", cluster.Info().ClusterName)
|
||||
fmt.Fprintf(w, "NETWORK NAME\t%s\n", cluster.Info().Network.Name)
|
||||
|
||||
ones, _ := cluster.Info().Network.CIDR.Mask.Size()
|
||||
fmt.Fprintf(w, "NETWORK CIDR\t%s/%d\n", cluster.Info().Network.CIDR.IP, ones)
|
||||
fmt.Fprintf(w, "NETWORK GATEWAY\t%s\n", cluster.Info().Network.GatewayAddr)
|
||||
fmt.Fprintf(w, "NETWORK MTU\t%d\n", cluster.Info().Network.MTU)
|
||||
|
||||
if err = w.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stdout, "\nNODES:\n\n")
|
||||
|
||||
w = tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
|
||||
fmt.Fprintf(w, "NAME\tTYPE\tIP\tCPU\tRAM\tDISK\n")
|
||||
|
||||
nodes := cluster.Info().Nodes
|
||||
sort.Slice(nodes, func(i, j int) bool { return nodes[i].Name < nodes[j].Name })
|
||||
|
||||
for _, node := range nodes {
|
||||
cpus := "-"
|
||||
if node.NanoCPUs > 0 {
|
||||
cpus = fmt.Sprintf("%.2f", float64(node.NanoCPUs)/1000.0/1000.0/1000.0)
|
||||
}
|
||||
|
||||
mem := "-"
|
||||
if node.Memory > 0 {
|
||||
mem = humanize.Bytes(uint64(node.Memory))
|
||||
}
|
||||
|
||||
disk := "-"
|
||||
if node.DiskSize > 0 {
|
||||
disk = humanize.Bytes(uint64(node.DiskSize))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
node.Name,
|
||||
node.Type,
|
||||
node.PrivateIP,
|
||||
cpus,
|
||||
mem,
|
||||
disk,
|
||||
)
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
func saveConfig(cluster provision.Cluster, talosConfigObj *clientconfig.Config) (err error) {
|
||||
c, err := clientconfig.Open(talosconfig)
|
||||
if err != nil {
|
||||
@ -418,39 +304,34 @@ func parseCPUShare() (int64, error) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
defaultStateDir, err := clientconfig.GetTalosDirectory()
|
||||
if err == nil {
|
||||
defaultStateDir = filepath.Join(defaultStateDir, "clusters")
|
||||
defaultTalosConfig, err := clientconfig.GetDefaultPath()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to find default Talos config path: %s", err)
|
||||
}
|
||||
|
||||
clusterUpCmd.Flags().StringVar(&nodeImage, "image", defaultImage(constants.DefaultTalosImageRepository), "the image to use")
|
||||
clusterUpCmd.Flags().StringVar(&nodeInstallImage, "install-image", defaultImage(constants.DefaultInstallerImageRepository), "the installer image to use")
|
||||
clusterUpCmd.Flags().StringVar(&nodeVmlinuxPath, "vmlinux-path", helpers.ArtifactPath(constants.KernelUncompressedAsset), "the uncompressed kernel image to use")
|
||||
clusterUpCmd.Flags().StringVar(&nodeInitramfsPath, "initrd-path", helpers.ArtifactPath(constants.InitramfsAsset), "the uncompressed kernel image to use")
|
||||
clusterUpCmd.Flags().BoolVar(&bootloaderEmulation, "with-bootloader-emulation", false, "enable bootloader emulation to load kernel and initramfs from disk image")
|
||||
clusterUpCmd.Flags().StringSliceVar(®istryMirrors, "registry-mirror", []string{}, "list of registry mirrors to use in format: <registry host>=<mirror URL>")
|
||||
clusterUpCmd.Flags().IntVar(&networkMTU, "mtu", 1500, "MTU of the docker bridge network")
|
||||
clusterUpCmd.Flags().StringVar(&networkCIDR, "cidr", "10.5.0.0/24", "CIDR of the docker bridge network")
|
||||
clusterUpCmd.Flags().StringSliceVar(&nameservers, "nameservers", []string{"8.8.8.8", "1.1.1.1"}, "list of nameservers to use (VM only)")
|
||||
clusterUpCmd.Flags().IntVar(&workers, "workers", 1, "the number of workers to create")
|
||||
clusterUpCmd.Flags().IntVar(&masters, "masters", 1, "the number of masters to create")
|
||||
clusterUpCmd.Flags().StringVar(&clusterCpus, "cpus", "1.5", "the share of CPUs as fraction (each container)")
|
||||
clusterUpCmd.Flags().IntVar(&clusterMemory, "memory", 1024, "the limit on memory usage in MB (each container)")
|
||||
clusterUpCmd.Flags().IntVar(&clusterDiskSize, "disk", 4*1024, "the limit on disk size in MB (each VM)")
|
||||
clusterUpCmd.Flags().BoolVar(&clusterWait, "wait", false, "wait for the cluster to be ready before returning")
|
||||
clusterUpCmd.Flags().DurationVar(&clusterWaitTimeout, "wait-timeout", 20*time.Minute, "timeout to wait for the cluster to be ready")
|
||||
clusterUpCmd.Flags().BoolVar(&forceInitNodeAsEndpoint, "init-node-as-endpoint", false, "use init node as endpoint instead of any load balancer endpoint")
|
||||
clusterUpCmd.Flags().StringVar(&forceEndpoint, "endpoint", "", "use endpoint instead of provider defaults")
|
||||
clusterUpCmd.Flags().StringVar(&kubernetesVersion, "kubernetes-version", constants.DefaultKubernetesVersion, "desired kubernetes version to run")
|
||||
clusterUpCmd.Flags().StringVarP(&inputDir, "input-dir", "i", "", "location of pre-generated config files")
|
||||
clusterUpCmd.Flags().StringSliceVar(&cniBinPath, "cni-bin-path", []string{"/opt/cni/bin"}, "search path for CNI binaries")
|
||||
clusterUpCmd.Flags().StringVar(&cniConfDir, "cni-conf-dir", "/etc/cni/conf.d", "CNI config directory path")
|
||||
clusterUpCmd.Flags().StringVar(&cniCacheDir, "cni-cache-dir", "/var/lib/cni", "CNI cache directory path")
|
||||
clusterCmd.PersistentFlags().StringVar(&provisioner, "provisioner", "docker", "Talos cluster provisioner to use")
|
||||
clusterCmd.PersistentFlags().StringVar(&stateDir, "state", defaultStateDir, "directory path to store cluster state")
|
||||
clusterCmd.PersistentFlags().StringVar(&clusterName, "name", "talos-default", "the name of the cluster")
|
||||
clusterCmd.AddCommand(clusterUpCmd)
|
||||
clusterCmd.AddCommand(clusterDownCmd)
|
||||
clusterCmd.AddCommand(clusterShowCmd)
|
||||
rootCmd.AddCommand(clusterCmd)
|
||||
createCmd.Flags().StringVar(&talosconfig, "talosconfig", defaultTalosConfig, "The path to the Talos configuration file")
|
||||
createCmd.Flags().StringVar(&nodeImage, "image", helpers.DefaultImage(constants.DefaultTalosImageRepository), "the image to use")
|
||||
createCmd.Flags().StringVar(&nodeInstallImage, "install-image", helpers.DefaultImage(constants.DefaultInstallerImageRepository), "the installer image to use")
|
||||
createCmd.Flags().StringVar(&nodeVmlinuxPath, "vmlinux-path", helpers.ArtifactPath(constants.KernelUncompressedAsset), "the uncompressed kernel image to use")
|
||||
createCmd.Flags().StringVar(&nodeInitramfsPath, "initrd-path", helpers.ArtifactPath(constants.InitramfsAsset), "the uncompressed kernel image to use")
|
||||
createCmd.Flags().BoolVar(&bootloaderEmulation, "with-bootloader-emulation", false, "enable bootloader emulation to load kernel and initramfs from disk image")
|
||||
createCmd.Flags().StringSliceVar(®istryMirrors, "registry-mirror", []string{}, "list of registry mirrors to use in format: <registry host>=<mirror URL>")
|
||||
createCmd.Flags().IntVar(&networkMTU, "mtu", 1500, "MTU of the docker bridge network")
|
||||
createCmd.Flags().StringVar(&networkCIDR, "cidr", "10.5.0.0/24", "CIDR of the docker bridge network")
|
||||
createCmd.Flags().StringSliceVar(&nameservers, "nameservers", []string{"8.8.8.8", "1.1.1.1"}, "list of nameservers to use (VM only)")
|
||||
createCmd.Flags().IntVar(&workers, "workers", 1, "the number of workers to create")
|
||||
createCmd.Flags().IntVar(&masters, "masters", 1, "the number of masters to create")
|
||||
createCmd.Flags().StringVar(&clusterCpus, "cpus", "1.5", "the share of CPUs as fraction (each container)")
|
||||
createCmd.Flags().IntVar(&clusterMemory, "memory", 1024, "the limit on memory usage in MB (each container)")
|
||||
createCmd.Flags().IntVar(&clusterDiskSize, "disk", 4*1024, "the limit on disk size in MB (each VM)")
|
||||
createCmd.Flags().BoolVar(&clusterWait, "wait", false, "wait for the cluster to be ready before returning")
|
||||
createCmd.Flags().DurationVar(&clusterWaitTimeout, "wait-timeout", 20*time.Minute, "timeout to wait for the cluster to be ready")
|
||||
createCmd.Flags().BoolVar(&forceInitNodeAsEndpoint, "init-node-as-endpoint", false, "use init node as endpoint instead of any load balancer endpoint")
|
||||
createCmd.Flags().StringVar(&forceEndpoint, "endpoint", "", "use endpoint instead of provider defaults")
|
||||
createCmd.Flags().StringVar(&kubernetesVersion, "kubernetes-version", constants.DefaultKubernetesVersion, "desired kubernetes version to run")
|
||||
createCmd.Flags().StringVarP(&inputDir, "input-dir", "i", "", "location of pre-generated config files")
|
||||
createCmd.Flags().StringSliceVar(&cniBinPath, "cni-bin-path", []string{"/opt/cni/bin"}, "search path for CNI binaries")
|
||||
createCmd.Flags().StringVar(&cniConfDir, "cni-conf-dir", "/etc/cni/conf.d", "CNI config directory path")
|
||||
createCmd.Flags().StringVar(&cniCacheDir, "cni-cache-dir", "/var/lib/cni", "CNI cache directory path")
|
||||
Cmd.AddCommand(createCmd)
|
||||
}
|
45
cmd/osctl/cmd/mgmt/cluster/destroy.go
Normal file
45
cmd/osctl/cmd/mgmt/cluster/destroy.go
Normal file
@ -0,0 +1,45 @@
|
||||
// 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 cluster
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/providers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// destroyCmd represents the cluster destroy command
|
||||
var destroyCmd = &cobra.Command{
|
||||
Use: "destroy",
|
||||
Short: "Destroys a local docker-based or firecracker-based kubernetes cluster",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return cli.WithContext(context.Background(), destroy)
|
||||
},
|
||||
}
|
||||
|
||||
func destroy(ctx context.Context) error {
|
||||
provisioner, err := providers.Factory(ctx, provisioner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer provisioner.Close() //nolint: errcheck
|
||||
|
||||
cluster, err := provisioner.Reflect(ctx, clusterName, stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return provisioner.Destroy(ctx, cluster)
|
||||
}
|
||||
|
||||
func init() {
|
||||
Cmd.AddCommand(destroyCmd)
|
||||
}
|
99
cmd/osctl/cmd/mgmt/cluster/show.go
Normal file
99
cmd/osctl/cmd/mgmt/cluster/show.go
Normal file
@ -0,0 +1,99 @@
|
||||
// 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 cluster
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/providers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// showCmd represents the cluster show command
|
||||
var showCmd = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "Shows info about a local provisioned kubernetes cluster",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return cli.WithContext(context.Background(), show)
|
||||
},
|
||||
}
|
||||
|
||||
func show(ctx context.Context) error {
|
||||
provisioner, err := providers.Factory(ctx, provisioner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer provisioner.Close() //nolint: errcheck
|
||||
|
||||
cluster, err := provisioner.Reflect(ctx, clusterName, stateDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
fmt.Fprintf(w, "PROVISIONER\t%s\n", cluster.Provisioner())
|
||||
fmt.Fprintf(w, "NAME\t%s\n", cluster.Info().ClusterName)
|
||||
fmt.Fprintf(w, "NETWORK NAME\t%s\n", cluster.Info().Network.Name)
|
||||
|
||||
ones, _ := cluster.Info().Network.CIDR.Mask.Size()
|
||||
fmt.Fprintf(w, "NETWORK CIDR\t%s/%d\n", cluster.Info().Network.CIDR.IP, ones)
|
||||
fmt.Fprintf(w, "NETWORK GATEWAY\t%s\n", cluster.Info().Network.GatewayAddr)
|
||||
fmt.Fprintf(w, "NETWORK MTU\t%d\n", cluster.Info().Network.MTU)
|
||||
|
||||
if err = w.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stdout, "\nNODES:\n\n")
|
||||
|
||||
w = tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
|
||||
fmt.Fprintf(w, "NAME\tTYPE\tIP\tCPU\tRAM\tDISK\n")
|
||||
|
||||
nodes := cluster.Info().Nodes
|
||||
sort.Slice(nodes, func(i, j int) bool { return nodes[i].Name < nodes[j].Name })
|
||||
|
||||
for _, node := range nodes {
|
||||
cpus := "-"
|
||||
if node.NanoCPUs > 0 {
|
||||
cpus = fmt.Sprintf("%.2f", float64(node.NanoCPUs)/1000.0/1000.0/1000.0)
|
||||
}
|
||||
|
||||
mem := "-"
|
||||
if node.Memory > 0 {
|
||||
mem = humanize.Bytes(uint64(node.Memory))
|
||||
}
|
||||
|
||||
disk := "-"
|
||||
if node.DiskSize > 0 {
|
||||
disk = humanize.Bytes(uint64(node.DiskSize))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
node.Name,
|
||||
node.Type,
|
||||
node.PrivateIP,
|
||||
cpus,
|
||||
mem,
|
||||
disk,
|
||||
)
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
func init() {
|
||||
Cmd.AddCommand(showCmd)
|
||||
}
|
167
cmd/osctl/cmd/mgmt/config.go
Normal file
167
cmd/osctl/cmd/mgmt/config.go
Normal file
@ -0,0 +1,167 @@
|
||||
// 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 mgmt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/mgmt/helpers"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
var (
|
||||
additionalSANs []string
|
||||
configVersion string
|
||||
dnsDomain string
|
||||
kubernetesVersion string
|
||||
installDisk string
|
||||
installImage string
|
||||
outputDir string
|
||||
registryMirrors []string
|
||||
)
|
||||
|
||||
// genConfigCmd represents the gen config command.
|
||||
var genConfigCmd = &cobra.Command{
|
||||
Use: "config <cluster name> https://<load balancer IP or DNS name>",
|
||||
Short: "Generates a set of configuration files for Talos cluster",
|
||||
Long: ``,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// Validate url input to ensure it has https:// scheme before we attempt to gen
|
||||
u, err := url.Parse(args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse load balancer IP or DNS name: %w", err)
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
return fmt.Errorf("no scheme specified for load balancer IP or DNS name\ntry \"https://<load balancer IP or DNS name>\"")
|
||||
}
|
||||
|
||||
switch configVersion {
|
||||
case "v1alpha1":
|
||||
return genV1Alpha1Config(args)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
//nolint: gocyclo
|
||||
func genV1Alpha1Config(args []string) error {
|
||||
// If output dir isn't specified, set to the current working dir
|
||||
var err error
|
||||
if outputDir == "" {
|
||||
outputDir, err = os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get working dir: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create dir path, ignoring "already exists" messages
|
||||
if err = os.MkdirAll(outputDir, os.ModePerm); err != nil && !os.IsExist(err) {
|
||||
return fmt.Errorf("failed to create output dir: %w", err)
|
||||
}
|
||||
|
||||
var genOptions []generate.GenOption //nolint: prealloc
|
||||
|
||||
for _, registryMirror := range registryMirrors {
|
||||
components := strings.SplitN(registryMirror, "=", 2)
|
||||
if len(components) != 2 {
|
||||
return fmt.Errorf("invalid registry mirror spec: %q", registryMirror)
|
||||
}
|
||||
|
||||
genOptions = append(genOptions, generate.WithRegistryMirror(components[0], components[1]))
|
||||
}
|
||||
|
||||
configBundle, err := config.NewConfigBundle(
|
||||
config.WithInputOptions(
|
||||
&config.InputOptions{
|
||||
ClusterName: args[0],
|
||||
Endpoint: args[1],
|
||||
KubeVersion: kubernetesVersion,
|
||||
GenOptions: append(genOptions,
|
||||
generate.WithInstallDisk(installDisk),
|
||||
generate.WithInstallImage(installImage),
|
||||
generate.WithAdditionalSubjectAltNames(additionalSANs),
|
||||
generate.WithDNSDomain(dnsDomain),
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate config bundle: %w", err)
|
||||
}
|
||||
|
||||
for _, t := range []machine.Type{machine.TypeInit, machine.TypeControlPlane, machine.TypeWorker} {
|
||||
name := strings.ToLower(t.String()) + ".yaml"
|
||||
fullFilePath := filepath.Join(outputDir, name)
|
||||
|
||||
var configString string
|
||||
|
||||
switch t {
|
||||
case machine.TypeInit:
|
||||
configString, err = configBundle.Init().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case machine.TypeControlPlane:
|
||||
configString, err = configBundle.ControlPlane().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case machine.TypeWorker:
|
||||
configString, err = configBundle.Join().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(fullFilePath, []byte(configString), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("created %s\n", fullFilePath)
|
||||
}
|
||||
|
||||
// We set the default endpoint to localhost for configs generated, with expectation user will tweak later
|
||||
configBundle.TalosConfig().Contexts[args[0]].Endpoints = []string{"127.0.0.1"}
|
||||
|
||||
data, err := yaml.Marshal(configBundle.TalosConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config: %+v", err)
|
||||
}
|
||||
|
||||
fullFilePath := filepath.Join(outputDir, "talosconfig")
|
||||
|
||||
if err = ioutil.WriteFile(fullFilePath, data, 0644); err != nil {
|
||||
return fmt.Errorf("%w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("created %s\n", fullFilePath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
genCmd.AddCommand(genConfigCmd)
|
||||
genConfigCmd.Flags().StringVar(&installDisk, "install-disk", "/dev/sda", "the disk to install to")
|
||||
genConfigCmd.Flags().StringVar(&installImage, "install-image", helpers.DefaultImage(constants.DefaultInstallerImageRepository), "the image used to perform an installation") // nolint: lll
|
||||
genConfigCmd.Flags().StringSliceVar(&additionalSANs, "additional-sans", []string{}, "additional Subject-Alt-Names for the APIServer certificate")
|
||||
genConfigCmd.Flags().StringVar(&dnsDomain, "dns-domain", "cluster.local", "the dns domain to use for cluster")
|
||||
genConfigCmd.Flags().StringVar(&configVersion, "version", "v1alpha1", "the desired machine config version to generate")
|
||||
genConfigCmd.Flags().StringVar(&kubernetesVersion, "kubernetes-version", constants.DefaultKubernetesVersion, "desired kubernetes version to run")
|
||||
genConfigCmd.Flags().StringVarP(&outputDir, "output-dir", "o", "", "destination to output generated files")
|
||||
genConfigCmd.Flags().StringSliceVar(®istryMirrors, "registry-mirror", []string{}, "list of registry mirrors to use in format: <registry host>=<mirror URL>")
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package mgmt
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
@ -23,5 +23,5 @@ var firecrackerLaunchCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(firecrackerLaunchCmd)
|
||||
addCommand(firecrackerLaunchCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package mgmt
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
@ -17,10 +17,22 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/crypto/x509"
|
||||
)
|
||||
|
||||
var (
|
||||
ca string
|
||||
csr string
|
||||
caHours int
|
||||
crtHours int
|
||||
ip string
|
||||
key string
|
||||
name string
|
||||
organization string
|
||||
rsa bool
|
||||
)
|
||||
|
||||
// genCmd represents the gen command
|
||||
var genCmd = &cobra.Command{
|
||||
Use: "gen",
|
||||
@ -231,30 +243,30 @@ var keypairCmd = &cobra.Command{
|
||||
func init() {
|
||||
// Certificate Authorities
|
||||
caCmd.Flags().StringVar(&organization, "organization", "", "X.509 distinguished name for the Organization")
|
||||
helpers.Should(cobra.MarkFlagRequired(caCmd.Flags(), "organization"))
|
||||
cli.Should(cobra.MarkFlagRequired(caCmd.Flags(), "organization"))
|
||||
caCmd.Flags().IntVar(&caHours, "hours", 87600, "the hours from now on which the certificate validity period ends")
|
||||
caCmd.Flags().BoolVar(&rsa, "rsa", false, "generate in RSA format")
|
||||
// Keys
|
||||
keyCmd.Flags().StringVar(&name, "name", "", "the basename of the generated file")
|
||||
helpers.Should(cobra.MarkFlagRequired(keyCmd.Flags(), "name"))
|
||||
cli.Should(cobra.MarkFlagRequired(keyCmd.Flags(), "name"))
|
||||
// Certificates
|
||||
crtCmd.Flags().StringVar(&name, "name", "", "the basename of the generated file")
|
||||
helpers.Should(cobra.MarkFlagRequired(crtCmd.Flags(), "name"))
|
||||
cli.Should(cobra.MarkFlagRequired(crtCmd.Flags(), "name"))
|
||||
crtCmd.Flags().StringVar(&ca, "ca", "", "path to the PEM encoded CERTIFICATE")
|
||||
helpers.Should(cobra.MarkFlagRequired(crtCmd.Flags(), "ca"))
|
||||
cli.Should(cobra.MarkFlagRequired(crtCmd.Flags(), "ca"))
|
||||
crtCmd.Flags().StringVar(&csr, "csr", "", "path to the PEM encoded CERTIFICATE REQUEST")
|
||||
helpers.Should(cobra.MarkFlagRequired(crtCmd.Flags(), "csr"))
|
||||
cli.Should(cobra.MarkFlagRequired(crtCmd.Flags(), "csr"))
|
||||
crtCmd.Flags().IntVar(&crtHours, "hours", 24, "the hours from now on which the certificate validity period ends")
|
||||
// Keypairs
|
||||
keypairCmd.Flags().StringVar(&ip, "ip", "", "generate the certificate for this IP address")
|
||||
keypairCmd.Flags().StringVar(&organization, "organization", "", "X.509 distinguished name for the Organization")
|
||||
helpers.Should(cobra.MarkFlagRequired(keypairCmd.Flags(), "organization"))
|
||||
cli.Should(cobra.MarkFlagRequired(keypairCmd.Flags(), "organization"))
|
||||
// Certificate Signing Requests
|
||||
csrCmd.Flags().StringVar(&key, "key", "", "path to the PEM encoded EC or RSA PRIVATE KEY")
|
||||
helpers.Should(cobra.MarkFlagRequired(csrCmd.Flags(), "key"))
|
||||
cli.Should(cobra.MarkFlagRequired(csrCmd.Flags(), "key"))
|
||||
csrCmd.Flags().StringVar(&ip, "ip", "", "generate the certificate for this IP address")
|
||||
helpers.Should(cobra.MarkFlagRequired(csrCmd.Flags(), "ip"))
|
||||
cli.Should(cobra.MarkFlagRequired(csrCmd.Flags(), "ip"))
|
||||
|
||||
genCmd.AddCommand(caCmd, keypairCmd, keyCmd, csrCmd, crtCmd)
|
||||
rootCmd.AddCommand(genCmd)
|
||||
addCommand(genCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package mgmt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -22,7 +22,7 @@ var loadbalancerLaunchCmdFlags struct {
|
||||
// loadbalancerLaunchCmd represents the loadbalancer-launch command
|
||||
var loadbalancerLaunchCmd = &cobra.Command{
|
||||
Use: "loadbalancer-launch",
|
||||
Short: "Intneral command used by Firecracker provisioner",
|
||||
Short: "Internal command used by Firecracker provisioner",
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
Hidden: true,
|
||||
@ -55,5 +55,5 @@ func init() {
|
||||
loadbalancerLaunchCmd.Flags().StringVar(&loadbalancerLaunchCmdFlags.addr, "loadbalancer-addr", "localhost", "load balancer listen address (IP or host)")
|
||||
loadbalancerLaunchCmd.Flags().StringSliceVar(&loadbalancerLaunchCmdFlags.upstreams, "loadbalancer-upstreams", []string{}, "load balancer upstreams (nodes to proxy to)")
|
||||
loadbalancerLaunchCmd.Flags().BoolVar(&loadbalancerLaunchCmdFlags.apidOnlyInitNode, "apid-only-init-node", false, "use only apid init node for load balancing")
|
||||
rootCmd.AddCommand(loadbalancerLaunchCmd)
|
||||
addCommand(loadbalancerLaunchCmd)
|
||||
}
|
14
cmd/osctl/cmd/mgmt/root.go
Normal file
14
cmd/osctl/cmd/mgmt/root.go
Normal file
@ -0,0 +1,14 @@
|
||||
// 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 mgmt
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
// Commands is a list of commands published by the package
|
||||
var Commands []*cobra.Command
|
||||
|
||||
func addCommand(cmd *cobra.Command) {
|
||||
Commands = append(Commands, cmd)
|
||||
}
|
@ -2,15 +2,15 @@
|
||||
// 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 cmd
|
||||
package mgmt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
)
|
||||
|
||||
@ -48,6 +48,6 @@ var validateCmd = &cobra.Command{
|
||||
func init() {
|
||||
validateCmd.Flags().StringVarP(&validateConfigArg, "config", "c", "", "the path of the config file")
|
||||
validateCmd.Flags().StringVarP(&validateModeArg, "mode", "m", "", "the mode to validate the config for")
|
||||
helpers.Should(validateCmd.MarkFlagRequired("mode"))
|
||||
rootCmd.AddCommand(validateCmd)
|
||||
cli.Should(validateCmd.MarkFlagRequired("mode"))
|
||||
addCommand(validateCmd)
|
||||
}
|
@ -5,39 +5,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/cmd/mgmt"
|
||||
"github.com/talos-systems/talos/cmd/osctl/cmd/talos"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client/config"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/grpc/tls"
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
)
|
||||
|
||||
var (
|
||||
ca string
|
||||
crt string
|
||||
additionalSANs []string
|
||||
csr string
|
||||
caHours int
|
||||
crtHours int
|
||||
ip string
|
||||
key string
|
||||
kubernetes bool
|
||||
useCRI bool
|
||||
name string
|
||||
organization string
|
||||
rsa bool
|
||||
talosconfig string
|
||||
endpoints []string
|
||||
nodes []string
|
||||
cmdcontext string
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
@ -58,10 +34,10 @@ func Execute() error {
|
||||
return err
|
||||
}
|
||||
|
||||
rootCmd.PersistentFlags().StringVar(&talosconfig, "talosconfig", defaultTalosConfig, "The path to the Talos configuration file")
|
||||
rootCmd.PersistentFlags().StringVar(&cmdcontext, "context", "", "Context to be used in command")
|
||||
rootCmd.PersistentFlags().StringSliceVarP(&nodes, "nodes", "n", []string{}, "target the specified nodes")
|
||||
rootCmd.PersistentFlags().StringSliceVarP(&endpoints, "endpoints", "e", []string{}, "override default endpoints in Talos configuration")
|
||||
rootCmd.PersistentFlags().StringVar(&talos.Talosconfig, "talosconfig", defaultTalosConfig, "The path to the Talos configuration file")
|
||||
rootCmd.PersistentFlags().StringVar(&talos.Cmdcontext, "context", "", "Context to be used in command")
|
||||
rootCmd.PersistentFlags().StringSliceVarP(&talos.Nodes, "nodes", "n", []string{}, "target the specified nodes")
|
||||
rootCmd.PersistentFlags().StringSliceVarP(&talos.Endpoints, "endpoints", "e", []string{}, "override default endpoints in Talos configuration")
|
||||
|
||||
cmd, err := rootCmd.ExecuteC()
|
||||
if err != nil {
|
||||
@ -79,58 +55,8 @@ func Execute() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// WithClient wraps common code to initialize Talos client and provide cancellable context.
|
||||
func WithClient(action func(context.Context, *client.Client) error) error {
|
||||
return helpers.WithCLIContext(context.Background(), func(ctx context.Context) error {
|
||||
configContext, creds, err := client.NewClientContextAndCredentialsFromConfig(talosconfig, cmdcontext)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting client credentials: %w", err)
|
||||
func init() {
|
||||
for _, cmd := range append(talos.Commands, mgmt.Commands...) {
|
||||
rootCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
configEndpoints := configContext.Endpoints
|
||||
|
||||
if len(endpoints) > 0 {
|
||||
// override endpoints from command-line flags
|
||||
configEndpoints = endpoints
|
||||
}
|
||||
|
||||
targetNodes := configContext.Nodes
|
||||
|
||||
if len(nodes) > 0 {
|
||||
targetNodes = nodes
|
||||
}
|
||||
|
||||
// Update context with grpc metadata for proxy/relay requests
|
||||
ctx = client.WithNodes(ctx, targetNodes...)
|
||||
|
||||
tlsconfig, err := tls.New(
|
||||
tls.WithKeypair(creds.Crt),
|
||||
tls.WithClientAuthType(tls.Mutual),
|
||||
tls.WithCACertPEM(creds.CA),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := client.NewClient(tlsconfig, configEndpoints, constants.ApidPort)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error constructing client: %w", err)
|
||||
}
|
||||
// nolint: errcheck
|
||||
defer c.Close()
|
||||
|
||||
return action(ctx, c)
|
||||
})
|
||||
}
|
||||
|
||||
func defaultImage(image string) string {
|
||||
return fmt.Sprintf("%s:%s", image, getEnv("TAG", version.Tag))
|
||||
}
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
return value
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
||||
|
172
cmd/osctl/cmd/talos/config.go
Normal file
172
cmd/osctl/cmd/talos/config.go
Normal file
@ -0,0 +1,172 @@
|
||||
// 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 talos
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
clientconfig "github.com/talos-systems/talos/cmd/osctl/pkg/client/config"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
ca string
|
||||
crt string
|
||||
key string
|
||||
)
|
||||
|
||||
// configCmd represents the config command.
|
||||
var configCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Manage the client configuration",
|
||||
Long: ``,
|
||||
}
|
||||
|
||||
// configEndpointCmd represents the config endpoint command.
|
||||
var configEndpointCmd = &cobra.Command{
|
||||
Use: "endpoint <endpoint>...",
|
||||
Aliases: []string{"endpoints"},
|
||||
Short: "Set the endpoint(s) for the current context",
|
||||
Long: ``,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := clientconfig.Open(Talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
if c.Context == "" {
|
||||
return fmt.Errorf("no context is set")
|
||||
}
|
||||
|
||||
c.Contexts[c.Context].Endpoints = args
|
||||
if err := c.Save(Talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configNodeCmd represents the config node command.
|
||||
var configNodeCmd = &cobra.Command{
|
||||
Use: "node <endpoint>...",
|
||||
Aliases: []string{"nodes"},
|
||||
Short: "Set the node(s) for the current context",
|
||||
Long: ``,
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := clientconfig.Open(Talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
if c.Context == "" {
|
||||
return fmt.Errorf("no context is set")
|
||||
}
|
||||
|
||||
c.Contexts[c.Context].Nodes = args
|
||||
if err := c.Save(Talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configContextCmd represents the configc context command.
|
||||
var configContextCmd = &cobra.Command{
|
||||
Use: "context <context>",
|
||||
Short: "Set the current context",
|
||||
Long: ``,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
context := args[0]
|
||||
|
||||
c, err := clientconfig.Open(Talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
|
||||
c.Context = context
|
||||
|
||||
if err := c.Save(Talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configAddCmd represents the config add command.
|
||||
var configAddCmd = &cobra.Command{
|
||||
Use: "add <context>",
|
||||
Short: "Add a new context",
|
||||
Long: ``,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
context := args[0]
|
||||
c, err := clientconfig.Open(Talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading config: %w", err)
|
||||
}
|
||||
|
||||
caBytes, err := ioutil.ReadFile(ca)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading CA: %w", err)
|
||||
}
|
||||
|
||||
crtBytes, err := ioutil.ReadFile(crt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading certificate: %w", err)
|
||||
}
|
||||
|
||||
keyBytes, err := ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading key: %w", err)
|
||||
}
|
||||
|
||||
newContext := &clientconfig.Context{
|
||||
CA: base64.StdEncoding.EncodeToString(caBytes),
|
||||
Crt: base64.StdEncoding.EncodeToString(crtBytes),
|
||||
Key: base64.StdEncoding.EncodeToString(keyBytes),
|
||||
}
|
||||
|
||||
if c.Contexts == nil {
|
||||
c.Contexts = map[string]*clientconfig.Context{}
|
||||
}
|
||||
|
||||
c.Contexts[context] = newContext
|
||||
if err := c.Save(Talosconfig); err != nil {
|
||||
return fmt.Errorf("error writing config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// configGenerateCmd represents the config generate stub command.
|
||||
var configGenerateCmd = &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate Talos config",
|
||||
Long: ``,
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("'osctl config generate' was renamed to 'osctl gen config'")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
configCmd.AddCommand(configContextCmd, configEndpointCmd, configNodeCmd, configAddCmd, configGenerateCmd)
|
||||
configAddCmd.Flags().StringVar(&ca, "ca", "", "the path to the CA certificate")
|
||||
configAddCmd.Flags().StringVar(&crt, "crt", "", "the path to the certificate")
|
||||
configAddCmd.Flags().StringVar(&key, "key", "", "the path to the key")
|
||||
cli.Should(configAddCmd.MarkFlagRequired("ca"))
|
||||
cli.Should(configAddCmd.MarkFlagRequired("crt"))
|
||||
cli.Should(configAddCmd.MarkFlagRequired("key"))
|
||||
addCommand(configCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -20,7 +20,8 @@ import (
|
||||
"github.com/talos-systems/talos/api/common"
|
||||
osapi "github.com/talos-systems/talos/api/os"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
@ -52,7 +53,7 @@ var containersCmd = &cobra.Command{
|
||||
return fmt.Errorf("error getting container list: %s", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
return containerRender(&remotePeer, resp)
|
||||
@ -96,5 +97,5 @@ func containerRender(remotePeer *peer.Peer, resp *osapi.ContainersResponse) erro
|
||||
func init() {
|
||||
containersCmd.Flags().BoolVarP(&kubernetes, "kubernetes", "k", false, "use the k8s.io containerd namespace")
|
||||
containersCmd.Flags().BoolVarP(&useCRI, "use-cri", "c", false, "use the CRI driver")
|
||||
rootCmd.AddCommand(containersCmd)
|
||||
addCommand(containersCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -15,7 +15,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
)
|
||||
|
||||
// cpCmd represents the cp command
|
||||
@ -83,5 +83,5 @@ captures ownership and permission bits.`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(cpCmd)
|
||||
addCommand(cpCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -15,7 +15,7 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
)
|
||||
|
||||
var dmesgTail bool
|
||||
@ -65,7 +65,7 @@ var dmesgCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(dmesgCmd)
|
||||
addCommand(dmesgCmd)
|
||||
dmesgCmd.Flags().BoolVarP(&follow, "follow", "f", false, "specify if the kernel log should be streamed")
|
||||
dmesgCmd.Flags().BoolVarP(&dmesgTail, "tail", "", false, "specify if only new messages should be sent (makes sense only when combined with --follow)")
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -16,7 +16,8 @@ import (
|
||||
|
||||
networkapi "github.com/talos-systems/talos/api/network"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// interfacesCmd represents the net interfaces command
|
||||
@ -35,7 +36,7 @@ var interfacesCmd = &cobra.Command{
|
||||
return fmt.Errorf("error getting interfaces: %s", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
return intersRender(&remotePeer, resp)
|
||||
@ -67,5 +68,5 @@ func intersRender(remotePeer *peer.Peer, resp *networkapi.InterfacesResponse) er
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(interfacesCmd)
|
||||
addCommand(interfacesCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -14,7 +14,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
)
|
||||
|
||||
var force bool
|
||||
@ -74,5 +74,5 @@ Kubeconfig will be written to PWD/kubeconfig or [local-path]/kubeconfig if speci
|
||||
|
||||
func init() {
|
||||
kubeconfigCmd.Flags().BoolVarP(&force, "force", "f", false, "Force overwrite of kubeconfig if already present")
|
||||
rootCmd.AddCommand(kubeconfigCmd)
|
||||
addCommand(kubeconfigCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -19,7 +19,7 @@ import (
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
)
|
||||
|
||||
const sixMonths = 6 * time.Hour * 24 * 30
|
||||
@ -171,5 +171,5 @@ func init() {
|
||||
lsCmd.Flags().BoolVarP(&recurse, "recurse", "r", false, "recurse into subdirectories")
|
||||
lsCmd.Flags().BoolVarP(&humanizeFlag, "humanize", "H", false, "humanize size and time in the output")
|
||||
lsCmd.Flags().Int32VarP(&recursionDepth, "depth", "d", 0, "maximum recursion depth")
|
||||
rootCmd.AddCommand(lsCmd)
|
||||
addCommand(lsCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -20,7 +20,8 @@ import (
|
||||
"github.com/talos-systems/talos/api/common"
|
||||
"github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
@ -177,7 +178,7 @@ func (slicer *lineSlicer) run(stream machine.MachineService_LogsClient) {
|
||||
}
|
||||
|
||||
_, err = slicer.getPipe(node).Write(data.Bytes)
|
||||
helpers.Should(err)
|
||||
cli.Should(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,5 +187,5 @@ func init() {
|
||||
logsCmd.Flags().BoolVarP(&useCRI, "use-cri", "c", false, "use the CRI driver")
|
||||
logsCmd.Flags().BoolVarP(&follow, "follow", "f", false, "specify if the logs should be streamed")
|
||||
logsCmd.Flags().Int32VarP(&tailLines, "tail", "", -1, "lines of log file to display (default is to show from the beginning)")
|
||||
rootCmd.AddCommand(logsCmd)
|
||||
addCommand(logsCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -16,7 +16,8 @@ import (
|
||||
|
||||
osapi "github.com/talos-systems/talos/api/os"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
var verbose bool
|
||||
@ -38,7 +39,7 @@ var memoryCmd = &cobra.Command{
|
||||
return fmt.Errorf("error getting memory stats: %s", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
if verbose {
|
||||
@ -146,5 +147,5 @@ func verboseRender(remotePeer *peer.Peer, resp *osapi.MemoryResponse) error {
|
||||
|
||||
func init() {
|
||||
memoryCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "display extended memory statistics")
|
||||
rootCmd.AddCommand(memoryCmd)
|
||||
addCommand(memoryCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -17,7 +17,8 @@ import (
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// mountsCmd represents the mounts command.
|
||||
@ -37,7 +38,7 @@ var mountsCmd = &cobra.Command{
|
||||
return fmt.Errorf("error getting interfaces: %s", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
return mountsRender(&remotePeer, resp)
|
||||
@ -74,5 +75,5 @@ func mountsRender(remotePeer *peer.Peer, resp *machineapi.MountsResponse) error
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(mountsCmd)
|
||||
addCommand(mountsCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -23,7 +23,8 @@ import (
|
||||
|
||||
osapi "github.com/talos-systems/talos/api/os"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -69,7 +70,7 @@ var processesCmd = &cobra.Command{
|
||||
func init() {
|
||||
processesCmd.Flags().StringVarP(&sortMethod, "sort", "s", "rss", "Column to sort output by. [rss|cpu]")
|
||||
processesCmd.Flags().BoolVarP(&watchProcesses, "watch", "w", false, "Stream running processes")
|
||||
rootCmd.AddCommand(processesCmd)
|
||||
addCommand(processesCmd)
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
@ -87,12 +88,12 @@ func processesUI(ctx context.Context, c *client.Client) {
|
||||
// Since we're getting this data on each call
|
||||
// we'll be able to handle terminal window resizing
|
||||
w, h, err := terminal.GetSize(0)
|
||||
helpers.Should(err)
|
||||
cli.Should(err)
|
||||
// x, y, w, h
|
||||
l.SetRect(0, 0, w, h)
|
||||
|
||||
processOutput, err = processesOutput(ctx, c)
|
||||
helpers.Should(err)
|
||||
cli.Should(err)
|
||||
|
||||
// Dont refresh if we dont have any output
|
||||
if processOutput == "" {
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -14,7 +14,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
)
|
||||
|
||||
// readCmd represents the read command
|
||||
@ -59,5 +59,5 @@ var readCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(readCmd)
|
||||
addCommand(readCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -31,5 +31,5 @@ var rebootCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(rebootCmd)
|
||||
addCommand(rebootCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -38,5 +38,5 @@ var resetCmd = &cobra.Command{
|
||||
func init() {
|
||||
resetCmd.Flags().BoolVar(&graceful, "graceful", true, "if true, attempt to cordon/drain node and leave etcd (if applicable)")
|
||||
resetCmd.Flags().BoolVar(&reboot, "reboot", false, "if true, reboot the node after resetting instead of shutting down")
|
||||
rootCmd.AddCommand(resetCmd)
|
||||
addCommand(resetCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -46,5 +46,5 @@ var restartCmd = &cobra.Command{
|
||||
func init() {
|
||||
restartCmd.Flags().BoolVarP(&kubernetes, "kubernetes", "k", false, "use the k8s.io containerd namespace")
|
||||
restartCmd.Flags().BoolVarP(&useCRI, "use-cri", "c", false, "use the CRI driver")
|
||||
rootCmd.AddCommand(restartCmd)
|
||||
addCommand(restartCmd)
|
||||
}
|
81
cmd/osctl/cmd/talos/root.go
Normal file
81
cmd/osctl/cmd/talos/root.go
Normal file
@ -0,0 +1,81 @@
|
||||
// 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 talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/grpc/tls"
|
||||
)
|
||||
|
||||
var (
|
||||
kubernetes bool
|
||||
useCRI bool
|
||||
)
|
||||
|
||||
// Common options set on root command
|
||||
var (
|
||||
Talosconfig string
|
||||
Endpoints []string
|
||||
Nodes []string
|
||||
Cmdcontext string
|
||||
)
|
||||
|
||||
// WithClient wraps common code to initialize Talos client and provide cancellable context.
|
||||
func WithClient(action func(context.Context, *client.Client) error) error {
|
||||
return cli.WithContext(context.Background(), func(ctx context.Context) error {
|
||||
configContext, creds, err := client.NewClientContextAndCredentialsFromConfig(Talosconfig, Cmdcontext)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting client credentials: %w", err)
|
||||
}
|
||||
|
||||
configEndpoints := configContext.Endpoints
|
||||
|
||||
if len(Endpoints) > 0 {
|
||||
// override endpoints from command-line flags
|
||||
configEndpoints = Endpoints
|
||||
}
|
||||
|
||||
targetNodes := configContext.Nodes
|
||||
|
||||
if len(Nodes) > 0 {
|
||||
targetNodes = Nodes
|
||||
}
|
||||
|
||||
// Update context with grpc metadata for proxy/relay requests
|
||||
ctx = client.WithNodes(ctx, targetNodes...)
|
||||
|
||||
tlsconfig, err := tls.New(
|
||||
tls.WithKeypair(creds.Crt),
|
||||
tls.WithClientAuthType(tls.Mutual),
|
||||
tls.WithCACertPEM(creds.CA),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := client.NewClient(tlsconfig, configEndpoints, constants.ApidPort)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error constructing client: %w", err)
|
||||
}
|
||||
// nolint: errcheck
|
||||
defer c.Close()
|
||||
|
||||
return action(ctx, c)
|
||||
})
|
||||
}
|
||||
|
||||
// Commands is a list of commands published by the package
|
||||
var Commands []*cobra.Command
|
||||
|
||||
func addCommand(cmd *cobra.Command) {
|
||||
Commands = append(Commands, cmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -16,7 +16,8 @@ import (
|
||||
|
||||
networkapi "github.com/talos-systems/talos/api/network"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// routesCmd represents the net routes command
|
||||
@ -33,7 +34,7 @@ var routesCmd = &cobra.Command{
|
||||
if resp == nil {
|
||||
return fmt.Errorf("error getting routes: %w", err)
|
||||
}
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
return routesRender(&remotePeer, resp)
|
||||
@ -63,5 +64,5 @@ func routesRender(remotePeer *peer.Peer, resp *networkapi.RoutesResponse) error
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(routesCmd)
|
||||
addCommand(routesCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -18,7 +18,8 @@ import (
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// serviceCmd represents the service command
|
||||
@ -72,7 +73,7 @@ func serviceList(ctx context.Context, c *client.Client) error {
|
||||
return fmt.Errorf("error listing services: %w", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
@ -106,7 +107,7 @@ func serviceInfo(ctx context.Context, c *client.Client, id string) error {
|
||||
return fmt.Errorf("error listing services: %w", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
@ -159,7 +160,7 @@ func serviceStart(ctx context.Context, c *client.Client, id string) error {
|
||||
return fmt.Errorf("error starting service: %w", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
defaultNode := helpers.AddrFromPeer(&remotePeer)
|
||||
@ -189,7 +190,7 @@ func serviceStop(ctx context.Context, c *client.Client, id string) error {
|
||||
return fmt.Errorf("error starting service: %w", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
defaultNode := helpers.AddrFromPeer(&remotePeer)
|
||||
@ -219,7 +220,7 @@ func serviceRestart(ctx context.Context, c *client.Client, id string) error {
|
||||
return fmt.Errorf("error starting service: %w", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
defaultNode := helpers.AddrFromPeer(&remotePeer)
|
||||
@ -276,5 +277,5 @@ func (svc serviceInfoWrapper) HealthStatus() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serviceCmd)
|
||||
addCommand(serviceCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -31,5 +31,5 @@ var shutdownCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(shutdownCmd)
|
||||
addCommand(shutdownCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -20,7 +20,8 @@ import (
|
||||
"github.com/talos-systems/talos/api/common"
|
||||
osapi "github.com/talos-systems/talos/api/os"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
@ -51,7 +52,7 @@ var statsCmd = &cobra.Command{
|
||||
return fmt.Errorf("error getting stats: %s", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
return statsRender(&remotePeer, resp)
|
||||
@ -96,5 +97,5 @@ func statsRender(remotePeer *peer.Peer, resp *osapi.StatsResponse) error {
|
||||
func init() {
|
||||
statsCmd.Flags().BoolVarP(&kubernetes, "kubernetes", "k", false, "use the k8s.io containerd namespace")
|
||||
statsCmd.Flags().BoolVarP(&useCRI, "use-cri", "c", false, "use the CRI driver")
|
||||
rootCmd.AddCommand(statsCmd)
|
||||
addCommand(statsCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -18,7 +18,8 @@ import (
|
||||
|
||||
timeapi "github.com/talos-systems/talos/api/time"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
// timeCmd represents the time command
|
||||
@ -50,7 +51,7 @@ var timeCmd = &cobra.Command{
|
||||
return fmt.Errorf("error fetching time: %w", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
@ -85,5 +86,5 @@ var timeCmd = &cobra.Command{
|
||||
|
||||
func init() {
|
||||
timeCmd.Flags().StringP("check", "c", "pool.ntp.org", "checks server time against specified ntp server")
|
||||
rootCmd.AddCommand(timeCmd)
|
||||
addCommand(timeCmd)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -16,7 +16,8 @@ import (
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
)
|
||||
|
||||
var upgradeImage string
|
||||
@ -34,7 +35,7 @@ var upgradeCmd = &cobra.Command{
|
||||
|
||||
func init() {
|
||||
upgradeCmd.Flags().StringVarP(&upgradeImage, "image", "i", "", "the container image to use for performing the install")
|
||||
rootCmd.AddCommand(upgradeCmd)
|
||||
addCommand(upgradeCmd)
|
||||
}
|
||||
|
||||
func upgrade() error {
|
||||
@ -49,7 +50,7 @@ func upgrade() error {
|
||||
return fmt.Errorf("error performing upgrade: %s", err)
|
||||
}
|
||||
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
@ -2,7 +2,7 @@
|
||||
// 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 cmd
|
||||
package talos
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -13,7 +13,8 @@ import (
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/talos/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
)
|
||||
|
||||
@ -50,7 +51,7 @@ var versionCmd = &cobra.Command{
|
||||
if resp == nil {
|
||||
return fmt.Errorf("error getting version: %s", err)
|
||||
}
|
||||
helpers.Warning("%s", err)
|
||||
cli.Warning("%s", err)
|
||||
}
|
||||
|
||||
defaultNode := helpers.AddrFromPeer(&remotePeer)
|
||||
@ -76,5 +77,5 @@ func init() {
|
||||
versionCmd.Flags().BoolVar(&shortVersion, "short", false, "Print the short version")
|
||||
versionCmd.Flags().BoolVar(&clientOnly, "client", false, "Print client version only")
|
||||
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
addCommand(versionCmd)
|
||||
}
|
@ -8,12 +8,12 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/osctl/cmd"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/startup"
|
||||
)
|
||||
|
||||
func main() {
|
||||
helpers.Should(startup.RandSeed())
|
||||
cli.Should(startup.RandSeed())
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
|
25
cmd/osctl/pkg/mgmt/helpers/image.go
Normal file
25
cmd/osctl/pkg/mgmt/helpers/image.go
Normal file
@ -0,0 +1,25 @@
|
||||
// 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 helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
)
|
||||
|
||||
// DefaultImage appends default image version.
|
||||
func DefaultImage(image string) string {
|
||||
return fmt.Sprintf("%s:%s", image, getEnv("TAG", version.Tag))
|
||||
}
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
return value
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
14
cmd/osctl/pkg/talos/helpers/helpers_test.go
Normal file
14
cmd/osctl/pkg/talos/helpers/helpers_test.go
Normal file
@ -0,0 +1,14 @@
|
||||
// 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 helpers_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -28,6 +28,5 @@ Manage the client configuration
|
||||
* [osctl config add](osctl_config_add.md) - Add a new context
|
||||
* [osctl config context](osctl_config_context.md) - Set the current context
|
||||
* [osctl config endpoint](osctl_config_endpoint.md) - Set the endpoint(s) for the current context
|
||||
* [osctl config generate](osctl_config_generate.md) - Generate a set of configuration files
|
||||
* [osctl config node](osctl_config_node.md) - Set the node(s) for the current context
|
||||
|
||||
|
@ -26,6 +26,7 @@ Generate CAs, certificates, and private keys
|
||||
|
||||
* [osctl](osctl.md) - A CLI for out-of-band management of Kubernetes nodes created by Talos
|
||||
* [osctl gen ca](osctl_gen_ca.md) - Generates a self-signed X.509 certificate authority
|
||||
* [osctl gen config](osctl_gen_config.md) - Generates a set of configuration files for Talos cluster
|
||||
* [osctl gen crt](osctl_gen_crt.md) - Generates an X.509 Ed25519 certificate
|
||||
* [osctl gen csr](osctl_gen_csr.md) - Generates a CSR using an Ed25519 private key
|
||||
* [osctl gen key](osctl_gen_key.md) - Generates an Ed25519 private key
|
||||
|
@ -1,14 +1,14 @@
|
||||
<!-- markdownlint-disable -->
|
||||
## osctl config generate
|
||||
## osctl gen config
|
||||
|
||||
Generate a set of configuration files
|
||||
Generates a set of configuration files for Talos cluster
|
||||
|
||||
### Synopsis
|
||||
|
||||
Generate a set of configuration files
|
||||
Generates a set of configuration files for Talos cluster
|
||||
|
||||
```
|
||||
osctl config generate <cluster name> https://<load balancer IP or DNS name> [flags]
|
||||
osctl gen config <cluster name> https://<load balancer IP or DNS name> [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
@ -16,7 +16,7 @@ osctl config generate <cluster name> https://<load balancer IP or DNS name> [fla
|
||||
```
|
||||
--additional-sans strings additional Subject-Alt-Names for the APIServer certificate
|
||||
--dns-domain string the dns domain to use for cluster (default "cluster.local")
|
||||
-h, --help help for generate
|
||||
-h, --help help for config
|
||||
--install-disk string the disk to install to (default "/dev/sda")
|
||||
--install-image string the image used to perform an installation (default "docker.io/autonomy/installer:latest")
|
||||
--kubernetes-version string desired kubernetes version to run (default "1.17.1")
|
||||
@ -36,5 +36,5 @@ osctl config generate <cluster name> https://<load balancer IP or DNS name> [fla
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [osctl config](osctl_config.md) - Manage the client configuration
|
||||
* [osctl gen](osctl_gen.md) - Generate CAs, certificates, and private keys
|
||||
|
@ -44,7 +44,7 @@ func (suite *ValidateSuite) TearDownTest() {
|
||||
|
||||
// TestValidate generates config and validates it for all the modes.
|
||||
func (suite *ValidateSuite) TestValidate() {
|
||||
suite.RunOsctl([]string{"config", "generate", "foobar", "https://10.0.0.1"})
|
||||
suite.RunOsctl([]string{"gen", "config", "foobar", "https://10.0.0.1"})
|
||||
|
||||
for _, configFile := range []string{"init.yaml", "controlplane.yaml", "join.yaml"} {
|
||||
for _, mode := range []string{"Cloud", "Container", "Interactive", "Metal"} {
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
talosclient "github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/mgmt/helpers"
|
||||
"github.com/talos-systems/talos/internal/integration/base"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/access"
|
||||
|
6
pkg/cli/cli.go
Normal file
6
pkg/cli/cli.go
Normal file
@ -0,0 +1,6 @@
|
||||
// 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 cli provides utilities for CLI tools.
|
||||
package cli
|
@ -2,7 +2,7 @@
|
||||
// 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 helpers
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -12,8 +12,8 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// WithCLIContext wraps function call to provide a context cancellable with ^C.
|
||||
func WithCLIContext(ctx context.Context, f func(context.Context) error) error {
|
||||
// WithContext wraps function call to provide a context cancellable with ^C.
|
||||
func WithContext(ctx context.Context, f func(context.Context) error) error {
|
||||
wrappedCtx, wrappedCtxCancel := context.WithCancel(ctx)
|
||||
defer wrappedCtxCancel()
|
||||
|
@ -2,7 +2,7 @@
|
||||
// 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 helpers
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -2,7 +2,7 @@
|
||||
// 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 helpers
|
||||
package cli
|
||||
|
||||
// Should panics if err != nil
|
||||
//
|
Loading…
x
Reference in New Issue
Block a user