diff --git a/cmd/sealos/cmd/restore.go b/cmd/sealos/cmd/restore.go new file mode 100644 index 000000000000..c7ad2d409649 --- /dev/null +++ b/cmd/sealos/cmd/restore.go @@ -0,0 +1,58 @@ +// Copyright © 2022 cuisongliu@qq.com. +// +// 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 cmd + +import ( + "errors" + + "github.com/spf13/cobra" + + "github.com/labring/sealos/pkg/apply" + "github.com/labring/sealos/pkg/utils/logger" +) + +const exampleRestore = ` +restore image : + sealos restore image kubernetes:v1.27.8 +` + +// addCmd represents the add command +func newRestoreCmd() *cobra.Command { + restoreArgs := &apply.RunArgs{ + Cluster: &apply.Cluster{}, + SSH: &apply.SSH{}, + } + var restoreCmd = &cobra.Command{ + Use: "restore", + Short: "restore cluster", + Args: cobra.NoArgs, + Example: exampleRestore, + RunE: func(cmd *cobra.Command, args []string) error { + return apply.Restorer(cmd, restoreArgs, args[0]) + }, + PreRunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errors.New("image can't be empty") + } + return nil + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + logger.Info(getContact()) + }, + } + setRequireBuildahAnnotation(restoreCmd) + restoreArgs.RegisterFlags(restoreCmd.Flags()) + return restoreCmd +} diff --git a/cmd/sealos/cmd/root.go b/cmd/sealos/cmd/root.go index 2b84de2362f4..191eb0ffd1d3 100644 --- a/cmd/sealos/cmd/root.go +++ b/cmd/sealos/cmd/root.go @@ -68,6 +68,7 @@ func init() { newRunCmd(), newResetCmd(), newStatusCmd(), + newRestoreCmd(), }, }, { diff --git a/pkg/apply/apply.go b/pkg/apply/apply.go index ce6011ad6849..d522f2be7a58 100644 --- a/pkg/apply/apply.go +++ b/pkg/apply/apply.go @@ -21,6 +21,8 @@ import ( "os" "path/filepath" + "github.com/labring/sealos/pkg/apply/processor" + "github.com/spf13/cobra" "github.com/labring/sealos/pkg/apply/applydrivers" @@ -72,3 +74,21 @@ func NewApplierFromFile(cmd *cobra.Command, path string, args *Args) (applydrive RunNewImages: GetNewImages(currentCluster, cluster), }, nil } + +func Restorer(cmd *cobra.Command, args *RunArgs, image string) error { + ctx := withCommonContext(cmd.Context(), cmd) + + cf := clusterfile.NewClusterFile(constants.Clusterfile(args.ClusterName)) + err := cf.Process() + if err != nil && err != clusterfile.ErrClusterFileNotExists { + return fmt.Errorf("failed to process clusterfile: %w", err) + } + restorer, err := processor.NewRestoreProcessor(ctx, args.ClusterName, cf) + if err != nil { + return fmt.Errorf("failed to create restore processor: %w", err) + } + cluster := cf.GetCluster() + + cluster.Spec.Image = []string{image} + return restorer.Restore(cf.GetCluster()) +} diff --git a/pkg/apply/processor/create.go b/pkg/apply/processor/create.go index dcf4d03657ae..595c1234a613 100644 --- a/pkg/apply/processor/create.go +++ b/pkg/apply/processor/create.go @@ -58,6 +58,20 @@ func (c *CreateProcessor) Execute(cluster *v2.Cluster) error { return nil } +func (c *CreateProcessor) Restore(cluster *v2.Cluster) error { + pipeLine, err := c.RestorePipeLine() + if err != nil { + return err + } + for _, f := range pipeLine { + if err = f(cluster); err != nil { + return err + } + } + + return nil +} + func (c *CreateProcessor) GetPipeLine() ([]func(cluster *v2.Cluster) error, error) { var todoList []func(cluster *v2.Cluster) error todoList = append(todoList, @@ -79,6 +93,22 @@ func (c *CreateProcessor) GetPipeLine() ([]func(cluster *v2.Cluster) error, erro return todoList, nil } +func (c *CreateProcessor) RestorePipeLine() ([]func(cluster *v2.Cluster) error, error) { + var todoList []func(cluster *v2.Cluster) error + todoList = append(todoList, + // c.GetPhasePluginFunc(plugin.PhaseOriginally), + c.Check, + c.PreProcess, + c.MountRootfs, + c.MirrorRegistry, + // c.GetPhasePluginFunc(plugin.PhasePreInit), + // c.GetPhasePluginFunc(plugin.PhasePreGuest), + // c.GetPhasePluginFunc(plugin.PhasePostInstall), + ) + + return todoList, nil +} + func (c *CreateProcessor) Check(cluster *v2.Cluster) error { logger.Info("Executing pipeline Check in CreateProcessor.") var ips []string @@ -176,6 +206,14 @@ func (c *CreateProcessor) RunGuest(cluster *v2.Cluster) error { } func NewCreateProcessor(ctx context.Context, name string, clusterFile clusterfile.Interface) (Interface, error) { + return newCreateProcessor(ctx, name, clusterFile) +} + +func NewRestoreProcessor(ctx context.Context, name string, clusterFile clusterfile.Interface) (Restorer, error) { + return newCreateProcessor(ctx, name, clusterFile) +} + +func newCreateProcessor(ctx context.Context, name string, clusterFile clusterfile.Interface) (*CreateProcessor, error) { bder, err := buildah.New(name) if err != nil { return nil, err diff --git a/pkg/apply/processor/interface.go b/pkg/apply/processor/interface.go index 5cb7ff62d903..ba39ced24887 100644 --- a/pkg/apply/processor/interface.go +++ b/pkg/apply/processor/interface.go @@ -41,6 +41,10 @@ type Interface interface { Execute(cluster *v2.Cluster) error } +type Restorer interface { + Restore(cluster *v2.Cluster) error +} + // compatible with older sealos versions func SyncNewVersionConfig(clusterName string) { d := constants.NewPathResolver(clusterName)