Skip to content

Commit

Permalink
Optimize: move experimental cmd to alpha stage (#1577)
Browse files Browse the repository at this point in the history
* optimize:move cmd to alpha

* move cmd to alpha

* update reviews

* update reviews
  • Loading branch information
kakaZhou719 authored Jul 14, 2022
1 parent a9919aa commit 08df4e0
Show file tree
Hide file tree
Showing 20 changed files with 614 additions and 548 deletions.
41 changes: 41 additions & 0 deletions cmd/sealer/cmd/alpha/alpha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright © 2021 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package alpha

import (
"github.com/spf13/cobra"
)

var longAlphaCmdDescription = `Alpha command of sealer is used to provide functionality incubation from immature to mature. Each function will experience a growing procedure. Alpha command policy calls on end users to experience alpha functionality as early as possible, and actively feedback the experience results to sealer community, and finally cooperate to promote function from incubation to graduation.
Please file an issue at https://github.com/sealerio/sealer/issues when you have any feedback on alpha commands.`

// NewCmdAlpha returns "sealer alpha" command.
func NewCmdAlpha() *cobra.Command {
cmd := &cobra.Command{
Use: "alpha",
Short: "sealer experimental sub-commands",
Long: longAlphaCmdDescription,
}

cmd.AddCommand(NewPruneCmd())
cmd.AddCommand(NewDebugCmd())
cmd.AddCommand(NewExecCmd())
cmd.AddCommand(NewMergeCmd())
cmd.AddCommand(NewUpgradeCmd())
cmd.AddCommand(NewGenCmd())
cmd.AddCommand(NewCertCmd())
return cmd
}
77 changes: 77 additions & 0 deletions cmd/sealer/cmd/alpha/cert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright © 2021 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package alpha

import (
"fmt"

"github.com/spf13/cobra"

"github.com/sealerio/sealer/common"
"github.com/sealerio/sealer/pkg/clusterfile"
"github.com/sealerio/sealer/pkg/runtime"
)

var altNames []string

var longCertCmdDescription = `This command will add the new domain or IP address in cert to update cluster API server.
sealer has some default domain and IP in the cert process builtin: localhost,outbound IP address and some DNS domain which is strongly related to the apiserver CertSANs configured by kubeadm.yml.
You need to restart your API server manually after using sealer alpha cert. Then, you can using cmd "openssl x509 -noout -text -in apiserver.crt" to check the cert details.
`

var exampleForCertCmd = `
The following command will generate keys and CSRs for all control-plane certificates and kubeconfig files:
sealer alpha cert --alt-names 39.105.169.253,sealer.cool
`

// NewCertCmd returns the sealer cert Cobra command
func NewCertCmd() *cobra.Command {
certCmd := &cobra.Command{
Use: "cert",
Short: "Update Kubernetes API server's cert",
Args: cobra.NoArgs,
Long: longCertCmdDescription,
Example: exampleForCertCmd,
RunE: func(cmd *cobra.Command, args []string) error {
if len(altNames) == 0 {
return fmt.Errorf("IP address or DNS domain needed for cert Subject Alternative Names")
}

cluster, err := clusterfile.GetDefaultCluster()
if err != nil {
return fmt.Errorf("failed to get default cluster: %v", err)
}

clusterFile, err := clusterfile.NewClusterFile(cluster.GetAnnotationsByKey(common.ClusterfileName))
if err != nil {
return err
}

r, err := runtime.NewDefaultRuntime(cluster, clusterFile.GetKubeadmConfig())
if err != nil {
return fmt.Errorf("failed to get default runtime: %v", err)
}

return r.UpdateCert(altNames)
},
}

certCmd.Flags().StringSliceVar(&altNames, "alt-names", []string{}, "add DNS domain or IP in certs, if it is already in the cert subject alternative names list, nothing will be changed")

return certCmd
}
158 changes: 158 additions & 0 deletions cmd/sealer/cmd/alpha/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright © 2021 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package alpha

import (
"fmt"

"github.com/sealerio/sealer/common"
"github.com/spf13/cobra"

"github.com/sealerio/sealer/pkg/debug"
)

// NewDebugCmd returns the sealer debug Cobra command
func NewDebugCmd() *cobra.Command {
var debugOptions = debug.NewDebugOptions()

var debugCommand = &cobra.Command{
Use: "debug",
Short: "Create debugging sessions for pods and nodes",
// TODO: add long description.
Long: "",
}

debugCommand.AddCommand(newDebugCleanCMD())
debugCommand.AddCommand(newDebugShowImageCMD())
debugCommand.AddCommand(newDebugPodCommand(debugOptions))
debugCommand.AddCommand(newDebugNodeCommand(debugOptions))

debugCommand.PersistentFlags().StringVar(&debugOptions.Image, "image", debugOptions.Image, "Container image to use for debug container.")
debugCommand.PersistentFlags().StringVar(&debugOptions.DebugContainerName, "name", debugOptions.DebugContainerName, "Container name to use for debug container.")
debugCommand.PersistentFlags().StringVar(&debugOptions.PullPolicy, "image-pull-policy", "IfNotPresent", "Container image pull policy, default policy is IfNotPresent.")
debugCommand.PersistentFlags().StringSliceVar(&debugOptions.CheckList, "check-list", debugOptions.CheckList, "Check items, such as network, volume.")
debugCommand.PersistentFlags().StringVarP(&debugOptions.Namespace, "namespace", "n", "default", "Namespace of Pod.")
debugCommand.PersistentFlags().BoolVarP(&debugOptions.Interactive, "stdin", "i", debugOptions.Interactive, "Keep stdin open on the container, even if nothing is attached.")
debugCommand.PersistentFlags().BoolVarP(&debugOptions.TTY, "tty", "t", debugOptions.TTY, "Allocate a TTY for the debugging container.")
debugCommand.PersistentFlags().StringToStringP("env", "e", nil, "Environment variables to set in the container.")

return debugCommand
}

func newDebugCleanCMD() *cobra.Command {
cleanCmd := &cobra.Command{
Use: "clean",
Short: "Clean the debug container od pod",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cleaner := debug.NewDebugCleaner()
cleaner.AdminKubeConfigPath = common.KubeAdminConf

if err := cleaner.CompleteAndVerifyOptions(args); err != nil {
return err
}
if err := cleaner.Run(); err != nil {
return err
}

return nil
},
}

return cleanCmd
}

func newDebugShowImageCMD() *cobra.Command {
showCmd := &cobra.Command{
Use: "show-images",
Short: "List default images",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
manager := debug.NewDebugImagesManager()
manager.RegistryURL = debug.DefaultSealerRegistryURL

if err := manager.ShowDefaultImages(); err != nil {
return err
}
return nil
},
}

return showCmd
}

func newDebugPodCommand(options *debug.DebuggerOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "pod",
Short: "Debug pod or container",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
debugger := debug.NewDebugger(options)
debugger.AdminKubeConfigPath = common.KubeAdminConf
debugger.Type = debug.TypeDebugPod
debugger.Motd = debug.SealerDebugMotd

imager := debug.NewDebugImagesManager()

if err := debugger.CompleteAndVerifyOptions(cmd, args, imager); err != nil {
return err
}
str, err := debugger.Run()
if err != nil {
return err
}
if len(str) != 0 {
fmt.Println("The debug ID:", str)
}

return nil
},
}

cmd.Flags().StringVarP(&options.TargetContainer, "container", "c", "", "The container to be debugged.")

return cmd
}

func newDebugNodeCommand(options *debug.DebuggerOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "node",
Short: "Debug node",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
debugger := debug.NewDebugger(options)
debugger.AdminKubeConfigPath = common.KubeAdminConf
debugger.Type = debug.TypeDebugNode
debugger.Motd = debug.SealerDebugMotd

imager := debug.NewDebugImagesManager()

if err := debugger.CompleteAndVerifyOptions(cmd, args, imager); err != nil {
return err
}
str, err := debugger.Run()
if err != nil {
return err
}
if len(str) != 0 {
fmt.Println("The debug ID:", str)
}

return nil
},
}

return cmd
}
102 changes: 102 additions & 0 deletions cmd/sealer/cmd/alpha/exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright © 2021 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package alpha

import (
"fmt"
"net"

"github.com/sealerio/sealer/common"
"github.com/sealerio/sealer/pkg/clusterfile"
"github.com/sealerio/sealer/pkg/exec"
v2 "github.com/sealerio/sealer/types/api/v2"

"github.com/spf13/cobra"
)

var (
clusterName string
roles []string
)

var longExecCmdDescription = `Using sealer builtin ssh client to run shell command on the node filtered by cluster and cluster role. it is convenient for cluster administrator to do quick investigate`

var exampleForExecCmd = `
Exec the default cluster node:
sealer alpha exec "cat /etc/hosts"
specify the cluster name:
sealer alpha exec -c my-cluster "cat /etc/hosts"
using role label to filter node and run exec cmd:
sealer alpha exec -c my-cluster -r master,slave,node1 "cat /etc/hosts"
`

// NewExecCmd implement the sealer exec command
func NewExecCmd() *cobra.Command {
execCmd := &cobra.Command{
Use: "exec",
Short: "Exec a shell command or script on a specified node",
Long: longExecCmdDescription,
Example: exampleForExecCmd,
Args: cobra.ExactArgs(1),
RunE: execActionFunc,
}

execCmd.Flags().StringVarP(&clusterName, "cluster-name", "c", "", "specify the name of cluster")
execCmd.Flags().StringSliceVarP(&roles, "roles", "r", []string{}, "set role label to filter node")

return execCmd
}

func execActionFunc(cmd *cobra.Command, args []string) error {
var ipList []net.IP

cluster, err := GetCurrentClusterByName(clusterName)
if err != nil {
return err
}

if len(roles) == 0 {
ipList = append(cluster.GetMasterIPList(), cluster.GetNodeIPList()...)
} else {
for _, role := range roles {
ipList = append(ipList, cluster.GetIPSByRole(role)...)
}
if len(ipList) == 0 {
return fmt.Errorf("failed to get target ipList: no IP gotten by role(%s)", roles)
}
}

execCmd := exec.NewExecCmd(cluster, ipList)
return execCmd.RunCmd(args[0])
}

func GetCurrentClusterByName(name string) (*v2.Cluster, error) {
var err error
if name == "" {
name, err = clusterfile.GetDefaultClusterName()
if err != nil {
return nil, fmt.Errorf("failed to get default cluster name from home dir: %v", err)
}
}

cluster, err := clusterfile.GetClusterFromFile(common.GetClusterWorkClusterfile(name))
if err != nil {
return nil, err
}

return cluster, nil
}
Loading

0 comments on commit 08df4e0

Please sign in to comment.