github.com/weaviate/weaviate@v1.24.6/adapters/clients/cluster_backups.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package clients 13 14 import ( 15 "bytes" 16 "context" 17 "encoding/json" 18 "fmt" 19 "io" 20 "net/http" 21 "net/url" 22 23 "github.com/weaviate/weaviate/usecases/backup" 24 ) 25 26 const ( 27 pathCanCommit = "/backups/can-commit" 28 pathCommit = "/backups/commit" 29 pathStatus = "/backups/status" 30 pathAbort = "/backups/abort" 31 ) 32 33 type ClusterBackups struct { 34 client *http.Client 35 } 36 37 func NewClusterBackups(client *http.Client) *ClusterBackups { 38 return &ClusterBackups{client: client} 39 } 40 41 func (c *ClusterBackups) CanCommit(ctx context.Context, 42 host string, req *backup.Request, 43 ) (*backup.CanCommitResponse, error) { 44 url := url.URL{Scheme: "http", Host: host, Path: pathCanCommit} 45 46 b, err := json.Marshal(req) 47 if err != nil { 48 return nil, fmt.Errorf("marshal can-commit request: %w", err) 49 } 50 51 httpReq, err := http.NewRequest(http.MethodPost, url.String(), bytes.NewReader(b)) 52 if err != nil { 53 return nil, fmt.Errorf("new can-commit request: %w", err) 54 } 55 56 respBody, statusCode, err := c.do(httpReq) 57 if err != nil { 58 return nil, fmt.Errorf("can-commit request: %w", err) 59 } 60 61 if statusCode != http.StatusOK { 62 return nil, fmt.Errorf("unexpected status code %d (%s)", 63 statusCode, respBody) 64 } 65 66 var resp backup.CanCommitResponse 67 err = json.Unmarshal(respBody, &resp) 68 if err != nil { 69 return nil, fmt.Errorf("unmarshal can-commit response: %w", err) 70 } 71 72 return &resp, nil 73 } 74 75 func (c *ClusterBackups) Commit(ctx context.Context, 76 host string, req *backup.StatusRequest, 77 ) error { 78 url := url.URL{Scheme: "http", Host: host, Path: pathCommit} 79 80 b, err := json.Marshal(req) 81 if err != nil { 82 return fmt.Errorf("marshal commit request: %w", err) 83 } 84 85 httpReq, err := http.NewRequest(http.MethodPost, url.String(), bytes.NewReader(b)) 86 if err != nil { 87 return fmt.Errorf("new commit request: %w", err) 88 } 89 90 respBody, statusCode, err := c.do(httpReq) 91 if err != nil { 92 return fmt.Errorf("commit request: %w", err) 93 } 94 95 if statusCode != http.StatusCreated { 96 return fmt.Errorf("unexpected status code %d (%s)", 97 statusCode, respBody) 98 } 99 100 return nil 101 } 102 103 func (c *ClusterBackups) Status(ctx context.Context, 104 host string, req *backup.StatusRequest, 105 ) (*backup.StatusResponse, error) { 106 url := url.URL{Scheme: "http", Host: host, Path: pathStatus} 107 108 b, err := json.Marshal(req) 109 if err != nil { 110 return nil, fmt.Errorf("marshal status request: %w", err) 111 } 112 113 httpReq, err := http.NewRequest(http.MethodPost, url.String(), bytes.NewReader(b)) 114 if err != nil { 115 return nil, fmt.Errorf("new status request: %w", err) 116 } 117 118 respBody, statusCode, err := c.do(httpReq) 119 if err != nil { 120 return nil, fmt.Errorf("status request: %w", err) 121 } 122 123 if statusCode != http.StatusOK { 124 return nil, fmt.Errorf("unexpected status code %d (%s)", 125 statusCode, respBody) 126 } 127 128 var resp backup.StatusResponse 129 err = json.Unmarshal(respBody, &resp) 130 if err != nil { 131 return nil, fmt.Errorf("unmarshal status response: %w", err) 132 } 133 134 return &resp, nil 135 } 136 137 func (c *ClusterBackups) Abort(_ context.Context, 138 host string, req *backup.AbortRequest, 139 ) error { 140 url := url.URL{Scheme: "http", Host: host, Path: pathAbort} 141 142 b, err := json.Marshal(req) 143 if err != nil { 144 return fmt.Errorf("marshal abort request: %w", err) 145 } 146 147 httpReq, err := http.NewRequest(http.MethodPost, url.String(), bytes.NewReader(b)) 148 if err != nil { 149 return fmt.Errorf("new abort request: %w", err) 150 } 151 152 respBody, statusCode, err := c.do(httpReq) 153 if err != nil { 154 return fmt.Errorf("abort request: %w", err) 155 } 156 157 if statusCode != http.StatusNoContent { 158 return fmt.Errorf("unexpected status code %d (%s)", 159 statusCode, respBody) 160 } 161 162 return nil 163 } 164 165 func (c *ClusterBackups) do(req *http.Request) (body []byte, statusCode int, err error) { 166 httpResp, err := c.client.Do(req) 167 if err != nil { 168 return nil, 0, fmt.Errorf("make request: %w", err) 169 } 170 171 body, err = io.ReadAll(httpResp.Body) 172 if err != nil { 173 return nil, httpResp.StatusCode, fmt.Errorf("read response: %w", err) 174 } 175 defer httpResp.Body.Close() 176 177 return body, httpResp.StatusCode, nil 178 }