Skip to content

Commit 9094d4a

Browse files
committed
replace get info with a http call
1 parent 980e90e commit 9094d4a

File tree

13 files changed

+242
-47
lines changed

13 files changed

+242
-47
lines changed

cmd/pgbackrest-server/api/info.go

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,6 @@ import (
1010
"github.com/superfly/percona-postgresql-operator/cmd/pgbackrest-server/exec"
1111
)
1212

13-
type InfoCommandOutput []InfoStanza
14-
15-
type InfoStanza struct {
16-
Name string `json:"name,omitempty"`
17-
Backup []InfoBackup `json:"backup,omitempty"`
18-
Status struct {
19-
Message string `json:"message,omitempty"`
20-
Code float64 `json:"code,omitempty"`
21-
Lock struct {
22-
Backup struct {
23-
Held bool `json:"held,omitempty"`
24-
} `json:"backup,omitempty"`
25-
} `json:"lock,omitempty"`
26-
} `json:"status,omitempty"`
27-
}
28-
29-
type InfoBackup struct {
30-
Annotation map[string]string `json:"annotation,omitempty"`
31-
Label string `json:"label,omitempty"`
32-
Type PGBackupType `json:"type,omitempty"`
33-
Timestamp struct {
34-
Start int64 `json:"start,omitempty"`
35-
Stop int64 `json:"stop,omitempty"`
36-
} `json:"timestamp,omitempty"`
37-
}
38-
39-
type PGBackupType string
40-
41-
const (
42-
PGBackupTypeFull PGBackupType = "full"
43-
PGBackupTypeDifferential PGBackupType = "differential"
44-
PGBackupTypeIncremental PGBackupType = "incremental"
45-
)
46-
4713
type InfoCommandOptions struct {
4814
// General Options
4915
Stanza string `json:"stanza"` // Required
@@ -141,7 +107,7 @@ func InfoCommandHandler(w http.ResponseWriter, r *http.Request) {
141107
return
142108
}
143109

144-
// var output InfoCommandOutput
110+
// var output InfoOutput
145111
// if err := json.Unmarshal(stdout.Bytes(), &output); err != nil {
146112
// // return InfoCommandOutput{}, errors.Wrap(err, "failed to unmarshal pgBackRest info output")
147113
// http.Error(w, fmt.Sprintf("could not decode output from pgbackrest info command: %v", err), http.StatusInternalServerError)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package api
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package api

cmd/pgbackrest-server/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func main() {
1313
r = r.PathPrefix("/pgbackrest").Subrouter()
1414

1515
// Endpoints
16-
r.HandleFunc("/info", api.InfoCommandHandler)
16+
r.HandleFunc("/info", api.InfoCommandHandler).Methods("POST")
1717

1818
http.Handle("/", r)
1919
err := http.ListenAndServe(":4422", nil)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/google/go-cmp v0.6.0
1414
github.com/google/uuid v1.6.0
1515
github.com/gorilla/mux v1.8.1
16+
github.com/hashicorp/go-cleanhttp v0.5.2
1617
github.com/hashicorp/go-version v1.7.0
1718
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0
1819
github.com/onsi/ginkgo/v2 v2.22.2

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa
113113
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
114114
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
115115
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
116+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
117+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
116118
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
117119
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
118120
github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc=

internal/feature/features.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ const (
8686

8787
// Support VolumeSnapshots
8888
VolumeSnapshots = "VolumeSnapshots"
89+
90+
// Use HTTP for interacting with pgBackRest
91+
PGBackRestHTTP = "PGBackRestHTTP"
8992
)
9093

9194
// NewGate returns a MutableGate with the Features defined in this package.
@@ -101,6 +104,7 @@ func NewGate() MutableGate {
101104
PGBouncerSidecars: {Default: false, PreRelease: featuregate.Alpha},
102105
TablespaceVolumes: {Default: false, PreRelease: featuregate.Alpha},
103106
VolumeSnapshots: {Default: false, PreRelease: featuregate.Alpha},
107+
PGBackRestHTTP: {Default: true, PreRelease: featuregate.Alpha},
104108
}); err != nil {
105109
panic(err)
106110
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"reflect"
8+
"strings"
9+
10+
"github.com/superfly/percona-postgresql-operator/internal/pgbackrest-server/exec"
11+
)
12+
13+
type InfoCommandOptions struct {
14+
// General Options
15+
Stanza string `json:"stanza"` // Required
16+
Config string `json:"config,omitempty"`
17+
ConfigIncludePath string `json:"config_include_path,omitempty"`
18+
ConfigPath string `json:"config_path,omitempty"`
19+
Output string `json:"output,omitempty"`
20+
21+
// Backup Set & Filter Options
22+
BackupSet string `json:"set,omitempty"`
23+
DBInclude []string `json:"db_include,omitempty"`
24+
Type string `json:"type,omitempty"`
25+
26+
// Archive Options
27+
ArchiveCheck bool `json:"archive_check,omitempty"`
28+
ArchiveCopy bool `json:"archive_copy,omitempty"`
29+
30+
// Repository Options
31+
Repo int `json:"repo,omitempty"`
32+
RepoPath string `json:"repo_path,omitempty"`
33+
RepoType string `json:"repo_type,omitempty"`
34+
RepoHardlink bool `json:"repo_hardlink,omitempty"`
35+
RepoRetentionFull int `json:"repo_retention_full,omitempty"`
36+
RepoRetentionFullType string `json:"repo_retention_full_type,omitempty"`
37+
38+
// S3 Repository Options
39+
RepoS3Bucket string `json:"repo_s3_bucket,omitempty"`
40+
RepoS3Endpoint string `json:"repo_s3_endpoint,omitempty"`
41+
RepoS3Region string `json:"repo_s3_region,omitempty"`
42+
}
43+
44+
func (c InfoCommandOptions) AsSlice() []string {
45+
var cmd []string
46+
47+
val := reflect.ValueOf(c)
48+
typ := val.Type()
49+
50+
for i := range val.NumField() {
51+
jsonTag := typ.Field(i).Tag.Get("json")
52+
if jsonTag == "" || jsonTag == "-" {
53+
continue
54+
}
55+
56+
field := val.Field(i)
57+
parts := strings.Split(jsonTag, ",")
58+
jsonKey := parts[0]
59+
isOmitEmpty := len(parts) > 1 && parts[1] == "omitempty"
60+
61+
if isOmitEmpty && field.IsZero() {
62+
continue
63+
}
64+
65+
flag := "--" + strings.ReplaceAll(jsonKey, "_", "-")
66+
67+
switch field.Kind() {
68+
case reflect.String:
69+
if strVal := field.String(); strVal != "" || !isOmitEmpty {
70+
cmd = append(cmd, fmt.Sprintf(" %s=%s", flag, strVal))
71+
}
72+
case reflect.Int, reflect.Int64:
73+
if intVal := field.Int(); intVal != 0 || !isOmitEmpty {
74+
cmd = append(cmd, fmt.Sprintf(" %s=%d", flag, intVal))
75+
}
76+
case reflect.Bool:
77+
if field.Bool() {
78+
cmd = append(cmd, fmt.Sprintf(" %s", flag))
79+
}
80+
case reflect.Slice:
81+
if field.Type().Elem().Kind() == reflect.String {
82+
for j := range field.Len() {
83+
cmd = append(cmd, fmt.Sprintf(" %s=%s", flag, field.Index(j).String()))
84+
}
85+
}
86+
}
87+
}
88+
89+
return cmd
90+
}
91+
92+
func InfoCommandHandler(w http.ResponseWriter, r *http.Request) {
93+
var opts InfoCommandOptions
94+
if err := json.NewDecoder(r.Body).Decode(&opts); err != nil {
95+
http.Error(w, fmt.Sprintf("could not decode json body: %v", err), http.StatusBadRequest)
96+
return
97+
}
98+
99+
cmd := exec.BackrestCommand{
100+
Command: "info",
101+
Opts: opts.AsSlice(),
102+
}
103+
104+
stdout, _, err := cmd.Run(r.Context())
105+
if err != nil {
106+
http.Error(w, fmt.Sprintf("failed to run pgbackrest info command: %v", err), http.StatusInternalServerError)
107+
return
108+
}
109+
110+
// var output InfoOutput
111+
// if err := json.Unmarshal(stdout.Bytes(), &output); err != nil {
112+
// // return InfoCommandOutput{}, errors.Wrap(err, "failed to unmarshal pgBackRest info output")
113+
// http.Error(w, fmt.Sprintf("could not decode output from pgbackrest info command: %v", err), http.StatusInternalServerError)
114+
// return
115+
// }
116+
117+
w.WriteHeader(http.StatusOK)
118+
w.Write(stdout.Bytes())
119+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package api
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package api

0 commit comments

Comments
 (0)