Compare commits

...

67 commits

Author SHA1 Message Date
79ba34714a [#79] cli: Fix panic when setting domain for container
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-03-01 11:11:11 +03:00
6d4f48f37a [TrueCloudLab#78] .github: Fix CODEOWNERS
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-28 16:44:50 +03:00
e9f3c24229 [#65] Use strings.Cut instead of strings.Split* where possible
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-28 13:39:14 +03:00
88e3868f47 [#37] cli: Add nns-name and nns-zone for container create
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-28 13:37:23 +03:00
6925fb4c59 [TrueCloudLab/hrw#2] node: Use typed HRW methods
Update HRW lib and use typed HRW methods to sort shards and nodes

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-02-28 13:36:25 +03:00
c3a7039801 [TrueCloudLab/hrw#2] node: Optimize shard hash
Compute shard hash only once

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-02-28 13:36:25 +03:00
a1ab25b33e [#72] .github: Fix CODEOWNERS
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-22 16:29:58 +03:00
73bb590cb1 [#64] node: Use pool_size_local and separate pool for local puts
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-02-22 13:43:19 +03:00
7eaf159a8b [#63] adm: Fix contract wallet creation
Create contract wallet only by init and update-config command.

Close #63

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-02-22 10:08:37 +03:00
cb5468abb8 [#66] node: Replace interface{} with any
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-02-21 16:47:07 +03:00
3d873237d5 [#44] Update Changelog
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 10:00:28 +03:00
633c5a35de [#44] adm: Support multiple configs
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 10:00:28 +03:00
5f06232d34 [#44] cli: Support multiple configs
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 10:00:28 +03:00
bed5a36235 [#44] ir: Support multiple configs
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 10:00:28 +03:00
87e69b9349 [#44] node: Support multiple configs
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 10:00:28 +03:00
Pavel Karpy
337049b2ce [#56] node: Allow reading expired locked object
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-21 09:56:57 +03:00
Pavel Karpy
3beef10f89 [#61] node: Do not fetch missing objects
If an object is missing in a `meta`, shard should not look for it in
a `blobstor`.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-20 14:47:38 +03:00
5303736acd [#62] Fix CHANGELOG.md
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-20 14:25:21 +03:00
22f3c7d080 [#1868] Reload config for pprof and metrics on SIGHUP
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-20 13:53:27 +03:00
2b755ddb12 [#2260] node: Use a separate client cache for PUT service
Currently, under a mixed load one failed PUT can lead to closing
connection for all concurrent GETs. For PUT it does no harm: we have
many other nodes to choose from. For GET we are limited by `REP N`
factor, so in case of failover we can close the connection with the only
node posessing an object, which leads to failing the whole operation.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
0b61a3c961 [#2260] network/cache: Ignore clients only on Dial errors
The problem is that accidental timeout errors can make us to ignore
other nodes for some time. The primary purpose of the whole ignore
mechanism is not to degrade in case of failover. For this case,
closing connection and limiting the amount of dials is enough.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
bf1e59bb83 [#2260] network/cache: Ignore context cancelled errors
Timeouts on client side should node affect inter-node communication.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
2567f8020e [#2260] services/object: Do not assemble object with TTL=1
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
d1d123d180 [#2234] writecache: Fix possible panic in initFlushMarks
In case we have many small objects in the write-cache, `indices` should
not be reused between iterations.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
315141dc2c [#2252] fstree: Allow concurrent writes
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
Pavel Karpy
b422ac9f94 [#2164] node: Fix multi-client error reporting
Missing `ReportError` method did not allow casing multi-client interface to
`errorReporter` interface and dropping broken connections.
`replicationClient` embeds that interface, and it is widely used across
node's code. Embedded interface does not allow casting its parent structure
to `errorReporter` and breaks multi client error reporting logic.
Multi-client scheme is extremely hard to maintain, it makes unpredictable
casts and does not allow tracking code flow, so it will be refactored in the
future anyway.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-20 13:53:27 +03:00
Pavel Karpy
95ee905861 [#2244] node: Fix subscriptions lock
Subscribing without async listening could lead to a dead-lock in the
`neo-go` client.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-20 13:53:27 +03:00
Pavel Karpy
07ec51ea60 [#2244] node: Add object address to WC's operations
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-20 13:53:27 +03:00
Pavel Karpy
dbbbef9ddb [#2244] node: Update expired storage ID by WC
Previously, node could get an "infinite" small object: it could be expired
and thus could not be flushed (update its storage ID) to metabase => could
not be marked as flushed => node never removes such object and repeat all
the cycle one more time. If object exists and is not marked with GC (meta
returns `ErrObjectIsExpired`, not `ObjectNotFound` and not
`ObjectAlreadyRemoved`), its ID is safe to update _in the same_ bbolt
transaction.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-20 13:53:27 +03:00
351fdd9fa2 [#2246] node: Allow to configure tombsone lifetime
Currently, DELETE service sets tombstone expiration epoch to
`current epoch + 5`. This works less than ideal in private networks
where an epoch can be e.g. 10 minutes. In this case, after a node is
unavailable for more than 1 hour, already deleted objects have a chance
to reappear.

After this commit tombstone lifetime can be configured.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
6fd88a036f [#2241] metrics: Fix request count metrics names
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
2272c55c4d [#2238] engine: Add test for component initialization failures
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
5cb2c5ae62 [#2238] engine: Add test for component initialization failures
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
59748b7ae8 [#2238] neofs-node: Gracefully handle shard initialization errors
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
427fe276f2 [#2238] shard: Try closing all components
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
c53903ccd0 [#2238] engine: Make Open and Init similar
1. Both could initialize shards in parallel.
2. Both should close shards after an error.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
e0309e398c [#2239] writecache: Fix possible deadlock
LRU `Peek`/`Contains` take LRU mutex _inside_ of a `View` transaction.
`View` transaction itself takes `mmapLock` [1], which is lifted after tx
finishes (in `tx.Commit()` -> `tx.close()` -> `tx.db.removeTx`)

When we evict items from LRU cache mutex order is different:
first we take LRU mutex and then execute `Batch` which _does_ take
`mmapLock` in case we need to remap. Thus the deadlock.

[1] 8f4a7e1f92/db.go (L708)

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
58367e4df6 [#2232] pilorama: Merge in-queue batches
To achieve high performance we must choose proper values for both
batch size and delay. For user operations we want to set low delay.
However it would prevent tree synchronization operations to form big
enough batches. For these operations, batching gives the most benefit
not only in terms of on-CPU execution cost, but also by speeding up
transaction persist (`fsync`).
In this commit we try merging batches that are already
_triggered_, but not yet _started to execute_. This way we can still
query batches for execution after the provided delay while also allowing
multiple formed batches to execute faster.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
236c4af615 [#2224] adm: Use native neo-go sessions in dump-hashes
If we had lots of domains in one zone, `dump-hashes` for all others
can miss some domains, because we need to restrict ourselves with _some_
number.
In this commit we use neo-go sessions by default, with a proper
failback to in-script iterator unwrapping.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
Pavel Karpy
40822adb51 [#2213] node: Do not return object expired object
"Object is expired" means that object is presented in `meta` but it is not
`ObjectNotFound` error. Previous implementation made `shard` search for an
object without `meta` which was an error.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-20 13:53:27 +03:00
Roman Khimov
ad93d4db7c CHANGELOG: add more fancy glyphs
How could you forget adding it?

Signed-off-by: Roman Khimov <roman@nspcc.ru>
2023-02-20 13:53:27 +03:00
Roman Khimov
a6f071d66f CHANGELOG: fix whitespacing errors
Signed-off-by: Roman Khimov <roman@nspcc.ru>
2023-02-20 13:53:27 +03:00
9afe86ba3e [#2212] morph: Fix subscription restoration
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-20 13:53:27 +03:00
c43b2dbac9 [#1465] Add log entry for morph components shutdown action
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-17 12:13:00 +03:00
85cf1f47ac [#1465] node: Prevent process from killing by systemd when shutting down
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-17 12:13:00 +03:00
362f24953a [#47] shard: Switch container size metric from physical to logical capacity
Signed-off-by: Artem Tataurov <a.tataurov@yadro.com>
2023-02-17 12:03:42 +03:00
Pavel Karpy
901d62567d [#57] node: Broadcast link objects
It boosts object assembling by an _average_ container node.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-17 11:58:27 +03:00
Aleksey Pastukhov
269a4e9b50 [#53] Fix dirty in version
Signed-off-by: Aleksey Pastukhov <a.pastukhov@yadro.com>
2023-02-16 11:10:43 +03:00
3e5bc394b5 [#48] adm: Add initialize test for 1 node
Single node is used in dev-env, worth testing.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-16 09:07:18 +03:00
1d3669232e [#48] adm: Allow using nonzero magic with local client
neo-go actor API uses `getVersion` call which returned incorrect magic.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-16 09:07:18 +03:00
204cd3a11c [#31] fstree: Optimize treePath
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-10 12:49:31 +03:00
dee4498c1e [#31] fstree: Do not check for a file existence twice
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-10 12:49:31 +03:00
abbecf49d6 [#31] fstree: Speedup string-to-address conversion
```
name                  old time/op    new time/op    delta
_addressFromString-8    1.25µs ±30%    1.02µs ± 6%  -18.49%  (p=0.000 n=9+9)

name                  old alloc/op   new alloc/op   delta
_addressFromString-8      352B ± 0%      256B ± 0%  -27.27%  (p=0.000 n=9+10)

name                  old allocs/op  new allocs/op  delta
_addressFromString-8      6.00 ± 0%      4.00 ± 0%  -33.33%  (p=0.000
n=10+10)
```

Also, assure compiler that `s` doesn't escape:
Before this commit:
```
./fstree.go:74:24: leaking param: s
./fstree.go:90:6: moved to heap: addr
```

After this commit:
```
./fstree.go:74:24: s does not escape
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-10 12:49:31 +03:00
ab21d90cfb [#1794] shard: Add increasing case for the payload size metric
Signed-off-by: Artem Tataurov <a.tataurov@yadro.com>
2023-02-09 13:30:23 +03:00
5ffa826897 [#1] Update Changelog
Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
cb016d53a6 [#1] Fix comments and error messages
Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
c761a95eef [#1] Fix project name in control service
Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
f825cfac78 [#1] Fix project name in comments here and there
Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
c6645ef775 [#1] Documentation rebranding
Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
488eece25f [#1] Fix Debian package references to old upstream
Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
1cedd446bb [#1] Fix sample configs
- Update sample configs to match unit tests
- Remove Docker container for N3 testnet
  Will return with updates when FrostFS enters N3

Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
1858f11146 [#1] Fix viper env prefix in cli tools
Changing env prefix and corresponding example config files.

Signed-off-by: Stanislav Bogatyrev <s.bogatyrev@yadro.com>
2023-02-06 17:41:14 +03:00
Pavel Karpy
73bc1b0b68 [#38] node: Fix linter warnings
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-02-06 17:27:54 +03:00
515c60bdf4 [#1889] adm: Add command morph netmap-candidates
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-06 17:26:34 +03:00
ee24815748 [#1889] Move flag --config in cmd/frostfs-adm/internal/commonflags/flags.go
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-06 17:26:34 +03:00
2b09564355 [#1889] Move netmap.go and exit.go from cli to cmd/internal/common
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-06 17:26:34 +03:00
5a9d6a09d8 [#8] cli: Set flag mode required for control shards set-mode
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-02-06 16:45:03 +03:00
324 changed files with 2402 additions and 1467 deletions

2
.github/CODEOWNERS vendored
View file

@ -1 +1 @@
* @carpawell @fyrchik @acid-ant
* @TrueCloudLab/storage-core @TrueCloudLab/committers

19
.gitignore vendored
View file

@ -30,5 +30,22 @@ testfile
.neofs-cli.yml
# debhelpers
**/.debhelper
debian/*debhelper*
# logfiles
debian/*.log
# .substvars
debian/*.substvars
# .bash-completion
debian/*.bash-completion
# Install folders and files
debian/frostfs-cli/
debian/frostfs-ir/
debian/files
debian/frostfs-storage/
debian/changelog
man/
debs/

View file

@ -8,16 +8,43 @@ Changelog for FrostFS Node
- Doc for extended headers (#2128)
- New `frostfs_node_object_container_size` metric for tracking size of reqular objects in a container (#2116)
- New `frostfs_node_object_payload_size` metric for tracking size of reqular objects on a single shard (#1794)
- Add command `frostfs-adm morph netmap-candidates` (#1889)
- `object.delete.tombstone_lifetime` config parameter to set tombstone lifetime in the DELETE service (#2246)
- Reload config for pprof and metrics on SIGHUP in `neofs-node` (#1868)
- Multiple configs support (#44)
- Parameters `nns-name` and `nns-zone` for command `frostfs-cli container create` (#37)
### Changed
- Change `frostfs_node_engine_container_size` to counting sizes of logical objects
- `common.PrintVerbose` prints via `cobra.Command.Printf` (#1962)
- Env prefix in configuration changed to `FROSTFS_*` (#43)
- Link object is broadcast throughout the whole container now (#57)
- Pilorama now can merge multiple batches into one (#2231)
- Storage engine now can start even when some shard components are unavailable (#2238)
- `neofs-cli` buffer for object put increased from 4 KiB to 3 MiB (#2243)
- Expired locked object is available for reading (#56)
### Fixed
- Increase payload size metric on shards' `put` operation (#1794)
- Big object removal with non-local parts (#1978)
- Disable pilorama when moving to degraded mode (#2197)
- Fetching blobovnicza objects that not found in write-cache (#2206)
- Do not search for the small objects in FSTree (#2206)
- Correct status error for expired session token (#2207)
- Set flag `mode` required for `frostfs-cli control shards set-mode` (#8)
- Fix `dirty` suffix in debian package version (#53)
- Prevent node process from killing by systemd when shutting down (#1465)
- Restore subscriptions correctly on morph client switch (#2212)
- Expired objects could be returned if not marked with GC yet (#2213)
- `neofs-adm morph dump-hashes` now properly iterates over custom domain (#2224)
- Possible deadlock in write-cache (#2239)
- Fix `*_req_count` and `*_req_count_success` metric values (#2241)
- Storage ID update by write-cache (#2244)
- `neo-go` client deadlock on subscription restoration (#2244)
- Possible panic during write-cache initialization (#2234)
- Do not fetch an object if `meta` is missing it (#61)
- Create contract wallet only by `init` and `update-config` command (#63)
- Actually use `object.put.pool_size_local` and independent pool for local puts (#64).
### Removed
### Updated
@ -27,11 +54,17 @@ Changelog for FrostFS Node
- `golang.org/x/term` to `v0.3.0`
- `google.golang.org/grpc` to `v1.51.0`
- `github.com/nats-io/nats.go` to `v1.22.1`
- `github.com/TrueCloudLab/hrw` to `v.1.1.1`
- Minimum go version to v1.18
### Updating from v0.35.0
## [0.35.0] - 2022-12-28 - Sindo (신도)
You need to change configuration environment variables to `FROSTFS_*` if you use any.
New config field `object.delete.tombstone_lifetime` allows to set tombstone lifetime
more appropriate for a specific deployment.
## [0.35.0] - 2022-12-28 - Sindo (신도, 信島)
### Added
- `morph list-containers` in `neofs-adm` (#1689)
@ -115,7 +148,6 @@ Changelog for FrostFS Node
- `spf13/viper` to `v1.8.0`
- `google.golang.org/grpc` to `v1.50.1`
### Updating from v0.34.0
Pass CID and OID parameters via the `--cid` and `--oid` flags, not as the command arguments.
@ -129,9 +161,9 @@ to match the container owner. Use `--force` (`-f`) flag to bypass this requireme
Tree service network replication can now be fine-tuned with `tree.replication_timeout` config field.
## [0.34.0] - 2022-10-31 - Marado (마라도, 馬羅島)
## [0.34.0] - 2022-10-31 - Marado (마라도, 馬羅島)
# ## Added
### Added
- `--timeout` flag in `neofs-cli control` commands (#1917)
- Document shard modes of operation (#1909)
- `tree list` CLI command (#1332)

View file

@ -38,7 +38,7 @@ $ git clone https://github.com/TrueCloudLab/frostfs-node
### Set up git remote as ``upstream``
```sh
$ cd neofs-node
$ cd frostfs-node
$ git remote add upstream https://github.com/TrueCloudLab/frostfs-node
$ git fetch upstream
$ git merge upstream/master

View file

@ -16,7 +16,7 @@ RELEASE = release
DIRS = $(BIN) $(RELEASE)
# List of binaries to build.
CMDS = $(notdir $(basename $(wildcard cmd/*)))
CMDS = $(notdir $(basename $(wildcard cmd/frostfs-*)))
BINS = $(addprefix $(BIN)/, $(CMDS))
# .deb package versioning

View file

@ -0,0 +1,14 @@
package commonflags
const (
ConfigFlag = "config"
ConfigFlagShorthand = "c"
ConfigFlagUsage = "Config file"
ConfigDirFlag = "config-dir"
ConfigDirFlagUsage = "Config directory"
Verbose = "verbose"
VerboseShorthand = "v"
VerboseUsage = "Verbose output"
)

View file

@ -140,14 +140,14 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
return wCtx.awaitTx()
}
func parseConfigPair(kvStr string, force bool) (key string, val interface{}, err error) {
kv := strings.SplitN(kvStr, "=", 2)
if len(kv) != 2 {
func parseConfigPair(kvStr string, force bool) (key string, val any, err error) {
k, v, found := strings.Cut(kvStr, "=")
if !found {
return "", nil, fmt.Errorf("invalid parameter format: must be 'key=val', got: %s", kvStr)
}
key = kv[0]
valRaw := kv[1]
key = k
valRaw := v
switch key {
case netmapAuditFeeKey, netmapBasicIncomeRateKey,
@ -162,7 +162,7 @@ func parseConfigPair(kvStr string, force bool) (key string, val interface{}, err
case netmapEigenTrustAlphaKey:
// just check that it could
// be parsed correctly
_, err = strconv.ParseFloat(kv[1], 64)
_, err = strconv.ParseFloat(v, 64)
if err != nil {
err = fmt.Errorf("could not parse %s's value '%s' as float: %w", key, valRaw, err)
}

View file

@ -2,6 +2,7 @@ package morph
import (
"bytes"
"errors"
"fmt"
"strings"
"text/tabwriter"
@ -107,31 +108,30 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error {
func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c Client) error {
const nnsMaxTokens = 100
inv := invoker.New(c, nil)
arr, err := unwrap.Array(inv.CallAndExpandIterator(nnsHash, "tokens", nnsMaxTokens))
if err != nil {
return fmt.Errorf("can't get a list of NNS domains: %w", err)
}
inv := invoker.New(c, nil)
if !strings.HasPrefix(zone, ".") {
zone = "." + zone
}
var infos []contractDumpInfo
for i := range arr {
bs, err := arr[i].TryBytes()
processItem := func(item stackitem.Item) {
bs, err := item.TryBytes()
if err != nil {
continue
cmd.PrintErrf("Invalid NNS record: %v\n", err)
return
}
if !bytes.HasSuffix(bs, []byte(zone)) {
continue
// Related https://github.com/nspcc-dev/neofs-contract/issues/316.
return
}
h, err := nnsResolveHash(inv, nnsHash, string(bs))
if err != nil {
continue
cmd.PrintErrf("Could not resolve name %s: %v\n", string(bs), err)
return
}
infos = append(infos, contractDumpInfo{
@ -140,6 +140,39 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string,
})
}
sessionID, iter, err := unwrap.SessionIterator(inv.Call(nnsHash, "tokens"))
if err != nil {
if errors.Is(err, unwrap.ErrNoSessionID) {
items, err := unwrap.Array(inv.CallAndExpandIterator(nnsHash, "tokens", nnsMaxTokens))
if err != nil {
return fmt.Errorf("can't get a list of NNS domains: %w", err)
}
if len(items) == nnsMaxTokens {
cmd.PrintErrln("Provided RPC endpoint doesn't support sessions, some hashes might be lost.")
}
for i := range items {
processItem(items[i])
}
} else {
return err
}
} else {
defer func() {
_ = inv.TerminateSession(sessionID)
}()
items, err := inv.TraverseIterator(sessionID, &iter, nnsMaxTokens)
for err == nil && len(items) != 0 {
for i := range items {
processItem(items[i])
}
items, err = inv.TraverseIterator(sessionID, &iter, nnsMaxTokens)
}
if err != nil {
return fmt.Errorf("error during NNS domains iteration: %w", err)
}
}
fillContractVersion(cmd, c, infos)
printContractInfo(cmd, infos)

View file

@ -115,8 +115,10 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
return nil, err
}
needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init"
var w *wallet.Wallet
if cmd.Name() != "deploy" {
if needContracts {
w, err = openContractWallet(v, cmd, walletDir)
if err != nil {
return nil, err
@ -157,7 +159,6 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
}
}
needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init"
if needContracts {
ctrPath, err = cmd.Flags().GetString(contractsInitFlag)
if err != nil {

View file

@ -167,7 +167,7 @@ func (c *initializeContext) updateContracts() error {
w := io2.NewBufBinWriter()
var keysParam []interface{}
var keysParam []any
// Update script size for a single-node committee is close to the maximum allowed size of 65535.
// Because of this we want to reuse alphabet contract NEF and manifest for different updates.
@ -299,7 +299,7 @@ func (c *initializeContext) updateContracts() error {
func (c *initializeContext) deployContracts() error {
alphaCs := c.getContract(alphabetContract)
var keysParam []interface{}
var keysParam []any
baseGroups := alphaCs.Manifest.Groups
@ -510,12 +510,12 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*contr
return m, nil
}
func getContractDeployParameters(cs *contractState, deployData []interface{}) []interface{} {
return []interface{}{cs.RawNEF, cs.RawManifest, deployData}
func getContractDeployParameters(cs *contractState, deployData []any) []any {
return []any{cs.RawNEF, cs.RawManifest, deployData}
}
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []interface{}) []interface{} {
items := make([]interface{}, 1, 6)
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any) []any {
items := make([]any, 1, 6)
items[0] = false // notaryDisabled is false
switch ctrName {
@ -551,7 +551,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []in
c.Contracts[netmapContract].Hash,
c.Contracts[containerContract].Hash)
case netmapContract:
configParam := []interface{}{
configParam := []any{
netmapEpochKey, viper.GetInt64(epochDurationInitFlag),
netmapMaxObjectSizeKey, viper.GetInt64(maxObjectSizeInitFlag),
netmapAuditFeeKey, viper.GetInt64(auditFeeInitFlag),
@ -580,8 +580,8 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []in
return items
}
func (c *initializeContext) getAlphabetDeployItems(i, n int) []interface{} {
items := make([]interface{}, 6)
func (c *initializeContext) getAlphabetDeployItems(i, n int) []any {
items := make([]any, 6)
items[0] = false
items[1] = c.Contracts[netmapContract].Hash
items[2] = c.Contracts[proxyContract].Hash

View file

@ -281,7 +281,7 @@ func nnsIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) {
case *rpcclient.Client:
return ct.NNSIsAvailable(nnsHash, name)
default:
b, err := unwrap.Bool(invokeFunction(c, nnsHash, "isAvailable", []interface{}{name}, nil))
b, err := unwrap.Bool(invokeFunction(c, nnsHash, "isAvailable", []any{name}, nil))
if err != nil {
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
}

View file

@ -16,7 +16,7 @@ func (c *initializeContext) setNotaryAndAlphabetNodes() error {
return err
}
var pubs []interface{}
var pubs []any
for _, acc := range c.Accounts {
pubs = append(pubs, acc.PrivateKey().PublicKey().Bytes())
}

View file

@ -27,6 +27,9 @@ func TestInitialize(t *testing.T) {
// It is here for performing local testing after the changes.
t.Skip()
t.Run("1 nodes", func(t *testing.T) {
testInitialize(t, 1)
})
t.Run("4 nodes", func(t *testing.T) {
testInitialize(t, 4)
})
@ -96,6 +99,7 @@ func generateTestData(t *testing.T, dir string, size int) {
}
cfg := config.Config{}
cfg.ProtocolConfiguration.Magic = 12345
cfg.ProtocolConfiguration.ValidatorsCount = size
cfg.ProtocolConfiguration.SecondsPerBlock = 1
cfg.ProtocolConfiguration.StandbyCommittee = pubs // sorted by glagolic letters

View file

@ -6,6 +6,7 @@ import (
"fmt"
"os"
"sort"
"time"
"github.com/google/uuid"
"github.com/nspcc-dev/neo-go/pkg/config"
@ -20,6 +21,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
@ -188,7 +190,7 @@ func (l *localClient) GetCommittee() (keys.PublicKeys, error) {
func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) {
var err error
pp := make([]interface{}, len(sPrm))
pp := make([]any, len(sPrm))
for i, p := range sPrm {
pp[i], err = smartcontract.ExpandParameterToEmitable(p)
if err != nil {
@ -226,7 +228,24 @@ func (l *localClient) TraverseIterator(_, _ uuid.UUID, _ int) ([]stackitem.Item,
// GetVersion return default version.
func (l *localClient) GetVersion() (*result.Version, error) {
return &result.Version{}, nil
c := l.bc.GetConfig()
return &result.Version{
Protocol: result.Protocol{
AddressVersion: address.NEO3Prefix,
Network: c.Magic,
MillisecondsPerBlock: int(c.TimePerBlock / time.Millisecond),
MaxTraceableBlocks: c.MaxTraceableBlocks,
MaxValidUntilBlockIncrement: c.MaxValidUntilBlockIncrement,
MaxTransactionsPerBlock: c.MaxTransactionsPerBlock,
MemoryPoolMaxTransactions: c.MemPoolSize,
ValidatorsCount: byte(c.ValidatorsCount),
InitialGasDistribution: c.InitialGASSupply,
CommitteeHistory: c.CommitteeHistory,
P2PSigExtensions: c.P2PSigExtensions,
StateRootInHeader: c.StateRootInHeader,
ValidatorsHistory: c.ValidatorsHistory,
},
}, nil
}
func (l *localClient) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
@ -327,7 +346,7 @@ func getSigners(sender *wallet.Account, cosigners []rpcclient.SignerAccount) ([]
}
func (l *localClient) NEP17BalanceOf(h util.Uint160, acc util.Uint160) (int64, error) {
res, err := invokeFunction(l, h, "balanceOf", []interface{}{acc}, nil)
res, err := invokeFunction(l, h, "balanceOf", []any{acc}, nil)
if err != nil {
return 0, err
}
@ -432,7 +451,7 @@ func (l *localClient) putTransactions() error {
return l.bc.AddBlock(b)
}
func invokeFunction(c Client, h util.Uint160, method string, parameters []interface{}, signers []transaction.Signer) (*result.Invoke, error) {
func invokeFunction(c Client, h util.Uint160, method string, parameters []any, signers []transaction.Signer) (*result.Invoke, error) {
w := io.NewBufBinWriter()
emit.Array(w.BinWriter, parameters...)
emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All)

View file

@ -0,0 +1,29 @@
package morph
import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) {
c, err := getN3Client(viper.GetViper())
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
inv := invoker.New(c, nil)
cs, err := c.GetContractStateByID(1)
commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err)
nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".frostfs")
commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err)
res, err := inv.Call(nmHash, "netmapCandidates")
commonCmd.ExitOnErr(cmd, "can't fetch list of network config keys from the netmap contract", err)
nm, err := netmap.DecodeNetMap(res.Stack)
commonCmd.ExitOnErr(cmd, "unable to decode netmap: %w", err)
commonCmd.PrettyPrintNetMap(cmd, *nm, !viper.GetBool(commonflags.Verbose))
}

View file

@ -111,7 +111,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
accHash,
notary.Hash,
big.NewInt(int64(gasAmount)),
[]interface{}{nil, int64(height) + till},
[]any{nil, int64(height) + till},
)
if err != nil {
return fmt.Errorf("could not send tx: %w", err)

View file

@ -27,23 +27,23 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error {
bw := io.NewBufBinWriter()
for i := range args {
kv := strings.SplitN(args[i], "=", 2)
if len(kv) != 2 {
k, v, found := strings.Cut(args[i], "=")
if !found {
return fmt.Errorf("invalid parameter format, must be Parameter=Value")
}
switch kv[0] {
switch k {
case execFeeParam, storagePriceParam, setFeeParam:
default:
return fmt.Errorf("parameter must be one of %s, %s and %s", execFeeParam, storagePriceParam, setFeeParam)
}
value, err := strconv.ParseUint(kv[1], 10, 32)
value, err := strconv.ParseUint(v, 10, 32)
if err != nil {
return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err)
}
emit.AppCall(bw.BinWriter, policy.Hash, "set"+kv[0], callflag.All, int64(value))
emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value))
}
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil {

View file

@ -226,6 +226,16 @@ var (
},
RunE: depositNotary,
}
netmapCandidatesCmd = &cobra.Command{
Use: "netmap-candidates",
Short: "List netmap candidates nodes",
PreRun: func(cmd *cobra.Command, _ []string) {
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
},
Run: listNetmapCandidatesNodes,
}
)
func init() {
@ -323,4 +333,7 @@ func init() {
depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address")
depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit")
depositNotaryCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks")
RootCmd.AddCommand(netmapCandidatesCmd)
netmapCandidatesCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
}

View file

@ -340,7 +340,7 @@ func manageSubnetAdmins(cmd *cobra.Command, rm bool) error {
}
// prepare call parameters
prm := make([]interface{}, 0, 3)
prm := make([]any, 0, 3)
prm = append(prm, id.Marshal())
var method string
@ -742,7 +742,7 @@ func init() {
)
}
func testInvokeMethod(key keys.PrivateKey, method string, args ...interface{}) ([]stackitem.Item, error) {
func testInvokeMethod(key keys.PrivateKey, method string, args ...any) ([]stackitem.Item, error) {
c, err := getN3Client(viper.GetViper())
if err != nil {
return nil, fmt.Errorf("morph client creation: %w", err)
@ -780,7 +780,7 @@ func testInvokeMethod(key keys.PrivateKey, method string, args ...interface{}) (
return res.Stack, nil
}
func invokeMethod(key keys.PrivateKey, tryNotary bool, method string, args ...interface{}) error {
func invokeMethod(key keys.PrivateKey, tryNotary bool, method string, args ...any) error {
c, err := getN3Client(viper.GetViper())
if err != nil {
return fmt.Errorf("morph client creation: %w", err)
@ -821,7 +821,7 @@ func invokeMethod(key keys.PrivateKey, tryNotary bool, method string, args ...in
return nil
}
func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...interface{}) error {
func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...any) error {
nnsCs, err := c.GetContractStateByID(1)
if err != nil {
return fmt.Errorf("NNS contract resolving: %w", err)
@ -868,7 +868,7 @@ func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...inter
return nil
}
func invokeNotary(c Client, key keys.PrivateKey, method string, notaryHash util.Uint160, args ...interface{}) error {
func invokeNotary(c Client, key keys.PrivateKey, method string, notaryHash util.Uint160, args ...any) error {
nnsCs, err := c.GetContractStateByID(1)
if err != nil {
return fmt.Errorf("NNS contract resolving: %w", err)

View file

@ -3,11 +3,13 @@ package modules
import (
"os"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/storagecfg"
"github.com/TrueCloudLab/frostfs-node/misc"
"github.com/TrueCloudLab/frostfs-node/pkg/util/autocomplete"
utilConfig "github.com/TrueCloudLab/frostfs-node/pkg/util/config"
"github.com/TrueCloudLab/frostfs-node/pkg/util/gendoc"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -22,8 +24,6 @@ manage FrostFS network deployment.`,
RunE: entryPoint,
SilenceUsage: true,
}
configFlag = "config"
)
func init() {
@ -34,7 +34,10 @@ func init() {
// use stdout as default output for cmd.Print()
rootCmd.SetOut(os.Stdout)
rootCmd.PersistentFlags().StringP(configFlag, "c", "", "Config file")
rootCmd.PersistentFlags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage)
rootCmd.PersistentFlags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage)
rootCmd.PersistentFlags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, commonflags.VerboseUsage)
_ = viper.BindPFlag(commonflags.Verbose, rootCmd.PersistentFlags().Lookup(commonflags.Verbose))
rootCmd.Flags().Bool("version", false, "Application version")
rootCmd.AddCommand(config.RootCmd)
@ -60,12 +63,23 @@ func entryPoint(cmd *cobra.Command, args []string) error {
}
func initConfig(cmd *cobra.Command) {
configFile, err := cmd.Flags().GetString(configFlag)
if err != nil || configFile == "" {
configFile, err := cmd.Flags().GetString(commonflags.ConfigFlag)
if err != nil {
return
}
viper.SetConfigType("yml")
viper.SetConfigFile(configFile)
_ = viper.ReadInConfig() // if config file is set but unavailable, ignore it
if configFile != "" {
viper.SetConfigType("yml")
viper.SetConfigFile(configFile)
_ = viper.ReadInConfig() // if config file is set but unavailable, ignore it
}
configDir, err := cmd.Flags().GetString(commonflags.ConfigDirFlag)
if err != nil {
return
}
if configDir != "" {
_ = utilConfig.ReadConfigDir(viper.GetViper(), configDir) // if config files cannot be read, ignore it
}
}

View file

@ -1,8 +1,8 @@
# How NeoFS CLI uses session mechanism of the NeoFS
# How FrostFS CLI uses session mechanism of the FrostFS
## Overview
NeoFS sessions implement a mechanism for issuing a power of attorney by one
FrostFS sessions implement a mechanism for issuing a power of attorney by one
party to another. A trusted party can provide a so-called session token as
proof of the right to act on behalf of another member of the network. The
client of operations carried out with such a token will be the user who opened
@ -15,7 +15,7 @@ attached session token is treated as performed by the original client.
## Types
NeoFS CLI supports two ways to execute operation within a session depending on
FrostFS CLI supports two ways to execute operation within a session depending on
whether the user of the command application is an original user (1) or a trusted
one (2).

View file

@ -2,26 +2,26 @@
## Overview
Extended headers are used for request/response. They may contain any user-defined headers
to be interpreted on application level.
Key name must be a unique valid UTF-8 string. Value can't be empty. Requests or
Responses with duplicated header names or headers with empty values are
considered invalid.
Extended headers are used for request/response. They may contain any
user-defined headers to be interpreted on application level. Key name must be a
unique valid UTF-8 string. Value can't be empty. Requests or Responses with
duplicated header names or headers with empty values are considered invalid.
## Existing headers
There are some "well-known" headers starting with `__NEOFS__` prefix that
affect system behaviour:
There are some "well-known" headers starting with `__FROSTFS__` prefix that
affect system behaviour. For backward compatibility, the same set of
"well-known" headers may also use `__NEOFS__` prefix:
* `__NEOFS__NETMAP_EPOCH` - netmap epoch to use for object placement calculation. The `value` is string
* `__FROSTFS__NETMAP_EPOCH` - netmap epoch to use for object placement calculation. The `value` is string
encoded `uint64` in decimal presentation. If set to '0' or omitted, the
current epoch only will be used.
* `__NEOFS__NETMAP_LOOKUP_DEPTH` - if object can't be found using current epoch's netmap, this header limits
how many past epochs the node can look up through. Depth is applied to a current epoch or the value
of `__NEOFS__NETMAP_EPOCH` attribute. The `value` is string encoded `uint64` in decimal presentation.
* `__FROSTFS__NETMAP_LOOKUP_DEPTH` - if object can't be found using current epoch's netmap, this header limits
how many past epochs the node can look up through. Depth is applied to a current epoch or the value
of `__FROSTFS__NETMAP_EPOCH` attribute. The `value` is string encoded `uint64` in decimal presentation.
If set to '0' or not set, only the current epoch is used.
## `neofs-cli` commands with `--xhdr`
## `frostfs-cli` commands with `--xhdr`
List of commands with support of extended headers:
* `container list-objects`
@ -30,5 +30,5 @@ List of commands with support of extended headers:
Example:
```shell
$ neofs-cli object put -r s01.neofs.devenv:8080 -w wallet.json --cid CID --file FILE --xhdr "__NEOFS__NETMAP_EPOCH=777"
$ frostfs-cli object put -r s01.frostfs.devenv:8080 -w wallet.json --cid CID --file FILE --xhdr "__FROSTFS__NETMAP_EPOCH=777"
```

View file

@ -34,7 +34,7 @@ func (x BalanceOfRes) Balance() accounting.Decimal {
return x.cliRes.Amount()
}
// BalanceOf requests the current balance of a NeoFS user.
// BalanceOf requests the current balance of a FrostFS user.
//
// Returns any error which prevented the operation from completing correctly in error return.
func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) {
@ -59,7 +59,7 @@ func (x ListContainersRes) IDList() []cid.ID {
return x.cliRes.Containers()
}
// ListContainers requests a list of NeoFS user's containers.
// ListContainers requests a list of FrostFS user's containers.
//
// Returns any error which prevented the operation from completing correctly in error return.
func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) {
@ -84,7 +84,7 @@ func (x PutContainerRes) ID() cid.ID {
return x.cnr
}
// PutContainer sends a request to save the container in NeoFS.
// PutContainer sends a request to save the container in FrostFS.
//
// Operation is asynchronous and not guaranteed even in the absence of errors.
// The required time is also not predictable.
@ -122,7 +122,7 @@ func (x GetContainerRes) Container() containerSDK.Container {
return x.cliRes.Container()
}
// GetContainer reads a container from NeoFS by ID.
// GetContainer reads a container from FrostFS by ID.
//
// Returns any error which prevented the operation from completing correctly in error return.
func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) {
@ -140,7 +140,7 @@ func IsACLExtendable(c *client.Client, cnr cid.ID) (bool, error) {
res, err := GetContainer(prm)
if err != nil {
return false, fmt.Errorf("get container from the NeoFS: %w", err)
return false, fmt.Errorf("get container from the FrostFS: %w", err)
}
return res.Container().BasicACL().Extendable(), nil
@ -155,7 +155,7 @@ type DeleteContainerPrm struct {
// DeleteContainerRes groups the resulting values of DeleteContainer operation.
type DeleteContainerRes struct{}
// DeleteContainer sends a request to remove a container from NeoFS by ID.
// DeleteContainer sends a request to remove a container from FrostFS by ID.
//
// Operation is asynchronous and not guaranteed even in the absence of errors.
// The required time is also not predictable.
@ -185,7 +185,7 @@ func (x EACLRes) EACL() eacl.Table {
return x.cliRes.Table()
}
// EACL reads eACL table from NeoFS by container ID.
// EACL reads eACL table from FrostFS by container ID.
//
// Returns any error which prevented the operation from completing correctly in error return.
func EACL(prm EACLPrm) (res EACLRes, err error) {
@ -203,7 +203,7 @@ type SetEACLPrm struct {
// SetEACLRes groups the resulting values of SetEACL operation.
type SetEACLRes struct{}
// SetEACL requests to save an eACL table in NeoFS.
// SetEACL requests to save an eACL table in FrostFS.
//
// Operation is asynchronous and no guaranteed even in the absence of errors.
// The required time is also not predictable.
@ -228,12 +228,12 @@ type NetworkInfoRes struct {
cliRes *client.ResNetworkInfo
}
// NetworkInfo returns structured information about the NeoFS network.
// NetworkInfo returns structured information about the FrostFS network.
func (x NetworkInfoRes) NetworkInfo() netmap.NetworkInfo {
return x.cliRes.Info()
}
// NetworkInfo reads information about the NeoFS network.
// NetworkInfo reads information about the FrostFS network.
//
// Returns any error which prevented the operation from completing correctly in error return.
func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) {
@ -258,12 +258,12 @@ func (x NodeInfoRes) NodeInfo() netmap.NodeInfo {
return x.cliRes.NodeInfo()
}
// LatestVersion returns the latest NeoFS API version in use.
// LatestVersion returns the latest FrostFS API version in use.
func (x NodeInfoRes) LatestVersion() version.Version {
return x.cliRes.LatestVersion()
}
// NodeInfo requests information about the remote server from NeoFS netmap.
// NodeInfo requests information about the remote server from FrostFS netmap.
//
// Returns any error which prevented the operation from completing correctly in error return.
func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) {
@ -282,7 +282,7 @@ type NetMapSnapshotRes struct {
cliRes *client.ResNetMapSnapshot
}
// NetMap returns current local snapshot of the NeoFS network map.
// NetMap returns current local snapshot of the FrostFS network map.
func (x NetMapSnapshotRes) NetMap() netmap.NetMap {
return x.cliRes.NetMap()
}
@ -362,7 +362,7 @@ func (x PutObjectRes) ID() oid.ID {
return x.id
}
// PutObject saves the object in NeoFS network.
// PutObject saves the object in FrostFS network.
//
// Returns any error which prevented the operation from completing correctly in error return.
func PutObject(prm PutObjectPrm) (*PutObjectRes, error) {
@ -404,8 +404,7 @@ func PutObject(prm PutObjectPrm) (*PutObjectRes, error) {
}
if prm.rdr != nil {
// TODO: (neofs-node#1198) explore better values or configure it
const defaultBufferSizePut = 4096
const defaultBufferSizePut = 3 << 20 // Maximum chunk size is 3 MiB in the SDK.
if sz == 0 || sz > defaultBufferSizePut {
sz = defaultBufferSizePut
@ -460,7 +459,7 @@ func (x DeleteObjectRes) Tombstone() oid.ID {
return x.tomb
}
// DeleteObject marks an object to be removed from NeoFS through tombstone placement.
// DeleteObject marks an object to be removed from FrostFS through tombstone placement.
//
// Returns any error which prevented the operation from completing correctly in error return.
func DeleteObject(prm DeleteObjectPrm) (*DeleteObjectRes, error) {
@ -576,7 +575,7 @@ type HeadObjectPrm struct {
mainOnly bool
}
// SetMainOnlyFlag sets flag to get only main fields of an object header in terms of NeoFS API.
// SetMainOnlyFlag sets flag to get only main fields of an object header in terms of FrostFS API.
func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) {
x.mainOnly = v
}
@ -812,7 +811,7 @@ func (x *PayloadRangePrm) SetRange(rng *object.Range) {
// PayloadRangeRes groups the resulting values of PayloadRange operation.
type PayloadRangeRes struct{}
// PayloadRange reads object payload range from NeoFS and writes it to the specified writer.
// PayloadRange reads object payload range from FrostFS and writes it to the specified writer.
//
// Interrupts on any writer error.
//
@ -872,7 +871,7 @@ func (s *SyncContainerPrm) SetContainer(c *containerSDK.Container) {
// operation.
type SyncContainerRes struct{}
// SyncContainerSettings reads global network config from NeoFS and
// SyncContainerSettings reads global network config from FrostFS and
// syncs container settings with it.
//
// Interrupts on any writer error.

View file

@ -1,12 +1,15 @@
// Package internal provides functionality for NeoFS CLI application communication with NeoFS network.
// Package internal provides functionality for FrostFS CLI application
// communication with FrostFS network.
//
// The base client for accessing remote nodes via NeoFS API is a NeoFS SDK Go API client.
// However, although it encapsulates a useful piece of business logic (e.g. the signature mechanism),
// the NeoFS CLI application does not fully use the client's flexible interface.
// The base client for accessing remote nodes via FrostFS API is a FrostFS SDK
// Go API client. However, although it encapsulates a useful piece of business
// logic (e.g. the signature mechanism), the FrostFS CLI application does not
// fully use the client's flexible interface.
//
// In this regard, this package provides functions over base API client necessary for the application.
// This allows you to concentrate the entire spectrum of the client's use in one place (this will be convenient
// both when updating the base client and for evaluating the UX of SDK library). So it is expected that all
// application packages will be limited to this package for the development of functionality requiring
// NeoFS API communication.
// In this regard, this package provides functions over base API client
// necessary for the application. This allows you to concentrate the entire
// spectrum of the client's use in one place (this will be convenient both when
// updating the base client and for evaluating the UX of SDK library). So it is
// expected that all application packages will be limited to this package for
// the development of functionality requiring FrostFS API communication.
package internal

View file

@ -16,7 +16,7 @@ type commonPrm struct {
cli *client.Client
}
// SetClient sets the base client for NeoFS API communication.
// SetClient sets the base client for FrostFS API communication.
func (x *commonPrm) SetClient(cli *client.Client) {
x.cli = cli
}

View file

@ -10,6 +10,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/network"
"github.com/TrueCloudLab/frostfs-sdk-go/client"
"github.com/spf13/cobra"
@ -23,7 +24,7 @@ var errInvalidEndpoint = errors.New("provided RPC endpoint is incorrect")
func GetSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) *client.Client {
cli, err := getSDKClientByFlag(cmd, key, endpointFlag)
if err != nil {
common.ExitOnErr(cmd, "can't create API client: %w", err)
commonCmd.ExitOnErr(cmd, "can't create API client: %w", err)
}
return cli
}

View file

@ -4,6 +4,7 @@ import (
"errors"
"os"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/core/version"
"github.com/TrueCloudLab/frostfs-sdk-go/eacl"
versionSDK "github.com/TrueCloudLab/frostfs-sdk-go/version"
@ -16,13 +17,13 @@ var errUnsupportedEACLFormat = errors.New("unsupported eACL format")
func ReadEACL(cmd *cobra.Command, eaclPath string) *eacl.Table {
_, err := os.Stat(eaclPath) // check if `eaclPath` is an existing file
if err != nil {
ExitOnErr(cmd, "", errors.New("incorrect path to file with EACL"))
commonCmd.ExitOnErr(cmd, "", errors.New("incorrect path to file with EACL"))
}
PrintVerbose(cmd, "Reading EACL from file: %s", eaclPath)
data, err := os.ReadFile(eaclPath)
ExitOnErr(cmd, "can't read file with EACL: %w", err)
commonCmd.ExitOnErr(cmd, "can't read file with EACL: %w", err)
table := eacl.NewTable()
@ -38,7 +39,7 @@ func ReadEACL(cmd *cobra.Command, eaclPath string) *eacl.Table {
return table
}
ExitOnErr(cmd, "", errUnsupportedEACLFormat)
commonCmd.ExitOnErr(cmd, "", errUnsupportedEACLFormat)
return nil
}

View file

@ -6,6 +6,7 @@ import (
"fmt"
"os"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/bearer"
"github.com/spf13/cobra"
)
@ -13,7 +14,7 @@ import (
// ReadBearerToken reads bearer token from the path provided in a specified flag.
func ReadBearerToken(cmd *cobra.Command, flagname string) *bearer.Token {
path, err := cmd.Flags().GetString(flagname)
ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
if len(path) == 0 {
return nil
@ -24,13 +25,13 @@ func ReadBearerToken(cmd *cobra.Command, flagname string) *bearer.Token {
var tok bearer.Token
err = ReadBinaryOrJSON(cmd, &tok, path)
ExitOnErr(cmd, "invalid bearer token: %v", err)
commonCmd.ExitOnErr(cmd, "invalid bearer token: %v", err)
return &tok
}
// BinaryOrJSON is an interface of entities which provide json.Unmarshaler
// and NeoFS binary decoder.
// and FrostFS binary decoder.
type BinaryOrJSON interface {
Unmarshal([]byte) error
json.Unmarshaler

View file

@ -12,7 +12,7 @@ import (
)
// PrintVerbose prints to the stdout if the commonflags.Verbose flag is on.
func PrintVerbose(cmd *cobra.Command, format string, a ...interface{}) {
func PrintVerbose(cmd *cobra.Command, format string, a ...any) {
if viper.GetBool(commonflags.Verbose) {
cmd.Printf(format+"\n", a...)
}

View file

@ -8,8 +8,8 @@ import (
const SessionToken = "session"
// InitSession registers SessionToken flag representing filepath to the token
// of the session with the given name. Supports NeoFS-binary and JSON files.
// InitSession registers SessionToken flag representing file path to the token of
// the session with the given name. Supports FrostFS-binary and JSON files.
func InitSession(cmd *cobra.Command, name string) {
cmd.Flags().String(
SessionToken,

View file

@ -6,8 +6,8 @@ import (
"fmt"
"os"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/spf13/cobra"
@ -21,7 +21,7 @@ var errCantGenerateKey = errors.New("can't generate new private key")
// This function assumes that all flags were bind to viper in a `PersistentPreRun`.
func Get(cmd *cobra.Command) *ecdsa.PrivateKey {
pk, err := get(cmd)
common.ExitOnErr(cmd, "can't fetch private key: %w", err)
commonCmd.ExitOnErr(cmd, "can't fetch private key: %w", err)
return pk
}
@ -46,7 +46,7 @@ func get(cmd *cobra.Command) (*ecdsa.PrivateKey, error) {
// GetOrGenerate is similar to get but generates a new key if commonflags.GenerateKey is set.
func GetOrGenerate(cmd *cobra.Command) *ecdsa.PrivateKey {
pk, err := getOrGenerate(cmd)
common.ExitOnErr(cmd, "can't fetch private key: %w", err)
commonCmd.ExitOnErr(cmd, "can't fetch private key: %w", err)
return pk
}

View file

@ -4,9 +4,9 @@ import (
"math/big"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/util/precision"
"github.com/TrueCloudLab/frostfs-sdk-go/accounting"
"github.com/TrueCloudLab/frostfs-sdk-go/user"
@ -32,7 +32,7 @@ var accountingBalanceCmd = &cobra.Command{
if balanceOwner == "" {
user.IDFromKey(&idUser, pk.PublicKey)
} else {
common.ExitOnErr(cmd, "can't decode owner ID wallet address: %w", idUser.DecodeString(balanceOwner))
commonCmd.ExitOnErr(cmd, "can't decode owner ID wallet address: %w", idUser.DecodeString(balanceOwner))
}
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
@ -42,7 +42,7 @@ var accountingBalanceCmd = &cobra.Command{
prm.SetAccount(idUser)
res, err := internalclient.BalanceOf(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
// print to stdout
prettyPrintDecimal(cmd, res.Balance())

View file

@ -1,8 +1,8 @@
package basic
import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/container/acl"
"github.com/spf13/cobra"
)
@ -23,6 +23,6 @@ InnerRing members are allowed to data audit ops only:
func printACL(cmd *cobra.Command, args []string) {
var bacl acl.Basic
common.ExitOnErr(cmd, "unable to parse basic acl: %w", bacl.DecodeString(args[0]))
commonCmd.ExitOnErr(cmd, "unable to parse basic acl: %w", bacl.DecodeString(args[0]))
util.PrettyPrintTableBACL(cmd, &bacl)
}

View file

@ -6,9 +6,9 @@ import (
"os"
"strings"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/eacl"
"github.com/spf13/cobra"
@ -84,7 +84,7 @@ func createEACL(cmd *cobra.Command, _ []string) {
}
tb := eacl.NewTable()
common.ExitOnErr(cmd, "unable to parse provided rules: %w", util.ParseEACLRules(tb, rules))
commonCmd.ExitOnErr(cmd, "unable to parse provided rules: %w", util.ParseEACLRules(tb, rules))
tb.SetCID(containerID)

View file

@ -4,8 +4,8 @@ import (
"os"
"strings"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/eacl"
"github.com/spf13/cobra"
)
@ -27,12 +27,12 @@ func printEACL(cmd *cobra.Command, _ []string) {
file, _ := cmd.Flags().GetString("file")
eaclTable := new(eacl.Table)
data, err := os.ReadFile(file)
common.ExitOnErr(cmd, "can't read file with EACL: %w", err)
commonCmd.ExitOnErr(cmd, "can't read file with EACL: %w", err)
if strings.HasSuffix(file, ".json") {
common.ExitOnErr(cmd, "unable to parse json: %w", eaclTable.UnmarshalJSON(data))
commonCmd.ExitOnErr(cmd, "unable to parse json: %w", eaclTable.UnmarshalJSON(data))
} else {
rules := strings.Split(strings.TrimSpace(string(data)), "\n")
common.ExitOnErr(cmd, "can't parse file with EACL: %w", util.ParseEACLRules(eaclTable, rules))
commonCmd.ExitOnErr(cmd, "can't parse file with EACL: %w", util.ParseEACLRules(eaclTable, rules))
}
util.PrettyPrintTableEACL(cmd, eaclTable)
}

View file

@ -10,6 +10,7 @@ import (
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/bearer"
eaclSDK "github.com/TrueCloudLab/frostfs-sdk-go/eacl"
"github.com/TrueCloudLab/frostfs-sdk-go/user"
@ -58,13 +59,13 @@ func init() {
func createToken(cmd *cobra.Command, _ []string) {
iat, iatRelative, err := common.ParseEpoch(cmd, issuedAtFlag)
common.ExitOnErr(cmd, "can't parse --"+issuedAtFlag+" flag: %w", err)
commonCmd.ExitOnErr(cmd, "can't parse --"+issuedAtFlag+" flag: %w", err)
exp, expRelative, err := common.ParseEpoch(cmd, commonflags.ExpireAt)
common.ExitOnErr(cmd, "can't parse --"+commonflags.ExpireAt+" flag: %w", err)
commonCmd.ExitOnErr(cmd, "can't parse --"+commonflags.ExpireAt+" flag: %w", err)
nvb, nvbRelative, err := common.ParseEpoch(cmd, notValidBeforeFlag)
common.ExitOnErr(cmd, "can't parse --"+notValidBeforeFlag+" flag: %w", err)
commonCmd.ExitOnErr(cmd, "can't parse --"+notValidBeforeFlag+" flag: %w", err)
if iatRelative || expRelative || nvbRelative {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
@ -72,7 +73,7 @@ func createToken(cmd *cobra.Command, _ []string) {
endpoint, _ := cmd.Flags().GetString(commonflags.RPC)
currEpoch, err := internalclient.GetCurrentEpoch(ctx, cmd, endpoint)
common.ExitOnErr(cmd, "can't fetch current epoch: %w", err)
commonCmd.ExitOnErr(cmd, "can't fetch current epoch: %w", err)
if iatRelative {
iat += currEpoch
@ -85,14 +86,14 @@ func createToken(cmd *cobra.Command, _ []string) {
}
}
if exp < nvb {
common.ExitOnErr(cmd, "",
commonCmd.ExitOnErr(cmd, "",
fmt.Errorf("expiration epoch is less than not-valid-before epoch: %d < %d", exp, nvb))
}
ownerStr, _ := cmd.Flags().GetString(ownerFlag)
var ownerID user.ID
common.ExitOnErr(cmd, "can't parse recipient: %w", ownerID.DecodeString(ownerStr))
commonCmd.ExitOnErr(cmd, "can't parse recipient: %w", ownerID.DecodeString(ownerStr))
var b bearer.Token
b.SetExp(exp)
@ -104,8 +105,8 @@ func createToken(cmd *cobra.Command, _ []string) {
if eaclPath != "" {
table := eaclSDK.NewTable()
raw, err := os.ReadFile(eaclPath)
common.ExitOnErr(cmd, "can't read extended ACL file: %w", err)
common.ExitOnErr(cmd, "can't parse extended ACL: %w", json.Unmarshal(raw, table))
commonCmd.ExitOnErr(cmd, "can't read extended ACL file: %w", err)
commonCmd.ExitOnErr(cmd, "can't parse extended ACL: %w", json.Unmarshal(raw, table))
b.SetEACLTable(*table)
}
@ -114,12 +115,12 @@ func createToken(cmd *cobra.Command, _ []string) {
toJSON, _ := cmd.Flags().GetBool(jsonFlag)
if toJSON {
data, err = json.Marshal(b)
common.ExitOnErr(cmd, "can't mashal token to JSON: %w", err)
commonCmd.ExitOnErr(cmd, "can't mashal token to JSON: %w", err)
} else {
data = b.Marshal()
}
out, _ := cmd.Flags().GetString(outFlag)
err = os.WriteFile(out, data, 0644)
common.ExitOnErr(cmd, "can't write token to file: %w", err)
commonCmd.ExitOnErr(cmd, "can't write token to file: %w", err)
}

View file

@ -7,10 +7,12 @@ import (
"strings"
"time"
containerApi "github.com/TrueCloudLab/frostfs-api-go/v2/container"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/container"
"github.com/TrueCloudLab/frostfs-sdk-go/container/acl"
"github.com/TrueCloudLab/frostfs-sdk-go/netmap"
@ -25,6 +27,8 @@ var (
containerAttributes []string
containerAwait bool
containerName string
containerNnsName string
containerNnsZone string
containerNoTimestamp bool
containerSubnet string
force bool
@ -37,7 +41,7 @@ var createContainerCmd = &cobra.Command{
It will be stored in sidechain when inner ring will accepts it.`,
Run: func(cmd *cobra.Command, args []string) {
placementPolicy, err := parseContainerPolicy(cmd, containerPolicy)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
key := key.Get(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
@ -47,16 +51,16 @@ It will be stored in sidechain when inner ring will accepts it.`,
prm.SetClient(cli)
resmap, err := internalclient.NetMapSnapshot(prm)
common.ExitOnErr(cmd, "unable to get netmap snapshot to validate container placement, "+
commonCmd.ExitOnErr(cmd, "unable to get netmap snapshot to validate container placement, "+
"use --force option to skip this check: %w", err)
nodesByRep, err := resmap.NetMap().ContainerNodes(*placementPolicy, nil)
common.ExitOnErr(cmd, "could not build container nodes based on given placement policy, "+
commonCmd.ExitOnErr(cmd, "could not build container nodes based on given placement policy, "+
"use --force option to skip this check: %w", err)
for i, nodes := range nodesByRep {
if placementPolicy.ReplicaNumberByIndex(i) > uint32(len(nodes)) {
common.ExitOnErr(cmd, "", fmt.Errorf(
commonCmd.ExitOnErr(cmd, "", fmt.Errorf(
"the number of nodes '%d' in selector is not enough for the number of replicas '%d', "+
"use --force option to skip this check",
len(nodes),
@ -70,7 +74,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
var subnetID subnetid.ID
err = subnetID.DecodeString(containerSubnet)
common.ExitOnErr(cmd, "could not parse subnetID: %w", err)
commonCmd.ExitOnErr(cmd, "could not parse subnetID: %w", err)
placementPolicy.RestrictSubnet(subnetID)
}
@ -79,10 +83,10 @@ It will be stored in sidechain when inner ring will accepts it.`,
cnr.Init()
err = parseAttributes(&cnr, containerAttributes)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
var basicACL acl.Basic
common.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL))
commonCmd.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL))
tok := getSession(cmd)
@ -104,7 +108,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
syncContainerPrm.SetContainer(&cnr)
_, err = internalclient.SyncContainerSettings(syncContainerPrm)
common.ExitOnErr(cmd, "syncing container's settings rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "syncing container's settings rpc error: %w", err)
var putPrm internalclient.PutContainerPrm
putPrm.SetClient(cli)
@ -115,7 +119,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
}
res, err := internalclient.PutContainer(putPrm)
common.ExitOnErr(cmd, "put container rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "put container rpc error: %w", err)
id := res.ID()
@ -138,7 +142,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
}
}
common.ExitOnErr(cmd, "", errCreateTimeout)
commonCmd.ExitOnErr(cmd, "", errCreateTimeout)
}
},
}
@ -159,6 +163,8 @@ func initContainerCreateCmd() {
flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2")
flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted")
flags.StringVar(&containerName, "name", "", "Container name attribute")
flags.StringVar(&containerNnsName, "nns-name", "", "Container nns name attribute")
flags.StringVar(&containerNnsZone, "nns-zone", "", "Container nns zone attribute")
flags.BoolVar(&containerNoTimestamp, "disable-timestamp", false, "Disable timestamp container attribute")
flags.StringVar(&containerSubnet, "subnet", "", "String representation of container subnetwork")
flags.BoolVarP(&force, commonflags.ForceFlag, commonflags.ForceFlagShorthand, false,
@ -196,12 +202,12 @@ func parseContainerPolicy(cmd *cobra.Command, policyString string) (*netmap.Plac
func parseAttributes(dst *container.Container, attributes []string) error {
for i := range attributes {
kvPair := strings.Split(attributes[i], attributeDelimiter)
if len(kvPair) != 2 {
k, v, found := strings.Cut(attributes[i], attributeDelimiter)
if !found {
return errors.New("invalid container attribute")
}
dst.SetAttribute(kvPair[0], kvPair[1])
dst.SetAttribute(k, v)
}
if !containerNoTimestamp {
@ -212,5 +218,12 @@ func parseAttributes(dst *container.Container, attributes []string) error {
container.SetName(dst, containerName)
}
if containerNnsName != "" {
dst.SetAttribute(containerApi.SysAttributeName, containerNnsName)
}
if containerNnsZone != "" {
dst.SetAttribute(containerApi.SysAttributeZone, containerNnsZone)
}
return nil
}

View file

@ -8,6 +8,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
objectSDK "github.com/TrueCloudLab/frostfs-sdk-go/object"
"github.com/TrueCloudLab/frostfs-sdk-go/user"
"github.com/spf13/cobra"
@ -34,7 +35,7 @@ Only owner of the container has a permission to remove container.`,
getPrm.SetContainer(id)
resGet, err := internalclient.GetContainer(getPrm)
common.ExitOnErr(cmd, "can't get the container: %w", err)
commonCmd.ExitOnErr(cmd, "can't get the container: %w", err)
owner := resGet.Container().Owner()
@ -42,7 +43,7 @@ Only owner of the container has a permission to remove container.`,
common.PrintVerbose(cmd, "Checking session issuer...")
if !tok.Issuer().Equals(owner) {
common.ExitOnErr(cmd, "", fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer()))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer()))
}
} else {
common.PrintVerbose(cmd, "Checking provided account...")
@ -51,7 +52,7 @@ Only owner of the container has a permission to remove container.`,
user.IDFromKey(&acc, pk.PublicKey)
if !acc.Equals(owner) {
common.ExitOnErr(cmd, "", fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc))
}
}
@ -72,10 +73,10 @@ Only owner of the container has a permission to remove container.`,
common.PrintVerbose(cmd, "Searching for LOCK objects...")
res, err := internalclient.SearchObjects(searchPrm)
common.ExitOnErr(cmd, "can't search for LOCK objects: %w", err)
commonCmd.ExitOnErr(cmd, "can't search for LOCK objects: %w", err)
if len(res.IDList()) != 0 {
common.ExitOnErr(cmd, "",
commonCmd.ExitOnErr(cmd, "",
fmt.Errorf("Container wasn't removed because LOCK objects were found.\n"+
"Use --%s flag to remove anyway.", commonflags.ForceFlag))
}
@ -91,7 +92,7 @@ Only owner of the container has a permission to remove container.`,
}
_, err := internalclient.DeleteContainer(delPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
cmd.Println("container delete method invoked")
@ -112,7 +113,7 @@ Only owner of the container has a permission to remove container.`,
}
}
common.ExitOnErr(cmd, "", errDeleteTimeout)
commonCmd.ExitOnErr(cmd, "", errDeleteTimeout)
}
},
}

View file

@ -9,6 +9,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/container"
"github.com/TrueCloudLab/frostfs-sdk-go/container/acl"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
@ -44,13 +45,13 @@ var getContainerInfoCmd = &cobra.Command{
if containerJSON {
data, err = cnr.MarshalJSON()
common.ExitOnErr(cmd, "can't JSON encode container: %w", err)
commonCmd.ExitOnErr(cmd, "can't JSON encode container: %w", err)
} else {
data = cnr.Marshal()
}
err = os.WriteFile(containerPathTo, data, 0644)
common.ExitOnErr(cmd, "can't write container to file: %w", err)
commonCmd.ExitOnErr(cmd, "can't write container to file: %w", err)
}
},
}
@ -96,7 +97,7 @@ func prettyPrintContainer(cmd *cobra.Command, cnr container.Container, jsonEncod
})
cmd.Println("placement policy:")
common.ExitOnErr(cmd, "write policy: %w", cnr.PlacementPolicy().WriteStringTo((*stringWriter)(cmd)))
commonCmd.ExitOnErr(cmd, "write policy: %w", cnr.PlacementPolicy().WriteStringTo((*stringWriter)(cmd)))
cmd.Println()
}
@ -137,10 +138,10 @@ func getContainer(cmd *cobra.Command) (container.Container, *ecdsa.PrivateKey) {
var pk *ecdsa.PrivateKey
if containerPathFrom != "" {
data, err := os.ReadFile(containerPathFrom)
common.ExitOnErr(cmd, "can't read file: %w", err)
commonCmd.ExitOnErr(cmd, "can't read file: %w", err)
err = cnr.Unmarshal(data)
common.ExitOnErr(cmd, "can't unmarshal container: %w", err)
commonCmd.ExitOnErr(cmd, "can't unmarshal container: %w", err)
} else {
id := parseContainerID(cmd)
pk = key.GetOrGenerate(cmd)
@ -151,7 +152,7 @@ func getContainer(cmd *cobra.Command) (container.Container, *ecdsa.PrivateKey) {
prm.SetContainer(id)
res, err := internalclient.GetContainer(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
cnr = res.Container()
}

View file

@ -7,6 +7,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
)
@ -24,7 +25,7 @@ var getExtendedACLCmd = &cobra.Command{
eaclPrm.SetContainer(id)
res, err := internalclient.EACL(eaclPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
eaclTable := res.EACL()
@ -39,16 +40,16 @@ var getExtendedACLCmd = &cobra.Command{
if containerJSON {
data, err = eaclTable.MarshalJSON()
common.ExitOnErr(cmd, "can't encode to JSON: %w", err)
commonCmd.ExitOnErr(cmd, "can't encode to JSON: %w", err)
} else {
data, err = eaclTable.Marshal()
common.ExitOnErr(cmd, "can't encode to binary: %w", err)
commonCmd.ExitOnErr(cmd, "can't encode to binary: %w", err)
}
cmd.Println("dumping data to file:", containerPathTo)
err = os.WriteFile(containerPathTo, data, 0644)
common.ExitOnErr(cmd, "could not write eACL to file: %w", err)
commonCmd.ExitOnErr(cmd, "could not write eACL to file: %w", err)
},
}

View file

@ -5,9 +5,9 @@ import (
"github.com/TrueCloudLab/frostfs-api-go/v2/container"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/user"
"github.com/spf13/cobra"
)
@ -37,7 +37,7 @@ var listContainersCmd = &cobra.Command{
user.IDFromKey(&idUser, key.PublicKey)
} else {
err := idUser.DecodeString(flagVarListContainerOwner)
common.ExitOnErr(cmd, "invalid user ID: %w", err)
commonCmd.ExitOnErr(cmd, "invalid user ID: %w", err)
}
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
@ -47,7 +47,7 @@ var listContainersCmd = &cobra.Command{
prm.SetAccount(idUser)
res, err := internalclient.ListContainers(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
var prmGet internalclient.GetContainerPrm
prmGet.SetClient(cli)

View file

@ -5,10 +5,10 @@ import (
v2object "github.com/TrueCloudLab/frostfs-api-go/v2/object"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
objectCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/spf13/cobra"
@ -52,7 +52,7 @@ var listContainerObjectsCmd = &cobra.Command{
prmSearch.SetFilters(*filters)
res, err := internalclient.SearchObjects(prmSearch)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
objectIDs := res.IDList()

View file

@ -4,9 +4,9 @@ import (
"crypto/sha256"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
containerAPI "github.com/TrueCloudLab/frostfs-sdk-go/container"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/netmap"
@ -32,7 +32,7 @@ var containerNodesCmd = &cobra.Command{
prm.SetClient(cli)
resmap, err := internalclient.NetMapSnapshot(prm)
common.ExitOnErr(cmd, "unable to get netmap snapshot", err)
commonCmd.ExitOnErr(cmd, "unable to get netmap snapshot", err)
var id cid.ID
containerAPI.CalculateID(&id, cnr)
@ -43,12 +43,12 @@ var containerNodesCmd = &cobra.Command{
var cnrNodes [][]netmap.NodeInfo
cnrNodes, err = resmap.NetMap().ContainerNodes(policy, binCnr)
common.ExitOnErr(cmd, "could not build container nodes for given container: %w", err)
commonCmd.ExitOnErr(cmd, "could not build container nodes for given container: %w", err)
for i := range cnrNodes {
cmd.Printf("Descriptor #%d, REP %d:\n", i+1, policy.ReplicaNumberByIndex(i))
for j := range cnrNodes[i] {
common.PrettyPrintNodeInfo(cmd, cnrNodes[i][j], j, "\t", short)
commonCmd.PrettyPrintNodeInfo(cmd, cnrNodes[i][j], j, "\t", short)
}
}
},

View file

@ -9,6 +9,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
)
@ -38,10 +39,10 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
cmd.Println("Checking the ability to modify access rights in the container...")
extendable, err := internalclient.IsACLExtendable(cli, id)
common.ExitOnErr(cmd, "Extensibility check failure: %w", err)
commonCmd.ExitOnErr(cmd, "Extensibility check failure: %w", err)
if !extendable {
common.ExitOnErr(cmd, "", errors.New("container ACL is immutable"))
commonCmd.ExitOnErr(cmd, "", errors.New("container ACL is immutable"))
}
cmd.Println("ACL extension is enabled in the container, continue processing.")
@ -56,11 +57,11 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
}
_, err := internalclient.SetEACL(setEACLPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
if containerAwait {
exp, err := eaclTable.Marshal()
common.ExitOnErr(cmd, "broken EACL table: %w", err)
commonCmd.ExitOnErr(cmd, "broken EACL table: %w", err)
cmd.Println("awaiting...")
@ -87,7 +88,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
}
}
common.ExitOnErr(cmd, "", errSetEACLTimeout)
commonCmd.ExitOnErr(cmd, "", errSetEACLTimeout)
}
},
}

View file

@ -5,6 +5,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/session"
"github.com/spf13/cobra"
@ -24,12 +25,12 @@ var (
func parseContainerID(cmd *cobra.Command) cid.ID {
if containerID == "" {
common.ExitOnErr(cmd, "", errors.New("container ID is not set"))
commonCmd.ExitOnErr(cmd, "", errors.New("container ID is not set"))
}
var id cid.ID
err := id.DecodeString(containerID)
common.ExitOnErr(cmd, "can't decode container ID value: %w", err)
commonCmd.ExitOnErr(cmd, "can't decode container ID value: %w", err)
return id
}
@ -49,7 +50,7 @@ func getSession(cmd *cobra.Command) *session.Container {
var res session.Container
err := common.ReadBinaryOrJSON(cmd, &res, path)
common.ExitOnErr(cmd, "read container session: %v", err)
commonCmd.ExitOnErr(cmd, "read container session: %v", err)
common.PrintVerbose(cmd, "Session successfully read.")

View file

@ -2,8 +2,8 @@ package control
import (
rawclient "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/spf13/cobra"
)
@ -40,7 +40,7 @@ var dropObjectsCmd = &cobra.Command{
resp, err = control.DropObjects(client, req)
return err
})
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -2,8 +2,8 @@ package control
import (
"github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/spf13/cobra"
)
@ -32,7 +32,7 @@ func evacuateShard(cmd *cobra.Command, _ []string) {
resp, err = control.EvacuateShard(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
cmd.Printf("Objects moved: %d\n", resp.GetBody().GetCount())

View file

@ -2,8 +2,8 @@ package control
import (
"github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/spf13/cobra"
)
@ -31,7 +31,7 @@ func flushCache(cmd *cobra.Command, _ []string) {
resp, err = control.FlushCache(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -4,8 +4,8 @@ import (
"crypto/ecdsa"
rawclient "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
ircontrol "github.com/TrueCloudLab/frostfs-node/pkg/services/control/ir"
ircontrolsrv "github.com/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
@ -52,7 +52,7 @@ func healthCheck(cmd *cobra.Command, _ []string) {
resp, err = control.HealthCheck(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
@ -66,14 +66,14 @@ func healthCheckIR(cmd *cobra.Command, key *ecdsa.PrivateKey, c *client.Client)
req.SetBody(new(ircontrol.HealthCheckRequest_Body))
err := ircontrolsrv.SignMessage(key, req)
common.ExitOnErr(cmd, "could not sign request: %w", err)
commonCmd.ExitOnErr(cmd, "could not sign request: %w", err)
var resp *ircontrol.HealthCheckResponse
err = c.ExecRaw(func(client *rawclient.Client) error {
resp, err = ircontrol.HealthCheck(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -7,6 +7,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/spf13/cobra"
)
@ -57,7 +58,7 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) {
switch st, _ := cmd.Flags().GetString(netmapStatusFlag); st {
default:
common.ExitOnErr(cmd, "", fmt.Errorf("unsupported status %s", st))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("unsupported status %s", st))
case netmapStatusOnline:
body.SetStatus(control.NetmapStatus_ONLINE)
printIgnoreForce(control.NetmapStatus_ONLINE)
@ -86,7 +87,7 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) {
resp, err = control.SetNetmapStatus(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -2,8 +2,8 @@ package control
import (
"github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/spf13/cobra"
)
@ -45,7 +45,7 @@ func dumpShard(cmd *cobra.Command, _ []string) {
resp, err = control.DumpShard(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -7,9 +7,9 @@ import (
"strings"
rawclient "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/mr-tron/base58"
"github.com/spf13/cobra"
@ -45,7 +45,7 @@ func listShards(cmd *cobra.Command, _ []string) {
resp, err = control.ListShards(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
@ -58,9 +58,9 @@ func listShards(cmd *cobra.Command, _ []string) {
}
func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) {
out := make([]map[string]interface{}, 0, len(ii))
out := make([]map[string]any, 0, len(ii))
for _, i := range ii {
out = append(out, map[string]interface{}{
out = append(out, map[string]any{
"shard_id": base58.Encode(i.Shard_ID),
"mode": shardModeToString(i.GetMode()),
"metabase": i.GetMetabasePath(),
@ -73,7 +73,7 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) {
buf := bytes.NewBuffer(nil)
enc := json.NewEncoder(buf)
enc.SetIndent("", " ")
common.ExitOnErr(cmd, "cannot shard info to JSON: %w", enc.Encode(out))
commonCmd.ExitOnErr(cmd, "cannot shard info to JSON: %w", enc.Encode(out))
cmd.Print(buf.String()) // pretty printer emits newline, to no need for Println
}

View file

@ -2,8 +2,8 @@ package control
import (
"github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/spf13/cobra"
)
@ -45,7 +45,7 @@ func restoreShard(cmd *cobra.Command, _ []string) {
resp, err = control.RestoreShard(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -5,8 +5,8 @@ import (
"strings"
rawclient "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
"github.com/mr-tron/base58"
"github.com/spf13/cobra"
@ -93,6 +93,7 @@ func initControlSetShardModeCmd() {
flags.String(shardModeFlag, "",
fmt.Sprintf("New shard mode (%s)", strings.Join(modes, ", ")),
)
_ = setShardModeCmd.MarkFlagRequired(shardModeFlag)
flags.Bool(shardClearErrorsFlag, false, "Set shard error count to 0")
setShardModeCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag)
@ -105,7 +106,7 @@ func setShardMode(cmd *cobra.Command, _ []string) {
mode, ok := lookUpShardModeFromString(strMode)
if !ok {
common.ExitOnErr(cmd, "", fmt.Errorf("unsupported mode %s", strMode))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("unsupported mode %s", strMode))
}
req := new(control.SetShardModeRequest)
@ -129,7 +130,7 @@ func setShardMode(cmd *cobra.Command, _ []string) {
resp, err = control.SetShardMode(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
@ -139,7 +140,7 @@ func setShardMode(cmd *cobra.Command, _ []string) {
func getShardID(cmd *cobra.Command) []byte {
sid, _ := cmd.Flags().GetString(shardIDFlag)
raw, err := base58.Decode(sid)
common.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err)
commonCmd.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err)
return raw
}
@ -151,7 +152,7 @@ func getShardIDList(cmd *cobra.Command) [][]byte {
sidList, _ := cmd.Flags().GetStringSlice(shardIDFlag)
if len(sidList) == 0 {
common.ExitOnErr(cmd, "", fmt.Errorf("either --%s or --%s flag must be provided", shardIDFlag, shardAllFlag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("either --%s or --%s flag must be provided", shardIDFlag, shardAllFlag))
}
// We can sort the ID list and perform this check without additional allocations,
@ -160,7 +161,7 @@ func getShardIDList(cmd *cobra.Command) [][]byte {
seen := make(map[string]struct{})
for i := range sidList {
if _, ok := seen[sidList[i]]; ok {
common.ExitOnErr(cmd, "", fmt.Errorf("duplicated shard IDs: %s", sidList[i]))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("duplicated shard IDs: %s", sidList[i]))
}
seen[sidList[i]] = struct{}{}
}
@ -168,7 +169,7 @@ func getShardIDList(cmd *cobra.Command) [][]byte {
res := make([][]byte, 0, len(sidList))
for i := range sidList {
raw, err := base58.Decode(sidList[i])
common.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err)
commonCmd.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err)
res = append(res, raw)
}

View file

@ -5,9 +5,9 @@ import (
"errors"
rawclient "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
controlSvc "github.com/TrueCloudLab/frostfs-node/pkg/services/control/server"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
@ -40,11 +40,11 @@ func synchronizeTree(cmd *cobra.Command, _ []string) {
var cnr cid.ID
cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag)
common.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr))
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr))
treeID, _ := cmd.Flags().GetString("tree-id")
if treeID == "" {
common.ExitOnErr(cmd, "", errors.New("tree ID must not be empty"))
commonCmd.ExitOnErr(cmd, "", errors.New("tree ID must not be empty"))
}
height, _ := cmd.Flags().GetUint64("height")
@ -61,7 +61,7 @@ func synchronizeTree(cmd *cobra.Command, _ []string) {
}
err := controlSvc.SignMessage(pk, req)
common.ExitOnErr(cmd, "could not sign request: %w", err)
commonCmd.ExitOnErr(cmd, "could not sign request: %w", err)
cli := getClient(cmd, pk)
@ -70,7 +70,7 @@ func synchronizeTree(cmd *cobra.Command, _ []string) {
resp, err = control.SynchronizeTree(client, req)
return err
})
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

View file

@ -6,8 +6,8 @@ import (
"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
controlSvc "github.com/TrueCloudLab/frostfs-node/pkg/services/control/server"
"github.com/TrueCloudLab/frostfs-sdk-go/client"
frostfscrypto "github.com/TrueCloudLab/frostfs-sdk-go/crypto"
@ -24,7 +24,7 @@ func initControlFlags(cmd *cobra.Command) {
func signRequest(cmd *cobra.Command, pk *ecdsa.PrivateKey, req controlSvc.SignedMessage) {
err := controlSvc.SignMessage(pk, req)
common.ExitOnErr(cmd, "could not sign request: %w", err)
commonCmd.ExitOnErr(cmd, "could not sign request: %w", err)
}
func verifyResponse(cmd *cobra.Command,
@ -37,7 +37,7 @@ func verifyResponse(cmd *cobra.Command,
},
) {
if sigControl == nil {
common.ExitOnErr(cmd, "", errors.New("missing response signature"))
commonCmd.ExitOnErr(cmd, "", errors.New("missing response signature"))
}
// TODO(@cthulhu-rider): #1387 use Signature message from NeoFS API to avoid conversion
@ -47,10 +47,10 @@ func verifyResponse(cmd *cobra.Command,
sigV2.SetSign(sigControl.GetSign())
var sig frostfscrypto.Signature
common.ExitOnErr(cmd, "can't read signature: %w", sig.ReadFromV2(sigV2))
commonCmd.ExitOnErr(cmd, "can't read signature: %w", sig.ReadFromV2(sigV2))
if !sig.Verify(body.StableMarshal(nil)) {
common.ExitOnErr(cmd, "", errors.New("invalid response signature"))
commonCmd.ExitOnErr(cmd, "", errors.New("invalid response signature"))
}
}

View file

@ -2,9 +2,9 @@ package netmap
import (
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
)
@ -20,7 +20,7 @@ var getEpochCmd = &cobra.Command{
prm.SetClient(cli)
res, err := internalclient.NetworkInfo(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
netInfo := res.NetworkInfo()

View file

@ -5,9 +5,9 @@ import (
"time"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/spf13/cobra"
)
@ -24,7 +24,7 @@ var netInfoCmd = &cobra.Command{
prm.SetClient(cli)
res, err := internalclient.NetworkInfo(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
netInfo := res.NetworkInfo()
@ -37,7 +37,7 @@ var netInfoCmd = &cobra.Command{
const format = " %s: %v\n"
cmd.Println("NeoFS network configuration (system)")
cmd.Println("FrostFS network configuration (system)")
cmd.Printf(format, "Audit fee", netInfo.AuditFee())
cmd.Printf(format, "Storage price", netInfo.StoragePrice())
cmd.Printf(format, "Container fee", netInfo.ContainerFee())
@ -50,7 +50,7 @@ var netInfoCmd = &cobra.Command{
cmd.Printf(format, "Homomorphic hashing disabled", netInfo.HomomorphicHashingDisabled())
cmd.Printf(format, "Maintenance mode allowed", netInfo.MaintenanceModeAllowed())
cmd.Println("NeoFS network configuration (other)")
cmd.Println("FrostFS network configuration (other)")
netInfo.IterateRawNetworkParameters(func(name string, value []byte) {
cmd.Printf(format, name, hex.EncodeToString(value))
})

View file

@ -7,6 +7,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/netmap"
"github.com/spf13/cobra"
)
@ -25,7 +26,7 @@ var nodeInfoCmd = &cobra.Command{
prm.SetClient(cli)
res, err := internalclient.NodeInfo(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
prettyPrintNodeInfo(cmd, res.NodeInfo())
},

View file

@ -2,9 +2,9 @@ package netmap
import (
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
)
@ -20,9 +20,9 @@ var snapshotCmd = &cobra.Command{
prm.SetClient(cli)
res, err := internalclient.NetMapSnapshot(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
common.PrettyPrintNetMap(cmd, res.NetMap())
commonCmd.PrettyPrintNetMap(cmd, res.NetMap(), false)
},
}

View file

@ -4,9 +4,9 @@ import (
"fmt"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/spf13/cobra"
@ -41,18 +41,18 @@ func deleteObject(cmd *cobra.Command, _ []string) {
if binary {
filename, _ := cmd.Flags().GetString(fileFlag)
if filename == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", fileFlag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", fileFlag))
}
objAddr = readObjectAddressBin(cmd, &cnr, &obj, filename)
} else {
cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag)
if cidVal == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
}
oidVal, _ := cmd.Flags().GetString(commonflags.OIDFlag)
if oidVal == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.OIDFlag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.OIDFlag))
}
objAddr = readObjectAddress(cmd, &cnr, &obj)
@ -66,7 +66,7 @@ func deleteObject(cmd *cobra.Command, _ []string) {
prm.SetAddress(objAddr)
res, err := internalclient.DeleteObject(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
tomb := res.Tombstone()

View file

@ -7,9 +7,9 @@ import (
"os"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
@ -55,7 +55,7 @@ func getObject(cmd *cobra.Command, _ []string) {
} else {
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
}
defer f.Close()
@ -110,7 +110,7 @@ func getObject(cmd *cobra.Command, _ []string) {
return
}
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
}
if binary {
@ -118,9 +118,9 @@ func getObject(cmd *cobra.Command, _ []string) {
// TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload
objToStore.SetPayload(payloadBuffer.Bytes())
objBytes, err := objToStore.Marshal()
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
_, err = out.Write(objBytes)
common.ExitOnErr(cmd, "unable to write binary object in out: %w ", err)
commonCmd.ExitOnErr(cmd, "unable to write binary object in out: %w ", err)
}
if filename != "" && !strictOutput(cmd) {
@ -130,7 +130,7 @@ func getObject(cmd *cobra.Command, _ []string) {
// Print header only if file is not streamed to stdout.
if filename != "" {
err = printHeader(cmd, res.Header())
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
}
}

View file

@ -6,9 +6,9 @@ import (
"strings"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/checksum"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
@ -54,14 +54,14 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
objAddr := readObjectAddress(cmd, &cnr, &obj)
ranges, err := getRangeList(cmd)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
typ, err := getHashType(cmd)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
strSalt := strings.TrimPrefix(cmd.Flag(getRangeHashSaltFlag).Value.String(), "0x")
salt, err := hex.DecodeString(strSalt)
common.ExitOnErr(cmd, "could not decode salt: %w", err)
commonCmd.ExitOnErr(cmd, "could not decode salt: %w", err)
pk := key.GetOrGenerate(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
@ -76,7 +76,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
// get hash of full payload through HEAD (may be user can do it through dedicated command?)
res, err := internalclient.HeadObject(headPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
var cs checksum.Checksum
var csSet bool
@ -109,7 +109,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
}
res, err := internalclient.HashPayloadRanges(hashPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
hs := res.HashList()

View file

@ -11,6 +11,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
@ -70,11 +71,11 @@ func getObjectHeader(cmd *cobra.Command, _ []string) {
return
}
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
}
err = saveAndPrintHeader(cmd, res.Header(), cmd.Flag(fileFlag).Value.String())
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
}
func saveAndPrintHeader(cmd *cobra.Command, obj *object.Object, filename string) error {

View file

@ -12,6 +12,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
objectSDK "github.com/TrueCloudLab/frostfs-sdk-go/object"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
@ -29,7 +30,7 @@ var objectLockCmd = &cobra.Command{
var cnr cid.ID
err := cnr.DecodeString(cidRaw)
common.ExitOnErr(cmd, "Incorrect container arg: %v", err)
commonCmd.ExitOnErr(cmd, "Incorrect container arg: %v", err)
oidsRaw, _ := cmd.Flags().GetStringSlice(commonflags.OIDFlag)
@ -37,7 +38,7 @@ var objectLockCmd = &cobra.Command{
for i := range oidsRaw {
err = lockList[i].DecodeString(oidsRaw[i])
common.ExitOnErr(cmd, fmt.Sprintf("Incorrect object arg #%d: %%v", i+1), err)
commonCmd.ExitOnErr(cmd, fmt.Sprintf("Incorrect object arg #%d: %%v", i+1), err)
}
key := key.GetOrGenerate(cmd)
@ -51,7 +52,7 @@ var objectLockCmd = &cobra.Command{
exp, _ := cmd.Flags().GetUint64(commonflags.ExpireAt)
lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
if exp == 0 && lifetime == 0 { // mutual exclusion is ensured by cobra
common.ExitOnErr(cmd, "", errors.New("either expiration epoch of a lifetime is required"))
commonCmd.ExitOnErr(cmd, "", errors.New("either expiration epoch of a lifetime is required"))
}
if lifetime != 0 {
@ -61,7 +62,7 @@ var objectLockCmd = &cobra.Command{
endpoint, _ := cmd.Flags().GetString(commonflags.RPC)
currEpoch, err := internalclient.GetCurrentEpoch(ctx, cmd, endpoint)
common.ExitOnErr(cmd, "Request current epoch: %w", err)
commonCmd.ExitOnErr(cmd, "Request current epoch: %w", err)
exp = currEpoch + lifetime
}
@ -85,7 +86,7 @@ var objectLockCmd = &cobra.Command{
prm.SetHeader(obj)
res, err := internalclient.PutObject(prm)
common.ExitOnErr(cmd, "Store lock object in NeoFS: %w", err)
commonCmd.ExitOnErr(cmd, "Store lock object in FrostFS: %w", err)
cmd.Printf("Lock object ID: %s\n", res.ID())
cmd.Println("Objects successfully locked.")

View file

@ -12,9 +12,9 @@ import (
objectV2 "github.com/TrueCloudLab/frostfs-api-go/v2/object"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
"github.com/TrueCloudLab/frostfs-sdk-go/user"
@ -63,7 +63,7 @@ func putObject(cmd *cobra.Command, _ []string) {
cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag)
if !binary && cidVal == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
}
pk := key.GetOrGenerate(cmd)
@ -73,17 +73,17 @@ func putObject(cmd *cobra.Command, _ []string) {
filename, _ := cmd.Flags().GetString(fileFlag)
f, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
if err != nil {
common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
}
var payloadReader io.Reader = f
obj := object.New()
if binary {
buf, err := os.ReadFile(filename)
common.ExitOnErr(cmd, "unable to read given file: %w", err)
commonCmd.ExitOnErr(cmd, "unable to read given file: %w", err)
objTemp := object.New()
// TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload
common.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf))
commonCmd.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf))
payloadReader = bytes.NewReader(objTemp.Payload())
cnr, _ = objTemp.ContainerID()
ownerID = *objTemp.OwnerID()
@ -93,7 +93,7 @@ func putObject(cmd *cobra.Command, _ []string) {
}
attrs, err := parseObjectAttrs(cmd)
common.ExitOnErr(cmd, "can't parse object attributes: %w", err)
commonCmd.ExitOnErr(cmd, "can't parse object attributes: %w", err)
expiresOn, _ := cmd.Flags().GetUint64(commonflags.ExpireAt)
if expiresOn > 0 {
@ -121,7 +121,7 @@ func putObject(cmd *cobra.Command, _ []string) {
obj.SetAttributes(attrs...)
notificationInfo, err := parseObjectNotifications(cmd)
common.ExitOnErr(cmd, "can't parse object notification information: %w", err)
commonCmd.ExitOnErr(cmd, "can't parse object notification information: %w", err)
if notificationInfo != nil {
obj.SetNotification(*notificationInfo)
@ -163,7 +163,7 @@ func putObject(cmd *cobra.Command, _ []string) {
if p != nil {
p.Finish()
}
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
cmd.Printf("[%s] Object successfully stored\n", filename)
cmd.Printf(" OID: %s\n CID: %s\n", res.ID(), cnr)
@ -179,12 +179,12 @@ func parseObjectAttrs(cmd *cobra.Command) ([]object.Attribute, error) {
attrs := make([]object.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes
for i := range rawAttrs {
kv := strings.SplitN(rawAttrs[i], "=", 2)
if len(kv) != 2 {
k, v, found := strings.Cut(rawAttrs[i], "=")
if !found {
return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i])
}
attrs[i].SetKey(kv[0])
attrs[i].SetValue(kv[1])
attrs[i].SetKey(k)
attrs[i].SetValue(v)
}
disableFilename, _ := cmd.Flags().GetBool("disable-filename")
@ -218,26 +218,26 @@ func parseObjectNotifications(cmd *cobra.Command) (*object.NotificationInfo, err
return nil, nil
}
rawSlice := strings.SplitN(raw, separator, 2)
if len(rawSlice) != 2 {
before, after, found := strings.Cut(raw, separator)
if !found {
return nil, fmt.Errorf("notification must be in the form of: *epoch*%s*topic*, got %s", separator, raw)
}
ni := new(object.NotificationInfo)
epoch, err := strconv.ParseUint(rawSlice[0], 10, 64)
epoch, err := strconv.ParseUint(before, 10, 64)
if err != nil {
return nil, fmt.Errorf("could not parse notification epoch %s: %w", rawSlice[0], err)
return nil, fmt.Errorf("could not parse notification epoch %s: %w", before, err)
}
ni.SetEpoch(epoch)
if rawSlice[1] == "" {
if after == "" {
return nil, fmt.Errorf("incorrect empty topic: use %s to force using default topic", useDefaultTopic)
}
if rawSlice[1] != useDefaultTopic {
ni.SetTopic(rawSlice[1])
if after != useDefaultTopic {
ni.SetTopic(after)
}
return ni, nil

View file

@ -10,9 +10,9 @@ import (
"strings"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
@ -50,10 +50,10 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
objAddr := readObjectAddress(cmd, &cnr, &obj)
ranges, err := getRangeList(cmd)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
if len(ranges) != 1 {
common.ExitOnErr(cmd, "", fmt.Errorf("exactly one range must be specified, got: %d", len(ranges)))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("exactly one range must be specified, got: %d", len(ranges)))
}
var out io.Writer
@ -64,7 +64,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
} else {
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, os.ModePerm)
if err != nil {
common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
}
defer f.Close()
@ -93,7 +93,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
return
}
common.ExitOnErr(cmd, "can't get object payload range: %w", err)
commonCmd.ExitOnErr(cmd, "can't get object payload range: %w", err)
}
if filename != "" {
@ -116,7 +116,7 @@ func printSplitInfoErr(cmd *cobra.Command, err error) bool {
func printSplitInfo(cmd *cobra.Command, info *object.SplitInfo) {
bs, err := marshalSplitInfo(cmd, info)
common.ExitOnErr(cmd, "can't marshal split info: %w", err)
commonCmd.ExitOnErr(cmd, "can't marshal split info: %w", err)
cmd.Println(string(bs))
}
@ -154,16 +154,16 @@ func getRangeList(cmd *cobra.Command) ([]*object.Range, error) {
vs := strings.Split(v, ",")
rs := make([]*object.Range, len(vs))
for i := range vs {
r := strings.Split(vs[i], rangeSep)
if len(r) != 2 {
before, after, found := strings.Cut(vs[i], rangeSep)
if !found {
return nil, fmt.Errorf("invalid range specifier: %s", vs[i])
}
offset, err := strconv.ParseUint(r[0], 10, 64)
offset, err := strconv.ParseUint(before, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid '%s' range offset specifier: %w", vs[i], err)
}
length, err := strconv.ParseUint(r[1], 10, 64)
length, err := strconv.ParseUint(after, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid '%s' range length specifier: %w", vs[i], err)
}

View file

@ -6,9 +6,9 @@ import (
"strings"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
oidSDK "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
@ -48,7 +48,7 @@ func searchObject(cmd *cobra.Command, _ []string) {
readCID(cmd, &cnr)
sf, err := parseSearchFilters(cmd)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
pk := key.GetOrGenerate(cmd)
@ -62,7 +62,7 @@ func searchObject(cmd *cobra.Command, _ []string) {
prm.SetFilters(sf)
res, err := internalclient.SearchObjects(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
ids := res.IDList()

View file

@ -11,6 +11,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
sessionCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/session"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/bearer"
"github.com/TrueCloudLab/frostfs-sdk-go/client"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
@ -62,12 +63,12 @@ func parseXHeaders(cmd *cobra.Command) []string {
xs := make([]string, 0, 2*len(xHeaders))
for i := range xHeaders {
kv := strings.SplitN(xHeaders[i], "=", 2)
if len(kv) != 2 {
k, v, found := strings.Cut(xHeaders[i], "=")
if !found {
panic(fmt.Errorf("invalid X-Header format: %s", xHeaders[i]))
}
xs = append(xs, kv[0], kv[1])
xs = append(xs, k, v)
}
return xs
@ -85,9 +86,9 @@ func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address
func readObjectAddressBin(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID, filename string) oid.Address {
buf, err := os.ReadFile(filename)
common.ExitOnErr(cmd, "unable to read given file: %w", err)
commonCmd.ExitOnErr(cmd, "unable to read given file: %w", err)
objTemp := object.New()
common.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf))
commonCmd.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf))
var addr oid.Address
*cnr, _ = objTemp.ContainerID()
@ -99,12 +100,12 @@ func readObjectAddressBin(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID, filename
func readCID(cmd *cobra.Command, id *cid.ID) {
err := id.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String())
common.ExitOnErr(cmd, "decode container ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
}
func readOID(cmd *cobra.Command, id *oid.ID) {
err := id.DecodeString(cmd.Flag(commonflags.OIDFlag).Value.String())
common.ExitOnErr(cmd, "decode object ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode object ID string: %w", err)
}
// SessionPrm is a common interface of object operation's input which supports
@ -140,7 +141,7 @@ func getSession(cmd *cobra.Command) *session.Object {
var tok session.Object
err := common.ReadBinaryOrJSON(cmd, &tok, path)
common.ExitOnErr(cmd, "read session: %v", err)
commonCmd.ExitOnErr(cmd, "read session: %v", err)
return &tok
}
@ -189,15 +190,15 @@ func _readVerifiedSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.Private
switch false {
case tok.AssertContainer(cnr):
common.ExitOnErr(cmd, "", errors.New("unrelated container in the session"))
commonCmd.ExitOnErr(cmd, "", errors.New("unrelated container in the session"))
case obj == nil || tok.AssertObject(*obj):
common.ExitOnErr(cmd, "", errors.New("unrelated object in the session"))
commonCmd.ExitOnErr(cmd, "", errors.New("unrelated object in the session"))
case tok.AssertVerb(cmdVerb):
common.ExitOnErr(cmd, "", errors.New("wrong verb of the session"))
commonCmd.ExitOnErr(cmd, "", errors.New("wrong verb of the session"))
case tok.AssertAuthKey((*frostfsecdsa.PublicKey)(&key.PublicKey)):
common.ExitOnErr(cmd, "", errors.New("unrelated key in the session"))
commonCmd.ExitOnErr(cmd, "", errors.New("unrelated key in the session"))
case tok.VerifySignature():
common.ExitOnErr(cmd, "", errors.New("invalid signature of the session data"))
commonCmd.ExitOnErr(cmd, "", errors.New("invalid signature of the session data"))
}
common.PrintVerbose(cmd, "Session is correct.")
@ -273,12 +274,12 @@ func OpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client
var tok session.Object
const sessionLifetime = 10 // in NeoFS epochs
const sessionLifetime = 10 // in FrostFS epochs
common.PrintVerbose(cmd, "Opening remote session with the node...")
err := sessionCli.CreateSession(&tok, cli, sessionLifetime)
common.ExitOnErr(cmd, "open remote session: %w", err)
commonCmd.ExitOnErr(cmd, "open remote session: %w", err)
common.PrintVerbose(cmd, "Session successfully opened.")
@ -321,7 +322,7 @@ func finalizeSession(cmd *cobra.Command, dst SessionPrm, tok *session.Object, ke
common.PrintVerbose(cmd, "Signing session...")
err := tok.Sign(*key)
common.ExitOnErr(cmd, "sign session: %w", err)
commonCmd.ExitOnErr(cmd, "sign session: %w", err)
common.PrintVerbose(cmd, "Session token successfully formed and attached to the request.")
@ -359,7 +360,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID,
switch {
default:
common.ExitOnErr(cmd, "failed to get raw object header: %w", err)
commonCmd.ExitOnErr(cmd, "failed to get raw object header: %w", err)
case err == nil:
common.PrintVerbose(cmd, "Raw header received - object is singular.")
return nil
@ -407,7 +408,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID,
prm.SetFilters(query)
res, err := internal.SearchObjects(prm)
common.ExitOnErr(cmd, "failed to search objects by split ID: %w", err)
commonCmd.ExitOnErr(cmd, "failed to search objects by split ID: %w", err)
members := res.IDList()
@ -418,7 +419,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID,
idMember, ok := splitInfo.LastPart()
if !ok {
common.ExitOnErr(cmd, "", errors.New("missing any data in received object split information"))
commonCmd.ExitOnErr(cmd, "", errors.New("missing any data in received object split information"))
}
common.PrintVerbose(cmd, "Traverse the object split chain in reverse...", idMember)
@ -436,7 +437,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID,
addrObj.SetObject(idMember)
res, err = internal.HeadObject(prmHead)
common.ExitOnErr(cmd, "failed to read split chain member's header: %w", err)
commonCmd.ExitOnErr(cmd, "failed to read split chain member's header: %w", err)
idMember, ok = res.Header().PreviousID()
if !ok {
@ -445,7 +446,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID,
}
if _, ok = chainSet[idMember]; ok {
common.ExitOnErr(cmd, "", fmt.Errorf("duplicated member in the split chain %s", idMember))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("duplicated member in the split chain %s", idMember))
}
chain = append(chain, idMember)
@ -463,7 +464,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID,
prmSearch.SetFilters(query)
resSearch, err := internal.SearchObjects(prmSearch)
common.ExitOnErr(cmd, "failed to find object children: %w", err)
commonCmd.ExitOnErr(cmd, "failed to find object children: %w", err)
list := resSearch.IDList()

View file

@ -17,7 +17,9 @@ import (
sgCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/storagegroup"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/tree"
utilCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/misc"
"github.com/TrueCloudLab/frostfs-node/pkg/util/config"
"github.com/TrueCloudLab/frostfs-node/pkg/util/gendoc"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
@ -25,12 +27,13 @@ import (
)
const (
envPrefix = "NEOFS_CLI"
envPrefix = "FROSTFS_CLI"
)
// Global scope flags.
var (
cfgFile string
cfgDir string
)
// rootCmd represents the base command when called without any subcommands.
@ -50,7 +53,7 @@ and much more!`,
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
common.ExitOnErr(rootCmd, "", err)
commonCmd.ExitOnErr(rootCmd, "", err)
}
func init() {
@ -63,6 +66,7 @@ func init() {
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file (default is $HOME/.config/frostfs-cli/config.yaml)")
rootCmd.PersistentFlags().StringVar(&cfgDir, "config-dir", "", "Config directory")
rootCmd.PersistentFlags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand,
false, commonflags.VerboseUsage)
@ -105,7 +109,7 @@ func initConfig() {
} else {
// Find home directory.
home, err := homedir.Dir()
common.ExitOnErr(rootCmd, "", err)
commonCmd.ExitOnErr(rootCmd, "", err)
// Search config in `$HOME/.config/frostfs-cli/` with name "config.yaml"
viper.AddConfigPath(filepath.Join(home, ".config", "frostfs-cli"))
@ -120,4 +124,10 @@ func initConfig() {
if err := viper.ReadInConfig(); err == nil {
common.PrintVerbose(rootCmd, "Using config file: %s", viper.ConfigFileUsed())
}
if cfgDir != "" {
if err := config.ReadConfigDir(viper.GetViper(), cfgDir); err != nil {
commonCmd.ExitOnErr(rootCmd, "failed to read config dir: %w", err)
}
}
}

View file

@ -5,9 +5,9 @@ import (
"os"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/network"
"github.com/TrueCloudLab/frostfs-sdk-go/client"
frostfsecdsa "github.com/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
@ -52,10 +52,10 @@ func createSession(cmd *cobra.Command, _ []string) {
var netAddr network.Address
addrStr, _ := cmd.Flags().GetString(commonflags.RPC)
common.ExitOnErr(cmd, "can't parse endpoint: %w", netAddr.FromString(addrStr))
commonCmd.ExitOnErr(cmd, "can't parse endpoint: %w", netAddr.FromString(addrStr))
c, err := internalclient.GetSDKClient(cmd, privKey, netAddr)
common.ExitOnErr(cmd, "can't create client: %w", err)
commonCmd.ExitOnErr(cmd, "can't create client: %w", err)
lifetime := uint64(defaultLifetime)
if lfArg, _ := cmd.Flags().GetUint64(commonflags.Lifetime); lfArg != 0 {
@ -65,23 +65,23 @@ func createSession(cmd *cobra.Command, _ []string) {
var tok session.Object
err = CreateSession(&tok, c, lifetime)
common.ExitOnErr(cmd, "can't create session: %w", err)
commonCmd.ExitOnErr(cmd, "can't create session: %w", err)
var data []byte
if toJSON, _ := cmd.Flags().GetBool(jsonFlag); toJSON {
data, err = tok.MarshalJSON()
common.ExitOnErr(cmd, "can't decode session token JSON: %w", err)
commonCmd.ExitOnErr(cmd, "can't decode session token JSON: %w", err)
} else {
data = tok.Marshal()
}
filename, _ := cmd.Flags().GetString(outFlag)
err = os.WriteFile(filename, data, 0644)
common.ExitOnErr(cmd, "can't write token to file: %w", err)
commonCmd.ExitOnErr(cmd, "can't write token to file: %w", err)
}
// CreateSession opens a new communication with NeoFS storage node using client connection.
// CreateSession opens a new communication with FrostFS storage node using client connection.
// The session is expected to be maintained by the storage node during the given
// number of epochs.
//

View file

@ -2,10 +2,10 @@ package storagegroup
import (
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
objectCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/spf13/cobra"
@ -44,7 +44,7 @@ func delSG(cmd *cobra.Command, _ []string) {
prm.SetAddress(addr)
res, err := internalclient.DeleteObject(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
tombstone := res.Tombstone()

View file

@ -8,6 +8,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
objectCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
storagegroupSDK "github.com/TrueCloudLab/frostfs-sdk-go/storagegroup"
@ -57,7 +58,7 @@ func getSG(cmd *cobra.Command, _ []string) {
prm.SetPayloadWriter(buf)
res, err := internalclient.GetObject(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
rawObj := res.Header()
rawObj.SetPayload(buf.Bytes())
@ -65,7 +66,7 @@ func getSG(cmd *cobra.Command, _ []string) {
var sg storagegroupSDK.StorageGroup
err = storagegroupSDK.ReadFromObject(&sg, *rawObj)
common.ExitOnErr(cmd, "could not read storage group from the obj: %w", err)
commonCmd.ExitOnErr(cmd, "could not read storage group from the obj: %w", err)
cmd.Printf("The last active epoch: %d\n", sg.ExpirationEpoch())
cmd.Printf("Group size: %d\n", sg.ValidationDataSize())

View file

@ -2,10 +2,10 @@ package storagegroup
import (
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
objectCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/object_manager/storagegroup"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/spf13/cobra"
@ -40,7 +40,7 @@ func listSG(cmd *cobra.Command, _ []string) {
prm.SetFilters(storagegroup.SearchQuery())
res, err := internalclient.SearchObjects(prm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
ids := res.IDList()

View file

@ -6,10 +6,10 @@ import (
"fmt"
internalclient "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
objectCli "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/object_manager/storagegroup"
"github.com/TrueCloudLab/frostfs-sdk-go/container"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
@ -60,10 +60,10 @@ func putSG(cmd *cobra.Command, _ []string) {
for i := range sgMembers {
err := members[i].DecodeString(sgMembers[i])
common.ExitOnErr(cmd, "could not parse object ID: %w", err)
commonCmd.ExitOnErr(cmd, "could not parse object ID: %w", err)
if _, alreadyExists := uniqueFilter[members[i]]; alreadyExists {
common.ExitOnErr(cmd, "", fmt.Errorf("%s member in not unique", members[i]))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("%s member in not unique", members[i]))
}
uniqueFilter[members[i]] = struct{}{}
@ -80,7 +80,7 @@ func putSG(cmd *cobra.Command, _ []string) {
getCnrPrm.SetContainer(cnr)
resGetCnr, err := internalclient.GetContainer(getCnrPrm)
common.ExitOnErr(cmd, "get container RPC call: %w", err)
commonCmd.ExitOnErr(cmd, "get container RPC call: %w", err)
objectCli.OpenSessionViaClient(cmd, &putPrm, cli, pk, cnr, nil)
objectCli.Prepare(cmd, &headPrm, &putPrm)
@ -94,13 +94,13 @@ func putSG(cmd *cobra.Command, _ []string) {
ownerID: &ownerID,
prm: headPrm,
}, cnr, members, !container.IsHomomorphicHashingDisabled(resGetCnr.Container()))
common.ExitOnErr(cmd, "could not collect storage group members: %w", err)
commonCmd.ExitOnErr(cmd, "could not collect storage group members: %w", err)
var netInfoPrm internalclient.NetworkInfoPrm
netInfoPrm.SetClient(cli)
ni, err := internalclient.NetworkInfo(netInfoPrm)
common.ExitOnErr(cmd, "can't fetch network info: %w", err)
commonCmd.ExitOnErr(cmd, "can't fetch network info: %w", err)
lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
sg.SetExpirationEpoch(ni.NetworkInfo().CurrentEpoch() + lifetime)
@ -114,7 +114,7 @@ func putSG(cmd *cobra.Command, _ []string) {
putPrm.SetHeader(obj)
res, err := internalclient.PutObject(putPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
cmd.Println("Storage group successfully stored")
cmd.Printf(" ID: %s\n CID: %s\n", res.ID(), cnr)
@ -127,7 +127,7 @@ type sgHeadReceiver struct {
prm internalclient.HeadObjectPrm
}
func (c sgHeadReceiver) Head(addr oid.Address) (interface{}, error) {
func (c sgHeadReceiver) Head(addr oid.Address) (any, error) {
c.prm.SetAddress(addr)
res, err := internalclient.HeadObject(c.prm)

View file

@ -3,8 +3,8 @@ package storagegroup
import (
"fmt"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/spf13/cobra"
@ -23,12 +23,12 @@ func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address
func readCID(cmd *cobra.Command, id *cid.ID) {
f := cmd.Flag(commonflags.CIDFlag)
if f == nil {
common.ExitOnErr(cmd, "", fmt.Errorf("missing container flag (%s)", commonflags.CIDFlag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("missing container flag (%s)", commonflags.CIDFlag))
return
}
err := id.DecodeString(f.Value.String())
common.ExitOnErr(cmd, "decode container ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
}
func readSGID(cmd *cobra.Command, id *oid.ID) {
@ -36,10 +36,10 @@ func readSGID(cmd *cobra.Command, id *oid.ID) {
f := cmd.Flag(flag)
if f == nil {
common.ExitOnErr(cmd, "", fmt.Errorf("missing storage group flag (%s)", flag))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("missing storage group flag (%s)", flag))
return
}
err := id.DecodeString(f.Value.String())
common.ExitOnErr(cmd, "decode storage group ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode storage group ID string: %w", err)
}

View file

@ -5,9 +5,9 @@ import (
"fmt"
"strings"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/tree"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/spf13/cobra"
@ -38,18 +38,18 @@ func add(cmd *cobra.Command, _ []string) {
var cnr cid.ID
err := cnr.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String())
common.ExitOnErr(cmd, "decode container ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
tid, _ := cmd.Flags().GetString(treeIDFlagKey)
pid, _ := cmd.Flags().GetUint64(parentIDFlagKey)
meta, err := parseMeta(cmd)
common.ExitOnErr(cmd, "meta data parsing: %w", err)
commonCmd.ExitOnErr(cmd, "meta data parsing: %w", err)
ctx := cmd.Context()
cli, err := _client(ctx)
common.ExitOnErr(cmd, "client: %w", err)
commonCmd.ExitOnErr(cmd, "client: %w", err)
rawCID := make([]byte, sha256.Size)
cnr.Encode(rawCID)
@ -63,10 +63,10 @@ func add(cmd *cobra.Command, _ []string) {
BearerToken: nil, // TODO: #1891 add token handling
}
common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
commonCmd.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
resp, err := cli.Add(ctx, req)
common.ExitOnErr(cmd, "rpc call: %w", err)
commonCmd.ExitOnErr(cmd, "rpc call: %w", err)
cmd.Println("Node ID: ", resp.Body.NodeId)
}
@ -79,14 +79,14 @@ func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) {
pairs := make([]*tree.KeyValue, 0, len(raws))
for i := range raws {
kv := strings.SplitN(raws[i], "=", 2)
if len(kv) != 2 {
k, v, found := strings.Cut(raws[i], "=")
if !found {
return nil, fmt.Errorf("invalid meta pair format: %s", raws[i])
}
var pair tree.KeyValue
pair.Key = kv[0]
pair.Value = []byte(kv[1])
pair.Key = k
pair.Value = []byte(v)
pairs = append(pairs, &pair)
}

View file

@ -7,6 +7,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/tree"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
@ -46,19 +47,19 @@ func addByPath(cmd *cobra.Command, _ []string) {
var cnr cid.ID
err := cnr.DecodeString(cidRaw)
common.ExitOnErr(cmd, "decode container ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
tid, _ := cmd.Flags().GetString(treeIDFlagKey)
ctx := cmd.Context()
cli, err := _client(ctx)
common.ExitOnErr(cmd, "client: %w", err)
commonCmd.ExitOnErr(cmd, "client: %w", err)
rawCID := make([]byte, sha256.Size)
cnr.Encode(rawCID)
meta, err := parseMeta(cmd)
common.ExitOnErr(cmd, "meta data parsing: %w", err)
commonCmd.ExitOnErr(cmd, "meta data parsing: %w", err)
path, _ := cmd.Flags().GetString(pathFlagKey)
//pAttr, _ := cmd.Flags().GetString(pathAttributeFlagKey)
@ -74,10 +75,10 @@ func addByPath(cmd *cobra.Command, _ []string) {
BearerToken: nil, // TODO: #1891 add token handling
}
common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
commonCmd.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
resp, err := cli.AddByPath(ctx, req)
common.ExitOnErr(cmd, "rpc call: %w", err)
commonCmd.ExitOnErr(cmd, "rpc call: %w", err)
cmd.Printf("Parent ID: %d\n", resp.GetBody().GetParentId())

View file

@ -7,6 +7,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/tree"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/TrueCloudLab/frostfs-sdk-go/object"
@ -46,13 +47,13 @@ func getByPath(cmd *cobra.Command, _ []string) {
var cnr cid.ID
err := cnr.DecodeString(cidRaw)
common.ExitOnErr(cmd, "decode container ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
tid, _ := cmd.Flags().GetString(treeIDFlagKey)
ctx := cmd.Context()
cli, err := _client(ctx)
common.ExitOnErr(cmd, "client: %w", err)
commonCmd.ExitOnErr(cmd, "client: %w", err)
rawCID := make([]byte, sha256.Size)
cnr.Encode(rawCID)
@ -73,10 +74,10 @@ func getByPath(cmd *cobra.Command, _ []string) {
BearerToken: nil, // TODO: #1891 add token handling
}
common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
commonCmd.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
resp, err := cli.GetNodeByPath(ctx, req)
common.ExitOnErr(cmd, "rpc call: %w", err)
commonCmd.ExitOnErr(cmd, "rpc call: %w", err)
nn := resp.GetBody().GetNodes()
if len(nn) == 0 {

View file

@ -3,9 +3,9 @@ package tree
import (
"crypto/sha256"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/services/tree"
cid "github.com/TrueCloudLab/frostfs-sdk-go/container/id"
"github.com/spf13/cobra"
@ -36,12 +36,12 @@ func list(cmd *cobra.Command, _ []string) {
var cnr cid.ID
err := cnr.DecodeString(cidString)
common.ExitOnErr(cmd, "decode container ID string: %w", err)
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
ctx := cmd.Context()
cli, err := _client(ctx)
common.ExitOnErr(cmd, "client: %w", err)
commonCmd.ExitOnErr(cmd, "client: %w", err)
rawCID := make([]byte, sha256.Size)
cnr.Encode(rawCID)
@ -52,10 +52,10 @@ func list(cmd *cobra.Command, _ []string) {
},
}
common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
commonCmd.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk))
resp, err := cli.TreeList(ctx, req)
common.ExitOnErr(cmd, "rpc call: %w", err)
commonCmd.ExitOnErr(cmd, "rpc call: %w", err)
for _, treeID := range resp.GetBody().GetIds() {
cmd.Println(treeID)

View file

@ -226,35 +226,32 @@ func parseEACLTable(tb *eacl.Table, args []string) error {
func parseEACLRecord(args []string) (*eacl.Record, error) {
r := new(eacl.Record)
for i := range args {
ss := strings.SplitN(args[i], ":", 2)
for _, arg := range args {
before, after, found := strings.Cut(arg, ":")
switch prefix := strings.ToLower(ss[0]); prefix {
switch prefix := strings.ToLower(before); prefix {
case "req", "obj": // filters
if len(ss) != 2 {
return nil, fmt.Errorf("invalid filter or target: %s", args[i])
}
i := strings.Index(ss[1], "=")
if i < 0 {
return nil, fmt.Errorf("invalid filter key-value pair: %s", ss[1])
if !found {
return nil, fmt.Errorf("invalid filter or target: %s", arg)
}
var key, value string
var op eacl.Match
var f bool
if 0 < i && ss[1][i-1] == '!' {
key = ss[1][:i-1]
key, value, f = strings.Cut(after, "!=")
if f {
op = eacl.MatchStringNotEqual
} else {
key = ss[1][:i]
key, value, f = strings.Cut(after, "=")
if !f {
return nil, fmt.Errorf("invalid filter key-value pair: %s", after)
}
op = eacl.MatchStringEqual
}
value = ss[1][i+1:]
typ := eacl.HeaderFromRequest
if ss[0] == "obj" {
if before == "obj" {
typ = eacl.HeaderFromObject
}
@ -263,8 +260,8 @@ func parseEACLRecord(args []string) (*eacl.Record, error) {
var err error
var pubs []ecdsa.PublicKey
if len(ss) == 2 {
pubs, err = parseKeyList(ss[1])
if found {
pubs, err = parseKeyList(after)
if err != nil {
return nil, err
}
@ -281,7 +278,7 @@ func parseEACLRecord(args []string) (*eacl.Record, error) {
eacl.AddFormedTarget(r, role, pubs...)
default:
return nil, fmt.Errorf("invalid prefix: %s", ss[0])
return nil, fmt.Errorf("invalid prefix: %s", before)
}
}

View file

@ -5,6 +5,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
)
@ -36,10 +37,10 @@ func convertEACLTable(cmd *cobra.Command, _ []string) {
var err error
if jsonFlag || len(to) == 0 {
data, err = table.MarshalJSON()
common.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err)
commonCmd.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err)
} else {
data, err = table.Marshal()
common.ExitOnErr(cmd, "can't binary encode extended ACL table: %w", err)
commonCmd.ExitOnErr(cmd, "can't binary encode extended ACL table: %w", err)
}
if len(to) == 0 {
@ -48,7 +49,7 @@ func convertEACLTable(cmd *cobra.Command, _ []string) {
}
err = os.WriteFile(to, data, 0644)
common.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err)
commonCmd.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err)
cmd.Printf("extended ACL table was successfully dumped to %s\n", to)
}

View file

@ -6,7 +6,7 @@ import (
"fmt"
"os"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-node/pkg/util/keyer"
"github.com/spf13/cobra"
)
@ -41,7 +41,7 @@ func processKeyer(cmd *cobra.Command, args []string) {
err = result.ParseMultiSig(args)
} else {
if len(args) > 1 {
common.ExitOnErr(cmd, "", errKeyerSingleArgument)
commonCmd.ExitOnErr(cmd, "", errKeyerSingleArgument)
}
var argument string
@ -59,7 +59,7 @@ func processKeyer(cmd *cobra.Command, args []string) {
}
}
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
result.PrettyPrint(uncompressed, useHex)
}

View file

@ -1,7 +1,7 @@
package util
import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
locodedb "github.com/TrueCloudLab/frostfs-node/pkg/util/locode/db"
airportsdb "github.com/TrueCloudLab/frostfs-node/pkg/util/locode/db/airports"
locodebolt "github.com/TrueCloudLab/frostfs-node/pkg/util/locode/db/boltdb"
@ -58,7 +58,7 @@ var (
})
err := targetDB.Open()
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
defer targetDB.Close()
@ -68,7 +68,7 @@ var (
}
err = locodedb.FillDatabase(locodeDB, airportDB, continentsDB, names, targetDB)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
},
}
)

View file

@ -1,7 +1,7 @@
package util
import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
locodedb "github.com/TrueCloudLab/frostfs-node/pkg/util/locode/db"
locodebolt "github.com/TrueCloudLab/frostfs-node/pkg/util/locode/db/boltdb"
"github.com/spf13/cobra"
@ -25,12 +25,12 @@ var (
}, locodebolt.ReadOnly())
err := targetDB.Open()
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
defer targetDB.Close()
record, err := locodedb.LocodeRecord(targetDB, locodeInfoCode)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
cmd.Printf("Country: %s\n", record.CountryName())
cmd.Printf("Location: %s\n", record.LocationName())

View file

@ -6,6 +6,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/spf13/cobra"
)
@ -37,7 +38,7 @@ func signBearerToken(cmd *cobra.Command, _ []string) {
pk := key.GetOrGenerate(cmd)
err := btok.Sign(*pk)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
to := cmd.Flag(signToFlag).Value.String()
jsonFlag, _ := cmd.Flags().GetBool(signBearerJSONFlag)
@ -45,7 +46,7 @@ func signBearerToken(cmd *cobra.Command, _ []string) {
var data []byte
if jsonFlag || len(to) == 0 {
data, err = btok.MarshalJSON()
common.ExitOnErr(cmd, "can't JSON encode bearer token: %w", err)
commonCmd.ExitOnErr(cmd, "can't JSON encode bearer token: %w", err)
} else {
data = btok.Marshal()
}
@ -56,7 +57,7 @@ func signBearerToken(cmd *cobra.Command, _ []string) {
}
err = os.WriteFile(to, data, 0644)
common.ExitOnErr(cmd, "can't write signed bearer token to file: %w", err)
commonCmd.ExitOnErr(cmd, "can't write signed bearer token to file: %w", err)
cmd.Printf("signed bearer token was successfully dumped to %s\n", to)
}

View file

@ -10,6 +10,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "github.com/TrueCloudLab/frostfs-node/cmd/internal/common"
"github.com/TrueCloudLab/frostfs-sdk-go/session"
"github.com/spf13/cobra"
)
@ -34,10 +35,10 @@ func initSignSessionCmd() {
func signSessionToken(cmd *cobra.Command, _ []string) {
fPath, err := cmd.Flags().GetString(signFromFlag)
common.ExitOnErr(cmd, "", err)
commonCmd.ExitOnErr(cmd, "", err)
if fPath == "" {
common.ExitOnErr(cmd, "", errors.New("missing session token flag"))
commonCmd.ExitOnErr(cmd, "", errors.New("missing session token flag"))
}
type iTokenSession interface {
@ -59,15 +60,15 @@ func signSessionToken(cmd *cobra.Command, _ []string) {
}
}
common.ExitOnErr(cmd, "decode session: %v", errLast)
commonCmd.ExitOnErr(cmd, "decode session: %v", errLast)
pk := key.GetOrGenerate(cmd)
err = stok.Sign(*pk)
common.ExitOnErr(cmd, "can't sign token: %w", err)
commonCmd.ExitOnErr(cmd, "can't sign token: %w", err)
data, err := stok.MarshalJSON()
common.ExitOnErr(cmd, "can't encode session token: %w", err)
commonCmd.ExitOnErr(cmd, "can't encode session token: %w", err)
to := cmd.Flag(signToFlag).Value.String()
if len(to) == 0 {
@ -77,7 +78,7 @@ func signSessionToken(cmd *cobra.Command, _ []string) {
err = os.WriteFile(to, data, 0644)
if err != nil {
common.ExitOnErr(cmd, "", fmt.Errorf("can't write signed session token to %s: %w", to, err))
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't write signed session token to %s: %w", to, err))
}
cmd.Printf("signed session token saved in %s\n", to)

View file

@ -4,18 +4,19 @@ import (
"strings"
"time"
"github.com/TrueCloudLab/frostfs-node/pkg/util/config"
"github.com/spf13/viper"
)
func newConfig(path string) (*viper.Viper, error) {
const innerRingPrefix = "neofs_ir"
func newConfig(path, directory string) (*viper.Viper, error) {
const envPrefix = "FROSTFS_IR"
var (
err error
v = viper.New()
)
v.SetEnvPrefix(innerRingPrefix)
v.SetEnvPrefix(envPrefix)
v.AutomaticEnv()
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
@ -28,7 +29,13 @@ func newConfig(path string) (*viper.Viper, error) {
} else {
v.SetConfigType("yml")
}
err = v.ReadInConfig()
if err = v.ReadInConfig(); err != nil {
return v, err
}
}
if directory != "" {
err = config.ReadConfigDir(v, directory)
}
return v, err

View file

@ -35,6 +35,7 @@ func exitErr(err error) {
func main() {
configFile := flag.String("config", "", "path to config")
configDir := flag.String("config-dir", "", "path to config directory")
versionFlag := flag.Bool("version", false, "frostfs-ir node version")
flag.Parse()
@ -44,7 +45,7 @@ func main() {
os.Exit(SuccessReturnCode)
}
cfg, err := newConfig(*configFile)
cfg, err := newConfig(*configFile, *configDir)
exitErr(err)
var logPrm logger.Prm
@ -126,7 +127,7 @@ func initHTTPServers(cfg *viper.Viper, log *logger.Logger) []*httputil.Server {
addr := cfg.GetString(item.cfgPrefix + ".address")
var prm httputil.Prm
var prm httputil.HTTPSrvPrm
prm.Address = addr
prm.Handler = item.handler()

View file

@ -0,0 +1,25 @@
package main
type closer struct {
name string
fn func()
}
func getCloser(c *cfg, name string) *closer {
for _, clsr := range c.closers {
if clsr.name == name {
return &clsr
}
}
return nil
}
func delCloser(c *cfg, name string) {
for i, clsr := range c.closers {
if clsr.name == name {
c.closers[i] = c.closers[len(c.closers)-1]
c.closers = c.closers[:len(c.closers)-1]
return
}
}
}

View file

@ -24,7 +24,6 @@ import (
blobovniczaconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza"
fstreeconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree"
loggerconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/logger"
metricsconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/metrics"
nodeconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node"
objectconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object"
replicatorconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator"
@ -48,6 +47,7 @@ import (
"github.com/TrueCloudLab/frostfs-node/pkg/network"
"github.com/TrueCloudLab/frostfs-node/pkg/network/cache"
"github.com/TrueCloudLab/frostfs-node/pkg/services/control"
objectService "github.com/TrueCloudLab/frostfs-node/pkg/services/object"
getsvc "github.com/TrueCloudLab/frostfs-node/pkg/services/object/get"
"github.com/TrueCloudLab/frostfs-node/pkg/services/object_manager/tombstone"
tsourse "github.com/TrueCloudLab/frostfs-node/pkg/services/object_manager/tombstone/source"
@ -308,7 +308,7 @@ type internals struct {
wg *sync.WaitGroup
workers []worker
closers []func()
closers []closer
apiVersion version.Version
healthStatus *atomic.Int32
@ -342,9 +342,10 @@ type shared struct {
privateTokenStore sessionStorage
persistate *state.PersistentStorage
clientCache *cache.ClientCache
bgClientCache *cache.ClientCache
localAddr network.AddressGroup
clientCache *cache.ClientCache
bgClientCache *cache.ClientCache
putClientCache *cache.ClientCache
localAddr network.AddressGroup
key *keys.PrivateKey
binPublicKey []byte
@ -363,12 +364,16 @@ type shared struct {
treeService *tree.Service
metricsCollector *metrics.NodeMetrics
metricsSvc *objectService.MetricCollector
}
// dynamicConfiguration stores parameters of the
// components that supports runtime reconfigurations.
type dynamicConfiguration struct {
logger *logger.Prm
logger *logger.Prm
pprof *httpComponent
metrics *httpComponent
}
type cfg struct {
@ -472,6 +477,8 @@ type cfgObject struct {
pool cfgObjectRoutines
cfgLocalStorage cfgLocalStorage
tombstoneLifetime uint64
}
type cfgNotifications struct {
@ -489,6 +496,10 @@ type cfgObjectRoutines struct {
putRemoteCapacity int
putLocal *ants.Pool
putLocalCapacity int
replicatorPoolSize int
replication *ants.Pool
@ -568,13 +579,14 @@ func initCfg(appCfg *config.Config) *cfg {
ReconnectTimeout: apiclientconfig.ReconnectTimeout(appCfg),
}
c.shared = shared{
key: key,
binPublicKey: key.PublicKey().Bytes(),
localAddr: netAddr,
respSvc: response.NewService(response.WithNetworkState(netState)),
clientCache: cache.NewSDKClientCache(cacheOpts),
bgClientCache: cache.NewSDKClientCache(cacheOpts),
persistate: persistate,
key: key,
binPublicKey: key.PublicKey().Bytes(),
localAddr: netAddr,
respSvc: response.NewService(response.WithNetworkState(netState)),
clientCache: cache.NewSDKClientCache(cacheOpts),
bgClientCache: cache.NewSDKClientCache(cacheOpts),
putClientCache: cache.NewSDKClientCache(cacheOpts),
persistate: persistate,
}
c.cfgAccounting = cfgAccounting{
scriptHash: contractsconfig.Balance(appCfg),
@ -598,7 +610,8 @@ func initCfg(appCfg *config.Config) *cfg {
proxyScriptHash: contractsconfig.Proxy(appCfg),
}
c.cfgObject = cfgObject{
pool: initObjectPool(appCfg),
pool: initObjectPool(appCfg),
tombstoneLifetime: objectconfig.TombstoneLifetime(appCfg),
}
c.cfgReputation = cfgReputation{
scriptHash: contractsconfig.Reputation(appCfg),
@ -607,13 +620,12 @@ func initCfg(appCfg *config.Config) *cfg {
user.IDFromKey(&c.ownerIDFromKey, key.PrivateKey.PublicKey)
if metricsconfig.Enabled(c.appCfg) {
c.metricsCollector = metrics.NewNodeMetrics()
netState.metrics = c.metricsCollector
}
c.metricsCollector = metrics.NewNodeMetrics()
netState.metrics = c.metricsCollector
c.onShutdown(c.clientCache.CloseAll) // clean up connections
c.onShutdown(c.bgClientCache.CloseAll) // clean up connections
c.onShutdown(c.clientCache.CloseAll) // clean up connections
c.onShutdown(c.bgClientCache.CloseAll) // clean up connections
c.onShutdown(c.putClientCache.CloseAll) // clean up connections
c.onShutdown(func() { _ = c.persistate.Close() })
return c
@ -790,13 +802,18 @@ func initLocalStorage(c *cfg) {
tombstone.WithTombstoneSource(tombstoneSrc),
)
var shardsAttached int
for _, optsWithMeta := range c.shardOpts() {
id, err := ls.AddShard(append(optsWithMeta.shOpts, shard.WithTombstoneSource(tombstoneSource))...)
fatalOnErr(err)
c.log.Info("shard attached to engine",
zap.Stringer("id", id),
)
if err != nil {
c.log.Error("failed to attach shard to engine", zap.Error(err))
} else {
shardsAttached++
c.log.Info("shard attached to engine", zap.Stringer("id", id))
}
}
if shardsAttached == 0 {
fatalOnErr(engineconfig.ErrNoShardConfigured)
}
c.cfgObject.cfgLocalStorage.localStorage = ls
@ -821,10 +838,13 @@ func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) {
optNonBlocking := ants.WithNonblocking(true)
pool.putRemoteCapacity = objectconfig.Put(cfg).PoolSizeRemote()
pool.putRemote, err = ants.NewPool(pool.putRemoteCapacity, optNonBlocking)
fatalOnErr(err)
pool.putLocalCapacity = objectconfig.Put(cfg).PoolSizeLocal()
pool.putLocal, err = ants.NewPool(pool.putLocalCapacity, optNonBlocking)
fatalOnErr(err)
pool.replicatorPoolSize = replicatorconfig.PoolSize(cfg)
if pool.replicatorPoolSize <= 0 {
pool.replicatorPoolSize = pool.putRemoteCapacity
@ -849,8 +869,8 @@ func (c *cfg) LocalNodeInfo() (*netmapV2.NodeInfo, error) {
return &res, nil
}
// handleLocalNodeInfo rewrites local node info from the NeoFS network map.
// Called with nil when storage node is outside the NeoFS network map
// handleLocalNodeInfo rewrites local node info from the FrostFS network map.
// Called with nil when storage node is outside the FrostFS network map
// (before entering the network and after leaving it).
func (c *cfg) handleLocalNodeInfo(ni *netmap.NodeInfo) {
c.cfgNetmap.state.setNodeInfo(ni)
@ -904,67 +924,107 @@ func (c *cfg) ObjectServiceLoad() float64 {
return float64(c.cfgObject.pool.putRemote.Running()) / float64(c.cfgObject.pool.putRemoteCapacity)
}
type dCfg struct {
name string
cfg interface {
Reload() error
}
type dCmp struct {
name string
reloadFunc func() error
}
func (c *cfg) configWatcher(ctx context.Context) {
func (c *cfg) signalWatcher() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGHUP)
signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
for {
select {
case <-ch:
c.log.Info("SIGHUP has been received, rereading configuration...")
case sig := <-ch:
switch sig {
case syscall.SIGHUP:
c.reloadConfig()
case syscall.SIGTERM, syscall.SIGINT:
c.log.Info("termination signal has been received, stopping...")
// TODO (@acid-ant): #49 need to cover case when stuck at the middle(node health UNDEFINED or STARTING)
err := c.readConfig(c.appCfg)
if err != nil {
c.log.Error("configuration reading", zap.Error(err))
continue
c.shutdown()
c.log.Info("termination signal processing is complete")
return
}
case err := <-c.internalErr: // internal application error
c.log.Warn("internal application error",
zap.String("message", err.Error()))
// all the components are expected to support
// Logger's dynamic reconfiguration approach
var components []dCfg
c.shutdown()
// Logger
logPrm, err := c.loggerPrm()
if err != nil {
c.log.Error("logger configuration preparation", zap.Error(err))
continue
}
components = append(components, dCfg{name: "logger", cfg: logPrm})
// Storage Engine
var rcfg engine.ReConfiguration
for _, optsWithID := range c.shardOpts() {
rcfg.AddShard(optsWithID.configID, optsWithID.shOpts)
}
err = c.cfgObject.cfgLocalStorage.localStorage.Reload(rcfg)
if err != nil {
c.log.Error("storage engine configuration update", zap.Error(err))
continue
}
for _, component := range components {
err = component.cfg.Reload()
if err != nil {
c.log.Error("updated configuration applying",
zap.String("component", component.name),
zap.Error(err))
}
}
c.log.Info("configuration has been reloaded successfully")
case <-ctx.Done():
c.log.Info("internal error processing is complete")
return
}
}
}
func (c *cfg) reloadConfig() {
c.log.Info("SIGHUP has been received, rereading configuration...")
err := c.readConfig(c.appCfg)
if err != nil {
c.log.Error("configuration reading", zap.Error(err))
return
}
// all the components are expected to support
// Logger's dynamic reconfiguration approach
var components []dCmp
// Logger
logPrm, err := c.loggerPrm()
if err != nil {
c.log.Error("logger configuration preparation", zap.Error(err))
return
}
components = append(components, dCmp{"logger", logPrm.Reload})
if cmp, updated := metricsComponent(c); updated {
if cmp.enabled {
cmp.preReload = enableMetricsSvc
} else {
cmp.preReload = disableMetricsSvc
}
components = append(components, dCmp{cmp.name, cmp.reload})
}
if cmp, updated := pprofComponent(c); updated {
components = append(components, dCmp{cmp.name, cmp.reload})
}
// Storage Engine
var rcfg engine.ReConfiguration
for _, optsWithID := range c.shardOpts() {
rcfg.AddShard(optsWithID.configID, optsWithID.shOpts)
}
err = c.cfgObject.cfgLocalStorage.localStorage.Reload(rcfg)
if err != nil {
c.log.Error("storage engine configuration update", zap.Error(err))
return
}
for _, component := range components {
err = component.reloadFunc()
if err != nil {
c.log.Error("updated configuration applying",
zap.String("component", component.name),
zap.Error(err))
}
}
c.log.Info("configuration has been reloaded successfully")
}
func (c *cfg) shutdown() {
c.setHealthStatus(control.HealthStatus_SHUTTING_DOWN)
c.ctxCancel()
for i := range c.closers {
c.closers[len(c.closers)-1-i].fn()
}
close(c.internalErr)
}

View file

@ -9,10 +9,10 @@ import (
const (
subsection = "apiclient"
// DialTimeoutDefault is a default dial timeout of NeoFS API client connection.
// DialTimeoutDefault is a default dial timeout of FrostFS API client connection.
DialTimeoutDefault = 5 * time.Second
// StreamTimeoutDefault is a default timeout of NeoFS API streaming operation.
// StreamTimeoutDefault is a default timeout of FrostFS API streaming operation.
StreamTimeoutDefault = 15 * time.Second
)

View file

@ -37,7 +37,7 @@ func (x *Config) Sub(name string) *Config {
// recommended.
//
// Returns nil if config is nil.
func (x *Config) Value(name string) interface{} {
func (x *Config) Value(name string) any {
value := x.v.Get(strings.Join(append(x.path, name), separator))
if value != nil || x.defaultPath == nil {
return value

View file

@ -5,6 +5,7 @@ import (
"strings"
"github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/internal"
"github.com/TrueCloudLab/frostfs-node/pkg/util/config"
"github.com/spf13/viper"
)
@ -54,6 +55,12 @@ func New(_ Prm, opts ...Option) *Config {
}
}
if o.configDir != "" {
if err := config.ReadConfigDir(v, o.configDir); err != nil {
panic(fmt.Errorf("failed to read config dir: %w", err))
}
}
return &Config{
v: v,
opts: *o,
@ -69,5 +76,11 @@ func (x *Config) Reload() error {
}
}
if x.opts.configDir != "" {
if err := config.ReadConfigDir(x.v, x.opts.configDir); err != nil {
return fmt.Errorf("rereading configuration dir: %w", err)
}
}
return nil
}

View file

@ -6,7 +6,7 @@ import (
// EnvPrefix is a prefix of ENV variables related
// to storage node configuration.
const EnvPrefix = "neofs"
const EnvPrefix = "FROSTFS"
// EnvSeparator is a section separator in ENV variables.
const EnvSeparator = "_"

View file

@ -9,7 +9,7 @@ import (
func TestEnv(t *testing.T) {
require.Equal(t,
"NEOFS_SECTION_PARAMETER",
"FROSTFS_SECTION_PARAMETER",
internal.Env("section", "parameter"),
)
}

View file

@ -25,8 +25,8 @@ func TestMorphSection(t *testing.T) {
var (
rpcs = []client.Endpoint{
{"wss://rpc1.morph.fs.neo.org:40341/ws", 1},
{"wss://rpc2.morph.fs.neo.org:40341/ws", 2},
{"wss://rpc1.morph.frostfs.info:40341/ws", 1},
{"wss://rpc2.morph.frostfs.info:40341/ws", 2},
}
)

View file

@ -39,3 +39,15 @@ func (g PutConfig) PoolSizeRemote() int {
return PutPoolSizeDefault
}
// PoolSizeLocal returns the value of "pool_size_local" config parameter.
//
// Returns PutPoolSizeDefault if the value is not a positive number.
func (g PutConfig) PoolSizeLocal() int {
v := config.Int(g.cfg, "pool_size_local")
if v > 0 {
return int(v)
}
return PutPoolSizeDefault
}

View file

@ -14,12 +14,16 @@ func TestObjectSection(t *testing.T) {
empty := configtest.EmptyConfig()
require.Equal(t, objectconfig.PutPoolSizeDefault, objectconfig.Put(empty).PoolSizeRemote())
require.Equal(t, objectconfig.PutPoolSizeDefault, objectconfig.Put(empty).PoolSizeLocal())
require.EqualValues(t, objectconfig.DefaultTombstoneLifetime, objectconfig.TombstoneLifetime(empty))
})
const path = "../../../../config/example/node"
var fileConfigTest = func(c *config.Config) {
require.Equal(t, 100, objectconfig.Put(c).PoolSizeRemote())
require.Equal(t, 200, objectconfig.Put(c).PoolSizeLocal())
require.EqualValues(t, 10, objectconfig.TombstoneLifetime(c))
}
configtest.ForEachFileType(path, fileConfigTest)

View file

@ -0,0 +1,19 @@
package objectconfig
import "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
const (
deleteSubsection = "delete"
// DefaultTombstoneLifetime is the default value of tombstone lifetime in epochs.
DefaultTombstoneLifetime = 5
)
// TombstoneLifetime returns the value of `tombstone_lifetime` config parameter.
func TombstoneLifetime(c *config.Config) uint64 {
ts := config.UintSafe(c.Sub(subsection).Sub(deleteSubsection), "tombstone_lifetime")
if ts <= 0 {
return DefaultTombstoneLifetime
}
return ts
}

Some files were not shown because too many files have changed in this diff Show more