From 4cddac3c00dafca0a6dc70f32d34ed15cea61729 Mon Sep 17 00:00:00 2001 From: Pavel Larkin Date: Tue, 5 Mar 2024 13:03:06 -0800 Subject: [PATCH] Implement Kopia storage filesystem opts (#2656) * Add safecli dependency * add new flag implementations based on the safecli package for the Kopia CLI * apply go fmt Signed-off-by: pavel.larkin * Add common Kopia args and flags * Add Kopia storage core flags * Add kopia filesystem storage flags * cleanup storage tests * Fix Apply and test.Suit Signed-off-by: pavel.larkin * Remove variadic args for Common and Cache flags Signed-off-by: pavel.larkin * pkg/kopia/cli/internal/flag is implemented in the safecli@v0.0.4 now Signed-off-by: pavel.larkin * Add pkg/kopia/cli package Signed-off-by: pavel.larkin * go mod tidy Signed-off-by: pavel.larkin * Add Kopia storage helpers Signed-off-by: pavel.larkin * Implement Kopia storage Filesystem opts Signed-off-by: pavel.larkin * Add (c) headers Signed-off-by: pavel.larkin * Remove unused error Signed-off-by: pavel.larkin * Reorganize imports Signed-off-by: pavel.larkin * Convert common flags from vars to funcs Signed-off-by: pavel.larkin * Add safecli dependency * add new flag implementations based on the safecli package for the Kopia CLI * apply go fmt Signed-off-by: pavel.larkin * Fix Apply and test.Suit Signed-off-by: pavel.larkin * pkg/kopia/cli/internal/flag is implemented in the safecli@v0.0.4 now Signed-off-by: pavel.larkin * Add pkg/kopia/cli package Signed-off-by: pavel.larkin * go mod tidy Signed-off-by: pavel.larkin * Update safecli to v0.0.5 Signed-off-by: pavel.larkin * Update safecli to v0.0.6 Signed-off-by: pavel.larkin * Fix tests Signed-off-by: pavel.larkin * Add Location.IsPointInTypeSupported Signed-off-by: pavel.larkin * Add tests for Location.IsPointInTypeSupported Signed-off-by: pavel.larkin * Fix formatting Signed-off-by: pavel.larkin * organize imports Signed-off-by: pavel.larkin * organize imports Signed-off-by: pavel.larkin --------- Signed-off-by: pavel.larkin --- pkg/kopia/cli/errors.go | 2 + pkg/kopia/cli/repository/storage/fs/fs.go | 45 ++++++++++++++++ .../cli/repository/storage/fs/fs_opts.go | 34 ++++++++++++ .../cli/repository/storage/fs/fs_opts_test.go | 40 ++++++++++++++ .../cli/repository/storage/fs/fs_test.go | 53 +++++++++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 pkg/kopia/cli/repository/storage/fs/fs.go create mode 100644 pkg/kopia/cli/repository/storage/fs/fs_opts.go create mode 100644 pkg/kopia/cli/repository/storage/fs/fs_opts_test.go create mode 100644 pkg/kopia/cli/repository/storage/fs/fs_test.go diff --git a/pkg/kopia/cli/errors.go b/pkg/kopia/cli/errors.go index 0f3b41b924..93afdca4e9 100644 --- a/pkg/kopia/cli/errors.go +++ b/pkg/kopia/cli/errors.go @@ -28,4 +28,6 @@ var ( var ( // ErrUnsupportedStorage is returned when the storage is not supported. ErrUnsupportedStorage = errors.New("unsupported storage") + // ErrInvalidRepoPath is returned when the repoPath is empty. + ErrInvalidRepoPath = errors.New("repository path cannot be empty") ) diff --git a/pkg/kopia/cli/repository/storage/fs/fs.go b/pkg/kopia/cli/repository/storage/fs/fs.go new file mode 100644 index 0000000000..5683c1ab85 --- /dev/null +++ b/pkg/kopia/cli/repository/storage/fs/fs.go @@ -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 fs + +import ( + "github.com/kanisterio/safecli/command" + + "github.com/kanisterio/kanister/pkg/kopia/cli" + "github.com/kanisterio/kanister/pkg/kopia/cli/internal" + "github.com/kanisterio/kanister/pkg/log" +) + +const ( + defaultFSMountPath = "/mnt/data" +) + +// New creates a new subcommand for the filesystem storage. +func New(location internal.Location, repoPathPrefix string, _ log.Logger) command.Applier { + path, err := generateFileSystemMountPath(location.Prefix(), repoPathPrefix) + if err != nil { + return command.NewErrorArgument(err) + } + return command.NewArguments(subcmdFilesystem, optRepoPath(path)) +} + +// generateFileSystemMountPath generates the mount path for the filesystem storage. +func generateFileSystemMountPath(locPrefix, repoPrefix string) (string, error) { + fullRepoPath := internal.GenerateFullRepoPath(locPrefix, repoPrefix) + if fullRepoPath == "" { + return "", cli.ErrInvalidRepoPath + } + return defaultFSMountPath + "/" + fullRepoPath, nil +} diff --git a/pkg/kopia/cli/repository/storage/fs/fs_opts.go b/pkg/kopia/cli/repository/storage/fs/fs_opts.go new file mode 100644 index 0000000000..23b3ba7a5c --- /dev/null +++ b/pkg/kopia/cli/repository/storage/fs/fs_opts.go @@ -0,0 +1,34 @@ +// 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 fs + +import ( + "github.com/kanisterio/safecli/command" + + "github.com/kanisterio/kanister/pkg/kopia/cli" +) + +var ( + subcmdFilesystem = command.NewArgument("filesystem") +) + +// optRepoPath creates a new path option with a given path. +// If the path is empty, it returns an error. +func optRepoPath(path string) command.Applier { + if path == "" { + return command.NewErrorArgument(cli.ErrInvalidRepoPath) + } + return command.NewOptionWithArgument("--path", path) +} diff --git a/pkg/kopia/cli/repository/storage/fs/fs_opts_test.go b/pkg/kopia/cli/repository/storage/fs/fs_opts_test.go new file mode 100644 index 0000000000..c84d90c138 --- /dev/null +++ b/pkg/kopia/cli/repository/storage/fs/fs_opts_test.go @@ -0,0 +1,40 @@ +// 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 fs + +import ( + "testing" + + "github.com/kanisterio/safecli/command" + "github.com/kanisterio/safecli/test" + "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/kopia/cli" +) + +func TestFilesystemOptions(t *testing.T) { check.TestingT(t) } + +var _ = check.Suite(&test.ArgumentSuite{Cmd: "cmd", Arguments: []test.ArgumentTest{ + { + Name: "optRepoPath", + Argument: command.NewArguments(optRepoPath("/path/to/repo")), + ExpectedCLI: []string{"cmd", "--path=/path/to/repo"}, + }, + { + Name: "Invalid RepoPath", + Argument: command.NewArguments(optRepoPath("")), + ExpectedErr: cli.ErrInvalidRepoPath, + }, +}}) diff --git a/pkg/kopia/cli/repository/storage/fs/fs_test.go b/pkg/kopia/cli/repository/storage/fs/fs_test.go new file mode 100644 index 0000000000..9f65dcdbe5 --- /dev/null +++ b/pkg/kopia/cli/repository/storage/fs/fs_test.go @@ -0,0 +1,53 @@ +// 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 fs + +import ( + "testing" + + "github.com/kanisterio/safecli/command" + "github.com/kanisterio/safecli/test" + "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/kopia/cli" + "github.com/kanisterio/kanister/pkg/kopia/cli/internal" +) + +func TestNewFilesystem(t *testing.T) { check.TestingT(t) } + +func newFilesystem(prefix, repoPath string) command.Applier { + l := internal.Location{ + "prefix": []byte(prefix), + } + return New(l, repoPath, nil) +} + +var _ = check.Suite(&test.ArgumentSuite{Cmd: "cmd", Arguments: []test.ArgumentTest{ + { + Name: "NewFilesystem", + Argument: newFilesystem("prefix", "repoPath"), + ExpectedCLI: []string{"cmd", "filesystem", "--path=/mnt/data/prefix/repoPath/"}, + }, + { + Name: "NewFilesystem with empty repoPath", + Argument: newFilesystem("prefix", ""), + ExpectedCLI: []string{"cmd", "filesystem", "--path=/mnt/data/prefix/"}, + }, + { + Name: "NewFilesystem with empty local prefix and repo prefix should return error", + Argument: newFilesystem("", ""), + ExpectedErr: cli.ErrInvalidRepoPath, + }, +}})