-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement Kopia storage helpers (#2655)
* Add safecli dependency * add new flag implementations based on the safecli package for the Kopia CLI * apply go fmt Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add common Kopia args and flags * Add Kopia storage core flags * Fix Apply and test.Suit Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Remove variadic args for Common and Cache flags Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * pkg/kopia/cli/internal/flag is implemented in the safecli@v0.0.4 now Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add pkg/kopia/cli package Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * go mod tidy Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add Kopia storage helpers Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Convert common flags from vars to funcs Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add safecli dependency * add new flag implementations based on the safecli package for the Kopia CLI * apply go fmt Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Fix Apply and test.Suit Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * pkg/kopia/cli/internal/flag is implemented in the safecli@v0.0.4 now Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add pkg/kopia/cli package Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * go mod tidy Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Update safecli to v0.0.5 Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Update safecli to v0.0.6 Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Fix tests Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add Location.IsPointInTypeSupported Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Add tests for Location.IsPointInTypeSupported Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * Fix formatting Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * organize imports Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> * organize imports Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> --------- Signed-off-by: pavel.larkin <pavel.larkin@veeam.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information
1 parent
ba26708
commit 30e4f5c
Showing
6 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2024 The Kanister Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package internal | ||
|
||
import ( | ||
"strconv" | ||
"strings" | ||
|
||
rs "github.com/kanisterio/kanister/pkg/secrets/repositoryserver" | ||
) | ||
|
||
// Location is a map of key-value pairs that represent different storage properties. | ||
type Location map[string][]byte | ||
|
||
// Type returns the location type. | ||
func (l Location) Type() rs.LocType { | ||
return rs.LocType(string(l[rs.TypeKey])) | ||
} | ||
|
||
// Region returns the location region. | ||
func (l Location) Region() string { | ||
return string(l[rs.RegionKey]) | ||
} | ||
|
||
// BucketName returns the location bucket name. | ||
func (l Location) BucketName() string { | ||
return string(l[rs.BucketKey]) | ||
} | ||
|
||
// Endpoint returns the location endpoint. | ||
func (l Location) Endpoint() string { | ||
return string(l[rs.EndpointKey]) | ||
} | ||
|
||
// Prefix returns the location prefix. | ||
func (l Location) Prefix() string { | ||
return string(l[rs.PrefixKey]) | ||
} | ||
|
||
// IsInsecureEndpoint returns true if the location endpoint is insecure/http. | ||
func (l Location) IsInsecureEndpoint() bool { | ||
return strings.HasPrefix(l.Endpoint(), "http:") | ||
} | ||
|
||
// HasSkipSSLVerify returns true if the location has skip SSL verification. | ||
func (l Location) HasSkipSSLVerify() bool { | ||
v, _ := strconv.ParseBool(string(l[rs.SkipSSLVerifyKey])) | ||
return v | ||
} | ||
|
||
// IsPointInTimeSupported returns true if the location supports point-in-time recovery. | ||
// Currently, only S3 and Azure support point-in-time recovery. | ||
func (l Location) IsPointInTypeSupported() bool { | ||
switch l.Type() { | ||
case rs.LocTypeAzure, rs.LocTypeS3, rs.LocTypes3Compliant: | ||
return true | ||
default: | ||
return false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2024 The Kanister Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package internal_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"gopkg.in/check.v1" | ||
|
||
"github.com/kanisterio/kanister/pkg/kopia/cli/internal" | ||
rs "github.com/kanisterio/kanister/pkg/secrets/repositoryserver" | ||
) | ||
|
||
func TestLocation(t *testing.T) { check.TestingT(t) } | ||
|
||
type LocationSuite struct{} | ||
|
||
var _ = check.Suite(&LocationSuite{}) | ||
|
||
func (s *LocationSuite) TestLocation(c *check.C) { | ||
type expected struct { | ||
Type rs.LocType | ||
Region string | ||
BucketName string | ||
Endpoint string | ||
Prefix string | ||
IsInsecure bool | ||
HasSkipSSLVerify bool | ||
IsPITSupported bool | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
location internal.Location | ||
expected expected | ||
}{ | ||
{ | ||
name: "Test with no fields", | ||
location: internal.Location{}, | ||
expected: expected{}, | ||
}, | ||
{ | ||
name: "Test with all fields", | ||
location: internal.Location{ | ||
rs.TypeKey: []byte("Type1"), | ||
rs.RegionKey: []byte("Region1"), | ||
rs.BucketKey: []byte("Bucket1"), | ||
rs.EndpointKey: []byte("http://Endpoint1"), | ||
rs.PrefixKey: []byte("Prefix1"), | ||
rs.SkipSSLVerifyKey: []byte("true"), | ||
}, | ||
expected: expected{ | ||
Type: "Type1", | ||
Region: "Region1", | ||
BucketName: "Bucket1", | ||
Endpoint: "http://Endpoint1", | ||
Prefix: "Prefix1", | ||
IsInsecure: true, | ||
HasSkipSSLVerify: true, | ||
}, | ||
}, | ||
{ | ||
name: "Test PIT Support for S3 Compliant", | ||
location: internal.Location{ | ||
rs.TypeKey: []byte(rs.LocTypes3Compliant), | ||
}, | ||
expected: expected{ | ||
Type: "s3Compliant", | ||
IsPITSupported: true, | ||
}, | ||
}, | ||
{ | ||
name: "Test PIT Support for S3", | ||
location: internal.Location{ | ||
rs.TypeKey: []byte(rs.LocTypeS3), | ||
}, | ||
expected: expected{ | ||
Type: "s3", | ||
IsPITSupported: true, | ||
}, | ||
}, | ||
{ | ||
name: "Test PIT Support for Azure", | ||
location: internal.Location{ | ||
rs.TypeKey: []byte(rs.LocTypeAzure), | ||
}, | ||
expected: expected{ | ||
Type: "azure", | ||
IsPITSupported: true, | ||
}, | ||
}, | ||
{ | ||
name: "Test No PIT Support for GCS", | ||
location: internal.Location{ | ||
rs.TypeKey: []byte(rs.LocTypeGCS), | ||
}, | ||
expected: expected{ | ||
Type: "gcs", | ||
IsPITSupported: false, | ||
}, | ||
}, | ||
{ | ||
name: "Test No PIT Support for FS", | ||
location: internal.Location{ | ||
rs.TypeKey: []byte(rs.LocTypeFilestore), | ||
}, | ||
expected: expected{ | ||
Type: "filestore", | ||
IsPITSupported: false, | ||
}, | ||
}, | ||
} | ||
for _, test := range tests { | ||
c.Check(test.location.Type(), check.Equals, test.expected.Type) | ||
c.Check(test.location.Region(), check.Equals, test.expected.Region) | ||
c.Check(test.location.BucketName(), check.Equals, test.expected.BucketName) | ||
c.Check(test.location.Endpoint(), check.Equals, test.expected.Endpoint) | ||
c.Check(test.location.Prefix(), check.Equals, test.expected.Prefix) | ||
c.Check(test.location.IsInsecureEndpoint(), check.Equals, test.expected.IsInsecure) | ||
c.Check(test.location.HasSkipSSLVerify(), check.Equals, test.expected.HasSkipSSLVerify) | ||
c.Check(test.location.IsPointInTypeSupported(), check.Equals, test.expected.IsPITSupported) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright 2024 The Kanister Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package storage | ||
|
||
import ( | ||
"context" | ||
"io" | ||
|
||
"github.com/kanisterio/kanister/pkg/field" | ||
"github.com/kanisterio/kanister/pkg/log" | ||
) | ||
|
||
// NopLogger is a logger that does nothing. | ||
// TODO: Move to log package | ||
type NopLogger struct{} | ||
|
||
// Print does nothing. | ||
func (NopLogger) Print(msg string, fields ...field.M) { | ||
} | ||
|
||
// PrintTo does nothing. | ||
func (NopLogger) PrintTo(w io.Writer, msg string, fields ...field.M) { | ||
} | ||
|
||
// WithContext does nothing. | ||
func (NopLogger) WithContext(ctx context.Context) log.Logger { | ||
return &NopLogger{} | ||
} | ||
|
||
// WithError does nothing. | ||
func (NopLogger) WithError(err error) log.Logger { | ||
return &NopLogger{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2022 The Kanister Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package internal | ||
|
||
import ( | ||
"path" | ||
) | ||
|
||
// GenerateFullRepoPath generates the full repository path. | ||
// If the location-specific prefix is empty, the repository-specific prefix is returned. | ||
func GenerateFullRepoPath(locPrefix, repoPathPrefix string) string { | ||
if locPrefix != "" { | ||
return path.Join(locPrefix, repoPathPrefix) + "/" | ||
} | ||
return repoPathPrefix | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright 2024 The Kanister Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package internal_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"gopkg.in/check.v1" | ||
|
||
"github.com/kanisterio/kanister/pkg/kopia/cli/internal" | ||
) | ||
|
||
func TestPath(t *testing.T) { check.TestingT(t) } | ||
|
||
type PathSuite struct{} | ||
|
||
var _ = check.Suite(&PathSuite{}) | ||
|
||
func (s *PathSuite) TestGenerateFullRepoPath(c *check.C) { | ||
tests := []struct { | ||
locPrefix string | ||
repoPathPrefix string | ||
expected string | ||
}{ | ||
{ | ||
locPrefix: "", | ||
repoPathPrefix: "repo", | ||
expected: "repo", | ||
}, | ||
{ | ||
locPrefix: "loc", | ||
repoPathPrefix: "repo", | ||
expected: "loc/repo/", | ||
}, | ||
} | ||
for _, test := range tests { | ||
got := internal.GenerateFullRepoPath(test.locPrefix, test.repoPathPrefix) | ||
c.Check(got, check.Equals, test.expected) | ||
} | ||
} |