Skip to content

Commit

Permalink
feat(backup): add backup subcmd
Browse files Browse the repository at this point in the history
add backup subcmd

Signed-off-by: ysicing <[email protected]>
  • Loading branch information
ysicing committed Sep 25, 2023
1 parent f088f7d commit c2dc8db
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 4 deletions.
24 changes: 24 additions & 0 deletions cmd/backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2021-2023 北京渠成软件有限公司(Beijing Qucheng Software Co., Ltd. www.qucheng.com) All rights reserved.
// Use of this source code is covered by the following dual licenses:
// (1) Z PUBLIC LICENSE 1.2 (ZPL 1.2)
// (2) Affero General Public License 3.0 (AGPL 3.0)
// license that can be found in the LICENSE file.

package cmd

import (
"github.com/easysoft/qcadmin/cmd/backup"
"github.com/easysoft/qcadmin/internal/pkg/util/factory"
"github.com/spf13/cobra"
)

func newCmdBackup(f factory.Factory) *cobra.Command {
backupCmd := &cobra.Command{
Use: "backup",
Short: "Backup commands",
Version: "20230925",
}
backupCmd.AddCommand(backup.NewCmdBackupCluster(f))
backupCmd.AddCommand(backup.NewCmdBackupApp(f))
return backupCmd
}
67 changes: 67 additions & 0 deletions cmd/backup/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2021-2023 北京渠成软件有限公司(Beijing Qucheng Software Co., Ltd. www.qucheng.com) All rights reserved.
// Use of this source code is covered by the following dual licenses:
// (1) Z PUBLIC LICENSE 1.2 (ZPL 1.2)
// (2) Affero General Public License 3.0 (AGPL 3.0)
// license that can be found in the LICENSE file.

package backup

import (
"strings"
"time"

"github.com/easysoft/qcadmin/internal/api/cne"
"github.com/easysoft/qcadmin/internal/pkg/util/factory"
"github.com/spf13/cobra"
)

func NewCmdBackupApp(f factory.Factory) *cobra.Command {
var app, ns, backupName string
var err error
log := f.GetLog()
bc := &cobra.Command{
Use: "app",
Short: "backup app",
Long: "backup app",
Run: func(cmd *cobra.Command, args []string) {
log.Infof("start backup app: %s", app)
cneClient := cne.NewCneAPI()
if backupName == "" {
backupName, err = cneClient.AppBackUP(ns, app)
if err != nil {
log.Errorf("backup app %s failed, reason: %v", app, err)
return
}
}

timeout := 5 * time.Minute
costtime := time.Now()
deadline := time.Now().Add(timeout)
for {
backupStatus, err := cneClient.AppBackUPStatus(ns, app, backupName)
if err != nil {
log.Errorf("backup app %s failed, reason: %v", app, err)
return
}
if strings.ToLower(backupStatus.Status) == "completed" {
log.Infof("backup app %s(%s) success, cost: %vs", app, backupName, time.Since(costtime).Seconds())
return
}
if strings.ToLower(backupStatus.Status) == "failed" {
log.Errorf("backup app %s(%s) failed, reason: %s", app, backupName, backupStatus.Reason)
return
}
if time.Now().After(deadline) {
log.Errorf("backup app %s(%s) timeout", app, backupName)
return
}
log.Infof("backup app %s(%s) status: %s", app, backupName, backupStatus.Status)
time.Sleep(5 * time.Second)
}
},
}
bc.Flags().StringVar(&app, "app", "", "app chart name")
bc.Flags().StringVarP(&ns, "namespace", "n", "", "namespace")
bc.Flags().StringVarP(&backupName, "backupName", "b", "", "existing backup name")
return bc
}
2 changes: 1 addition & 1 deletion cmd/backup/backup.go → cmd/backup/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
func NewCmdBackupCluster(f factory.Factory) *cobra.Command {
log := f.GetLog()
bc := &cobra.Command{
Use: "backup",
Use: "cluster",
Short: "backup cluster",
Long: "backup cluster",
Aliases: []string{"snapshot"},
Expand Down
2 changes: 0 additions & 2 deletions cmd/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package cmd

import (
"github.com/easysoft/qcadmin/cmd/backup"
"github.com/easysoft/qcadmin/cmd/cluster"
"github.com/easysoft/qcadmin/cmd/precheck"
"github.com/easysoft/qcadmin/cmd/storage"
Expand Down Expand Up @@ -46,6 +45,5 @@ func newCmdCluster(f factory.Factory) *cobra.Command {
clusterCmd.AddCommand(cluster.StatusCommand(f))
clusterCmd.AddCommand(cluster.StopCommand(f))
clusterCmd.AddCommand(storage.NewCmdStorage(f))
clusterCmd.AddCommand(backup.NewCmdBackupCluster(f))
return clusterCmd
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func BuildRoot(f factory.Factory) *cobra.Command {
rootCmd.AddCommand(newCmdUpgrade(f))
rootCmd.AddCommand(newCmdCluster(f))
rootCmd.AddCommand(newCmdPlatform(f))
rootCmd.AddCommand(newCmdBackup(f))
// Add plugin commands
rootCmd.AddCommand(newCmdExperimental(f))
rootCmd.AddCommand(newManCmd())
Expand Down
1 change: 1 addition & 0 deletions common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const (
MiuiGenerate204URL = "https://connect.rom.miui.com/generate_204"
V2exGenerate204URL = "https://captive.v2ex.co/generate_204"
CloudflareEdgeTraceURL = "https://www.cloudflare.com/cdn-cgi/trace"
CneAPITokenHeader = "X-Auth-Token"
)

const (
Expand Down
56 changes: 56 additions & 0 deletions internal/api/cne/cne.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2021-2023 北京渠成软件有限公司(Beijing Qucheng Software Co., Ltd. www.qucheng.com) All rights reserved.
// Use of this source code is covered by the following dual licenses:
// (1) Z PUBLIC LICENSE 1.2 (ZPL 1.2)
// (2) Affero General Public License 3.0 (AGPL 3.0)
// license that can be found in the LICENSE file.

package cne

import (
"fmt"

"github.com/easysoft/qcadmin/common"
"github.com/easysoft/qcadmin/internal/app/config"
"github.com/imroc/req/v3"
)

type CneAPI struct {
Req *req.Request
Endpoint string
}

func NewCneAPI() *CneAPI {
config, _ := config.LoadConfig()
c := req.C().R().SetHeader(common.CneAPITokenHeader, config.APIToken)
return &CneAPI{
Req: c,
Endpoint: fmt.Sprintf("http://%s:32380", config.Cluster.InitNode),
}
}

func (c *CneAPI) AppBackUP(ns, chartName string) (string, error) {
var result AppBackUPResp
appbackup := &AppBackUPReq{Namespace: ns, Name: chartName}
resp, err := c.Req.SetBody(appbackup).
SetSuccessResult(&result).
Post(c.Endpoint + "/api/cne/app/backup")
if resp.IsSuccessState() {
return result.Data.BackupName, nil
}
return "", err
}

func (c *CneAPI) AppBackUPStatus(ns, chartName, backupName string) (*AppBackUPStatus, error) {
var result AppBackUPStatusResp
resp, err := c.Req.SetQueryParams(map[string]string{
"namespace": ns,
"name": chartName,
"backup_name": backupName,
}).
SetSuccessResult(&result).
Get(c.Endpoint + "/api/cne/app/backup/status")
if resp.IsSuccessState() {
return &result.Data, nil
}
return nil, err
}
36 changes: 36 additions & 0 deletions internal/api/cne/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2021-2023 北京渠成软件有限公司(Beijing Qucheng Software Co., Ltd. www.qucheng.com) All rights reserved.
// Use of this source code is covered by the following dual licenses:
// (1) Z PUBLIC LICENSE 1.2 (ZPL 1.2)
// (2) Affero General Public License 3.0 (AGPL 3.0)
// license that can be found in the LICENSE file.

package cne

type AppBackUPReq struct {
Cluster string `json:"cluster,omitempty"`
Namespace string `json:"namespace"`
Name string `json:"name"` // chartname
UserName string `json:"username,omitempty"` // 操作用户
}

type AppBackUPResp struct {
Code int `json:"code"`
Message string `json:"message"`
Data AppBackUPData `json:"data"`
}

type AppBackUPData struct {
BackupName string `json:"backup_name"`
CreateTime int64 `json:"create_time"`
}

type AppBackUPStatusResp struct {
Code int `json:"code"`
Message string `json:"message"`
Data AppBackUPStatus `json:"data"`
}

type AppBackUPStatus struct {
Reason string `json:"reason,omitempty"`
Status string `json:"status"`
}
2 changes: 1 addition & 1 deletion internal/pkg/util/kutil/kutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func NeedCacheHelmFile() bool {
data, _ := file.ReadAll(cachefile)
old := time.Unix(exstr.Str2Int64(string(data)), 0)
now := time.Now()
if now.Sub(old) > 10*time.Minute {
if now.Sub(old) > 2*time.Minute {
os.Remove(cachefile)
file.WriteFile(cachefile, ztime.NowUnixString(), true)
return true
Expand Down
7 changes: 7 additions & 0 deletions pkg/qucheng/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ func Upgrade(flagVersion string, log log.Logger) error {
for _, cv := range qv.Components {
if cv.CanUpgrade {
defaultValue, _ := helmClient.GetValues(cv.Name)
if devops && cv.Name == common.DefaultZentaoPaasName {
deploy := defaultValue["deploy"]
product := deploy.(map[string]interface{})["product"]
versions := deploy.(map[string]interface{})["versions"]
appVersion := versions.(map[string]interface{})[product.(string)]
log.Infof("devops mode, product: %v, version: %v", product, appVersion)
}
if _, err := helmClient.Upgrade(cv.Name, common.DefaultHelmRepoName, cv.Name, "", defaultValue); err != nil {
log.Warnf("upgrade %s failed, reason: %v", cv.Name, err)
} else {
Expand Down

0 comments on commit c2dc8db

Please sign in to comment.