Skip to content

Commit

Permalink
Add support for getting snapshots for a repository (#983)
Browse files Browse the repository at this point in the history
  • Loading branch information
wesleyk authored and olivere committed Dec 1, 2018
1 parent b100010 commit f7e6cd8
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 17 deletions.
5 changes: 5 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,11 @@ func (c *Client) SnapshotGetRepository(repositories ...string) *SnapshotGetRepos
return NewSnapshotGetRepositoryService(c).Repository(repositories...)
}

// SnapshotGet lists snapshot for a repository.
func (c *Client) SnapshotGet(repository string) *SnapshotGetService {
return NewSnapshotGetService(c).Repository(repository)
}

// SnapshotVerifyRepository verifies a snapshot repository.
func (c *Client) SnapshotVerifyRepository(repository string) *SnapshotVerifyRepositoryService {
return NewSnapshotVerifyRepositoryService(c).Repository(repository)
Expand Down
18 changes: 1 addition & 17 deletions snapshot_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"encoding/json"
"fmt"
"net/url"
"time"

"github.com/olivere/elastic/uritemplates"
)
Expand Down Expand Up @@ -172,20 +171,5 @@ type SnapshotCreateResponse struct {
Accepted *bool `json:"accepted"`

// Snapshot is available when waitForCompletion is true.
Snapshot *struct {
Snapshot string `json:"snapshot"`
UUID string `json:"uuid"`
VersionID int `json:"version_id"`
Version string `json:"version"`
Indices []string `json:"indices"`
State string `json:"state"`
Reason string `json:"reason"`
StartTime time.Time `json:"start_time"`
StartTimeInMillis int64 `json:"start_time_in_millis"`
EndTime time.Time `json:"end_time"`
EndTimeInMillis int64 `json:"end_time_in_millis"`
DurationInMillis int64 `json:"duration_in_millis"`
Failures []SnapshotShardFailure `json:"failures"`
Shards *ShardsInfo `json:"shards"`
} `json:"snapshot"`
Snapshot *Snapshot `json:"snapshot"`
}
165 changes: 165 additions & 0 deletions snapshot_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"

"github.com/olivere/elastic/uritemplates"
)

// SnapshotGetService lists the snapshots on a repository
// See https://www.elastic.co/guide/en/elasticsearch/reference/6.2/modules-snapshots.html
// for details.
type SnapshotGetService struct {
client *Client
repository string
snapshot []string
masterTimeout string
ignoreUnavailable bool
verbose bool
}

// NewSnapshotGetService creates a new SnapshotGetService.
func NewSnapshotGetService(client *Client) *SnapshotGetService {
return &SnapshotGetService{
client: client,
snapshot: make([]string, 0),
}
}

// Repository is the repository name.
func (s *SnapshotGetService) Repository(repository string) *SnapshotGetService {
s.repository = repository
return s
}

// Snapshot is the list of snapshot names. If not set, defaults to all snapshots.
func (s *SnapshotGetService) Snapshot(snapshots ...string) *SnapshotGetService {
s.snapshot = append(s.snapshot, snapshots...)
return s
}

// MasterTimeout specifies an explicit operation timeout for connection to master node.
func (s *SnapshotGetService) MasterTimeout(masterTimeout string) *SnapshotGetService {
s.masterTimeout = masterTimeout
return s
}

// IgnoreUnavailable specifies whether to ignore unavailable snapshots, defaults to false
func (s *SnapshotGetService) IgnoreUnavailable(ignoreUnavailable bool) *SnapshotGetService {
s.ignoreUnavailable = ignoreUnavailable
return s
}

// Verbose specifies whether to show verbose snapshot info or only show the basic info found in the repository index blob
func (s *SnapshotGetService) Verbose(verbose bool) *SnapshotGetService {
s.verbose = verbose
return s
}

// buildURL builds the URL for the operation.
func (s *SnapshotGetService) buildURL() (string, url.Values, error) {
// Build URL
var err error
var path string
if len(s.snapshot) > 0 {
path, err = uritemplates.Expand("/_snapshot/{repository}/{snapshot}", map[string]string{
"repository": s.repository,
"snapshot": strings.Join(s.snapshot, ","),
})
} else {
path, err = uritemplates.Expand("/_snapshot/{repository}/_all", map[string]string{
"repository": s.repository,
})
}
if err != nil {
return "", url.Values{}, err
}

// Add query string parameters
params := url.Values{}
if s.masterTimeout != "" {
params.Set("master_timeout", s.masterTimeout)
}
if s.ignoreUnavailable {
params.Set("ignore_unavailable", "true")
}
if s.verbose {
params.Set("verbose", "true")
}
return path, params, nil
}

// Validate checks if the operation is valid.
func (s *SnapshotGetService) Validate() error {
var invalid []string
if s.repository == "" {
invalid = append(invalid, "Repository")
}
if len(invalid) > 0 {
return fmt.Errorf("missing required fields: %v", invalid)
}
return nil
}

// Do executes the operation.
func (s *SnapshotGetService) Do(ctx context.Context) (*SnapshotGetResponse, error) {
// Check pre-conditions
if err := s.Validate(); err != nil {
return nil, err
}

// Get URL for request
path, params, err := s.buildURL()
if err != nil {
return nil, err
}

// Get HTTP response
res, err := s.client.PerformRequest(ctx, PerformRequestOptions{
Method: "GET",
Path: path,
Params: params,
})
if err != nil {
return nil, err
}

// Return operation response
ret := new(SnapshotGetResponse)
if err := json.Unmarshal(res.Body, ret); err != nil {
return nil, err
}
return ret, nil
}

// SnapshotGetResponse is the response of SnapshotGetService.Do.
type SnapshotGetResponse struct {
Snapshots []*Snapshot `json:"snapshots"`
}

// Snapshot contains all information about a single snapshot
type Snapshot struct {
Snapshot string `json:"snapshot"`
UUID string `json:"uuid"`
VersionID int `json:"version_id"`
Version string `json:"version"`
Indices []string `json:"indices"`
State string `json:"state"`
Reason string `json:"reason"`
StartTime time.Time `json:"start_time"`
StartTimeInMillis int64 `json:"start_time_in_millis"`
EndTime time.Time `json:"end_time"`
EndTimeInMillis int64 `json:"end_time_in_millis"`
DurationInMillis int64 `json:"duration_in_millis"`
Failures []SnapshotShardFailure `json:"failures"`
Shards *ShardsInfo `json:"shards"`
}
77 changes: 77 additions & 0 deletions snapshot_get_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package elastic

import (
"net/url"
"reflect"
"testing"
)

func TestSnapshotGetValidate(t *testing.T) {
var client *Client

err := NewSnapshotGetService(client).Validate()
got := err.Error()
expected := "missing required fields: [Repository]"
if got != expected {
t.Errorf("expected %q; got: %q", expected, got)
}
}

func TestSnapshotGetURL(t *testing.T) {
client := setupTestClient(t)

tests := []struct {
Repository string
Snapshot []string
MasterTimeout string
IgnoreUnavailable bool
Verbose bool
ExpectedPath string
ExpectedParams url.Values
}{
{
Repository: "repo",
Snapshot: []string{},
MasterTimeout: "60s",
IgnoreUnavailable: true,
Verbose: true,
ExpectedPath: "/_snapshot/repo/_all",
ExpectedParams: url.Values{
"master_timeout": []string{"60s"},
"ignore_unavailable": []string{"true"},
"verbose": []string{"true"},
},
},
{
Repository: "repo",
Snapshot: []string{"snapA", "snapB"},
MasterTimeout: "60s",
IgnoreUnavailable: true,
Verbose: true,
ExpectedPath: "/_snapshot/repo/snapA%2CsnapB",
ExpectedParams: url.Values{
"master_timeout": []string{"60s"},
"ignore_unavailable": []string{"true"},
"verbose": []string{"true"},
},
},
}

for _, test := range tests {
path, params, err := client.SnapshotGet(test.Repository).
MasterTimeout(test.MasterTimeout).
Snapshot(test.Snapshot...).
IgnoreUnavailable(true).
Verbose(true).
buildURL()
if err != nil {
t.Fatal(err)
}
if path != test.ExpectedPath {
t.Errorf("expected %q; got: %q", test.ExpectedPath, path)
}
if !reflect.DeepEqual(params, test.ExpectedParams) {
t.Errorf("expected %q; got: %q", test.ExpectedParams, params)
}
}
}

0 comments on commit f7e6cd8

Please sign in to comment.