diff --git a/pkg/kopia/cli/args/cache_args.go b/pkg/kopia/cli/args/cache_args.go new file mode 100644 index 0000000000..2bc77b9c60 --- /dev/null +++ b/pkg/kopia/cli/args/cache_args.go @@ -0,0 +1,26 @@ +// 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 args + +// Cache provides the cache arguments for Kopia CLI. +type Cache struct { + CacheDirectory string // the directory where cache is stored. Default is "/tmp/kopia-cache". + ContentCacheSizeLimitMB int // the maximum size of the content cache in MB. + MetadataCacheSizeLimitMB int // the maximum size of the metadata cache in MB. + + // unused? + ContentCacheSizeMB int // the size of the content cache in MB. + MetadataCacheSizeMB int // the size of the metadata cache in MB. +} diff --git a/pkg/kopia/cli/args/common_args.go b/pkg/kopia/cli/args/common_args.go new file mode 100644 index 0000000000..52422f56bb --- /dev/null +++ b/pkg/kopia/cli/args/common_args.go @@ -0,0 +1,23 @@ +// 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 args + +// Common provides the common arguments for Kopia CLI. +type Common struct { + ConfigFilePath string // the path to the config file. + LogDirectory string // the directory where logs are stored. + LogLevel string // the level of logging. Default is "error". + RepoPassword string // the password for the repository. +} diff --git a/pkg/kopia/cli/errors.go b/pkg/kopia/cli/errors.go new file mode 100644 index 0000000000..d2db47ccd7 --- /dev/null +++ b/pkg/kopia/cli/errors.go @@ -0,0 +1,25 @@ +// 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 cli + +import ( + "github.com/pkg/errors" +) + +// Common errors +var ( + // ErrInvalidID is returned when the ID is empty. + ErrInvalidID = errors.New("invalid ID") +) diff --git a/pkg/kopia/cli/internal/args/args.go b/pkg/kopia/cli/internal/args/args.go new file mode 100644 index 0000000000..cad732dc9d --- /dev/null +++ b/pkg/kopia/cli/internal/args/args.go @@ -0,0 +1,29 @@ +// 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 args + +import ( + "github.com/kanisterio/safecli/command" + + "github.com/kanisterio/kanister/pkg/kopia/cli" +) + +// ID creates a new ID argument. +func ID(id string) command.Applier { + if id == "" { + return command.NewErrorArgument(cli.ErrInvalidID) + } + return command.NewArgument(id) +} diff --git a/pkg/kopia/cli/internal/args/args_test.go b/pkg/kopia/cli/internal/args/args_test.go new file mode 100644 index 0000000000..c8362009e8 --- /dev/null +++ b/pkg/kopia/cli/internal/args/args_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 args_test + +import ( + "testing" + + "github.com/kanisterio/safecli/test" + "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/kopia/cli" + "github.com/kanisterio/kanister/pkg/kopia/cli/internal/args" +) + +func TestArgs(t *testing.T) { check.TestingT(t) } + +var _ = check.Suite(&test.ArgumentSuite{Cmd: "cmd", Arguments: []test.ArgumentTest{ + { + Name: "Invalid ID", + Argument: args.ID(""), + ExpectedErr: cli.ErrInvalidID, + }, + { + Name: "ID", + Argument: args.ID("id12345"), + ExpectedCLI: []string{"cmd", "id12345"}, + }, +}}) diff --git a/pkg/kopia/cli/internal/opts/cache_opts.go b/pkg/kopia/cli/internal/opts/cache_opts.go new file mode 100644 index 0000000000..fb1222b4af --- /dev/null +++ b/pkg/kopia/cli/internal/opts/cache_opts.go @@ -0,0 +1,69 @@ +// 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 opts + +import ( + "strconv" + + "github.com/kanisterio/safecli/command" + + "github.com/kanisterio/kanister/pkg/kopia/cli/args" +) + +const ( + defaultCacheDirectory = "/tmp/kopia-cache" +) + +// CacheDirectory creates a new cache directory option with a given directory. +// If the directory is empty, the default cache directory is used. +func CacheDirectory(dir string) command.Applier { + if dir == "" { + dir = defaultCacheDirectory + } + return command.NewOptionWithArgument("--cache-directory", dir) +} + +// ContentCacheSizeLimitMB creates a new content cache size option with a given size. +func ContentCacheSizeLimitMB(size int) command.Applier { + val := strconv.Itoa(size) + return command.NewOptionWithArgument("--content-cache-size-limit-mb", val) +} + +// MetadataCacheSizeLimitMB creates a new metadata cache size option with a given size. +func MetadataCacheSizeLimitMB(size int) command.Applier { + val := strconv.Itoa(size) + return command.NewOptionWithArgument("--metadata-cache-size-limit-mb", val) +} + +// ContentCacheSizeMB creates a new content cache size option with a given size. +func ContentCacheSizeMB(size int) command.Applier { + val := strconv.Itoa(size) + return command.NewOptionWithArgument("--content-cache-size-mb", val) +} + +// MetadataCacheSizeMB creates a new metadata cache size option with a given size. +func MetadataCacheSizeMB(size int) command.Applier { + val := strconv.Itoa(size) + return command.NewOptionWithArgument("--metadata-cache-size-mb", val) +} + +// Cache maps the Cache arguments to the CLI command options. +func Cache(args args.Cache) command.Applier { + return command.NewArguments( + CacheDirectory(args.CacheDirectory), + ContentCacheSizeLimitMB(args.ContentCacheSizeLimitMB), + MetadataCacheSizeLimitMB(args.MetadataCacheSizeLimitMB), + ) +} diff --git a/pkg/kopia/cli/internal/opts/cache_opts_test.go b/pkg/kopia/cli/internal/opts/cache_opts_test.go new file mode 100644 index 0000000000..ee87091144 --- /dev/null +++ b/pkg/kopia/cli/internal/opts/cache_opts_test.go @@ -0,0 +1,55 @@ +// 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 opts_test + +import ( + "testing" + + "github.com/kanisterio/safecli/command" + "github.com/kanisterio/safecli/test" + "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/kopia/cli/args" + "github.com/kanisterio/kanister/pkg/kopia/cli/internal/opts" +) + +func TestCacheOptions(t *testing.T) { check.TestingT(t) } + +var _ = check.Suite(&test.ArgumentSuite{Cmd: "cmd", Arguments: []test.ArgumentTest{ + { + Name: "CacheDirectory", + Argument: command.NewArguments(opts.CacheDirectory(""), opts.CacheDirectory("/path/to/cache")), + ExpectedCLI: []string{"cmd", "--cache-directory=/tmp/kopia-cache", "--cache-directory=/path/to/cache"}, + }, + { + Name: "ContentCacheSizeLimitMB", + Argument: command.NewArguments(opts.ContentCacheSizeLimitMB(0), opts.ContentCacheSizeLimitMB(1024)), + ExpectedCLI: []string{"cmd", "--content-cache-size-limit-mb=0", "--content-cache-size-limit-mb=1024"}, + }, + { + Name: "MetadataCacheSizeLimitMB", + Argument: command.NewArguments(opts.MetadataCacheSizeLimitMB(0), opts.MetadataCacheSizeLimitMB(1024)), + ExpectedCLI: []string{"cmd", "--metadata-cache-size-limit-mb=0", "--metadata-cache-size-limit-mb=1024"}, + }, + { + Name: "Cache", + Argument: opts.Cache(args.Cache{ + CacheDirectory: "/path/to/cache", + ContentCacheSizeLimitMB: 1024, + MetadataCacheSizeLimitMB: 2048, + }), + ExpectedCLI: []string{"cmd", "--cache-directory=/path/to/cache", "--content-cache-size-limit-mb=1024", "--metadata-cache-size-limit-mb=2048"}, + }, +}}) diff --git a/pkg/kopia/cli/internal/opts/common_opts.go b/pkg/kopia/cli/internal/opts/common_opts.go new file mode 100644 index 0000000000..d17f71e5c3 --- /dev/null +++ b/pkg/kopia/cli/internal/opts/common_opts.go @@ -0,0 +1,71 @@ +// 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 opts + +import ( + "github.com/kanisterio/safecli/command" + + "github.com/kanisterio/kanister/pkg/kopia/cli/args" +) + +const ( + defaultLogLevel = "error" +) + +// LogDirectory creates a new log directory option with a given directory. +// if the directory is empty, the log directory option is not set. +func LogDirectory(dir string) command.Applier { + if dir == "" { + return command.NewNoopArgument() + } + return command.NewOptionWithArgument("--log-dir", dir) +} + +// LogLevel creates a new log level flag with a given level. +// If the level is empty, the default log level is used. +func LogLevel(level string) command.Applier { + if level == "" { + level = defaultLogLevel + } + return command.NewOptionWithArgument("--log-level", level) +} + +// ConfigFilePath creates a new config file path option with a given path. +// If the path is empty, the config file path option is not set. +func ConfigFilePath(path string) command.Applier { + if path == "" { + return command.NewNoopArgument() + } + return command.NewOptionWithArgument("--config-file", path) +} + +// RepoPassword creates a new repository password option with a given password. +// If the password is empty, the repository password option is not set. +func RepoPassword(password string) command.Applier { + if password == "" { + return command.NewNoopArgument() + } + return command.NewOptionWithRedactedArgument("--password", password) +} + +// Common maps the common arguments to the CLI command options. +func Common(args args.Common) command.Applier { + return command.NewArguments( + ConfigFilePath(args.ConfigFilePath), + LogDirectory(args.LogDirectory), + LogLevel(args.LogLevel), + RepoPassword(args.RepoPassword), + ) +} diff --git a/pkg/kopia/cli/internal/opts/common_opts_test.go b/pkg/kopia/cli/internal/opts/common_opts_test.go new file mode 100644 index 0000000000..28560a9537 --- /dev/null +++ b/pkg/kopia/cli/internal/opts/common_opts_test.go @@ -0,0 +1,61 @@ +// 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 opts_test + +import ( + "testing" + + "github.com/kanisterio/safecli/command" + "github.com/kanisterio/safecli/test" + "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/kopia/cli/args" + "github.com/kanisterio/kanister/pkg/kopia/cli/internal/opts" +) + +func TestCommonOptions(t *testing.T) { check.TestingT(t) } + +var _ = check.Suite(&test.ArgumentSuite{Cmd: "cmd", Arguments: []test.ArgumentTest{ + { + Name: "LogDirectory", + Argument: command.NewArguments(opts.LogDirectory(""), opts.LogDirectory("/path/to/logs")), + ExpectedCLI: []string{"cmd", "--log-dir=/path/to/logs"}, + }, + { + Name: "LogLevel", + Argument: command.NewArguments(opts.LogLevel(""), opts.LogLevel("info")), + ExpectedCLI: []string{"cmd", "--log-level=error", "--log-level=info"}, + }, + { + Name: "ConfigFilePath", + Argument: command.NewArguments(opts.ConfigFilePath(""), opts.ConfigFilePath("/path/to/config")), + ExpectedCLI: []string{"cmd", "--config-file=/path/to/config"}, + }, + { + Name: "RepoPassword", + Argument: command.NewArguments(opts.RepoPassword(""), opts.RepoPassword("pass123")), + ExpectedCLI: []string{"cmd", "--password=pass123"}, + }, + { + Name: "Common", + Argument: opts.Common(args.Common{ + LogDirectory: "/path/to/logs", + LogLevel: "trace", + ConfigFilePath: "/path/to/config", + RepoPassword: "pass123", + }), + ExpectedCLI: []string{"cmd", "--config-file=/path/to/config", "--log-dir=/path/to/logs", "--log-level=trace", "--password=pass123"}, + }, +}}) diff --git a/pkg/kopia/cli/internal/opts/opts.go b/pkg/kopia/cli/internal/opts/opts.go new file mode 100644 index 0000000000..fb53f5d679 --- /dev/null +++ b/pkg/kopia/cli/internal/opts/opts.go @@ -0,0 +1,57 @@ +// 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 opts + +import "github.com/kanisterio/safecli/command" + +// All creates a new all option. +func All(enabled bool) command.Applier { + return command.NewOption("--all", enabled) +} + +// Delta creates a new delta option. +func Delta(enabled bool) command.Applier { + return command.NewOption("--delta", enabled) +} + +// ShowIdentical creates a new show identical option. +func ShowIdentical(enabled bool) command.Applier { + return command.NewOption("--show-identical", enabled) +} + +// ReadOnly creates a new read only option. +func ReadOnly(enabled bool) command.Applier { + return command.NewOption("--readonly", enabled) +} + +// GRPC creates a new gRPC option. +func GRPC(enabled bool) command.Applier { + return command.NewToggleOption("--grpc", "--no-grpc", enabled) +} + +// CheckForUpdates creates a new check for updates option. +func CheckForUpdates(enabled bool) command.Applier { + return command.NewToggleOption("--check-for-updates", "--no-check-for-updates", enabled) +} + +// JSON creates a new JSON option. +func JSON(enabled bool) command.Applier { + return command.NewOption("--json", enabled) +} + +// Delete creates a new delete option. +func Delete(enabled bool) command.Applier { + return command.NewOption("--delete", enabled) +} diff --git a/pkg/kopia/cli/internal/opts/opts_test.go b/pkg/kopia/cli/internal/opts/opts_test.go new file mode 100644 index 0000000000..c0e955fd85 --- /dev/null +++ b/pkg/kopia/cli/internal/opts/opts_test.go @@ -0,0 +1,70 @@ +// 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 opts_test + +import ( + "testing" + + "github.com/kanisterio/safecli/command" + "github.com/kanisterio/safecli/test" + "gopkg.in/check.v1" + + "github.com/kanisterio/kanister/pkg/kopia/cli/internal/opts" +) + +func TestOptions(t *testing.T) { check.TestingT(t) } + +var _ = check.Suite(&test.ArgumentSuite{Cmd: "cmd", Arguments: []test.ArgumentTest{ + { + Name: "All", + Argument: command.NewArguments(opts.All(true), opts.All(false)), + ExpectedCLI: []string{"cmd", "--all"}, + }, + { + Name: "Delta", + Argument: command.NewArguments(opts.Delta(true), opts.Delta(false)), + ExpectedCLI: []string{"cmd", "--delta"}, + }, + { + Name: "ShowIdentical", + Argument: command.NewArguments(opts.ShowIdentical(true), opts.ShowIdentical(false)), + ExpectedCLI: []string{"cmd", "--show-identical"}, + }, + { + Name: "Readonly", + Argument: command.NewArguments(opts.ReadOnly(true), opts.ReadOnly(false)), + ExpectedCLI: []string{"cmd", "--readonly"}, + }, + { + Name: "GRPC", + Argument: command.NewArguments(opts.GRPC(true), opts.GRPC(false)), + ExpectedCLI: []string{"cmd", "--grpc", "--no-grpc"}, + }, + { + Name: "CheckForUpdates", + Argument: command.NewArguments(opts.CheckForUpdates(true), opts.CheckForUpdates(false)), + ExpectedCLI: []string{"cmd", "--check-for-updates", "--no-check-for-updates"}, + }, + { + Name: "JSON", + Argument: command.NewArguments(opts.JSON(true), opts.JSON(false)), + ExpectedCLI: []string{"cmd", "--json"}, + }, + { + Name: "Delete", + Argument: command.NewArguments(opts.Delete(true), opts.Delete(false)), + ExpectedCLI: []string{"cmd", "--delete"}, + }, +}})