This is an automated email from the ASF dual-hosted git repository.
miaoliyao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shardingsphere-on-cloud.git
The following commit(s) were added to refs/heads/main by this push:
new 110fd9c chore(pitr): agent add health check api, cli check duplicate
agent ip.
new 7a88262 Merge pull request #331 from Xu-Wentao/pitr
110fd9c is described below
commit 110fd9cc4e62203564c66f4784b24d1e12d6f040
Author: xuwentao <[email protected]>
AuthorDate: Thu Apr 27 16:48:16 2023 +0800
chore(pitr): agent add health check api, cli check duplicate agent ip.
---
pitr/agent/internal/handler/handler_suite_test.go | 1 +
.../{handler_suite_test.go => healthcheck.go} | 50 +++-----
.../{handler_suite_test.go => healthcheck_test.go} | 46 +++----
pitr/agent/internal/handler/view/healthcheck.go | 25 ++++
pitr/agent/main.go | 2 +
pitr/agent/pkg/gsutil/conn.go | 2 +-
pitr/cli/internal/cmd/backup.go | 11 +-
pitr/cli/internal/cmd/backup_test.go | 11 +-
pitr/cli/internal/cmd/restore_test.go | 2 +-
pitr/cli/internal/cmd/root.go | 25 +++-
pitr/cli/internal/pkg/agent-server.go | 142 ++++++---------------
pitr/cli/internal/pkg/agent-server_test.go | 17 ++-
pitr/cli/internal/pkg/mocks/agent-server.go | 8 +-
pitr/cli/internal/pkg/model/as_healthcheck.go | 25 ++++
pitr/cli/internal/pkg/xerr/err.go | 6 +
pitr/cli/pkg/httputils/mocks/req.go | 26 +---
pitr/cli/pkg/httputils/req.go | 32 +++--
.../pkg/kubernetes/deployment/deployment_test.go | 2 +-
18 files changed, 213 insertions(+), 220 deletions(-)
diff --git a/pitr/agent/internal/handler/handler_suite_test.go
b/pitr/agent/internal/handler/handler_suite_test.go
index 816ef69..30dbb4b 100644
--- a/pitr/agent/internal/handler/handler_suite_test.go
+++ b/pitr/agent/internal/handler/handler_suite_test.go
@@ -56,5 +56,6 @@ var _ = BeforeSuite(func() {
app.Route("/api", func(r fiber.Router) {
r.Post("/diskspace", handler.DiskSpace)
r.Delete("/backup", handler.DeleteBackup)
+ r.Post("/healthz", handler.HealthCheck)
})
})
diff --git a/pitr/agent/internal/handler/handler_suite_test.go
b/pitr/agent/internal/handler/healthcheck.go
similarity index 56%
copy from pitr/agent/internal/handler/handler_suite_test.go
copy to pitr/agent/internal/handler/healthcheck.go
index 816ef69..877adc0 100644
--- a/pitr/agent/internal/handler/handler_suite_test.go
+++ b/pitr/agent/internal/handler/healthcheck.go
@@ -15,46 +15,28 @@
* limitations under the License.
*/
-package handler_test
+package handler
import (
- "os"
- "testing"
+ "fmt"
- "github.com/apache/shardingsphere-on-cloud/pitr/agent/internal/handler"
- "github.com/apache/shardingsphere-on-cloud/pitr/agent/pkg/logging"
+ "github.com/apache/shardingsphere-on-cloud/pitr/agent/internal/cons"
+
"github.com/apache/shardingsphere-on-cloud/pitr/agent/internal/handler/view"
+ "github.com/apache/shardingsphere-on-cloud/pitr/agent/internal/pkg"
"github.com/apache/shardingsphere-on-cloud/pitr/agent/pkg/responder"
"github.com/gofiber/fiber/v2"
- "github.com/golang/mock/gomock"
- . "github.com/onsi/ginkgo/v2"
- . "github.com/onsi/gomega"
- "go.uber.org/zap"
)
-var (
- app *fiber.App
- ctrl *gomock.Controller
-)
-
-func TestHandler(t *testing.T) {
- RegisterFailHandler(Fail)
- RunSpecs(t, "Handler Suite")
-}
+func HealthCheck(ctx *fiber.Ctx) error {
+ in := &view.HealthCheckIn{}
+ if err := ctx.BodyParser(in); err != nil {
+ return fmt.Errorf("body parse err=%s,wrap=%w", err,
cons.BodyParseFailed)
+ }
-var _ = BeforeSuite(func() {
- // init log
- logging.Init(zap.DebugLevel)
+ if err := pkg.OG.Auth(in.Username, in.Password, in.DBName, in.DBPort);
err != nil {
+ efmt := "pkg.OG.Auth failure[un=%s,pw.len=%d,db=%s],err=%w"
+ return fmt.Errorf(efmt, in.Username, len(in.Password),
in.DBName, err)
+ }
- Expect(os.Setenv("SHELL", "/bin/bash")).To(Succeed())
-
- // init app
- app = fiber.New()
- app.Get("/ping", func(ctx *fiber.Ctx) error {
- return responder.Success(ctx, "pong")
- })
-
- app.Route("/api", func(r fiber.Router) {
- r.Post("/diskspace", handler.DiskSpace)
- r.Delete("/backup", handler.DeleteBackup)
- })
-})
+ return responder.Success(ctx, "")
+}
diff --git a/pitr/agent/internal/handler/handler_suite_test.go
b/pitr/agent/internal/handler/healthcheck_test.go
similarity index 52%
copy from pitr/agent/internal/handler/handler_suite_test.go
copy to pitr/agent/internal/handler/healthcheck_test.go
index 816ef69..185ee18 100644
--- a/pitr/agent/internal/handler/handler_suite_test.go
+++ b/pitr/agent/internal/handler/healthcheck_test.go
@@ -18,43 +18,27 @@
package handler_test
import (
- "os"
- "testing"
+ "net/http"
+ "net/http/httptest"
+ "strings"
- "github.com/apache/shardingsphere-on-cloud/pitr/agent/internal/handler"
- "github.com/apache/shardingsphere-on-cloud/pitr/agent/pkg/logging"
- "github.com/apache/shardingsphere-on-cloud/pitr/agent/pkg/responder"
- "github.com/gofiber/fiber/v2"
- "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
- "go.uber.org/zap"
)
-var (
- app *fiber.App
- ctrl *gomock.Controller
-)
-
-func TestHandler(t *testing.T) {
- RegisterFailHandler(Fail)
- RunSpecs(t, "Handler Suite")
-}
-
-var _ = BeforeSuite(func() {
- // init log
- logging.Init(zap.DebugLevel)
-
- Expect(os.Setenv("SHELL", "/bin/bash")).To(Succeed())
-
- // init app
- app = fiber.New()
- app.Get("/ping", func(ctx *fiber.Ctx) error {
- return responder.Success(ctx, "pong")
+var _ = Describe("Test Health Check", func() {
+ It("should failed with empty body", func() {
+ req := httptest.NewRequest(http.MethodPost, "/api/healthz", nil)
+ resp, err := app.Test(req)
+ Expect(err).To(BeNil())
+
Expect(resp.StatusCode).To(Equal(http.StatusInternalServerError))
})
- app.Route("/api", func(r fiber.Router) {
- r.Post("/diskspace", handler.DiskSpace)
- r.Delete("/backup", handler.DeleteBackup)
+ It("should success", func() {
+ body := `{"username": "root", "password": "root", "db_name":
"test", "db_port": 3306}`
+ req := httptest.NewRequest(http.MethodPost, "/api/healthz",
strings.NewReader(body))
+ resp, err := app.Test(req)
+ Expect(err).To(BeNil())
+
Expect(resp.StatusCode).To(Equal(http.StatusInternalServerError))
})
})
diff --git a/pitr/agent/internal/handler/view/healthcheck.go
b/pitr/agent/internal/handler/view/healthcheck.go
new file mode 100644
index 0000000..f214fa0
--- /dev/null
+++ b/pitr/agent/internal/handler/view/healthcheck.go
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 view
+
+type HealthCheckIn struct {
+ DBPort uint16 `json:"db_port"`
+ DBName string `json:"db_name"`
+ Username string `json:"username"`
+ Password string `json:"password"`
+}
diff --git a/pitr/agent/main.go b/pitr/agent/main.go
index 8c11df7..a2bdddd 100644
--- a/pitr/agent/main.go
+++ b/pitr/agent/main.go
@@ -149,6 +149,7 @@ func SetupApp() {
)
app.Get("/ping", func(ctx *fiber.Ctx) error {
+
return responder.Success(ctx, "pong")
})
@@ -160,6 +161,7 @@ func SetupApp() {
app.Route("/api", func(r fiber.Router) {
r.Use(middleware.RequestIDChecker())
+ r.Post("/healthz", handler.HealthCheck)
r.Post("/backup", handler.Backup)
r.Delete("/backup", handler.DeleteBackup)
r.Post("/restore", handler.Restore)
diff --git a/pitr/agent/pkg/gsutil/conn.go b/pitr/agent/pkg/gsutil/conn.go
index 72a6e8a..a5bca1d 100644
--- a/pitr/agent/pkg/gsutil/conn.go
+++ b/pitr/agent/pkg/gsutil/conn.go
@@ -66,5 +66,5 @@ func (og *OpenGauss) Ping() error {
efmt := "db ping
fail[user=%s,pwLen=%d,dbName=%s],err=%s,wrap=%w"
return fmt.Errorf(efmt, og.user, og.pwLen, og.dbName, err,
cons.DBConnectionFailed)
}
- return nil
+ return og.db.Close()
}
diff --git a/pitr/cli/internal/cmd/backup.go b/pitr/cli/internal/cmd/backup.go
index 9ef1b63..8537501 100644
--- a/pitr/cli/internal/cmd/backup.go
+++ b/pitr/cli/internal/cmd/backup.go
@@ -143,6 +143,7 @@ func backup() error {
// Step3. Check agent server status
logging.Info("Checking agent server status...")
if available := checkAgentServerStatus(lsBackup); !available {
+ logging.Error("Cancel! One or more agent server are not
available.")
err = xerr.NewCliErr("One or more agent server are not
available.")
return err
}
@@ -179,6 +180,10 @@ func backup() error {
logging.Info("Starting check backup status ...")
status := checkBackupStatus(lsBackup)
logging.Info(fmt.Sprintf("Backup result: %s", status))
+ if status != model.SsBackupStatusCompleted && status !=
model.SsBackupStatusCanceled {
+ err = xerr.NewCliErr("Backup failed")
+ return err
+ }
// Step9. finished backup and update backup file
logging.Info("Starting update backup file ...")
@@ -437,7 +442,7 @@ func deleteBackupFiles(lsBackup *model.LsBackup) {
sn := sn
dn, ok := dataNodeMap[sn.IP]
if !ok {
- logging.Error(fmt.Sprintf("data node %s:%d not found,
SKIPPED!", sn.IP, sn.Port))
+ logging.Warn(fmt.Sprintf("SKIPPED! data node %s:%d not
found in backup info.", sn.IP, sn.Port))
continue
}
as := pkg.NewAgentServer(fmt.Sprintf("%s:%d",
convertLocalhost(sn.IP), AgentPort))
@@ -447,8 +452,12 @@ func deleteBackupFiles(lsBackup *model.LsBackup) {
time.Sleep(time.Millisecond * 100)
for pw.IsRenderInProgress() {
+ if pw.LengthActive() == 0 {
+ pw.Stop()
+ }
time.Sleep(time.Millisecond * 100)
}
+
close(resultCh)
t := table.NewWriter()
diff --git a/pitr/cli/internal/cmd/backup_test.go
b/pitr/cli/internal/cmd/backup_test.go
index 6fbf352..bc531d6 100644
--- a/pitr/cli/internal/cmd/backup_test.go
+++ b/pitr/cli/internal/cmd/backup_test.go
@@ -383,18 +383,21 @@ var _ = Describe("test backup mock", func() {
})
It("agent server is not running", func() {
- mockIreq.EXPECT().Send(gomock.Any()).Return(-1,
errors.New("error")).AnyTimes()
+
mockIreq.EXPECT().Send(gomock.Any()).Return(errors.New("error")).AnyTimes()
+ mockIreq.EXPECT().Header(gomock.Any()).AnyTimes()
Expect(checkAgentServerStatus(ls)).To(BeFalse())
})
It("agent server are running", func() {
- mockIreq.EXPECT().Send(gomock.Any()).Return(200,
nil).AnyTimes()
+
mockIreq.EXPECT().Send(gomock.Any()).Return(nil).AnyTimes()
+ mockIreq.EXPECT().Header(gomock.Any()).AnyTimes()
Expect(checkAgentServerStatus(ls)).To(BeTrue())
})
It("one agent server is not running", func() {
- mockIreq.EXPECT().Send(gomock.Any()).Return(500, nil)
- mockIreq.EXPECT().Send(gomock.Any()).Return(200,
nil).AnyTimes()
+
mockIreq.EXPECT().Send(gomock.Any()).Return(errors.New("failed"))
+
mockIreq.EXPECT().Send(gomock.Any()).Return(nil).AnyTimes()
+ mockIreq.EXPECT().Header(gomock.Any()).AnyTimes()
Expect(checkAgentServerStatus(ls)).To(BeFalse())
})
})
diff --git a/pitr/cli/internal/cmd/restore_test.go
b/pitr/cli/internal/cmd/restore_test.go
index 04a12e1..7da6dea 100644
--- a/pitr/cli/internal/cmd/restore_test.go
+++ b/pitr/cli/internal/cmd/restore_test.go
@@ -126,7 +126,7 @@ var _ = Describe("test restore", func() {
RecordID = "backup-id"
proxy.EXPECT().ExportMetaData().Return(&model.ClusterInfo{},
nil)
proxy.EXPECT().ImportMetaData(gomock.Any()).Return(nil)
- as.EXPECT().CheckStatus().Return(nil)
+ as.EXPECT().CheckStatus(gomock.Any()).Return(nil)
as.EXPECT().Restore(gomock.Any()).Return(nil)
Expect(restore()).To(BeNil())
diff --git a/pitr/cli/internal/cmd/root.go b/pitr/cli/internal/cmd/root.go
index 6df5fc7..33a4f40 100644
--- a/pitr/cli/internal/cmd/root.go
+++ b/pitr/cli/internal/cmd/root.go
@@ -93,10 +93,20 @@ func checkAgentServerStatus(lsBackup *model.LsBackup) bool {
// all agent server are available
available := true
+ // IMPORTANT: we don't support multiple agent server run on the same
host
+ asMap := make(map[string]bool)
+ asDuplicate := false
+
for _, node := range lsBackup.SsBackup.StorageNodes {
sn := node
as := pkg.NewAgentServer(fmt.Sprintf("%s:%d",
convertLocalhost(sn.IP), AgentPort))
- if err := as.CheckStatus(); err != nil {
+ in := &model.HealthCheckIn{
+ DBPort: sn.Port,
+ DBName: convertLocalhost(sn.IP),
+ Username: sn.Username,
+ Password: sn.Password,
+ }
+ if err := as.CheckStatus(in); err != nil {
statusList = append(statusList,
&model.AgentServerStatus{IP: sn.IP, Port: sn.Port, Status: "Unavailable"})
available = false
} else {
@@ -116,6 +126,19 @@ func checkAgentServerStatus(lsBackup *model.LsBackup) bool
{
t.Render()
+ for _, node := range lsBackup.SsBackup.StorageNodes {
+ if _, ok := asMap[node.IP]; ok {
+ asDuplicate = true
+ break
+ }
+ asMap[node.IP] = true
+ }
+
+ if asDuplicate {
+ logging.Error("IMPORTANT!: we don't support multiple agent
server run on the same host.\n")
+ return false
+ }
+
return available
}
diff --git a/pitr/cli/internal/pkg/agent-server.go
b/pitr/cli/internal/pkg/agent-server.go
index 9a35146..d6286a9 100644
--- a/pitr/cli/internal/pkg/agent-server.go
+++ b/pitr/cli/internal/pkg/agent-server.go
@@ -25,21 +25,21 @@ import (
"github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/model"
"github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/xerr"
"github.com/apache/shardingsphere-on-cloud/pitr/cli/pkg/httputils"
- "github.com/google/uuid"
)
type agentServer struct {
addr string
- _apiBackup string
- _apiRestore string
- _apiShowDetail string
- _apiShowList string
- _apiDiskspace string
+ _apiBackup string
+ _apiRestore string
+ _apiShowDetail string
+ _apiShowList string
+ _apiDiskspace string
+ _apiHealthCheck string
}
type IAgentServer interface {
- CheckStatus() error
+ CheckStatus(in *model.HealthCheckIn) error
Backup(in *model.BackupIn) (string, error)
DeleteBackup(in *model.DeleteBackupIn) error
Restore(in *model.RestoreIn) error
@@ -54,26 +54,25 @@ func NewAgentServer(addr string) IAgentServer {
return &agentServer{
addr: addr,
- _apiBackup: "/api/backup",
- _apiRestore: "/api/restore",
- _apiShowDetail: "/api/show",
- _apiShowList: "/api/show/list",
- _apiDiskspace: "/api/diskspace",
+ _apiBackup: "/api/backup",
+ _apiRestore: "/api/restore",
+ _apiShowDetail: "/api/show",
+ _apiShowList: "/api/show/list",
+ _apiDiskspace: "/api/diskspace",
+ _apiHealthCheck: "/api/healthz",
}
}
// CheckStatus check agent server is alive
-func (as *agentServer) CheckStatus() error {
- url := fmt.Sprintf("%s/%s", as.addr, "ping")
- r := httputils.NewRequest(context.Background(), http.MethodGet, url)
- httpCode, err := r.Send(nil)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s] return err=%s,wrap=%w"
- return fmt.Errorf(efmt, url, err, xerr.NewCliErr(xerr.Unknown))
- }
- if httpCode != http.StatusOK {
- return fmt.Errorf("httpCode=%d", httpCode)
+func (as *agentServer) CheckStatus(in *model.HealthCheckIn) error {
+ url := fmt.Sprintf("%s%s", as.addr, as._apiHealthCheck)
+
+ r := httputils.NewRequest(context.Background(), http.MethodPost, url)
+
+ if err := r.Send(in); err != nil {
+ return xerr.NewUnknownErr(url, in, nil, err)
}
+
return nil
}
@@ -82,25 +81,14 @@ func (as *agentServer) Backup(in *model.BackupIn) (string,
error) {
out := &model.BackupOutResp{}
r := httputils.NewRequest(context.Background(), http.MethodPost, url)
- r.Header(map[string]string{
- "x-request-id": uuid.New().String(),
- "content-type": "application/json",
- })
r.Body(in)
- httpCode, err := r.Send(out)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
- return "", fmt.Errorf(efmt, url, in, out, err,
xerr.NewCliErr(xerr.Unknown))
- }
-
- if httpCode != http.StatusOK {
- return "", fmt.Errorf("unknown http status[code=%d],err=%w",
httpCode, xerr.NewCliErr(xerr.InvalidHTTPStatus))
+ if err := r.Send(out); err != nil {
+ return "", xerr.NewUnknownErr(url, in, out, err)
}
if out.Code != 0 {
- asErr := xerr.NewAgentServerErr(out.Code, out.Msg)
- return "", fmt.Errorf("agent server
error[code=%d,msg=%s],err=%w", out.Code, out.Msg, asErr)
+ return "", xerr.NewAgentServerErr(out.Code, out.Msg)
}
return out.Data.ID, nil
@@ -112,24 +100,14 @@ func (as *agentServer) Restore(in *model.RestoreIn) error
{
out := &model.RestoreResp{}
r := httputils.NewRequest(context.Background(), http.MethodPost, url)
- r.Header(map[string]string{
- "x-request-id": uuid.New().String(),
- "content-type": "application/json",
- })
r.Body(in)
- httpCode, err := r.Send(out)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
- return fmt.Errorf(efmt, url, in, out, err,
xerr.NewCliErr(xerr.Unknown))
- }
- if httpCode != http.StatusOK {
- return fmt.Errorf("unknown http status[code=%d],err=%w",
httpCode, xerr.NewCliErr(xerr.InvalidHTTPStatus))
+ if err := r.Send(out); err != nil {
+ return xerr.NewUnknownErr(url, in, out, err)
}
if out.Code != 0 {
- asErr := xerr.NewAgentServerErr(out.Code, out.Msg)
- return fmt.Errorf("agent server error[code=%d,msg=%s],err=%w",
out.Code, out.Msg, asErr)
+ return xerr.NewAgentServerErr(out.Code, out.Msg)
}
return nil
@@ -140,24 +118,14 @@ func (as *agentServer) ShowDetail(in *model.ShowDetailIn)
(*model.BackupInfo, er
out := &model.BackupDetailResp{}
r := httputils.NewRequest(context.Background(), http.MethodPost, url)
- r.Header(map[string]string{
- "x-request-id": uuid.New().String(),
- "content-type": "application/json",
- })
r.Body(in)
- httpCode, err := r.Send(out)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
- return nil, fmt.Errorf(efmt, url, in, out, err,
xerr.NewCliErr(xerr.Unknown))
- }
- if httpCode != http.StatusOK {
- return nil, fmt.Errorf("unknown http status[code=%d],err=%w",
httpCode, xerr.NewCliErr(xerr.InvalidHTTPStatus))
+ if err := r.Send(out); err != nil {
+ return nil, xerr.NewUnknownErr(url, in, out, err)
}
if out.Code != 0 {
- asErr := xerr.NewAgentServerErr(out.Code, out.Msg)
- return nil, fmt.Errorf("agent server
error[code=%d,msg=%s],err=%w", out.Code, out.Msg, asErr)
+ return nil, xerr.NewAgentServerErr(out.Code, out.Msg)
}
return &out.Data, nil
@@ -168,24 +136,14 @@ func (as *agentServer) ShowList(in *model.ShowListIn)
([]model.BackupInfo, error
out := &model.BackupListResp{}
r := httputils.NewRequest(context.Background(), http.MethodPost, url)
- r.Header(map[string]string{
- "x-request-id": uuid.New().String(),
- "content-type": "application/json",
- })
r.Body(in)
- httpCode, err := r.Send(out)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
- return nil, fmt.Errorf(efmt, url, in, out, err,
xerr.NewCliErr(xerr.Unknown))
- }
- if httpCode != http.StatusOK {
- return nil, fmt.Errorf("unknown http status[code=%d],err=%w",
httpCode, xerr.NewCliErr(xerr.InvalidHTTPStatus))
+ if err := r.Send(out); err != nil {
+ return nil, xerr.NewUnknownErr(url, in, out, err)
}
if out.Code != 0 {
- asErr := xerr.NewAgentServerErr(out.Code, out.Msg)
- return nil, fmt.Errorf("agent server
error[code=%d,msg=%s],err=%w", out.Code, out.Msg, asErr)
+ return nil, xerr.NewAgentServerErr(out.Code, out.Msg)
}
return out.Data, nil
@@ -196,25 +154,14 @@ func (as *agentServer) ShowDiskSpace(in
*model.DiskSpaceIn) (*model.DiskSpaceInf
out := &model.DiskSpaceInfo{}
r := httputils.NewRequest(context.Background(), http.MethodPost, url)
- r.Header(map[string]string{
- "x-request-id": uuid.New().String(),
- "content-type": "application/json",
- })
r.Body(in)
- httpCode, err := r.Send(out)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
- return nil, fmt.Errorf(efmt, url, in, out, err,
xerr.NewCliErr(xerr.Unknown))
- }
-
- if httpCode != http.StatusOK {
- return nil, fmt.Errorf("unknown http status[code=%d],err=%w",
httpCode, xerr.NewCliErr(xerr.InvalidHTTPStatus))
+ if err := r.Send(out); err != nil {
+ return nil, xerr.NewUnknownErr(url, in, out, err)
}
if out.Code != 0 {
- asErr := xerr.NewAgentServerErr(out.Code, out.Msg)
- return nil, fmt.Errorf("agent server
error[code=%d,msg=%s],err=%w", out.Code, out.Msg, asErr)
+ return nil, xerr.NewAgentServerErr(out.Code, out.Msg)
}
return out, nil
@@ -226,25 +173,14 @@ func (as *agentServer) DeleteBackup(in
*model.DeleteBackupIn) error {
out := &model.DeleteBackupOut{}
r := httputils.NewRequest(context.Background(), http.MethodDelete, url)
- r.Header(map[string]string{
- "x-request-id": uuid.New().String(),
- "content-type": "application/json",
- })
r.Body(in)
- httpCode, err := r.Send(out)
- if err != nil {
- efmt := "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
- return fmt.Errorf(efmt, url, in, out, err,
xerr.NewCliErr(xerr.Unknown))
- }
-
- if httpCode != http.StatusOK {
- return fmt.Errorf("unknown http status[code=%d],err=%w",
httpCode, xerr.NewCliErr(xerr.InvalidHTTPStatus))
+ if err := r.Send(out); err != nil {
+ return xerr.NewUnknownErr(url, in, out, err)
}
if out.Code != 0 {
- asErr := xerr.NewAgentServerErr(out.Code, out.Msg)
- return fmt.Errorf("agent server error[code=%d,msg=%s],err=%w",
out.Code, out.Msg, asErr)
+ return xerr.NewAgentServerErr(out.Code, out.Msg)
}
return nil
diff --git a/pitr/cli/internal/pkg/agent-server_test.go
b/pitr/cli/internal/pkg/agent-server_test.go
index 1bf05f2..e76b8f3 100644
--- a/pitr/cli/internal/pkg/agent-server_test.go
+++ b/pitr/cli/internal/pkg/agent-server_test.go
@@ -132,7 +132,6 @@ var _ = Describe("AgentServer", func() {
as = NewAgentServer("http://agent-server:18080")
ctrl = gomock.NewController(GinkgoT())
req = mock_httputils.NewMockIreq(ctrl)
- req.EXPECT().Header(gomock.Any())
req.EXPECT().Body(gomock.Any())
monkey.Patch(httputils.NewRequest, func(c context.Context,
method, url string) httputils.Ireq {
return req
@@ -145,7 +144,7 @@ var _ = Describe("AgentServer", func() {
Context("backup", func() {
It("backup failed", func() {
- req.EXPECT().Send(gomock.Any()).Return(-1,
fmt.Errorf("error"))
+
req.EXPECT().Send(gomock.Any()).Return(fmt.Errorf("error"))
_, err := as.Backup(&model.BackupIn{})
Expect(err).ShouldNot(BeNil())
})
@@ -153,7 +152,7 @@ var _ = Describe("AgentServer", func() {
It("backup success", func() {
req.EXPECT().Send(gomock.Any()).Do(func(i
*model.BackupOutResp) {
i.Data.ID = "backup-id"
- }).Return(200, nil)
+ }).Return(nil)
as := NewAgentServer("http://agent-server:18080")
resp, err := as.Backup(&model.BackupIn{})
Expect(err).Should(BeNil())
@@ -163,13 +162,13 @@ var _ = Describe("AgentServer", func() {
Context("restore", func() {
It("restore failed", func() {
- req.EXPECT().Send(gomock.Any()).Return(-1,
fmt.Errorf("error"))
+
req.EXPECT().Send(gomock.Any()).Return(fmt.Errorf("error"))
err := as.Restore(&model.RestoreIn{})
Expect(err).ShouldNot(BeNil())
})
// restore success
It("restore success", func() {
- req.EXPECT().Send(gomock.Any()).Return(200, nil)
+ req.EXPECT().Send(gomock.Any()).Return(nil)
err := as.Restore(&model.RestoreIn{})
Expect(err).Should(BeNil())
})
@@ -178,7 +177,7 @@ var _ = Describe("AgentServer", func() {
Context("show detail", func() {
It("show detail failed", func() {
- req.EXPECT().Send(gomock.Any()).Return(-1,
fmt.Errorf("error"))
+
req.EXPECT().Send(gomock.Any()).Return(fmt.Errorf("error"))
_, err := as.ShowDetail(&model.ShowDetailIn{})
Expect(err).ShouldNot(BeNil())
})
@@ -186,7 +185,7 @@ var _ = Describe("AgentServer", func() {
It("show detail success", func() {
req.EXPECT().Send(gomock.Any()).Do(func(i
*model.BackupDetailResp) {
i.Data = model.BackupInfo{}
- }).Return(200, nil)
+ }).Return(nil)
resp, err := as.ShowDetail(&model.ShowDetailIn{})
Expect(err).Should(BeNil())
Expect(resp).Should(Equal(&model.BackupInfo{}))
@@ -195,7 +194,7 @@ var _ = Describe("AgentServer", func() {
Context("show list", func() {
It("show list failed", func() {
- req.EXPECT().Send(gomock.Any()).Return(-1,
fmt.Errorf("error"))
+
req.EXPECT().Send(gomock.Any()).Return(fmt.Errorf("error"))
_, err := as.ShowList(&model.ShowListIn{})
Expect(err).ShouldNot(BeNil())
})
@@ -203,7 +202,7 @@ var _ = Describe("AgentServer", func() {
It("show list success", func() {
req.EXPECT().Send(gomock.Any()).Do(func(i
*model.BackupListResp) {
i.Data = []model.BackupInfo{}
- }).Return(200, nil)
+ }).Return(nil)
resp, err := as.ShowList(&model.ShowListIn{})
Expect(err).Should(BeNil())
Expect(resp).Should(Equal([]model.BackupInfo{}))
diff --git a/pitr/cli/internal/pkg/mocks/agent-server.go
b/pitr/cli/internal/pkg/mocks/agent-server.go
index e736033..c9047d8 100644
--- a/pitr/cli/internal/pkg/mocks/agent-server.go
+++ b/pitr/cli/internal/pkg/mocks/agent-server.go
@@ -50,17 +50,17 @@ func (mr *MockIAgentServerMockRecorder) Backup(in
interface{}) *gomock.Call {
}
// CheckStatus mocks base method.
-func (m *MockIAgentServer) CheckStatus() error {
+func (m *MockIAgentServer) CheckStatus(in *model.HealthCheckIn) error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "CheckStatus")
+ ret := m.ctrl.Call(m, "CheckStatus", in)
ret0, _ := ret[0].(error)
return ret0
}
// CheckStatus indicates an expected call of CheckStatus.
-func (mr *MockIAgentServerMockRecorder) CheckStatus() *gomock.Call {
+func (mr *MockIAgentServerMockRecorder) CheckStatus(in interface{})
*gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckStatus",
reflect.TypeOf((*MockIAgentServer)(nil).CheckStatus))
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckStatus",
reflect.TypeOf((*MockIAgentServer)(nil).CheckStatus), in)
}
// DeleteBackup mocks base method.
diff --git a/pitr/cli/internal/pkg/model/as_healthcheck.go
b/pitr/cli/internal/pkg/model/as_healthcheck.go
new file mode 100644
index 0000000..4dae579
--- /dev/null
+++ b/pitr/cli/internal/pkg/model/as_healthcheck.go
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 model
+
+type HealthCheckIn struct {
+ DBPort uint16 `json:"db_port"`
+ DBName string `json:"db_name"`
+ Username string `json:"username"`
+ Password string `json:"password"`
+}
diff --git a/pitr/cli/internal/pkg/xerr/err.go
b/pitr/cli/internal/pkg/xerr/err.go
index 5e363d6..66f8dd3 100644
--- a/pitr/cli/internal/pkg/xerr/err.go
+++ b/pitr/cli/internal/pkg/xerr/err.go
@@ -24,6 +24,8 @@ type err struct {
}
const (
+ postErrFmt = "httputils.NewRequest[url=%s,body=%v,out=%v] return
err=%s,wrap=%w"
+
Unknown = "Unknown error"
InvalidHTTPStatus = "Invalid http status"
NotFound = "Not found"
@@ -39,6 +41,10 @@ func NewCliErr(msg string) error {
}
}
+func NewUnknownErr(url string, in, out interface{}, err error) error {
+ return fmt.Errorf(postErrFmt, url, in, out, err, NewCliErr(Unknown))
+}
+
func NewAgentServerErr(code int, msg string) error {
return &err{
msg: fmt.Sprintf("agent server err[code=%d,msg=%s]", code, msg),
diff --git a/pitr/cli/pkg/httputils/mocks/req.go
b/pitr/cli/pkg/httputils/mocks/req.go
index 0cfe247..c7bc91a 100644
--- a/pitr/cli/pkg/httputils/mocks/req.go
+++ b/pitr/cli/pkg/httputils/mocks/req.go
@@ -1,22 +1,5 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements. See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You 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.
- */
-
// Code generated by MockGen. DO NOT EDIT.
-// Source: pkg/httputils/req.go
+// Source: req.go
// Package mock_httputils is a generated GoMock package.
package mock_httputils
@@ -87,12 +70,11 @@ func (mr *MockIreqMockRecorder) Query(m interface{})
*gomock.Call {
}
// Send mocks base method.
-func (m *MockIreq) Send(body any) (int, error) {
+func (m *MockIreq) Send(body any) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", body)
- ret0, _ := ret[0].(int)
- ret1, _ := ret[1].(error)
- return ret0, ret1
+ ret0, _ := ret[0].(error)
+ return ret0
}
// Send indicates an expected call of Send.
diff --git a/pitr/cli/pkg/httputils/req.go b/pitr/cli/pkg/httputils/req.go
index 7d99079..61ae871 100644
--- a/pitr/cli/pkg/httputils/req.go
+++ b/pitr/cli/pkg/httputils/req.go
@@ -26,6 +26,8 @@ import (
"io"
"net/http"
"strings"
+
+ "github.com/google/uuid"
)
type req struct {
@@ -41,7 +43,7 @@ type Ireq interface {
Header(h map[string]string)
Body(b any)
Query(m map[string]string)
- Send(body any) (int, error)
+ Send(body any) error
}
func NewRequest(ctx context.Context, method, url string) Ireq {
@@ -68,7 +70,7 @@ func (r *req) Query(m map[string]string) {
r.query = m
}
-func (r *req) Send(body any) (int, error) {
+func (r *req) Send(body any) error {
var (
bs []byte
err error
@@ -77,19 +79,29 @@ func (r *req) Send(body any) (int, error) {
if r.body != nil {
bs, err = json.Marshal(r.body)
if err != nil {
- return -1, fmt.Errorf("json.Marshal return err=%w", err)
+ return fmt.Errorf("json.Marshal return err=%w", err)
}
}
_req, err := http.NewRequestWithContext(r.ctx, r.method, r.url,
bytes.NewReader(bs))
if err != nil {
- return -1, fmt.Errorf("new request failure,err=%w", err)
+ return fmt.Errorf("new request failure,err=%w", err)
}
for k, v := range r.header {
_req.Header.Set(k, v)
}
+ // set default header
+ if r.method == http.MethodPost {
+ if _req.Header.Get("Content-Type") == "" {
+ _req.Header.Set("Content-Type", "application/json")
+ }
+ if _req.Header.Get("x-request-id") == "" {
+ _req.Header.Set("x-request-id", uuid.New().String())
+ }
+ }
+
for k, v := range r.query {
values := _req.URL.Query()
values.Add(k, v)
@@ -103,20 +115,24 @@ func (r *req) Send(body any) (int, error) {
c := &http.Client{Transport: tr}
resp, err := c.Do(_req)
if err != nil {
- return -1, fmt.Errorf("http request err=%w", err)
+ return fmt.Errorf("http request err=%w", err)
}
defer resp.Body.Close()
all, err := io.ReadAll(resp.Body)
if err != nil {
- return -1, fmt.Errorf("invalid response,err=%w", err)
+ return fmt.Errorf("invalid response,err=%w", err)
}
if body != nil {
if err = json.Unmarshal(all, body); err != nil {
- return -1, fmt.Errorf("json unmarshal return err=%w",
err)
+ return fmt.Errorf("json unmarshal return err=%w", err)
}
}
- return resp.StatusCode, nil
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("response status code is not 200, code=%d",
resp.StatusCode)
+ }
+
+ return nil
}
diff --git
a/shardingsphere-operator/pkg/kubernetes/deployment/deployment_test.go
b/shardingsphere-operator/pkg/kubernetes/deployment/deployment_test.go
index 2267ff0..d1270cd 100644
--- a/shardingsphere-operator/pkg/kubernetes/deployment/deployment_test.go
+++ b/shardingsphere-operator/pkg/kubernetes/deployment/deployment_test.go
@@ -273,7 +273,7 @@ func Test_NewDeployment(t *testing.T) {
"k1": "v1",
},
Annotations: map[string]string{
- "anno1": "value1",
+
defaultAnnotationJavaAgentEnabled: "true",
},
},
Spec: appsv1.DeploymentSpec{