2020-04-24 19:35:03 +00:00
package snapshot
import (
"encoding/json"
"errors"
2024-02-08 14:52:00 +00:00
"flag"
2020-04-24 19:35:03 +00:00
"fmt"
2022-08-21 21:13:44 +00:00
"io"
2020-04-24 19:35:03 +00:00
"net/http"
"net/url"
2024-02-08 14:52:00 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputils"
2020-04-24 19:35:03 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
)
2024-02-08 14:52:00 +00:00
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 ` )
)
2020-04-24 19:35:03 +00:00
type snapshot struct {
Status string ` json:"status" `
Snapshot string ` json:"snapshot" `
Msg string ` json:"msg" `
}
2022-05-04 19:12:03 +00:00
// Create creates a snapshot via the provided api endpoint and returns the snapshot name
2020-04-24 19:35:03 +00:00
func Create ( createSnapshotURL string ) ( string , error ) {
2020-11-23 15:09:59 +00:00
logger . Infof ( "Creating snapshot" )
2020-04-24 19:35:03 +00:00
u , err := url . Parse ( createSnapshotURL )
if err != nil {
return "" , err
}
2024-02-08 14:52:00 +00:00
// create Transport
tr , err := httputils . Transport ( createSnapshotURL , * tlsCertFile , * tlsKeyFile , * tlsCAFile , * tlsServerName , * tlsInsecureSkipVerify )
if err != nil {
2024-08-16 09:32:04 +00:00
return "" , fmt . Errorf ( "failed to create transport for createSnapshotURL=%q: %s" , createSnapshotURL , err )
2024-02-08 14:52:00 +00:00
}
hc := & http . Client { Transport : tr }
resp , err := hc . Get ( u . String ( ) )
2020-04-24 19:35:03 +00:00
if err != nil {
return "" , err
}
2022-08-21 21:13:44 +00:00
body , err := io . ReadAll ( resp . Body )
2020-04-24 19:35:03 +00:00
if err != nil {
return "" , err
}
2020-11-30 12:49:07 +00:00
if resp . StatusCode != http . StatusOK {
2024-04-24 11:47:57 +00:00
return "" , fmt . Errorf ( "unexpected status code returned from %q: %d; expecting %d; response body: %q" , u . Redacted ( ) , resp . StatusCode , http . StatusOK , body )
2020-11-30 12:49:07 +00:00
}
2020-04-24 19:35:03 +00:00
snap := snapshot { }
err = json . Unmarshal ( body , & snap )
if err != nil {
2024-04-24 11:47:57 +00:00
return "" , fmt . Errorf ( "cannot parse JSON response from %q: %w; response body: %q" , u . Redacted ( ) , err , body )
2020-04-24 19:35:03 +00:00
}
if snap . Status == "ok" {
logger . Infof ( "Snapshot %s created" , snap . Snapshot )
return snap . Snapshot , nil
2023-11-02 20:37:49 +00:00
}
if snap . Status == "error" {
2020-04-24 19:35:03 +00:00
return "" , errors . New ( snap . Msg )
}
2024-04-24 11:47:57 +00:00
return "" , fmt . Errorf ( "Unkown status: %v" , snap . Status )
2020-04-24 19:35:03 +00:00
}
2022-05-04 19:12:03 +00:00
// Delete deletes a snapshot via the provided api endpoint
2020-04-24 19:35:03 +00:00
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
}
2024-02-08 14:52:00 +00:00
// create Transport
tr , err := httputils . Transport ( deleteSnapshotURL , * tlsCertFile , * tlsKeyFile , * tlsCAFile , * tlsServerName , * tlsInsecureSkipVerify )
if err != nil {
2024-08-16 09:32:04 +00:00
return fmt . Errorf ( "failed to create transport for deleteSnapshotURL=%q: %s" , deleteSnapshotURL , err )
2024-02-08 14:52:00 +00:00
}
hc := & http . Client { Transport : tr }
resp , err := hc . PostForm ( u . String ( ) , formData )
2020-04-24 19:35:03 +00:00
if err != nil {
return err
}
2022-08-21 21:13:44 +00:00
body , err := io . ReadAll ( resp . Body )
2020-04-24 19:35:03 +00:00
if err != nil {
return err
}
2020-11-30 12:49:07 +00:00
if resp . StatusCode != http . StatusOK {
2024-04-24 11:47:57 +00:00
return fmt . Errorf ( "unexpected status code returned from %q: %d; expecting %d; response body: %q" , u . Redacted ( ) , resp . StatusCode , http . StatusOK , body )
2020-11-30 12:49:07 +00:00
}
2020-04-24 19:35:03 +00:00
snap := snapshot { }
err = json . Unmarshal ( body , & snap )
if err != nil {
2024-04-24 11:47:57 +00:00
return fmt . Errorf ( "cannot parse JSON response from %q: %w; response body: %q" , u . Redacted ( ) , err , body )
2020-04-24 19:35:03 +00:00
}
if snap . Status == "ok" {
logger . Infof ( "Snapshot %s deleted" , snapshotName )
return nil
2023-11-02 20:37:49 +00:00
}
if snap . Status == "error" {
2020-04-24 19:35:03 +00:00
return errors . New ( snap . Msg )
}
2024-04-24 11:47:57 +00:00
return fmt . Errorf ( "Unkown status: %v" , snap . Status )
2020-04-24 19:35:03 +00:00
}