mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
029060af60
The new flag type is supposed to be used for specifying URL values which could contain sensitive information such as auth tokens in GET params or HTTP basic authentication. The URL flag also allows loading its value from files if `file://` prefix is specified. As example, the new flag type was used in app/vmbackup as it requires specifying `authKey` param for making the snapshot. See related issue https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5973 Thanks to @wasim-nihal for initial implementation https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6060 --------- Signed-off-by: hagen1778 <roman@victoriametrics.com>
115 lines
3.5 KiB
Go
115 lines
3.5 KiB
Go
package snapshot
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputils"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
|
)
|
|
|
|
var (
|
|
tlsInsecureSkipVerify = flag.Bool("snapshot.tlsInsecureSkipVerify", false, "Whether to skip tls verification when connecting to -snapshotCreateURL")
|
|
tlsCertFile = flag.String("snapshot.tlsCertFile", "", "Optional path to client-side TLS certificate file to use when connecting to -snapshotCreateURL")
|
|
tlsKeyFile = flag.String("snapshot.tlsKeyFile", "", "Optional path to client-side TLS certificate key to use when connecting to -snapshotCreateURL")
|
|
tlsCAFile = flag.String("snapshot.tlsCAFile", "", `Optional path to TLS CA file to use for verifying connections to -snapshotCreateURL. By default, system CA is used`)
|
|
tlsServerName = flag.String("snapshot.tlsServerName", "", `Optional TLS server name to use for connections to -snapshotCreateURL. By default, the server name from -snapshotCreateURL is used`)
|
|
)
|
|
|
|
type snapshot struct {
|
|
Status string `json:"status"`
|
|
Snapshot string `json:"snapshot"`
|
|
Msg string `json:"msg"`
|
|
}
|
|
|
|
// Create creates a snapshot via the provided api endpoint and returns the snapshot name
|
|
func Create(createSnapshotURL string) (string, error) {
|
|
logger.Infof("Creating snapshot")
|
|
u, err := url.Parse(createSnapshotURL)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// create Transport
|
|
tr, err := httputils.Transport(createSnapshotURL, *tlsCertFile, *tlsKeyFile, *tlsCAFile, *tlsServerName, *tlsInsecureSkipVerify)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
hc := &http.Client{Transport: tr}
|
|
|
|
resp, err := hc.Get(u.String())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("unexpected status code: %d; expecting %d; response body: %q", resp.StatusCode, http.StatusOK, body)
|
|
}
|
|
|
|
snap := snapshot{}
|
|
err = json.Unmarshal(body, &snap)
|
|
if err != nil {
|
|
return "", fmt.Errorf("cannot parse JSON response: %w; response body: %q", err, body)
|
|
}
|
|
|
|
if snap.Status == "ok" {
|
|
logger.Infof("Snapshot %s created", snap.Snapshot)
|
|
return snap.Snapshot, nil
|
|
}
|
|
if snap.Status == "error" {
|
|
return "", errors.New(snap.Msg)
|
|
}
|
|
return "", fmt.Errorf("unknown status: %v", snap.Status)
|
|
}
|
|
|
|
// Delete deletes a snapshot via the provided api endpoint
|
|
func Delete(deleteSnapshotURL string, snapshotName string) error {
|
|
logger.Infof("Deleting snapshot %s", snapshotName)
|
|
formData := url.Values{
|
|
"snapshot": {snapshotName},
|
|
}
|
|
u, err := url.Parse(deleteSnapshotURL)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// create Transport
|
|
tr, err := httputils.Transport(deleteSnapshotURL, *tlsCertFile, *tlsKeyFile, *tlsCAFile, *tlsServerName, *tlsInsecureSkipVerify)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hc := &http.Client{Transport: tr}
|
|
resp, err := hc.PostForm(u.String(), formData)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.StatusCode != http.StatusOK {
|
|
return fmt.Errorf("unexpected status code: %d; expecting %d; response body: %q", resp.StatusCode, http.StatusOK, body)
|
|
}
|
|
|
|
snap := snapshot{}
|
|
err = json.Unmarshal(body, &snap)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot parse JSON response: %w; response body: %q", err, body)
|
|
}
|
|
|
|
if snap.Status == "ok" {
|
|
logger.Infof("Snapshot %s deleted", snapshotName)
|
|
return nil
|
|
}
|
|
if snap.Status == "error" {
|
|
return errors.New(snap.Msg)
|
|
}
|
|
return fmt.Errorf("unknown status: %v", snap.Status)
|
|
}
|