Compare commits

...

559 commits

Author SHA1 Message Date
d86cf85b39 [#311] client/container: Remove outdated comment
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-11 15:53:53 +03:00
3dbae11efa
[#310] client/container: Remove commented code
Refs #291.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-11 14:23:44 +03:00
c4463df8d4 [#291] container: Rename field Account to OwnerID in PrmContainerList
Renaming this field so that it matches PrmContainerListStream.

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-10 13:49:38 +03:00
852dac1476 [#291] container: Add ListStream method
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-10 13:49:38 +03:00
e3026d3f4c [#291] container: Add ListStream to api
Since api was moved from `TrueCloudLab/frostfs-api-go` to sdk,
moving changes from TrueCloudLab/frostfs-api-go#125 here.

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-10 12:05:56 +03:00
81c423e709 [#301] rpc: Make client stream initialization get cancelled by dial timeout
* `c.conn` may be already invalidated but the rpc client can't detect this.
  `NewStream` may hang trying to open a stream with invalidated connection.
  Using timer with `dialTimeout` for `NewStream` fixes this problem.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-06 09:49:44 +00:00
f7da6ba99c
[#306] netmap: Allow to select empty set of nodes
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-05 15:33:29 +03:00
0352b5b191
[#185] Implement rpc/client for tree service
Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
2024-11-29 15:23:14 +03:00
afdc2d8340 [#297] bearer: Update module docstring
Module top level docstring was referencing outdated APIs which do not
exist anymore.

Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
2024-11-13 10:41:25 +03:00
cb813e27a8 [#293] object: Fix payload size limiter
* Sending empty chunks by `writeChunk` should not release new
  objects as this doesn't change `payloadSizeLimiter` internal
  state.
* This also fixes the bug with patcher when an offset of a patch
  equals to `MaxSize` - `payloadSizeLimiter` releases object again
  although state is the same. This led to error because EC-encoder
  receieved empty payload and couldn't not process it.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-07 12:11:19 +00:00
6980651785 [#296] Stop using obsolete .github directory
This commit is a part of multi-repo cleanup effort:
TrueCloudLab/frostfs-infra#136

Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
2024-11-07 06:15:50 +00:00
43d5c8dbac [#185] tree/pool: Control timeout of tree service operations
Implemented context timeout for all tree service operations except those that return a GRPC stream

Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
2024-11-06 08:12:37 +00:00
56c4aaaaca
[#292] .golangci.yml: Add intrange linter, fix warnings
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-31 09:40:42 +03:00
afbe15086f
[#292] Makefile: Update golangci-lint to v1.61.0
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-31 09:40:42 +03:00
56c357d520
[#292] Makefile: Update truecloudlab lint to v0.0.7
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-31 09:40:42 +03:00
5e926df3ab
[#292] .golangci.yml: Replace exportloopref with copyloopvar
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-31 09:40:42 +03:00
6ce73790ea [#276] Merge repo with frostfs-api-go
Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
2024-10-22 14:05:12 +00:00
5361f0eceb [#279] pool: Count errors in object search
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2024-10-22 12:41:11 +00:00
05aa3becae [#278] pool: Don't make maintenance node healthy in rebalance
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-10-17 16:31:49 +03:00
79f387317a [#283] pool: Mark node unhealthy if node is under maintenance
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-10-16 15:22:05 +03:00
3ea4741231 [#283] go.mod: Tidy
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-10-16 15:20:53 +03:00
d7872061f8
[#284] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-11 15:17:23 +03:00
99c5c58365
[#282] client: Close connection on non-nil error in Dial
A particular status code does not imply that a connection has not been
established. However, `Dial()` requires user to call `Close()` only if
the error was nil. Thus, it is `Dial()` responsibility to close
everything if it returns an error.

Introduced after the gRPC update in #270 (6009d089fc).

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-10 14:03:44 +03:00
4c310ae1c7 [#280] client: Use DialTimeout for gRPC dial
After removing `grpc.Dial` from client `DialTimeout` used only if
custom dialer provided. Client uses `BalanceOf` instead of `grpc.Dial`,
so it is required to use `DialTimeout` to not to use RPC timeout.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-10-07 16:58:05 +03:00
997346ef95
[#274] client/status: Add missing test cases for commom statuses
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-10-03 17:05:15 +03:00
7f6eda566a
[#274] client/status: Fix check in TestNodeUnderMaintenance test
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-10-03 17:05:15 +03:00
d00892f418
[#274] client/status: Support INVALID_ARGUMENT status
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-10-03 17:05:08 +03:00
b9092aeb0c
[#274] go.mod: Update api-go
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-10-02 11:07:19 +03:00
1b67ab9608 [#275] client: Return status from all methods
Since status is checked first in handleError method, it should be returned from client methods

Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2024-09-24 18:29:32 +03:00
99d5bf913b [#269] netmap: Add tests for non-ascii attributes in SELECT IN
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-20 11:09:16 +00:00
e50838a33d [#269] netmap: Regenerate policy parser
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-20 11:09:16 +00:00
97cf56ba41 [#269] netmap: Support non-ascii attributes in SELECT IN
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-20 11:09:16 +00:00
07625e3bd1 [#269] Update ANTLR version 4.13.0 -> 4.13.1
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-20 11:09:16 +00:00
da2f0e7532 [#269] .gitignore: Ignore ANTLR jar file
The previous wildcard failed to properly match the ANTLR jar file.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-20 11:09:16 +00:00
114b4c14b5 [#269] Makefile: Update policy target
The previous policy target generated device-specific comments
(e.g., `/home/john_doe/repos/<...>`), which could result in
unnecessary file changes This behavior would confuse git and
require manual changes to resolve. The update ensures comments
are now device-agnostic, preventing unwanted changes.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-20 11:09:16 +00:00
e580ee991d [#271] Drop handling of system attributes with NeoFS prefix
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-18 09:59:38 +00:00
6821fe6fb2 [#271] object: Add UserAttributes method
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-18 09:59:38 +00:00
6009d089fc [#270] client: Use RPC call instead of Dial
After api-go upgrade created client doesn't establish connection after created,
so RPC call is required to establish and check connection.
RPC call returns status error, so conversion from status error to context error
is required to satisfy Dial contract and unit tests.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-09-16 15:31:51 +03:00
3e455777fd [#270] go.mod: Upgrade api-go version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-09-16 15:10:02 +03:00
1dc3b77ac7 [#270] pool: Replace deprecated DialContext
`Healthcheck` request performed after client creation, so no extra RPC required.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-09-16 15:09:59 +03:00
88c6556c37 [#270] go.mod: Upgrade google.golang.org/grpc
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-09-16 15:09:54 +03:00
d342c0bc16 [#268] client: Make PayloadPatch correctly receive empty patch payload
* Make the method `PatchPayload` send a patch with empty
  payload patch if range's length is non-zero and if it's the
  first call.
* Empty payload patches just cut original object payload. So, these
  patches are also valid.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-09-12 15:12:52 +03:00
f0c599d06d [#268] client: Fix sequential PayloadPatch calls
* The flag 'firstPayloadPatch' keeps its state after first
  `PatchPayload` that make other calls incorrectly set patch
  ranges.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-09-12 15:09:01 +03:00
7d84d104fb [#260] *: Fix linter warnings
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-09 08:55:32 +00:00
812126a8ff [#260] .golangci.yml: Add protogetter linter
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-09 08:55:32 +00:00
d86223ed56 [#260] Makefile: Add pre-commit targets
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-09 08:55:32 +00:00
76a0cfdadb [#217] netmap: Return node netmap state directly
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-09 08:51:51 +00:00
46ee543899 [#265] go.mod: Use range over int
Since Go 1.22 a `for` statement with a `range` clause is able
to iterate through integer values from zero to an upper limit.

gopatch script:
@@
var i, e expression
@@
-for i := 0; i <= e - 1; i++ {
+for i := range e {
    ...
}

@@
var i, e expression
@@
-for i := 0; i <= e; i++ {
+for i := range e + 1 {
    ...
}

@@
var i, e expression
@@
-for i := 0; i < e; i++ {
+for i := range e {
    ...
}

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-09-04 12:37:46 +03:00
8f751d9dd0
[#263] go.mod: Update api-go
Remove `client.ContainerEACL` and related references. This change
was initiated by the removal of `ContainerService.GetExtendedACL`
from the API.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-09-03 12:36:28 +03:00
3c00f4eeac [#203] Add pool docs
Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
2024-08-30 08:24:31 +03:00
f0b9493ce3 [#261] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-08-27 11:33:09 +03:00
28f140bf06 [#254] pool: Add parameter gracefulCloseOnSwitchTimeout
Add new param for waiting a little until current in-flight requests will be finished

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-08-22 08:02:51 +00:00
9115d3f281 [#1316] lint: Fix warnings
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-08-21 17:59:10 +03:00
cf225be0df [#1316] go.mod: Bump go version to 1.22
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-08-21 16:42:58 +03:00
338d1ef254 [#258] pool/tree: Add node address to error
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-08-20 14:19:58 +03:00
6dd7be11d1 [#256] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-08-20 10:20:28 +03:00
203bba65a0 [#253] pool: Don't count regular FrostFS errors
Previously we count all frostfs errors like:
ObjectNotFound, EACLNotFound
because frostfs status is unconditionally resolved into built-in go errors
but handleError method handled built-in errors like internal network ones.
Since after resolving frostfs errors status is also returned we start check this first

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-08-14 16:48:51 +03:00
98aabc45a7 [#252] patcher: Fix applying patch from the same offset
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-13 18:58:21 +03:00
908c96a94d [#251] pool: Fix handlerError panic for objectPatch
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-13 15:28:39 +03:00
2077b35736 [#231] netmap: Add LIKE operation for filter
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-08-12 09:49:12 +03:00
92c7596157 [#231] go.mod: Update version for frostfs-api-go/v2
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-08-12 09:49:04 +03:00
a15b1264f5 [#231] policy: Bump jre version to 17
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-08-12 09:44:30 +03:00
5d58519253 [#249] pool: Introduce objectPatch method
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-08 18:26:40 +03:00
93171b3319 [#249] session: Support patch verb
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-08 18:26:40 +03:00
3ba7446157 [#249] client: Introduce ObjectPatch
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-08 18:26:35 +03:00
335aa18dc6 [#249] go.mod: Bump frostfs-api-go/v2 version
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-06 16:57:42 +03:00
361739e860 [#247] object: Introduce patcher package
* Introduce `patcher` package that contains such interfaces to be
  implemented:
  - `PatchApplier` - the main patching engine that merges the stream
    of patches and the stream of original object payload divided by
    ranges. The merged streams result is output to `ChunkedObjectWriter`;
  - `RangeProvider` - provides the original object payload by ranges;
  - `HeaderProvider` - provides the original object header.
* Introduce `patcher` that implements `PatchApplier`;
* Cover all possible cases with unit-tests.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-05 12:32:14 +00:00
6dd500def9 [#247] object: Introduce Patch type
* Make ToV2, FromV2 converters for Patch and PayloadPatch;
* Add unit-tests.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-05 12:32:14 +00:00
e83d6b7c6a [#244] pool/tree: Collect request duration statistic
After each request for tree pool statistic accumulated values are reset to zero.

Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2024-08-02 13:01:14 +03:00
9da46f566f [#243] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-26 14:13:49 +03:00
fa89999d91 [#242] pool: Log error that caused healthy status change
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2024-07-22 15:12:27 +03:00
7e94a6adf2 [#237] pool: Return creation epoch from object put
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2024-07-22 06:15:23 +00:00
ce8270568d [#239] go.mod: Update frostfs-contract
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-07-18 17:17:40 +03:00
7c06cdff2d [#239] pool/tree: Update tree service client
Update tree service to fix split tree problem.
Tree intermediate nodes can be duplicated so we must handle this.

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-07-17 14:32:04 +03:00
e18b916231 [#238] go.mod: Update frostfs-contract to v0.19.3
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-07-16 11:36:21 +03:00
c4ff8a6cda [#236] go.mod: Update neo-go to v0.106.2
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 15:43:11 +03:00
fc7c524fcb [#236] *: Replace slice.Copy() with bytes.Clone()
The former is deprecated.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 15:43:07 +03:00
e977b8a94c [#236] netmap: Remove unused field from meanIQRAgg
It was there since the inception [1], but we never got to use it.

[1] 5931284e07

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 14:25:07 +03:00
6729f54c4e [#236] netmap: Reuse slice for weights in ContainerNodes()
```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                                              │    alloc     │               weights               │
                                                              │    sec/op    │    sec/op     vs base               │
Netmap_ContainerNodes/REP_2-8                                   8.677µ ±  6%   8.384µ ± 10%       ~ (p=0.247 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   7.946µ ± 14%   7.998µ ±  6%       ~ (p=0.481 n=10)
geomean                                                         8.303µ         8.189µ        -1.38%

                                                              │    alloc     │               weights               │
                                                              │     B/op     │     B/op      vs base               │
Netmap_ContainerNodes/REP_2-8                                   7.734Ki ± 0%   7.617Ki ± 0%  -1.52% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   7.156Ki ± 0%   7.039Ki ± 0%  -1.64% (p=0.000 n=10)
geomean                                                         7.440Ki        7.322Ki       -1.58%

                                                              │   alloc    │              weights               │
                                                              │ allocs/op  │ allocs/op   vs base                │
Netmap_ContainerNodes/REP_2-8                                   92.00 ± 0%   77.00 ± 0%  -16.30% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   92.00 ± 0%   77.00 ± 0%  -16.30% (p=0.000 n=10)
geomean                                                         92.00        77.00       -16.30%
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 14:25:07 +03:00
159a50fcf0 [#236] netmap: Reduce allocations in getSelection()
```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                                              │     new      │                alloc                 │
                                                              │    sec/op    │    sec/op     vs base                │
Netmap_ContainerNodes/REP_2-8                                   9.227µ ± 13%   8.677µ ±  6%        ~ (p=0.165 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   9.189µ ±  7%   7.946µ ± 14%  -13.53% (p=0.001 n=10)
geomean                                                         9.208µ         8.303µ         -9.82%

                                                              │     new      │                alloc                │
                                                              │     B/op     │     B/op      vs base               │
Netmap_ContainerNodes/REP_2-8                                   8.320Ki ± 0%   7.734Ki ± 0%  -7.04% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   7.742Ki ± 0%   7.156Ki ± 0%  -7.57% (p=0.000 n=10)
geomean                                                         8.026Ki        7.440Ki       -7.31%

                                                              │     new     │               alloc                │
                                                              │  allocs/op  │ allocs/op   vs base                │
Netmap_ContainerNodes/REP_2-8                                   122.00 ± 0%   92.00 ± 0%  -24.59% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   122.00 ± 0%   92.00 ± 0%  -24.59% (p=0.000 n=10)
geomean                                                          122.0        92.00       -24.59%
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 14:25:07 +03:00
a69f00903c [#236] netmap: Replace sort.Slice() with slices.Sort()
```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                                              │      old      │                 new                  │
                                                              │    sec/op     │    sec/op     vs base                │
Netmap_ContainerNodes/REP_2-8                                   10.395µ ± 14%   9.227µ ± 13%  -11.24% (p=0.015 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   10.110µ ± 16%   9.189µ ±  7%        ~ (p=0.105 n=10)
geomean                                                          10.25µ         9.208µ        -10.18%

                                                              │     old      │                 new                 │
                                                              │     B/op     │     B/op      vs base               │
Netmap_ContainerNodes/REP_2-8                                   8.695Ki ± 0%   8.320Ki ± 0%  -4.31% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   8.117Ki ± 0%   7.742Ki ± 0%  -4.62% (p=0.000 n=10)
geomean                                                         8.401Ki        8.026Ki       -4.47%

                                                              │    old     │                new                 │
                                                              │ allocs/op  │ allocs/op   vs base                │
Netmap_ContainerNodes/REP_2-8                                   138.0 ± 0%   122.0 ± 0%  -11.59% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   138.0 ± 0%   122.0 ± 0%  -11.59% (p=0.000 n=10)
geomean                                                         138.0        122.0       -11.59%
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 14:25:07 +03:00
9d89f08c7b [#236] go.mod: Bump min go version to go1.21
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-07-12 14:25:06 +03:00
51cefd4908 [#232] netmap: Allow empty values for unknown parameters in network config
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-07-09 12:19:25 +03:00
560cbbd1f1 [#234] pool: Update token expiration check in cache
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2024-07-05 12:36:17 +03:00
27e965007d [#233] pool: Introduce ape-manager methods
* Remove GetEACL, SetEACL methods as they are deprecated;
* Fix mock;
* Introduce add/remove/list methods to request ape-manager from
  the client.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-07-04 01:29:35 +03:00
1a5886e776 [#228] client: Move isClientErrMaintenance from node
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-06-17 17:07:30 +03:00
ebd8fcd168 [#224] object: Introduce parent attributes in EC-header
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-31 16:20:48 +03:00
717a7d00ef [#225] bearer: Introduce APEOverride field for the token
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-31 12:14:42 +00:00
dd23c6fd2b [#225] apemanager: Move apemanager to ape package
* Update go.mod;
* Fix packages;
* Fix client's `apemanager` methods.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-31 12:14:42 +00:00
6a52487edd [#226] pool/tree: Fix handling access denied error
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-05-30 14:59:35 +03:00
c5c6272029 [#221] pool: Make sampler safe for concurrent using
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-05-20 14:14:14 +03:00
3de256d05e [#223] object: Introduce new fields for ECHeader
* Introduce `parentSplitID`, `parentSplitParentID` fields
  for `ECHeader`;
* Fix ECHeader's constructor;
* Fix `Split` and `Reconstruct`;
* Add unit-tests.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-17 15:16:28 +03:00
09b79d13f3 [#223] object: Introduce ec_parent search filter
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-17 15:03:40 +03:00
d4e6f4e125 [#223] go.mod: Update frosts-api-go/v2 version
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-17 15:02:44 +03:00
b2ad1f3b3e [#215] client: Introduce apemanager rpc interface
* Introduce `APEManagerAddChain`, `APEManagerRemoveChain`, `APEManagerListChains`.
* Introduce reqeuest/response types for these handlers (Prm*, Res*).
* Inroduce status type for apemanager `APEManagerAccessDenied`; add unit-tests.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-14 10:59:52 +03:00
32a975a20d [#215] apemanager: Introduce apemanager types
* Introduce `Chain`, `ChainTarget` and `TargetType`.
* Implement api-v2 converters for the introduced types.
* Add unit-tests.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-14 10:59:49 +03:00
eaf36706a2 [#215] go.mod: Update frostfs-api-go/v2 package version
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-05-08 11:18:18 +03:00
02c936f397 [#216] netmap: Add policy decode fuzz test
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-05-07 11:10:37 +00:00
99e02858af [#220] netmap: Fix setters for Replica.DataCount/ParityCount
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-05-07 09:34:14 +03:00
12ddefe078 [#218] object: Implement Range\RangeHash requests for EC object
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-05-02 11:01:21 +03:00
20ab57bf7e [#214] object: Implement Get\Head requests for EC object
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-04-24 11:07:26 +03:00
3790142b10 [#212] pool: Control sub tree nodes order
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-02 17:15:49 +03:00
ec0cb2169f [#211] object: Fix setIDWithSignature
* Calculate and set checksum before ID is calculated.
* Add header verification for parts in unit-test.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-03-29 13:48:04 +03:00
425d48f68b [#211] netmap: Introduce ReplicaDescriptor method
* Make ReplicaNumberByIndex deprecated.
* Introduce ReplicaDescriptor method that access i-th replica directly.
* Introduce new getters for ReplicaDescriptor.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-03-29 13:48:04 +03:00
6d0da3f861 [#211] go.mod: Update frostfs-api-go version
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-03-29 13:48:04 +03:00
1af9b6d18b [#155] sdk-go: Add buffer support for payloadSizeLimiter
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-03-25 10:47:04 +03:00
bd2d350b09 [#205] object: Initial EC implementation
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-22 10:14:12 +00:00
e9be3e6d94 [#205] netmap: Add well-known EC parameters to network config
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-22 10:14:12 +00:00
70e9e40c7f [#205] netmap: Add EC statement to placement policy
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-22 10:14:12 +00:00
d33b54d280 [#205] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-22 10:14:12 +00:00
6f248436a5 [#210] client/put_transformer: Fix error handling
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-03-19 15:36:51 +03:00
edd40474e8 [#209] pre-commit: Add unit-test hook
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-14 13:35:48 +03:00
d9ec7c1988 [#209] Makefile: Allow to override test flags
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-14 13:35:48 +03:00
64b83f8220 [#209] Makefile: Update golangci-lint to 1.56.2
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-14 13:35:48 +03:00
7212f38115 [#209] pre-commit: Remove gitlint
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-14 13:35:48 +03:00
8081445ff2 [#208] go.mod: Bump frostfs-api-go version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-03-06 13:34:04 +03:00
6a7ef9d8c3 [#208] go.mod: Bump protobuf version
Found by vulncheck:
Vulnerability #1: GO-2024-2611
    Infinite loop in JSON unmarshaling in google.golang.org/protobuf
  More info: https://pkg.go.dev/vuln/GO-2024-2611
  Module: google.golang.org/protobuf
    Found in: google.golang.org/protobuf@v1.32.0
    Fixed in: google.golang.org/protobuf@v1.33.0

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-03-06 13:23:32 +03:00
6fe4e2541d [#207] netmap: Fix string escape in PlacementPolicy.String()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-03-01 15:02:05 +00:00
a5fab572ff [#206] Add session tokens for container read operations
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-03-01 15:18:53 +03:00
a86170f53a [#202] object: Reset marshal data on CutPayload
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-02-15 15:23:47 +03:00
aa41f71dcc [#202] eacl: Drop storage group test
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-02-15 15:23:47 +03:00
3a00fd51e4 [#202] go.mod: Update api-go version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-02-15 15:23:43 +03:00
65b4525b3b [#198] object/user: Add ScriptHash method
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-01-26 14:10:09 +00:00
7efff9d53d [#201] .forgejo: Update dco-go to v3
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-01-26 12:21:42 +03:00
110b7e4170 [#200] pre-commit: Fix linter invocation target
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-01-17 17:56:20 +03:00
56debcfa56 [#190] sdk-go: Gofumpt fixes
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-11-22 19:21:20 +03:00
157a9930e8 [#190] sdk-go: Pass user.ID by value
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-11-22 19:21:20 +03:00
1c07098740 [#194] make: Fix make test
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2023-11-17 11:48:51 +00:00
03d35dd1f3 [#166] netmap: Add support YML tests
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2023-11-17 14:43:03 +03:00
dea8759762 [#166] netmap: Move tests from JSON to YML
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2023-11-17 14:42:39 +03:00
3787477133 [#189] client: Make PrmDial fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-11-14 11:18:00 +03:00
e91d40e250 [#189] client: Make PrmInit fields public for client
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-11-13 15:18:07 +03:00
ab75edd709 [#191] pool/tree: Support limit request attempts
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-11-07 14:45:40 +03:00
8999d2f080 [#191] pool/tree: Support request id
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-11-07 14:45:35 +03:00
6fbe1595cb [#121] pool: Refactor PrmObjectSearch usage
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-11-01 17:45:15 +03:00
a9237aabd2 [#121] client: Make PrmObjectSearch fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-11-01 17:45:06 +03:00
a487033505 [#121] client: Nuke out unused prmCommonMeta
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-10-31 22:55:25 +03:00
51c3618850 [#121] client: Make PrmContainerList fields public
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-10-31 22:55:25 +03:00
665e5807bc [#188] transformer: Allow to provide size hint
For big objects with known size we can optimize allocation patterns
by providing size hint. As with any hint, it does not affect transformer
functionality: slices with capacity > MaxSize are never allocated.

```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                                                │     out     │
                                                │   sec/op    │
Transformer/small/no_size_hint-8                  65.44µ ± 3%
Transformer/small/no_size_hint,_with_buffer-8     64.24µ ± 5%
Transformer/small/with_size_hint,_with_buffer-8   58.70µ ± 5%
Transformer/big/no_size_hint-8                    367.8m ± 3%
Transformer/big/no_size_hint,_with_buffer-8       562.7m ± 0%
Transformer/big/with_size_hint,_with_buffer-8     385.6m ± 7%
geomean                                           5.197m

                                                │     out      │
                                                │     B/op     │
Transformer/small/no_size_hint-8                  13.40Ki ± 0%
Transformer/small/no_size_hint,_with_buffer-8     13.40Ki ± 0%
Transformer/small/with_size_hint,_with_buffer-8   13.39Ki ± 0%
Transformer/big/no_size_hint-8                    288.0Mi ± 0%
Transformer/big/no_size_hint,_with_buffer-8       1.390Gi ± 0%
Transformer/big/with_size_hint,_with_buffer-8     288.0Mi ± 0%
geomean                                           2.533Mi

                                                │    out     │
                                                │ allocs/op  │
Transformer/small/no_size_hint-8                  92.00 ± 0%
Transformer/small/no_size_hint,_with_buffer-8     92.00 ± 0%
Transformer/small/with_size_hint,_with_buffer-8   92.00 ± 0%
Transformer/big/no_size_hint-8                    546.5 ± 0%
Transformer/big/no_size_hint,_with_buffer-8       607.5 ± 0%
Transformer/big/with_size_hint,_with_buffer-8     545.5 ± 0%
geomean                                           228.1
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-10-30 12:13:04 +00:00
a02c0bfac8 [#186] netmap: Marshal policy with brackets
Brackets can be semantically important and must not be omitted,
otherwise the output is plain wrong.
We do not take the responsibility to preserve every bracket, though,
because parser does some optimizations related to grouping long chains
of filters combined with the same operation.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-10-27 10:54:45 +03:00
20d325e307 [#167] netmap: Fix reverse min agregator
The higher the price, the lower reverse min weight should be.
Previously nodes with 0 price had 0 weight which is a bit misleading.

Introduced in d71a0e0755.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-10-27 07:53:19 +00:00
670619d242 [#131] client: keep backwards-compatibility, update README.md, fix chore
Signed-off-by: Egor Olefirenko <egor.olefirenko892@gmail.com>
2023-10-26 14:35:49 +00:00
0d79d10482 [#131] client: rename option consistently and fix test
Signed-off-by: Egor Olefirenko <egor.olefirenko892@gmail.com>
2023-10-26 14:35:49 +00:00
9727beb47d [#131] client: Switch ResolveFrostFSFailures to DontResolveFrostFSFailures option
Signed-off-by: Egor Olefirenko <egor.olefirenko892@gmail.com>
2023-10-26 14:35:49 +00:00
84315fab6a [#121] client: Make PrmBalanceGet fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-10-23 18:53:14 +03:00
71335489ae [#183] forgejo: Make linter great again
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-10-23 18:13:40 +03:00
4c1feaf2cb [#182] pool: Fix linter error about deprecated methods
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-10-23 17:40:00 +03:00
5804128ff3 [#121] client: Make PrmObjectPutSingle fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-10-19 08:38:13 +00:00
abd38c918e [#177] pool: Support NetMapSnapshot method
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-10-18 11:31:53 +03:00
fc4551b843 [#172] pool: Use priority of errors in tree pool
When retry happens, use priority map to decide
which error to return. Consider network errors
less desirable than business logic errors.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-10-11 12:00:34 +03:00
eb5288f4a5 [#172] pool: Do more retries on unexpected tree service responses
1. Try its best by looking for nodes during 'GetNodeByPath'
2. Retry on 'tree not found' and other not found errors

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-10-06 11:12:48 +03:00
60463871db [#171] pool: Add test for healthy status monitor
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-10-03 19:47:22 +03:00
8a04638749 [#171] pool: Close only dialed connections
To avoid panics during close operation, close
only dialed connections.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-10-03 19:47:22 +03:00
ddbfb758c9 [#171] pool: Use dial status to close connections during restarts
Every client restart, pool creates new client instance. If client
failed due to dial error, there was no prior connection and go
routine on a server side. If client failed due to communication
or business logic errors, then server side maintains connection and
client should close it to avoid routine and connection leak.

Dialing is a part of healthcheck, so health status is now a enum
of three values:
- unhealthy due to dial fail,
- unhealthy due to transmission fail,
- healthy.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-10-03 17:00:36 +03:00
d71a0e0755 [#88] netmap: use bool, fix hrw_sort tests
Signed-off-by: Andrew Danilin <andnilin@gmail.com>
2023-10-03 07:05:03 +00:00
163b3e1961 [#88] netmap: fix min aggregator bug, add tests
Signed-off-by: Andrew Danilin <andnilin@gmail.com>
2023-10-03 07:05:03 +00:00
84b9d29fc9 [#170] checksum: Use constant mapping for checksum types
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-28 17:20:24 +03:00
99c273f499 [#169] pool: Close inner pools during close routine
Some apps do not reuse pool instance and expect that
`pool.Close()` free resources. But it didn't actually
close inner SDK clients, so it leads to goroutine leak
in storage.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-09-20 12:16:13 +03:00
555ccc63b2 [#167] netmap: Allow to select insufficient number of nodes
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-15 14:47:54 +03:00
0550438b53 [#167] netmap/tests: Add replica to invalid tests
Make sure we fail exactly because of the reason specified.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-15 14:33:44 +03:00
c899163860 [#167] netmap/tests: Add json file name to the test output
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-15 14:33:44 +03:00
ac8fc6d440 [#162] netmap: Allow to parse single unnamed selectors
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-11 15:22:24 +03:00
0a0b590df3 [#162] Fix pre-commit warnings
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-11 15:21:35 +03:00
4df642e941 [#162] netmap: Fix possible panic
Placement policy is unvalidated external input.
Under no circumstances should we panic here.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-11 15:19:56 +03:00
8bc64e088e [#161] .golangci.yml: Reenable deprecated usage warnings
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-08 17:17:02 +03:00
49ad985cad [#161] *: Do not use math/rand.Read()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-09-08 17:17:02 +03:00
aa12d8c6a6 [#121] client: Make PrmObjectHash fields public
* Introduce buildRequest for PrmObjectHash

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-08 13:36:45 +00:00
303508328a [#121] pool: Refactor PrmSessionCreate usage
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-05 17:32:03 +03:00
55699d1480 [#121] client: Make PrmSessionCreate fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-05 17:30:42 +03:00
55a1f23e71 [#121] client: Make PrmEndpointInfo, PrmNetworkInfo fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-04 19:55:23 +03:00
291a71ba84 [#121] client: Make PrmAnnounceSpace fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-04 19:53:34 +03:00
5a471e5002 [#121] client: Make PrmObjectDelete fields public
* Introduce buildRequest for PrmObjectDelete
* Refactor the usage of these params in pool

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-09-04 14:14:22 +00:00
b5fe52d6bd [#150] policy: Check for redundant selectors and filters
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-08-29 14:16:57 +03:00
84e7e69f98 [#121] client: Make PrmObjectGet/Head/GetRange fields public
* Remove common PrmObjectRead structure
* Introduce buildRequest for PrmObjectGet/Head/GetRange
* Refactor the usage of these params in pool

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-08-28 11:26:57 +03:00
46a214d065 [#149] pool: Configure homomorphic hash and buffer size
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-08-25 09:45:15 +03:00
202412230a [#115] pool: Drop part buffer pool
Tests showed that using part buffer pool doesn't save memory a lot.
Especially on big parts.
Probably we can use pool only for small parts
after adding buffer in payloadSizeLimiter

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-08-21 12:03:03 +03:00
3cb3841073 [#115] pool: Try putSingle if possible
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-08-21 12:03:03 +03:00
faeeeab87a [#114] pool: Don't use part buffers when client cut is off
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-08-21 12:02:40 +03:00
cae215534f [#114] pool: Fix linter errors
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-08-21 12:02:40 +03:00
518fb79bc0 [#114] pool: Support client cut with memory limiter
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-08-21 12:02:40 +03:00
342524159a [#121] pool: Make PrmContainerSetEACL fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-08-21 10:33:19 +03:00
22978303f8 [#121] clientt: Make PrmContainerSetEACL fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-08-18 18:05:47 +03:00
6fdbe75517 [#121] pool: Make PrmContainerEACL fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-08-16 09:53:47 +00:00
3353940554 [#121] client: Make PrmContainerEACL fields public
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2023-08-16 09:53:47 +00:00
a3b5d4d4f5 [#51] Add node addresses as debug information
Signed-off-by: Artem Tataurov <a.tataurov@yadro.com>
2023-08-15 09:51:40 +03:00
0314b326d3 [#51] Add current nodes as external statistics
Signed-off-by: Artem Tataurov <a.tataurov@yadro.com>
2023-08-15 09:51:13 +03:00
0382785763 [#146] .forgejo: Update DCO action
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-11 12:34:29 +03:00
548a81d3e6 [#48] client: Refactor accounting.Balance()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-10 11:05:30 +00:00
d48788c7a9 [#144] Bump required go version to go1.20
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-09 09:52:35 +03:00
6353df8bca [#142] Fix unwrapErr for go 1.20
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-08-05 15:58:25 +00:00
936e6d230b [#121] pool: Add wait params validation for containerPut method
* Add WaitParams.CheckValidity() check because SetWaitParams is deprecated,
  but parameters were checked within this setter with checkForPositive()

Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-05 15:58:14 +00:00
be28b89312 [#121] pool: Make PrmContainerDelete fields public
* Refactor client PrmContainerDelete usage
* Introduce WaitParams CheckValidity method

Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-05 15:58:14 +00:00
9e5faaf829 [#121] client: Make PrmContainerDelete fields public
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-05 15:58:14 +00:00
3dc8129ed7 [#135] Make all error status receivers pointers
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-08-04 08:35:01 +00:00
55c52c8d5d [#121] pool: Make PrmContainerGet fields public
* Also refactor client PrmContainerGet usage

Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-03 10:54:13 +03:00
d376302a3b [#121] client: Make PrmContainerGet fields public
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-02 18:23:32 +03:00
363f153eaf [#136] pool: Set order field to get subtree
With new revision of tree service protocol, getSubTree
requires to use explicit order field.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-08-02 10:32:37 +00:00
95b987b818 [#137] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-08-02 12:04:10 +03:00
13d0b170d2 [#121] client: Make pool PrmContainerPut struct fields public
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-01 09:59:57 +00:00
18a9e4bceb [#121] client: Make PrmContainerPut struct fields public
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-08-01 09:59:57 +00:00
0fe0d71678 [#133] .forgejo: Add names to actions
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-31 11:33:39 +00:00
78d1439b2c [#133] go.mod: Update api-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-31 11:33:39 +00:00
0886d80083 [#69] Add close for nns.Dial
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
2023-07-31 11:05:26 +03:00
ecb1fef78c [#129] client: Do not override error status WriteObject()
Here is a scenario:
1. `resolveFrostFSErrors` is false.
2. The first object part was not written, which was signified in status.
3. The second part was written correctly.

Client now thinks that the object is written even though it was not.
In theory we could also return only status, but client-side splitting
is not a single RPC, so it makes sense.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-26 14:38:43 +03:00
5defed4ab4 [#126] go.mod: Update frostfs-api-go package version
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-07-19 16:03:56 +03:00
fb05f7dc5e [#112] Add basic documentation for placement policies
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-07-18 10:53:54 +00:00
b91f9d8c79 [#xx] Add support for SELECT-FILTER expressions
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-07-17 10:29:48 +00:00
b9afe7a2f9 [#42] Add ResolveContractHash method
Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
2023-07-12 22:22:58 +03:00
998fe1a7ab [#102] netmap: properly process multiple REP
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-11 14:21:35 +00:00
c359a7465a [#64] transformer: Simplify interface
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-07-11 07:33:12 +00:00
d70ef2187b [#97] Add a method IterateUserAttributes in Container
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-07-10 09:05:01 +00:00
ac95b87e7c [#101] Add Equals for Address
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-07-10 09:05:01 +00:00
863be6034f [#104] Update neo-go/pkg/interop version
neo-go module uses broken commit of interop package.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-07-10 09:04:10 +00:00
35346a01c9 [#109] Bump neo-go version
Synced version with frostfs-node, see frostfs-node#417

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-07-10 09:04:10 +00:00
fe35373d8f [#107] go.mod: Tidy dependencies
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-07-07 14:57:16 +03:00
388d1ca1de [#107] pool/tree: Support grpc schemas
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-07-07 14:57:13 +03:00
14ed3e177d [#104] nemtap: Escape special symbols in filters
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-07-07 09:33:00 +00:00
fe28c33277 [#104] netmap: Add test with quote escaping
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-07-07 09:33:00 +00:00
98cab7ed61 [#103] object: Add PutSingle method code
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-07-06 17:06:17 +03:00
37e22b33ad [#103] sdk-go: Update api-go version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-07-05 18:10:42 +03:00
769f6eec05 [#105] client: Fix revive linter warning
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-07-05 15:52:06 +03:00
5d62cef27e [#98] Fix linter issues
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-06-28 12:13:02 +00:00
c0c0c588b5 [#98] Add forgejo workflows
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-06-28 12:13:02 +00:00
2f88460172 [#83] Allow to split objects in the client
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-06-28 12:12:37 +00:00
66cb5dcf34 [#83] Update .gitignore
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-06-28 12:12:37 +00:00
91e80ba743 [#73] pool/tree: Fix index in retry loop
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-28 13:06:23 +03:00
c243b443bc [#80] objectwriter: Allow custimize maxChunkLen
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-06-26 18:13:04 +03:00
aa8ffebc63 [#95] transformer: Set parent version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-06-23 13:48:02 +03:00
9d40228cec [#73] pool/tree: Fix client healthy status
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 17:01:55 +03:00
af40dc68f0 [#84] pool/tree: Allow to pass gRPC dial options
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 15:55:07 +03:00
981d24a493 [#84] pool: Allow to pass gRPC dial options
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 15:54:48 +03:00
19adb4dffa [#73] pool/tree: Add tests
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 14:37:57 +03:00
51e022ab8c [#73] pool/tree: Add tree pool
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 14:37:57 +03:00
0d3dacb515 [#73] pool: Add getters for NodeParam
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 14:37:57 +03:00
b2e302624d [#73] pool/tree: Add proto tree service client
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-06-08 14:37:57 +03:00
fcbf96add6 [#76] Add UNIQUE keyword
Signed-off-by: Alejandro Lopez <a.lopez@yadro.com>
2023-06-06 13:54:07 +03:00
4f48f6c9e0 [#78] netmap: Add new keywords NOT and UNIQUE
* Add the rule for NOT operation to the policy parser grammar
* Regenerate query parse
* Implement NOT in filter
* Add unit-tests

Signed-off-by: Airat Arifullin a.arifullin@yadro.com
2023-06-02 17:47:20 +03:00
ec59ebfd88 [#87] go.mod: Update hrw
```
                                                              │      old      │                 new                  │
                                                              │    sec/op     │    sec/op     vs base                │
Netmap_ContainerNodes/REP_2-8                                    13.07µ ± 12%   11.03µ ± 12%  -15.63% (p=0.003 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   11.383µ ±  9%   9.970µ ± 19%  -12.42% (p=0.005 n=10)
geomean                                                          12.20µ         10.49µ        -14.04%

                                                              │      old      │                 new                  │
                                                              │     B/op      │     B/op      vs base                │
Netmap_ContainerNodes/REP_2-8                                   10.203Ki ± 0%   7.711Ki ± 0%  -24.43% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8    9.641Ki ± 0%   7.148Ki ± 0%  -25.85% (p=0.000 n=10)
geomean                                                          9.918Ki        7.424Ki       -25.14%

                                                              │    old     │                new                 │
                                                              │ allocs/op  │ allocs/op   vs base                │
Netmap_ContainerNodes/REP_2-8                                   216.0 ± 0%   131.0 ± 0%  -39.35% (p=0.000 n=10)
Netmap_ContainerNodes/REP_2_IN_X_CBF_2_SELECT_2_FROM_*_AS_X-8   215.0 ± 0%   130.0 ± 0%  -39.53% (p=0.000 n=10)
geomean                                                         215.5        130.5       -39.44%
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-06-02 14:54:40 +03:00
030ff2f122 [#87] netmap: Add benchmark for ContainerNodes()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-06-02 14:54:40 +03:00
0f7455ff7a [#75] Update antlr4 version to 4.13.0
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-06-01 13:15:11 +00:00
e6b662cfa6 [#75] Add make targets policy and docker/%
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-06-01 13:15:11 +00:00
406c2324d4 [#85] go.mod: Tidy
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-06-01 10:02:23 +03:00
10482ffbed [#82] client: Allow to pass gRPC dial options
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-05-30 16:51:22 +03:00
f5b23eb225 [#74] netmap/parser: Update antlr4 generator
Also, add -no-listener option, as we use visitor only.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-19 17:47:24 +03:00
70f23dd1ea [#74] pre-commit: Exclude auto-generated files
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-19 17:47:24 +03:00
57f874048b [#74] go.mod: Update antlr4 dependency
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-19 17:47:24 +03:00
a397d1fd15 [#74] go.mod: Update dependencies
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-19 17:47:23 +03:00
9803c2816a [#74] pool: move to sync/atomic
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-19 14:58:30 +03:00
d04d96b42e [#74] go.mod: Move to go1.19
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-19 14:53:47 +03:00
9a072a8f49 [#68] Replace interface{} with any
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-05-15 17:21:49 +03:00
15b4287092 [#49] bearer: Allow empty eacl if token is impersonated
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-05-05 12:45:39 +03:00
d4fe9a193d [#66] transformer: Accept constructor in NextTarget
The code of frostfs-node is not yet ready to reuse egress target for
multiple objects, let's postpone until #64.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-03 11:22:09 +03:00
c42a6119ff [#66] transformer: Extend tests
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-03 11:22:09 +03:00
29b188db57 [#52] Remove storage groups and audit
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-05-03 08:20:37 +00:00
38b03ff28b [#63] transformer: Resolve funlen linter
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-25 13:29:42 +03:00
0fa23a9b14 [#63] transformer: Add context to methods
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-25 13:29:42 +03:00
d0762d037d [#44] pool: Add copies number vector when putting object
Signed-off-by: Artem Tataurov <a.tataurov@yadro.com>
2023-04-20 13:41:05 +03:00
db5b89496d [#49] bearer: Consider impersonate in fillBody
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-04-18 14:54:05 +00:00
7c75db2f2d [#59] netmap: Remove unused param from getSelection()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-18 14:11:04 +00:00
dce55a436a [#9999] sdk: Up api-go version
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-04-18 09:59:52 +00:00
cae2f37cdd client: rename formRequest() to buildRequest()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-18 09:58:34 +00:00
f60bea4be5 [#48] client: Refactor SessionCreate()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-18 09:58:34 +00:00
a16fc40c39 [#48] client: Refactor EndpointInfo()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-18 09:58:34 +00:00
40d966bec2 [#48] client: Refactor NetworkInfo()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-18 09:58:34 +00:00
Pavel Karpy
d0c5d837d2 [#56] *: Drop reputation system
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-04-18 07:52:16 +00:00
237b90f744 [#49] bearer: Add impersonate flag
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-04-17 11:51:38 +03:00
c8e620ad24 [#53] sdk-go: Drop subnet
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-04-14 16:31:08 +03:00
591dd1247d [#48] client: Refactor ContainerPut()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
57619fbbe4 [#48] client: Refactor ContainerSetEACL()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
8bc8f1f365 [#48] client: Refactor ContainerDelete()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
09ed2863fc [#48] client: Refactor ContainerEACL()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
8e2f77890f [#48] client: Refactor ContainerGet()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
8852b262f2 [#48] client: Refactor ContainerList()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
b2c66cb99e [#48] client: Refactor ContainerAnnounceUsedSpace()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
6c9b92c9dc [#48] client: Execute metainfo callback in processResponse()
It was lost in 8c5333ea55.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:07:18 +03:00
772fa90983 [#48] client/container: Form requests in a separate function
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-14 09:06:52 +03:00
1bfa9ecdb0 [#48] client: Remove ctx == nil checks
Much less useful after we made context to be passed explicitly.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-13 09:04:09 +03:00
55b06cd764 [#48] client: Split container methods by files
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-13 09:04:09 +03:00
Pavel Karpy
f41860f9bd [#46] client: Allow set copy_number for every placement vector
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-04-11 10:06:55 +00:00
Pavel Karpy
423b320f91 [#46] go.mod: Update api-go version
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2023-04-11 10:06:55 +00:00
f8c34b45f3 [#47] eacl: Fix duplicate imports
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
fa9573e857 [#47] client: Pass context to Dial() explicitly
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
bc62e2f712 [#47] pool: Resolve contextcheck and containedctx linters
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
31271ad8b1 [#47] netmap: Make PlacementPolicy.WriteStringTo() pass nofunlen, cogognit
REP statement is obligatory, thus insert newline before each statement
after REP.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
25e9336d68 [#47] container: Make readFromV2() pass funlen
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
4cd755877c [#47] client: Do not check context in NetmapSnapshot()
It is passed explicitly, non-nil by convention.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
1395b282fe [#47] acl: Remove unused resetBit()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
708d933fe3 [#47] .golangci.yml: Unify with other FrostFS repos
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
4fa52312c7 [#47] reputation: Fix misspelling
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-04-07 08:59:19 +03:00
552219b8e1 [#16] pool: Fix counting context canceled error
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-03-29 15:58:04 +03:00
cfb8a7b914 [#41] .gitlint: Synchronize settings across FrostFS repos
This change allows to use `[#xx]` placeholders for issue number.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-24 22:07:13 +03:00
4438f115fb [#39] Add Issue Template
Add bug report and feature request templates

Signed-off-by: Liza <e.chichindaeva@yadro.com>
2023-03-23 12:25:57 +03:00
bec77f280a [#37] container: Support legacy sys attributes
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-03-16 11:14:42 +03:00
df2090c2be [#37] netmap: Update tests for new sys attributes
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-03-16 11:14:36 +03:00
7e6592b28e [#37] go.mod: Update api-go for new sys attributes
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-03-16 11:14:27 +03:00
d589d51509 [#19] transformer: Fix dependencies
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-03-16 09:51:03 +03:00
25588ee3be [#19] transformer: Do not allocate intermeate slice for hashers
```
name                 old time/op    new time/op    delta
Transformer/small-8    73.7µs ±15%    72.4µs ±16%    ~     (p=0.604 n=10+9)
Transformer/big-8       1.36s ± 4%     1.36s ± 8%    ~     (p=0.579 n=10+10)

name                 old alloc/op   new alloc/op   delta
Transformer/small-8    7.67kB ± 0%    7.57kB ± 0%  -1.36%  (p=0.000 n=10+10)
Transformer/big-8      49.0kB ± 0%    48.3kB ± 0%  -1.48%  (p=0.000 n=10+10)

name                 old allocs/op  new allocs/op  delta
Transformer/small-8       101 ± 0%        98 ± 0%  -2.97%  (p=0.000 n=10+10)
Transformer/big-8         609 ± 0%       591 ± 1%  -3.00%  (p=0.000 n=10+9)
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
9407f30248 [#19] transformer: Optimize payload hashers a bit
```
name                 old time/op    new time/op    delta
Transformer/small-8    74.8µs ±11%    73.7µs ±15%    ~     (p=0.529 n=10+10)
Transformer/big-8       1.38s ±11%     1.36s ± 4%    ~     (p=0.796 n=10+10)

name                 old alloc/op   new alloc/op   delta
Transformer/small-8    7.69kB ± 0%    7.67kB ± 0%  -0.21%  (p=0.000 n=10+10)
Transformer/big-8      49.2kB ± 0%    49.0kB ± 0%  -0.48%  (p=0.004 n=10+10)

name                 old allocs/op  new allocs/op  delta
Transformer/small-8       102 ± 0%       101 ± 0%  -0.98%  (p=0.000 n=9+10)
Transformer/big-8         620 ± 1%       609 ± 0%  -1.66%  (p=0.000 n=10+10)
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
94c0a607b5 [#19] transformer: Add a target which sends parts to a channel
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
e45647de3c [#19] transformer: Do not reuse memory of sent objects
Slower, but more correct.
```
name                 old time/op    new time/op    delta
Transformer/small-8    72.4µs ± 8%    74.8µs ±11%     ~     (p=0.278 n=9+10)
Transformer/big-8       1.31s ± 8%     1.38s ±11%   +5.50%  (p=0.035 n=10+10)

name                 old alloc/op   new alloc/op   delta
Transformer/small-8    7.39kB ± 0%    7.69kB ± 0%   +4.04%  (p=0.000 n=10+10)
Transformer/big-8      46.9kB ± 0%    49.2kB ± 0%   +4.87%  (p=0.000 n=10+10)

name                 old allocs/op  new allocs/op  delta
Transformer/small-8      94.6 ± 1%     102.0 ± 0%   +7.82%  (p=0.000 n=10+9)
Transformer/big-8         560 ± 0%       620 ± 1%  +10.66%  (p=0.000 n=10+10)
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
611e20587b [#19] transformer/test: Check owner ID and payload hash for parts
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
eba6831125 [#19] transformer/test: Add helper functions
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
7e3810d654 [#19] transformer: Move EpochSource to other types
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
cc0fef2c55 [#19] transformer: Merge formatter and payload splitter
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
b696d3c70e [#19] transformer: Make writeChunk non-recursive
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
1c94309d7a [#19] transformer: Simplify AccessIdentifiers
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
f43f18ecda [#19] transformer: Cover with unit-tests
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
ac8442bf99 [#19] object: Move transformer implementation from node
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-15 05:39:09 +00:00
0ad877288e [TrueCloudLab#16] pool: Don't count grpc canceled error
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-03-10 06:58:34 +00:00
0e1999c965 [#23] pre-commit: Add gitlint hook
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-09 22:53:16 +03:00
b461aa64b8 [#23] pre-commit: Add golangci-lint hook
Also, fix minor issues. Skip deprecated warning for now.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-09 22:53:14 +03:00
b761fd8070 [#23] pre-commit: Add initial configuration
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-03-09 22:52:51 +03:00
94476f9055 Rename package name
Due to source code relocation from GitHub.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-03-07 15:47:21 +03:00
5e759bf089 [#2] Remove panic from RPCs
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-03-01 10:29:23 +03:00
d4f5bba459 [#2] Update lint config, fix lint errors
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2023-03-01 10:29:23 +03:00
e9c1a2ab2b [TrueCloudLab/hrw#2] sdk-go: Optimize node hash
Compute node hash by node initialization

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-02-28 18:07:14 +03:00
2cbc585edd [TrueCloudLab/hrw#2] sdk-go: Use typed HRW methods
Update HRW pkg and use typed HRW methods to sort nodes

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-02-28 18:07:14 +03:00
e355e5eeba [TrueCloudLab#22] .github: Fix CODEOWNERS
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-28 16:35:38 +03:00
f08069ceeb [#20] .github: Update CODEOWNERS
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-27 17:47:21 +03:00
dad99bad48 [#20] .github: Drop go1.17, add go1.20
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-27 17:47:21 +03:00
0d3a238d9c [#5] pool: Update hashicorp/lru to v2
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2023-02-24 17:32:40 +03:00
cf64ddfb14 [TrueCloudLab#13] pool: Renew token before it expired
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-01-30 15:06:02 +03:00
cf9a54dcda [TrueCloudLab#11] pool: Fix handling SplitInfoError
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-01-23 11:07:29 +03:00
Denis Kirillov
b2a37543d3 [#362] pool: Don't use default session token for read
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2023-01-13 13:21:29 +03:00
f0ac49b8f0 [TrueCloudLab#6] pool: Decrease rebalanceInterval
Set default rebalance interval to 15s

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-01-13 13:16:22 +03:00
54696acf48 [TrueCloudLab#6] pool: Log node healthy changing
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-01-13 13:16:22 +03:00
dd88a5c5e0 [#4] go.mod: Bump supported go version to 1.18
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-30 13:40:50 +03:00
4ff9c00de3 [#4] Rename NeoFS mentions in comments and method names
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-30 13:40:50 +03:00
b204a62da1 [#4] go.mod: Update ANTLR
Current `go:generate` command was, probably, executed only on my laptop.
Replace it with explicit version, because package in the generated code
depends on in.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-30 13:40:50 +03:00
377a5a0517 [#4] go.mod: Update dependencies
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-30 13:40:50 +03:00
43c046f343 [#4] go.mod: Update neo-go to v0.100.1
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-30 13:40:50 +03:00
Denis Kirillov
8c0c7789ca [#365] pool: Add request callback
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-29 16:34:13 +03:00
Evgenii Stratonikov
339e2702f8 [#367] client: Allow to override key in Object.Hash RPC
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-29 16:34:13 +03:00
Pavel Karpy
a1748ae0e7 [#370] bearer, session: Clarify expiration epoch
The expiration epoch is the _last_ valid epoch for an entity. Also, clarify
the expiration epoch meaning for tombstones and regular objects.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2022-12-29 16:34:13 +03:00
Pavel Karpy
4c779423f5 Move to frostfs-sdk-go
Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2022-12-14 09:59:29 +03:00
Pavel Karpy
45a6e7a7c2 [#369] status: Make errors return default messages
Use default messages in `Error` methods like in `ToStatusV2`.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
2022-12-14 09:59:29 +03:00
Denis Kirillov
b4b07a3c4e [#364] pool: Adopt client stream timeout param
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-11-15 17:08:20 +03:00
Denis Kirillov
d047289182 [#360] object: Add new package relations
Package relations provides feature to process inner object structure.

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-11-14 17:46:17 +03:00
Denis Kirillov
1cacf472a3 [#360] pool: Fix removing virtual object
Include phy objects in session token scope

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-11-14 17:46:17 +03:00
Denis Kirillov
e35f0df1ca [#358] pool: Make ErrPoolClientUnhealthy unexported
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-11-09 10:22:33 +03:00
Denis Kirillov
5f9d846fb4 [#358] pool: Don't init session with dead node
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-11-09 10:22:33 +03:00
Denis Kirillov
2eefdab0e4 [#358] pool: Start even if not all node healthy
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-11-09 10:22:33 +03:00
Denis Kirillov
7a2a76af95 [#356] ns: Use domain instead of name in NNS resolver
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-10-28 12:24:56 +04:00
Evgenii Stratonikov
da4ddcf337 [#353] netmap: Get rid of ioutil
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-10-19 12:05:49 +04:00
Evgenii Stratonikov
231ec66054 [#353] go.mod: Update external dependencies
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-10-19 12:05:49 +04:00
Evgenii Stratonikov
a02a3870a5 [#353] go.mod: Update neofs-api-go to v2.14.0
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-10-19 12:05:49 +04:00
Evgenii Stratonikov
9d4b36a8e6 [#353] go.mod: Update neo-contract to v0.16.0
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-10-19 12:05:49 +04:00
Evgenii Stratonikov
d3a09cbe7f [#353] go.mod: Update neo-go to v0.99.4
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-10-19 12:05:49 +04:00
anastasia prasolova
f21d63bded Add CODEOWNERS file
Signed-off-by: anastasia prasolova <anastasia@nspcc.ru>
2022-10-16 21:06:24 +03:00
21eef1ae7f [#351] Add StringifyPublicKey method for NodeInfo
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2022-10-13 10:27:18 +03:00
Leonard Lyubich
d2f3929b51 [#349] client: Use context.Background in Dial by default
Passing `nil` context to `rpc.Balance` leads to panic. To prevent panic,
we need to provide some default context in `Dial`.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
2022-10-12 17:50:55 +04:00
Leonard Lyubich
8c682641bf [#343] pool: Provide dial context to clients
After recent changes `client.Client` accepts dial context. There is a
need to forward the context passed into `Pool.Dial` to the underlying
`Client` instances.

Define type aliases of different client constructors: context-based and
non-context. Use context-based constructor in `Pool`. Pass `ctx`
parameter of `Pool.Dial` method to the client builder.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
2022-10-07 13:24:02 +03:00
Leonard Lyubich
452a50e9d5 [#343] client: Accept context parameter in Dial
In previous implementation of `Client.Dial` there was no ability to
specify parent context (e.g. global application context).

Add `PrmDial.SetContext` method which accepts optional base dial
context. Use the context to open client connection or fall back to using
`context.Background()`.

Upgraded version of `github.com/nspcc-dev/neofs-api-go/v2` module
also fixes the problem when dial timeout didn't work properly.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
2022-10-07 13:24:02 +03:00
Leonard Lyubich
1325b4f272 [#336] session: Support group object sessions
Rename `LimitByObject` method of the `session.Object` type to
`LimitByObjects` and make it to accept variadic parameter.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
2022-10-05 13:39:51 +04:00
Evgenii Stratonikov
c6576c8112 [#344] netmap: Support ExternalAddr well-known attribute
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-26 13:28:39 +03:00
Leonard Lyubich
8e3173eacd [#270] client/netmap: Cover NetMapSnapshot with unit tests
There is a need to test each `Client` operation. In previous
implementation `Client` was based on real socket connection. This didn't
allow to test the `Client` without OS resources. In order to write
convenient and useful unit tests we need to slightly refactor the code.

Introduce `neoFSAPIServer` interface as a provider of `Client` type's
abstraction from the exact NeoFS API server. Add `netMapSnapshot` method
for initial implementation. Define core interface provider used in real
code. Set `coreServer` as an underlying `neoFSAPIServer` in
`Client.Dial`. Cover `Client.NetMapSnapshot` method with unit tests
using the opportunity to override the server.

From now client library can be tested not only with real physical
listeners but with imitations.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-09-22 10:51:07 +04:00
Leonard Lyubich
89124d442d [#312] client/netmap: Simplify NetMapSnapshot implementaiton
Make flat set of instructions similar to `ObjectDelete` operation.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-09-22 10:51:07 +04:00
Leonard Lyubich
664392afc2 [#312] netmap: Support NetmapService.NetmapSnapshot RPC
Extend functionality of `NetMap` type. Add `NetMapSnapshot` operation to
`client` package.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-09-22 10:51:07 +04:00
Leonard Lyubich
f2f97f656d [#315] apistatus: Write default message in NodeUnderMaintenance.Error
Use `node is under maintenance` message in `NodeUnderMaintenance.Error`
is `message` field is unset in the status message.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-09-20 11:23:22 +04:00
Leonard Lyubich
be9a1aca90 [#315] apistatus: Support NodeUnderMaintenance in FromStatusV2
Support decoding `NodeUnderMaintenance` status errors in `FromStatusV2`
function.

From now `NodeUnderMaintenance` instance can be decoded from
`status.Status` message of NeoFS API V2 protocol.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-09-20 11:23:22 +04:00
Evgenii Stratonikov
3d6b5d807b [#315] netmap: Add maintenance node state
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-19 16:49:27 +04:00
Evgenii Stratonikov
3dad44232e [#315] netmap: Add maintenance mode network setting
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-19 16:49:27 +04:00
Evgenii Stratonikov
4662d39886 [#315] client/status: Add NodeUnderMaintenance status
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-19 16:49:27 +04:00
Evgenii Stratonikov
f75a5feba3 [#334] client: Use parameter key in object.Get
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-14 11:34:56 +04:00
Evgenii Stratonikov
1929b634a1 [#332] netmap/parser: Disallow trailing garbage
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-12 10:45:37 +03:00
Evgenii Stratonikov
402d72e629 [#332] go.mod: Update antlr dependency
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-12 10:45:37 +03:00
Evgenii Stratonikov
43a57d42dd [#331] client: Allow to set timeout for streaming operations
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-09-07 11:51:28 +04:00
Pavel Karpy
71891029da [#327] nns: Support Null returned value
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-09-06 17:27:07 +04:00
Pavel Karpy
d808f72c38 [#327] Add go 1.19 tests
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-09-06 17:27:07 +04:00
Pavel Karpy
511886b8d2 [#327] Update go to 1.17
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-09-06 17:27:07 +04:00
Pavel Karpy
01c238ddc0 [#327] nns: Simplify code using neo-go v0.99.2
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-09-06 17:27:07 +04:00
Pavel Karpy
2e5c66934c [#327] go.mod: Update neo-go to v0.99.2
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-09-06 17:27:07 +04:00
Denis Kirillov
74234623b2 [#215] object: Add well-known FilePath attribute
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-09-06 17:21:37 +04:00
Evgenii Stratonikov
ee92df3203 [#326] client: Sign message in object.GetRange'
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-29 14:45:50 +03:00
Evgenii Stratonikov
cf7bee3087 [#326] client: Provide pointers requests for signing
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-29 14:45:50 +03:00
Evgenii Stratonikov
456167e777 [#325] go.mod: Update neofs-api-go
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-29 11:53:34 +03:00
Evgenii Stratonikov
0e4d07fb06 [#323] client: Remove xheaders length check in a common helper
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
d6d6a41f5d [#323] client: Refactor object.Put
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
724d30db1a [#323] client: Refactor object.Get
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
1f593d0fb2 [#323] client: Refactor object.GetRange
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
f543ba68d3 [#323] client: Refactor object.Delete
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
dd5826d071 [#323] client: Refactor object.Head
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
02bc2bc236 [#323] client: Unify parameter processing for Get* methods
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
992b26a3ff [#323] client: Form meta header during parameter initialization
Unify with other client methods.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
6a43accf96 [#323] client: Refactor object.Search
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
5d7650c3e7 [#323] client: Use checksum parameter directly in object.Hash
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
a926e5a1de [#323] client: Replace writeToMetaHeader method with function
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
8c5333ea55 [#323] client: Refactor object.Hash
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
0236b03fa7 [#323] client: Use constant for error message
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
2f843de3ed [#323] client: Remove initCallContextWithoutKey
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-26 17:34:27 +03:00
Evgenii Stratonikov
84888854ab [#322] *: Go fmt -s
go1.19 rewrites comments to proper render them in docs.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-24 18:58:59 +03:00
Evgenii Stratonikov
7537fa0dec [#321] client: Set object ID field in Put
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-08-24 17:04:10 +03:00
Pavel Karpy
7578b54fac [#319] crypto: Fix signing in go v1.19
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-08-22 13:19:10 +03:00
Leonard Lyubich
737e690482 [#299] pool: Do not use pointers to the resulting values
In previous implementation `pool` package provided access to resulting
values as pointers to them. This caused clients to handle nil
cases even when the field presence in the response is required.

Avoid returning pointers to values in result getters. This also reduces
reference counter load and allows values from `client.Client` to be
forwarded directly without additional assignment.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-08-16 15:31:57 +04:00
Leonard Lyubich
f8148c954b [#317] client: Fix processing of the Object PUT failed response
In previous implementation `ObjectWrite.Close` called `close` method
which in turn called `result` callback. Thus failed statuses could lead
to false-positive result processing.

Replace calling `close` method with direct `closer` method's call in
`ObjectWrite.Close`.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-08-16 15:31:37 +04:00
Leonard Lyubich
4e31b4f231 [#299] client: Do not use pointers to required response fields
In previous implementation `client` package provided access to nested
response fields as pointers to them. This caused clients to handle nil
cases even when the field presence in the response is required.

Avoid returning pointers to required fields in response getters. This
also reduces reference counter load and allows fields to be decoded
directly without additional assignment.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-08-08 12:55:25 +03:00
Denis Kirillov
30bf79f075 [#302] client: Adopt SetCopiesNumber
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-08-03 15:22:13 +03:00
Pavel Karpy
7a99cc916c [#307] status: Support EACL_NOT_FOUND status code
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-08-01 19:57:07 +03:00
Pavel Karpy
a0f7c903d3 [#307] go.mod: Update neofs-api-go to v2.13.1
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-08-01 19:57:07 +03:00
Evgenii Stratonikov
7de66159d4 [#304] go.mod: Update neo-go to v0.99.1
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-07-29 11:43:51 +03:00
Denis Kirillov
90255e9efa [#291] pool: Use more robust way to init methods
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-26 21:47:06 +03:00
Denis Kirillov
828cfdc5bf [#291] pool: Improve docs
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-26 21:47:06 +03:00
Denis Kirillov
90f1cc7a1a [#301] ns: Adopt neo-go int parameter
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-25 13:14:11 +03:00
Evgenii Stratonikov
3a95686aab [#300] go.mod: Update neofs-contract
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-07-22 17:02:58 +03:00
Denis Kirillov
f4ac75423c [#283] pool: Store methods status in slice
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
b4f4ee4f79 [#283] pool: Compute avg time for every method
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
54145916a9 [#283] pool: Change batch of atomics to mutex
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
0d54757545 [#283] pool: Add res nil check
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
58fe1768cc [#283] pool: Fix incErrorRate
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
0b8c53ebc9 [#283] pool: Add number of requests to statistic
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
1b30d228da [#283] pool: Expose statistic
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
423804de84 [#283] pool: Add latency calculating
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
99e185690e [#283] pool: Add error threshold
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
9d3a1835d1 [#283] pool: Drop gomock
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Denis Kirillov
e6cb5f2ee1 [#283] pool: Add counter for errors
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-07-22 15:57:37 +03:00
Leonard Lyubich
7d10b432d1 [#284] *: Return error from all ReadFromV2 methods
Return `error` from all `ReadFromV2` methods in order to support
backward compatibility if message will be extended with some formatted
field.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-07 14:20:18 +03:00
Evgenii Stratonikov
0d862d8568 [#294] go.mod: Update tzhash to v1.6.1
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-07-06 18:10:41 +03:00
Pavel Karpy
48ba86f4dd [#293] version: Update API version constants
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-06 12:05:58 +03:00
Evgenii Stratonikov
f91b1facd5 [#292] go.mod: Update tzhash to v1.6.0
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-07-05 20:44:56 +03:00
Pavel Karpy
c6fee6d01a [#240] pool: Add SyncContainerWithNetwork
It is a helper function that uses a `Pool` to fetch network information and
apply it to the container (change the container if it does not fit the
network). Currently, only applies the homomorphic hashing parameter.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-05 15:37:49 +03:00
Pavel Karpy
a6ecf6b881 [#240] client: Add SyncContainerWithNetwork func
It requests network configuration and syncs it (changes if required) with
passed container.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-05 15:37:49 +03:00
Pavel Karpy
9996b3be01 [#240] container: Support disabling homomorphic hashing
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-05 15:37:49 +03:00
Pavel Karpy
0cd790cfe0 [#240] netmap: Support HomomorphicHashingDisabled network config
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-05 15:37:49 +03:00
Pavel Karpy
df6538c68c [#282] apistatus: Support OUT_OF_RANGE error
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-05 11:53:29 +03:00
Pavel Karpy
27fe9c19a7 [#273] status: Support signature status
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-07-05 11:50:44 +03:00
Leonard Lyubich
6994eb0e55 [#222] client: Fix docs of resolving the failure statuses
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-05 11:43:38 +03:00
Leonard Lyubich
cec2373b50 [#222] reputation: Clarify docs of GlobalTrust formation
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-05 11:42:58 +03:00
Leonard Lyubich
ff09b1cfe1 Upgrade NeoFS API Go to v2.13.0
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-05 11:42:58 +03:00
Leonard Lyubich
041e1ef2b6 [#286] reputation: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-05 11:42:58 +03:00
Leonard Lyubich
30d27c3050 [#289] oid: Add JSON encoding of Address type
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-04 14:58:00 +03:00
Leonard Lyubich
2ad89085a3 [#225] container: Clarify docs of Container type initialization
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-04 11:21:16 +03:00
Leonard Lyubich
70845147f6 [#225] container: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-07-04 11:21:16 +03:00
Angira Kekteeva
86a447bc80 [#288] pool: Fix lost err in fmt.Errorf
Signed-off-by: Angira Kekteeva <kira@nspcc.ru>
2022-07-01 15:09:26 +03:00
Leonard Lyubich
ab4d1e34a8 [#280] policy: Use policyVisitor as ErrorListener for QueryLexer
Share `policyVisitor` instance as an `ErrorListener` provider for both
`QueryLexer` and `Query`.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 14:47:22 +03:00
Leonard Lyubich
dea3d9c419 [#280] policy: Remove error listeners from query lexer
In previous implementation `PlacementPolicy.DecodeString` produced
undesired console logs.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 14:47:22 +03:00
Leonard Lyubich
d2cd9ebfbd [#278] client: Increase depth of error wrapping in IsErr* tests
Wrap test error twice just to be sure error unwrapping goes deep.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 09:06:13 +03:00
Leonard Lyubich
1e1139f305 [#278] pool: Avoid using strings.Contains for error assertion
`client` package now provides functions for error checking.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 09:06:13 +03:00
Leonard Lyubich
dcaf454c1d [#278] client: Add session error checkers
Add `IsErrSessionExpired` and `IsErrSessionNotFound` functions which
assert corresponding session errors.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 09:06:13 +03:00
Leonard Lyubich
09ed6077f9 [#278] client: Support wrapped errors in error checkers
Client errors are quite often wrapped in context. When checking a
specific error, it is required not to lose the ability to determine it,
regardless of the attached context. In previous implementation `IsErr*`
functions didn't support wrapped errors.

Make `IsErr*` functions to preliminarily unwrap `error` argument before
type assertion. Use `errors.Unwrap` for this instead of `errors.As`
since the latter has the overhead of filling in an error.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 09:06:13 +03:00
Leonard Lyubich
40942affe9 [#278] client: Add unit test for error checkers
`IsErr*` functions assert `error` argument corresponds to particular
typed error.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-28 09:06:13 +03:00
Leonard Lyubich
aa5ee1dcde [#225] container/acl: Make Basic type numeric
Also make well-known values constant not variables.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-23 11:05:32 +03:00
Leonard Lyubich
3b15a01327 [#225] container/acl: Fix minor places
Make test value generator to be random as documented. Add `default`
keyword to switch-case to avoid linter comments.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-23 11:05:32 +03:00
Leonard Lyubich
c4ebe8d854 [#225] container: Replace basic ACL code to a separate package
Create `acl` package inside `container` path. Replace basic ACL
functionality into it.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-23 11:05:32 +03:00
Leonard Lyubich
e82a2d86ef [#225] container: Refactor and document basic ACL
Replace basic ACL functionality from `acl` package to the `container`
one. Create `BasicACL` type and provide convenient interface to work
with it.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-23 11:05:32 +03:00
Evgenii Stratonikov
af7e20073b [#277] netmap: Allow more uint64 config values
NEO VM uses little-endian format for integers,
however the resulting byte slice can contain less than 8 bytes.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-06-22 15:51:36 +03:00
Evgenii Stratonikov
596f43a540 [#274] crypto: Add WalletConnect API support
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-06-22 11:20:54 +03:00
Leonard Lyubich
721df386c5 [#276] container: Remove session token and signature from Container/eACL
Session token and signature isn't presented in `Container` and
`EACLTable` messages of NeoFS API V2 protocol. These entities are needed
for access control and doesn't carry payload of these messages.

Remove `SetSessionToken` / `SessionToken` methods of
`container.Container` and `eacl.Table` types. Provide methods to specify
these components in corresponding `Client` operations.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-21 20:03:07 +03:00
Leonard Lyubich
e986f47807 [#227] netmap: Add more encoding methods for PlacementPolicy
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-16 11:23:21 +03:00
Leonard Lyubich
e999fb00c3 [#227] netmap: Remove unnecessary unit tests
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-16 11:23:21 +03:00
Leonard Lyubich
d51a324147 [#227] netmap: Clarify some fields of PlacementPolicy
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
d648b86776 [#227] netmap: Fix minor blots in documentation/code
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
ca523f1ff1 [#227] netmap: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
5bfdb64251 [#227] netmap: Do not export bucket weight calculator
`GetBucketWeight` is not usable outside placement context.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
86bdc670d5 [#227] netmap: Do not export default weightFunc initializer
`GetDefaultWeightFunc` is not usable outside placement context.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
6796b4a29a [#227] netmap: Remove unused aggregators and normalizers
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
723ba5ee45 [#227] netmap: Do not use intermediate types for placement
Support preprocessing within the `NodeInfo` type. Provide methods for
placement directly from the `NodeInfo` type. Returns slice of slices of
`NodeInfo` from placement methods of `Netmap`. Remove no longer needed
`Node` and `Nodes` types.

```
name            old time/op    new time/op    delta
ManySelects-12    19.7µs ±14%    15.8µs ±15%  -19.70%  (p=0.000 n=20+20)

name            old alloc/op   new alloc/op   delta
ManySelects-12    8.65kB ± 0%    6.22kB ± 0%  -28.03%  (p=0.000 n=20+20)

name            old allocs/op  new allocs/op  delta
ManySelects-12      82.0 ± 0%      81.0 ± 0%   -1.22%  (p=0.000 n=20+20)
```

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
2b21146185 [#227] netmap/test: Assert source placement builder is pure for nodes
`GetContainerNodes` / `GetPlacementVectors` must not mutate source slice
of nodes.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
9c47fca7c2 [#227] netmap: Pre-calculate resulting slice capacity in flattenNodes
```
name           old time/op  new time/op  delta
ManySelects-12  17.5µs ±27%   15.5µs ±24%  -11.57%  (p=0.024 n=20+20)

name           old alloc/op  new alloc/op  delta
ManySelects-12  9.03kB ± 0%   8.65kB ± 0%  -4.25%  (p=0.000 n=20+20)

name           old allocs/op  new allocs/op  delta
ManySelects-12  86.0 ± 0%     82.0 ± 0%     -4.65%  (p=0.000 n=20+20)
```

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
a8fd2ef954 [#227] netmap: Benchmark JSON tests
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00
Leonard Lyubich
ea21cdf731 [#269] client: Fix response processing of Object.Put rpc
After 85e3c7b087 `processResponse` method
sets `err` field or sets status in `statusRes` field of `contextCall`.
In previous implementation `ObjectWriter.Close` method returned
`ctxCall.err` on `false` return of `processResponse` method. This could
cause NPE-panic if status failure resolving was disabled.

Make `ObjectWriter.Close` to return internal `err` field only if it is
set, otherwise return status response.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 15:30:39 +03:00
Leonard Lyubich
eb3b990812 [#210] subnet: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 11:52:07 +03:00
Pavel Karpy
6709b00c89 [#245] storagegroup: Add Object <-> SG converters
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-06-15 10:33:47 +03:00
Evgenii Stratonikov
517d7a1e4a [#266] eacl: Allow lossless conversion of reserved filters
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-06-09 09:45:32 +03:00
Pavel Karpy
6ac9deabb8 [#264] storagegroup: Fix out of range
It panicked when the previous members slice had capacity more than a new one
because of incorrect slicing that led to `out of range`.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-06-09 09:38:02 +03:00
Evgenii Stratonikov
5518b63432 [#243] eacl: Return success flag in CalculateAction
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-06-09 09:35:32 +03:00
Leonard Lyubich
031eac2f48 [#265] session: Implement method to verify session data signature
There is a need to verify session data signatures calculated using
private session key. `Container` token encapsulates public session key,
so we need to provide method for signature check.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-07 21:53:39 +03:00
Leonard Lyubich
67ff996dc3 Revert "[#261] session: Make failed Sign pure on failed signature calculation"
This reverts commit 458c882ff4.

If `issuerSet` is set after signature calculation then issuer ID isn't
written to signed data, in other words not signed.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-06 10:02:17 +03:00
Leonard Lyubich
bf8312a547 [#263] session: Add Sign / VerifySignature test
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-06 10:02:17 +03:00
Leonard Lyubich
0ef49cf851 Upgrade NeoFS API Go to v2.12.2
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-03 17:07:45 +03:00
Leonard Lyubich
458c882ff4 [#261] session: Make failed Sign pure on failed signature calculation
Make `Sign` method implementation to not modify `issuerSet` state
variable after signature calculation's failures.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-03 14:46:18 +03:00
Leonard Lyubich
0bb40b3245 [#261] session: Share common code between Container and Object
`Container` and `Object` types are transmitted in single `session.Token`
message. They differ only by session context.

Share common parts of the message in `commonData` struct. Embed struct
into `Container` and `Object`. Make `ReadFromV2` methods to check
protocol compliance. Make `Unmarshal`/`UmarshalJSON` to check field
format in case of presence only.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-03 14:46:18 +03:00
Pavel Karpy
d3b998d672 [#250] eacl: Do not require CID in eACL table
Container ID of extended ACL table can be omitted in bearer token according
to API.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-06-03 14:19:57 +03:00
Leonard Lyubich
c65be6d469 [#259] bearer: Align with the protocol
Sync lifetime names with `session` package. Add `AssertContainer` and
`AssertUser` methods which cover specific cases describe in protocol.
Increase test coverage.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-01 18:32:49 +03:00
Leonard Lyubich
82d762f536 [#258] Fix string encoding of identifiers
Use `EncodeToString` method to get protocol string according to type
docs.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-31 12:14:04 +03:00
Leonard Lyubich
6cb513c976 [#257] Upgrade NeoFS API Go module
New version contains fix for `object.GetRangeResponse` message type.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-31 09:47:55 +03:00
Denis Kirillov
3953c2166e [#255] Create session token using arbitrary key
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-05-30 20:09:43 +03:00
Leonard Lyubich
85e3c7b087 [#254] client: Fix incorrect response processing case
In previous implementation `processResponse` returned `true` if
`resolveAPIFailures` is set and status failure is received. This led to
post-processing of the results, which no longer pays attention to the
status. For example, `ObjectHead` returned `unexpected header type`
error due to empty body.

Make `contextCall.processResponse` to return success flag regardless of
`resolveAPIFailures` setting. Make `contextCall.processCall` to return
`err` field presence flag on `processResponse` false return.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-30 17:23:56 +03:00
Leonard Lyubich
3bbf7ee15d [#252] object/id: Fix typos in docs
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-27 12:41:35 +03:00
Leonard Lyubich
85affc3c93 object: Remove debug printline
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-27 12:41:35 +03:00
Leonard Lyubich
f0a5eb6dbc [#251] object/address: Refactor and document package functionality
Merge `address` package into `oid` one. Bring `session.Object`
implementation into conformity with the NeoFS API protocol.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-27 12:41:35 +03:00
Leonard Lyubich
bef4618cd6 [#252] session: Add Object.Issuer method
Add method to get `Object` session's issuer similar to `Container`.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-26 09:54:57 +03:00
Evgenii Stratonikov
1f7fe6864d [#229] netmap: make context private
It isn't used anywhere outside of the package.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-05-25 11:02:51 +03:00
Leonard Lyubich
60ef026923 [#248] session: Add Issuer method
There is a need to duplicate session token owner, e.g. in container
created within the session. For such cases we need to have the ability
to receive session issuer.

Add `Container.Issuer` method. Transform `IssuedBy` to helper function.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-05-25 10:57:53 +03:00
Evgenii Stratonikov
c976332e20 [#242] object: Require only 1 field to be set for SplitInfo
Also write more tests.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-05-23 19:09:53 +03:00
Alex Vanin
12ea1e8d74 [#238] session: Add container.IssuedBy method
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-05-04 22:24:02 +03:00
Alex Vanin
539ac9915e [#237] client: Sign container ID value at container removal
Container contract expects signature of container ID value,
which is SHA256 of container body. Not the signature of stable
marshaled container.ID structure.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-05-04 15:22:48 +03:00
Leonard Lyubich
526b45e207 [#197] session: Link issues for further TODO resolving
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
5fe6d96bf1 [#197] session: Fix Container.AppliedTo method docs
Method checks propagation, not limit.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
4cbbbdd3e2 [#197] pool: Change function signature
Make `createSessionTokenForDuration` to accept a pointer to
`session.Object` and write the response on session creation request
through the pointer. Rename function to `initSessionForDuration`. As a
consequence, problem in `openDefaultSession` with uncached sessions is
fixed.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
f0134ef26e [#197] pool: Remove no longer needed test func
`TestCopySessionTokenWithoutSignatureAndContext` was based on already
removed function.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
e468f409d7 [#197] pool: Remove unused function parameter
`owner.ID` parameter of `createSessionTokenForDuration` function is no
longer used since session owner is set automatically during the sign
operation. As a consequence, remove `Pool.sessionOwner` field and its
getter.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
4dc3a7669e [#197] client: Link FIXME with an issue
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
48434d9999 [#197] client: Remove no longer used type
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Leonard Lyubich
552c7875bf [#197] session: Refactor and document the package
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-27 11:09:29 +03:00
Denis Kirillov
497053c785 [#228] ns: use neofs-contract for nns constants
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-24 14:11:16 +03:00
Alex Vanin
6e81e13e1b [#218] client: Decode status at io.EOF in the client-side stream
Object service of NeoFS API contains one client-side stream method:
object.Put. In client-side streams, server can return an error after
processing stream message. In this case write method returns `io.EOF`
and actual error reason is encoded in response status, which is
obtained after `Close()`. Client library should process such case.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-21 15:57:37 +03:00
Leonard Lyubich
1ed426b8a6 [#199] owner: Rename to user, refactor and doc
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 18:44:02 +03:00
Leonard Lyubich
d20999113a [#190] crypto/ecdsa: Actualize package docs
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Leonard Lyubich
6554c681c8 [#190] crypto: Doc RegisterScheme isn't thread-unsafe
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Leonard Lyubich
9f20d74d76 [#190] crypto/ecdsa: Use separate types for RFC-6979 signature algo
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Leonard Lyubich
7fe75d2cd9 [#190] crypto: Replace public key encoding methods to PublicKey
This make `neofscrypto.Signer` interface more similar to the one from
standard `crypto` package.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Leonard Lyubich
bcbffd516a [#190] crypto: Provide fmt.Stringer of the Scheme type
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Leonard Lyubich
2f9cc50fec [#190] crypto: Start Scheme enum from zero
Enumerate signature schemes of `Scheme` type from 0 in order to sync
with NeoFS API protocol by values.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Leonard Lyubich
ea043f4ca3 [#190] Refactor cryptographic functionality
Remove `signature` and `util/signature` packages. Re-implement their
functionality in new `crypto` package. Generalize the approach of
digital signature computation and verification by adding `Signer` and
`PublicKey` primitives similar to standard `crypto` package. Support
already exising in protocol signature schemes.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-19 12:55:11 +03:00
Pavel Karpy
2deaaeef05 [#170] object: Fix comments about checksums
Delete "must not be nil" where there are no pointers.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 18:33:33 +03:00
Pavel Karpy
9b63c07c59 [#170] storagegroup: Refactor and document package functionality
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 18:33:33 +03:00
Pavel Karpy
1186f2f703 [#170] oid, cid: Add marshal format checks
Also add checking presence of the `oid`, `cid` fields via `set` flag.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 17:32:25 +03:00
Pavel Karpy
f7172adf18 [#170] oid, cid: Refactor and document package functionality
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 17:32:25 +03:00
Alex Vanin
24d6c2221f [#170] bearer: Return presence flag in getters of optional fields
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-13 11:24:15 +03:00
Alex Vanin
27cd721422 [#170] bearer: Add docs, refactor
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-13 11:24:15 +03:00
Pavel Karpy
96892d7bc4 [#170] checksum: Drop Empty method
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 10:53:57 +03:00
Pavel Karpy
168b3ee7a4 [#170] checksum: Add examples
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 10:53:57 +03:00
Pavel Karpy
caa055236b [#170] checksum: Do not use pointers
Do not return pointers from getters. Do not pass pointers to the methods
that does not modify the checksum. Add `Empty` method.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 10:53:57 +03:00
Pavel Karpy
fd13e61266 [#170] checksum: Drop Empty method
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-04-13 10:53:57 +03:00
Leonard Lyubich
9c502a9cae [#179] resolver: Support wss connection scheme in NNS.Dial
WebSocket Secure scheme should also lead to using `neoclient.WSClient`
by `NNS`.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-13 10:46:27 +03:00
Leonard Lyubich
d51d18d5f3 [#179] ns: Select Neo connection scheme dynamically in NNS.Dial
WebSocket protocol is optionally supported by Neo servers.

Make `NNS.Dial` to select between HTTP and WebSocket connections
according to URL address scheme.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-13 10:46:27 +03:00
Leonard Lyubich
55283d3c91 [#179] Rename resolver package to ns
`resolver` isn't suitable name for the package with NeoFS name system
functionality.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-13 10:46:27 +03:00
Leonard Lyubich
75a5b6588d [#179] resolver: Use Client with WSClient in NNS
WebSocket client (`WSClient` type) from Neo Go library shows better
performance than HTTP one (`Client` type).

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-13 10:46:27 +03:00
Leonard Lyubich
146fc4f07a [#179] resolver: Refactor and document the package
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-04-13 10:46:27 +03:00
Alex Vanin
c961aea144 [#170] version: Add specification string encoder
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-13 10:28:12 +03:00
Alex Vanin
ade8822a2f [#170] version: Add docs, refactor
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-13 10:28:12 +03:00
Denis Kirillov
3e75660802 [#205] pool: fix using default key for requests
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 18:12:50 +03:00
Denis Kirillov
53e064e556 [#206] pool: fix waitForContainerRemoved
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 18:12:39 +03:00
Denis Kirillov
385f1b10f9 [#203] pool: fix PrmContainerDelete
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 14:26:08 +03:00
Denis Kirillov
1e8aa6a99f [#85] pool: update tests
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 10:30:28 +03:00
Denis Kirillov
97c8274dc0 [#85] pool: use non-pointer client inside wrapper
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 10:30:28 +03:00
Denis Kirillov
9e8e12f6ae [#85] pool: make client interface methods private
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 10:30:28 +03:00
Denis Kirillov
aa6a4950d5 [#85] pool: fix skipped tests
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 10:30:28 +03:00
Denis Kirillov
e56eef495d [#85] pool: refactor client interface
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-12 10:30:28 +03:00
Denis Kirillov
e50e6d2828 [#137] pool: simplify session creation
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
df0573d521 [#137] pool: drop sessionTokenThreshold
Description

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
c4adb03f8e [#137] pool: drop retry for object operations
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
fcfae4a249 [#137] Use callback response to update epoch
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
9814748958 [#137] pool: fix tests
Description

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
7df00fb0eb [#137] Add exp to ResSessionCreate
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
11a25bb413 [#137] Expire session tokens locally
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 13:33:16 +03:00
Denis Kirillov
b8d2158acd [#180] eacl: make equal methods functions
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 09:50:02 +03:00
Denis Kirillov
a709cf5444 [#180] pool: make some operations synchronous
Operations: PutContainer, DeleteContainer, SetEACL

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 09:50:02 +03:00
Denis Kirillov
0dbea5452a [#180] pool: add WaitForContainerRemoved
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 09:50:02 +03:00
Denis Kirillov
47345a33da [#180] pool: add WaitForEACLPresence
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 09:50:02 +03:00
Denis Kirillov
d568458fab [#180] eacl: add EqualTo for table
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-07 09:50:02 +03:00
Alex Vanin
2104945f9e [#193] pool: Return copy of session token in cache
To avoid side effects after token re-sign.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-06 12:06:24 +03:00
Alex Vanin
f38a24e8b5 [#193] pool: Add test to check side effects in token cache
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-04-06 12:06:24 +03:00
Denis Kirillov
e0281c3b34 [#191] pool: use bearer token
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-04-06 10:27:58 +04:00
Evgenii Stratonikov
f18b4a2a75 [#177] *: Remove logger package
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-03-29 09:54:46 +03:00
Pavel Karpy
58d4f4a55f [#170] acl: Document package functionality
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
2022-03-25 19:15:22 +03:00
Denis Kirillov
030bbce2cf [#165] pool: drop prmCommon from container params
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
59b49dd7e6 [#165] pool: update WaitForContainerPresence
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
191d85e607 [#165] pool: change exported fields to setters
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
9be9697856 [#165] pool: make client interface unexported
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
52548fe176 [#165] pool: add docs
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
7811d8eefc [#165] pool: distinguish init step and run
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
d03523a3bc [#165] pool: replace options with parameters
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
ec5c223f29 [#165] pool: make private inner structs
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Denis Kirillov
f5cabe26cb [#165] pool: drop builder
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
2022-03-21 12:41:08 +03:00
Leonard Lyubich
aeb4ac638a [#170] accounting: Remove message sub-string from V2-methods
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-03-21 12:37:53 +03:00
Leonard Lyubich
7d31de57ec [#170] audit: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-03-21 12:37:53 +03:00
Leonard Lyubich
48150852f3 [#170] accounting: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-03-21 12:37:53 +03:00
Alex Vanin
a55ffa4796 [#176] status: Do not lose built-in error text message
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2022-03-16 17:16:20 +03:00
592 changed files with 63902 additions and 21249 deletions

View file

@ -0,0 +1,45 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: community, triage, bug
assignees: ''
---
<!--- Provide a general summary of the issue in the Title above -->
## Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
## Current Behavior
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
## Possible Solution
<!--- Not obligatory -->
<!--- If no reason/fix/additions for the bug can be suggested, -->
<!--- uncomment the following phrase: -->
<!--- No fix can be suggested by a QA engineer. Further solutions shall be up to developers. -->
## Steps to Reproduce (for bugs)
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. -->
1.
## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
## Regression
<!-- Is this issue a regression? (Yes / No) -->
<!-- If Yes, optionally please include version or commit id or PR# that caused this regression, if you have these details. -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Version used:
* Server setup and configuration:
* Operating System and version (`uname -a`):

View file

@ -0,0 +1 @@
blank_issues_enabled: false

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: community, triage
assignees: ''
---
## Is your feature request related to a problem? Please describe.
<!--- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
## Describe the solution you'd like
<!--- A clear and concise description of what you want to happen. -->
## Describe alternatives you've considered
<!--- A clear and concise description of any alternative solutions or features you've considered. -->
## Additional context
<!--- Add any other context or screenshots about the feature request here. -->

View file

@ -0,0 +1,21 @@
name: DCO
on: [pull_request]
jobs:
dco:
name: DCO
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: '1.23'
- name: Run commit format checker
uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3
with:
from: 'origin/${{ github.event.pull_request.base.ref }}'

View file

@ -0,0 +1,39 @@
name: Tests and linters
on: [pull_request]
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '1.23'
cache: true
- name: Install linters
run: make lint-install
- name: Run linters
run: make lint
tests:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
go_versions: [ '1.22', '1.23' ]
fail-fast: false
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '${{ matrix.go_versions }}'
- name: Run tests
run: make test

3
.gitattributes vendored
View file

@ -2,3 +2,6 @@
/pkg/policy/parser/generate.go diff /pkg/policy/parser/generate.go diff
**/*.interp -diff **/*.interp -diff
**/*.tokens -diff **/*.tokens -diff
/**/*.pb.go -diff -merge
/**/*.pb.go linguist-generated=true
/go.sum -diff

View file

@ -1,21 +0,0 @@
name: DCO check
on:
pull_request:
branches:
- master
jobs:
commits_check_job:
runs-on: ubuntu-latest
name: Commits Check
steps:
- name: Get PR Commits
id: 'get-pr-commits'
uses: tim-actions/get-pr-commits@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: DCO Check
uses: tim-actions/dco@master
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}

View file

@ -1,52 +0,0 @@
name: neofs-sdk-go tests
on:
pull_request:
branches:
- master
types: [opened, synchronize]
paths-ignore:
- '**/*.md'
workflow_dispatch:
jobs:
tests:
name: Tests
runs-on: ubuntu-20.04
strategy:
matrix:
go_versions: [ '1.16.x', '1.17.x' ]
fail-fast: false
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: '${{ matrix.go_versions }}'
- name: Restore Go modules from cache
uses: actions/cache@v2
with:
path: /home/runner/go/pkg/mod
key: deps-${{ hashFiles('go.sum') }}
- name: Update Go modules
run: make dep
- name: Run tests
run: make test
lint:
runs-on: ubuntu-20.04
steps:
- name: Check out code
uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: latest
only-new-issues: true

10
.gitignore vendored
View file

@ -21,3 +21,13 @@ vendor/
# coverage # coverage
coverage.txt coverage.txt
coverage.html coverage.html
# antlr tool jar
antlr*.jar
# tempfiles
.cache
# binary
bin/
release/

View file

@ -4,15 +4,16 @@
# options for analysis running # options for analysis running
run: run:
# timeout for analysis, e.g. 30s, 5m, default is 1m # timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 5m timeout: 10m
# include test files or not, default is true # include test files or not, default is true
tests: true tests: false
# output configuration options # output configuration options
output: output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: tab formats:
- format: tab
# all available settings of specific linters # all available settings of specific linters
linters-settings: linters-settings:
@ -24,6 +25,13 @@ linters-settings:
govet: govet:
# report about shadowed variables # report about shadowed variables
check-shadowing: false check-shadowing: false
staticcheck:
checks: ["all"]
funlen:
lines: 80 # default 60
statements: 60 # default 40
gocognit:
min-complexity: 40 # default 30
linters: linters:
enable: enable:
@ -32,28 +40,30 @@ linters:
- revive - revive
# some default golangci-lint linters # some default golangci-lint linters
- deadcode
- errcheck - errcheck
- gosimple - gosimple
- godot
- ineffassign - ineffassign
- staticcheck - staticcheck
- structcheck
- typecheck - typecheck
- unused - unused
- varcheck
# extra linters # extra linters
- bidichk
- durationcheck
- exhaustive - exhaustive
- godot - copyloopvar
- gofmt - gofmt
- whitespace
- goimports - goimports
- misspell
- predeclared
- reassign
- whitespace
- containedctx
- funlen
- gocognit
- contextcheck
- protogetter
- intrange
disable-all: true disable-all: true
fast: false fast: false
issues:
include:
- EXC0002 # should have a comment
- EXC0003 # test/Test ... consider calling this
- EXC0004 # govet
- EXC0005 # C-style breaks

36
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,36 @@
ci:
autofix_prs: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: check-merge-conflict
- id: check-json
- id: check-xml
- id: check-yaml
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
exclude: "(.key|.interp|.tokens)$"
- repo: local
hooks:
- id: go-unit-tests
name: go unit tests
entry: make test GOFLAGS=''
pass_filenames: false
types: [go]
language: system
- repo: local
hooks:
- id: make-lint
name: Run Make Lint
entry: make lint
language: system
pass_filenames: false

1
CODEOWNERS Normal file
View file

@ -0,0 +1 @@
.* @TrueCloudLab/storage-core @TrueCloudLab/storage-services

4
Dockerfile Normal file
View file

@ -0,0 +1,4 @@
FROM golang:1.22
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install make openjdk-17-jre -y
WORKDIR /work

121
Makefile Normal file → Executable file
View file

@ -1,8 +1,81 @@
#!/usr/bin/make -f #!/usr/bin/make -f
ANTLR_VERSION=4.13.1
TMP_DIR := .cache
LINT_VERSION ?= 1.61.0
TRUECLOUDLAB_LINT_VERSION ?= 0.0.7
OUTPUT_LINT_DIR ?= $(shell pwd)/bin
LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION)
PROTOC_VERSION ?= 27.2
PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf)
PROTOC_OS_VERSION=osx-x86_64
ifeq ($(shell uname), Linux)
PROTOC_OS_VERSION=linux-x86_64
endif
BIN = bin
PROTOBUF_DIR ?= $(abspath $(BIN))/protobuf
PROTOC_DIR ?= $(PROTOBUF_DIR)/protoc-v$(PROTOC_VERSION)
PROTOC_GEN_GO_DIR ?= $(PROTOBUF_DIR)/protoc-gen-go-$(PROTOC_GEN_GO_VERSION)
.PHONY: dep imports protoc test lint help $(BIN)/protogen protoc-test
# Run tests # Run tests
test: GOFLAGS ?= "-cover -count=1"
test: test:
@go test ./... -cover @GOFLAGS=$(GOFLAGS) go test ./...
# Reformat imports
imports:
@echo "⇒ Processing goimports check"
@for f in `find . -type f -name '*.go' -not -name '*.pb.go' -prune`; do \
goimports -w $$f; \
done
# Install protoc
protoc-install:
@rm -rf $(PROTOBUF_DIR)
@mkdir -p $(PROTOBUF_DIR)
@echo "⇒ Installing protoc... "
@wget -q -O $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip 'https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(PROTOC_OS_VERSION).zip'
@unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR)
@rm $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip
@echo "⇒ Installing protoc-gen-go..."
@GOBIN=$(PROTOC_GEN_GO_DIR) go install -v google.golang.org/protobuf/...@$(PROTOC_GEN_GO_VERSION)
# Regenerate code for proto files
protoc:
@if [ ! -d "$(PROTOC_DIR)" ] || [ ! -d "$(PROTOC_GEN_GO_DIR)" ]; then \
make protoc-install; \
fi
# Protoc generate
@for f in `find . -type f -name '*.proto' -not -path './bin/*' -not -path './api/util/proto/test/*'`; do \
echo "⇒ Processing $$f "; \
$(PROTOC_DIR)/bin/protoc \
--proto_path=.:$(PROTOC_DIR)/include:/usr/local/include \
--plugin=protoc-gen-go-frostfs=$(abspath ./bin/protogen) \
--go-frostfs_out=fuzz=true:. \
--go-frostfs_opt=paths=source_relative \
--go-grpc_opt=require_unimplemented_servers=false \
--go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \
done
$(BIN)/protogen:
@go build -v -trimpath \
-o $(BIN)/protogen \
./api/util/protogen
protoc-test: protoc $(BIN)/protogen
@$(PROTOC_DIR)/bin/protoc \
--go_out=. --go_opt=paths=source_relative \
--plugin=protoc-gen-go-frostfs=$(abspath $(BIN)/protogen) \
--go-frostfs_opt=Mapi/util/proto/test/test.proto=git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/test/custom \
--go-frostfs_opt=module=git.frostfs.info/TrueCloudLab/frostfs-sdk-go \
--go-frostfs_out=. --go-frostfs_opt=paths=import \
./api/util/proto/test/test.proto
# Pull go dependencies # Pull go dependencies
dep: dep:
@ -13,9 +86,23 @@ dep:
@CGO_ENABLED=0 \ @CGO_ENABLED=0 \
go mod tidy -v && echo OK go mod tidy -v && echo OK
# Install linters
lint-install:
@mkdir -p $(TMP_DIR)
@rm -rf $(TMP_DIR)/linters
@git -c advice.detachedHead=false clone --branch v$(TRUECLOUDLAB_LINT_VERSION) https://git.frostfs.info/TrueCloudLab/linters.git $(TMP_DIR)/linters
@@make -C $(TMP_DIR)/linters lib CGO_ENABLED=1 OUT_DIR=$(OUTPUT_LINT_DIR)
@rm -rf $(TMP_DIR)/linters
@rmdir $(TMP_DIR) 2>/dev/null || true
@CGO_ENABLED=1 GOBIN=$(LINT_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$(LINT_VERSION)
# Run linters # Run linters
lint: lint:
@golangci-lint --timeout=5m run @if [ ! -d "$(LINT_DIR)" ]; then \
echo "Run make lint-install"; \
exit 1; \
fi
$(LINT_DIR)/golangci-lint run
# Run tests with race detection and produce coverage output # Run tests with race detection and produce coverage output
cover: cover:
@ -29,6 +116,24 @@ format:
@echo "⇒ Processing goimports check" @echo "⇒ Processing goimports check"
@goimports -w ./ @goimports -w ./
policy:
@wget -q https://www.antlr.org/download/antlr-${ANTLR_VERSION}-complete.jar -O antlr4-tool.jar
@java -Xmx500M -cp antlr4-tool.jar org.antlr.v4.Tool -Dlanguage=Go \
-no-listener -visitor netmap/parser/Query.g4 netmap/parser/QueryLexer.g4
# Run `make %` in truecloudlab/frostfs-sdk-go container(Golang+Java)
docker/%:
@docker build -t truecloudlab/frostfs-sdk-go --platform linux/amd64 . > /dev/null
@docker run --rm -t \
-v `pwd`:/work \
-u "$$(id -u):$$(id -g)" \
--env HOME=/work \
truecloudlab/frostfs-sdk-go make $*
# Synchronize tree service
sync-tree:
@./syncTree.sh
# Show this help prompt # Show this help prompt
help: help:
@echo ' Usage:' @echo ' Usage:'
@ -38,3 +143,15 @@ help:
@echo ' Targets:' @echo ' Targets:'
@echo '' @echo ''
@awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+ ?:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort -u @awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+ ?:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort -u
# Activate pre-commit hooks
pre-commit:
pre-commit install --hook-type pre-commit
# Deactivate pre-commit hooks
unpre-commit:
pre-commit uninstall --hook-type pre-commit
# Run pre-commit hooks
pre-commit-run:
@pre-commit run --all-files --hook-stage manual

View file

@ -1,6 +1,6 @@
# neofs-sdk-go # frostfs-sdk-go
Go implementation of NeoFS SDK. It contains high-level version-independent wrappers Go implementation of FrostFS SDK. It contains high-level version-independent wrappers
for structures from [neofs-api-go](https://github.com/nspcc-dev/neofs-api-go) as well as for structures from [frostfs-api-go](https://git.frostfs.info/TrueCloudLab/frostfs-api-go) as well as
helper functions for simplifying node/dApp implementations. helper functions for simplifying node/dApp implementations.
## Repository structure ## Repository structure
@ -10,63 +10,73 @@ Contains fixed-point `Decimal` type for performing balance calculations.
### eacl ### eacl
Contains Extended ACL types for fine-grained access control. Contains Extended ACL types for fine-grained access control.
There is also a reference implementation of checking algorithm which is used in NeoFS node. There is also a reference implementation of checking algorithm which is used in FrostFS node.
### checksum ### checksum
Contains `Checksum` type encapsulating checksum as well as it's kind. Contains `Checksum` type encapsulating checksum as well as it's kind.
Currently Sha256 and [Tillich-Zemor hashsum](https://github.com/nspcc-dev/tzhash) are in use. Currently Sha256 and [Tillich-Zemor hashsum](https://git.frostfs.info/TrueCloudLab/tzhash) are in use.
### owner ### owner
`owner.ID` type represents single account interacting with NeoFS. In v2 version of protocol `owner.ID` type represents single account interacting with FrostFS. In v2 version of protocol
it is just raw bytes behing [base58-encoded address](https://docs.neo.org/docs/en-us/basic/concept/wallets.html#address) it is just raw bytes behing [base58-encoded address](https://docs.neo.org/docs/en-us/basic/concept/wallets.html#address)
in Neo blockchain. Note that for historical reasons it contains in Neo blockchain. Note that for historical reasons it contains
version prefix and checksum in addition to script-hash. version prefix and checksum in addition to script-hash.
### token ### token
Contains Bearer token type with several NeoFS-specific methods. Contains Bearer token type with several FrostFS-specific methods.
### resolver ### ns
In NeoFS there are 2 types of name resolution: DNS and NNS. NNS stands for Neo Name Service In FrostFS there are 2 types of name resolution: DNS and NNS. NNS stands for Neo Name Service
is just a [contract](https://github.com/nspcc-dev/neofs-contract/) deployed on a Neo blockchain. is just a [contract](https://git.frostfs.info/TrueCloudLab/frostfs-contract) deployed on a Neo blockchain.
Basically, NNS is just a DNS-on-chain which can be used for resolving container nice-names as well Basically, NNS is just a DNS-on-chain which can be used for resolving container nice-names as well
as any other name in dApps. See our [CoreDNS plugin](https://github.com/nspcc-dev/coredns/tree/master/plugin/nns) as any other name in dApps. See our [CoreDNS plugin](https://github.com/nspcc-dev/coredns/tree/master/plugin/nns)
for the example of how NNS can be integrated in DNS. for the example of how NNS can be integrated in DNS.
### session ### session
To help lightweight clients interact with NeoFS without sacrificing trust, NeoFS has a concept To help lightweight clients interact with FrostFS without sacrificing trust, FrostFS has a concept
of session token. It is signed by client and allows any node with which a session is established of session token. It is signed by client and allows any node with which a session is established
to perform certain actions on behalf of the user. to perform certain actions on behalf of the user.
### client ### client
Contains client for working with NeoFS. Contains client for working with FrostFS.
```go ```go
c, _ := client.New( var prmInit client.PrmInit
client.WithAddress("localhost:40005"), // endpoint address prmInit.SetDefaultPrivateKey(key) // private key for request signing
client.WithDefaultPrivateKey(key), // private key for request signing
client.WithNeoFSErrorHandling(), // enable erroneous status parsing
client.WithTLSConfig(&tls.Config{})) // custom TLS configuration
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second) var c client.Client
defer cancel() c.Init(prmInit)
res, err := c.BalanceGet(ctx, owner) var prmDial client.PrmDial
prmDial.SetServerURI("grpcs://localhost:40005") // endpoint address
err := c.Dial(prmDial)
if err != nil { if err != nil {
return return
} }
fmt.Printf("Balance for %s: %s\n", owner, res.Amount()) ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()
var prm client.PrmBalanceGet
prm.SetAccount(acc)
res, err := c.BalanceGet(ctx, prm)
if err != nil {
return
}
fmt.Printf("Balance for %s: %v\n", acc, res.Amount())
``` ```
#### Response status #### Response status
In NeoFS every operation can fail on multiple levels, so a single `error` doesn't suffice, In FrostFS every operation can fail on multiple levels, so a single `error` doesn't suffice,
e.g. consider a case when object was put on 4 out of 5 replicas. Thus, all request execution e.g. consider a case when object was put on 4 out of 5 replicas. Thus, all request execution
details are contained in `Status` returned from every RPC call. dApp can inspect them details are contained in `Status` returned from every RPC call. dApp can inspect them
if needed and perform any desired action. In the case above we may want to report if needed and perform any desired action. In the case above we may want to report
these details to the user as well as retry an operation, possibly with different parameters. these details to the user as well as retry an operation, possibly with different parameters.
Status wire-format is extendable and each node can report any set of details it wants. Status wire-format is extendable and each node can report any set of details it wants.
The set of reserved status codes can be found in The set of reserved status codes can be found in
[NeoFS API](https://github.com/nspcc-dev/neofs-api/blob/master/status/types.proto). There is also [FrostFS API](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/branch/master/status/types.proto).
a `client.WithNeoFSErrorHandling()` to seamlessly convert erroneous statuses into Go error type.
### policy ### policy
Contains helpers allowing conversion of placing policy from/to JSON representation Contains helpers allowing conversion of placing policy from/to JSON representation
@ -90,12 +100,12 @@ outdated in some details.
```go ```go
import ( import (
"github.com/nspcc-dev/neofs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
) )
func placementNodes(addr *object.Address, p *netmap.PlacementPolicy, neofsNodes []netmap.NodeInfo) { func placementNodes(addr *object.Address, p *netmap.PlacementPolicy, frostfsNodes []netmap.NodeInfo) {
// Convert list of nodes in NeoFS API format to the intermediate representation. // Convert list of nodes in FrostFS API format to the intermediate representation.
nodes := netmap.NodesFromInfo(nodes) nodes := netmap.NodesFromInfo(nodes)
// Create new netmap (errors are skipped for the sake of clarity). // Create new netmap (errors are skipped for the sake of clarity).
@ -110,13 +120,13 @@ func placementNodes(addr *object.Address, p *netmap.PlacementPolicy, neofsNodes
``` ```
### pool ### pool
Simple pool for managing connections to NeoFS nodes. Simple pool for managing connections to FrostFS nodes.
### acl, checksum, version, signature ### acl, checksum, version, signature
Contain simple API wrappers. Contain simple API wrappers.
### logger ### logger
Wrapper over `zap.Logger` which is used across NeoFS codebase. Wrapper over `zap.Logger` which is used across FrostFS codebase.
### util ### util
Utilities for working with signature-related code. Utilities for working with signature-related code.

View file

@ -1,69 +1,64 @@
package accounting package accounting
import "github.com/nspcc-dev/neofs-api-go/v2/accounting" import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting"
// Decimal represents decimal number for accounting operations. // Decimal represents decimal number for accounting operations.
//
// Decimal is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting.Decimal
// message. See ReadFromV2 / WriteToV2 methods.
//
// Instances can be created using built-in var declaration.
//
// Note that direct typecast is not safe and may result in loss of compatibility:
//
// _ = Decimal(accounting.Decimal{}) // not recommended
type Decimal accounting.Decimal type Decimal accounting.Decimal
// NewDecimal creates, initializes and returns empty Decimal instance. // ReadFromV2 reads Decimal from the accounting.Decimal message. Checks if the
// message conforms to FrostFS API V2 protocol.
// //
// Defaults: // See also WriteToV2.
// - value: 0 func (d *Decimal) ReadFromV2(m accounting.Decimal) error {
// - precision: 0 *d = Decimal(m)
func NewDecimal() *Decimal { return nil
return NewDecimalFromV2(new(accounting.Decimal))
} }
// NewDecimalFromV2 converts v2 Decimal to Decimal. // WriteToV2 writes Decimal to the accounting.Decimal message.
// The message must not be nil.
// //
// Nil Decimal converts to nil. // See also ReadFromV2.
func NewDecimalFromV2(d *accounting.Decimal) *Decimal { func (d Decimal) WriteToV2(m *accounting.Decimal) {
return (*Decimal)(d) *m = (accounting.Decimal)(d)
}
// ToV2 returns the v2 Decimal message.
//
// Nil Decimal converts to nil.
func (d *Decimal) ToV2() *accounting.Decimal {
return (*accounting.Decimal)(d)
} }
// Value returns value of the decimal number. // Value returns value of the decimal number.
func (d *Decimal) Value() int64 { //
return (*accounting.Decimal)(d).GetValue() // Zero Decimal has zero value.
//
// See also SetValue.
func (d Decimal) Value() int64 {
return (*accounting.Decimal)(&d).GetValue()
} }
// SetValue sets value of the decimal number. // SetValue sets value of the decimal number.
//
// See also Value.
func (d *Decimal) SetValue(v int64) { func (d *Decimal) SetValue(v int64) {
(*accounting.Decimal)(d).SetValue(v) (*accounting.Decimal)(d).SetValue(v)
} }
// Precision returns precision of the decimal number. // Precision returns precision of the decimal number.
func (d *Decimal) Precision() uint32 { //
return (*accounting.Decimal)(d).GetPrecision() // Zero Decimal has zero precision.
//
// See also SetPrecision.
func (d Decimal) Precision() uint32 {
return (*accounting.Decimal)(&d).GetPrecision()
} }
// SetPrecision sets precision of the decimal number. // SetPrecision sets precision of the decimal number.
//
// See also Precision.
func (d *Decimal) SetPrecision(p uint32) { func (d *Decimal) SetPrecision(p uint32) {
(*accounting.Decimal)(d).SetPrecision(p) (*accounting.Decimal)(d).SetPrecision(p)
} }
// Marshal marshals Decimal into a protobuf binary form.
func (d *Decimal) Marshal() ([]byte, error) {
return (*accounting.Decimal)(d).StableMarshal(nil)
}
// Unmarshal unmarshalls protobuf binary representation of Decimal.
func (d *Decimal) Unmarshal(data []byte) error {
return (*accounting.Decimal)(d).Unmarshal(data)
}
// MarshalJSON encodes Decimal to protobuf JSON format.
func (d *Decimal) MarshalJSON() ([]byte, error) {
return (*accounting.Decimal)(d).MarshalJSON()
}
// UnmarshalJSON decodes Decimal from protobuf JSON format.
func (d *Decimal) UnmarshalJSON(data []byte) error {
return (*accounting.Decimal)(d).UnmarshalJSON(data)
}

View file

@ -3,15 +3,19 @@ package accounting_test
import ( import (
"testing" "testing"
"github.com/nspcc-dev/neofs-sdk-go/accounting" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
accountingtest "github.com/nspcc-dev/neofs-sdk-go/accounting/test" v2accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestDecimal(t *testing.T) { func TestDecimalData(t *testing.T) {
const v, p = 4, 2 const v, p = 4, 2
d := accounting.NewDecimal() var d accounting.Decimal
require.Zero(t, d.Value())
require.Zero(t, d.Precision())
d.SetValue(v) d.SetValue(v)
d.SetPrecision(p) d.SetPrecision(p)
@ -19,26 +23,24 @@ func TestDecimal(t *testing.T) {
require.EqualValues(t, p, d.Precision()) require.EqualValues(t, p, d.Precision())
} }
func TestDecimalEncoding(t *testing.T) { func TestDecimalMessageV2(t *testing.T) {
d := accountingtest.Decimal() var (
d accounting.Decimal
m v2accounting.Decimal
)
t.Run("binary", func(t *testing.T) { m.SetValue(7)
data, err := d.Marshal() m.SetPrecision(8)
require.NoError(t, err)
d2 := accounting.NewDecimal() require.NoError(t, d.ReadFromV2(m))
require.NoError(t, d2.Unmarshal(data))
require.Equal(t, d, d2) require.EqualValues(t, m.GetValue(), d.Value())
}) require.EqualValues(t, m.GetPrecision(), d.Precision())
t.Run("json", func(t *testing.T) { var m2 v2accounting.Decimal
data, err := d.MarshalJSON()
require.NoError(t, err)
d2 := accounting.NewDecimal() d.WriteToV2(&m2)
require.NoError(t, d2.UnmarshalJSON(data))
require.Equal(t, d, d2) require.EqualValues(t, d.Value(), m2.GetValue())
}) require.EqualValues(t, d.Precision(), m2.GetPrecision())
} }

35
accounting/doc.go Normal file
View file

@ -0,0 +1,35 @@
/*
Package accounting provides primitives to perform accounting operations in FrostFS.
Decimal type provides functionality to process user balances. For example, when
working with Fixed8 balance precision:
var dec accounting.Decimal
dec.SetValue(val)
dec.SetPrecision(8)
Instances can be also used to process FrostFS API V2 protocol messages
(see neo.fs.v2.accounting package in https://git.frostfs.info/TrueCloudLab/frostfs-api).
On client side:
import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting"
var msg accounting.Decimal
dec.WriteToV2(&msg)
// send msg
On server side:
// recv msg
var dec accounting.Decimal
dec.ReadFromV2(msg)
// process dec
Using package types in an application is recommended to potentially work with
different protocol versions with which these types are compatible.
*/
package accounting

View file

@ -3,14 +3,14 @@ package accountingtest
import ( import (
"math/rand" "math/rand"
"github.com/nspcc-dev/neofs-sdk-go/accounting" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
) )
// Decimal returns random accounting.Decimal. // Decimal returns random accounting.Decimal.
func Decimal() *accounting.Decimal { func Decimal() *accounting.Decimal {
d := accounting.NewDecimal() var d accounting.Decimal
d.SetValue(rand.Int63()) d.SetValue(rand.Int63())
d.SetPrecision(rand.Uint32()) d.SetPrecision(rand.Uint32())
return d return &d
} }

13
accounting/test/doc.go Normal file
View file

@ -0,0 +1,13 @@
/*
Package accountingtest provides functions for convenient testing of accounting package API.
Note that importing the package into source files is highly discouraged.
Random instance generation functions can be useful when testing expects any value, e.g.:
import accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting/test"
dec := accountingtest.Decimal()
// test the value
*/
package accountingtest

View file

@ -1,105 +0,0 @@
package acl
import (
"fmt"
"strconv"
"strings"
)
// BasicACL is Access Control List that defines who can interact with containers and what exactly they can do.
type BasicACL uint32
func (a BasicACL) String() string {
return fmt.Sprintf("0x%08x", uint32(a))
}
const (
// PublicBasicRule is a basic ACL value for final public-read-write container for which extended ACL CANNOT be set.
PublicBasicRule BasicACL = 0x1FBFBFFF
// PrivateBasicRule is a basic ACL value for final private container for which extended ACL CANNOT be set.
PrivateBasicRule BasicACL = 0x1C8C8CCC
// ReadOnlyBasicRule is a basic ACL value for final public-read container for which extended ACL CANNOT be set.
ReadOnlyBasicRule BasicACL = 0x1FBF8CFF
// PublicAppendRule is a basic ACL value for final public-append container for which extended ACL CANNOT be set.
PublicAppendRule BasicACL = 0x1FBF9FFF
// EACLPublicBasicRule is a basic ACL value for non-final public-read-write container for which extended ACL CAN be set.
EACLPublicBasicRule BasicACL = 0x0FBFBFFF
// EACLPrivateBasicRule is a basic ACL value for non-final private container for which extended ACL CAN be set.
EACLPrivateBasicRule BasicACL = 0x0C8C8CCC
// EACLReadOnlyBasicRule is a basic ACL value for non-final public-read container for which extended ACL CAN be set.
EACLReadOnlyBasicRule BasicACL = 0x0FBF8CFF
// EACLPublicAppendRule is a basic ACL value for non-final public-append container for which extended ACL CAN be set.
EACLPublicAppendRule BasicACL = 0x0FBF9FFF
)
const (
// PublicBasicName is a well-known name for 0x1FBFBFFF basic ACL.
// It represents fully-public container without eACL.
PublicBasicName = "public-read-write"
// PrivateBasicName is a well-known name for 0x1C8C8CCC basic ACL.
// It represents fully-private container without eACL.
PrivateBasicName = "private"
// ReadOnlyBasicName is a well-known name for 0x1FBF8CFF basic ACL.
// It represents public read-only container without eACL.
ReadOnlyBasicName = "public-read"
// PublicAppendName is a well-known name for 0x1FBF9FFF basic ACL.
// It represents fully-public container without eACL except DELETE operation is only allowed on the owner.
PublicAppendName = "public-append"
// EACLPublicBasicName is a well-known name for 0x0FBFBFFF basic ACL.
// It represents fully-public container that allows eACL.
EACLPublicBasicName = "eacl-public-read-write"
// EACLPrivateBasicName is a well-known name for 0x0C8C8CCC basic ACL.
// It represents fully-private container that allows eACL.
EACLPrivateBasicName = "eacl-private"
// EACLReadOnlyBasicName is a well-known name for 0x0FBF8CFF basic ACL.
// It represents public read-only container that allows eACL.
EACLReadOnlyBasicName = "eacl-public-read"
// EACLPublicAppendName is a well-known name for 0x0FBF9FFF basic ACL.
// It represents fully-public container that allows eACL except DELETE operation is only allowed on the owner.
EACLPublicAppendName = "eacl-public-append"
)
// ParseBasicACL parse string ACL (well-known names or hex representation).
func ParseBasicACL(basicACL string) (BasicACL, error) {
switch basicACL {
case PublicBasicName:
return PublicBasicRule, nil
case PrivateBasicName:
return PrivateBasicRule, nil
case ReadOnlyBasicName:
return ReadOnlyBasicRule, nil
case PublicAppendName:
return PublicAppendRule, nil
case EACLPublicBasicName:
return EACLPublicBasicRule, nil
case EACLPrivateBasicName:
return EACLPrivateBasicRule, nil
case EACLReadOnlyBasicName:
return EACLReadOnlyBasicRule, nil
case EACLPublicAppendName:
return EACLPublicAppendRule, nil
default:
basicACL = strings.TrimPrefix(strings.ToLower(basicACL), "0x")
value, err := strconv.ParseUint(basicACL, 16, 32)
if err != nil {
return 0, fmt.Errorf("can't parse basic ACL: %s", basicACL)
}
return BasicACL(value), nil
}
}

View file

@ -1,82 +0,0 @@
package acl
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestParser(t *testing.T) {
for _, tc := range []struct {
acl string
expected BasicACL
err bool
}{
{
acl: PublicBasicName,
expected: PublicBasicRule,
},
{
acl: PrivateBasicName,
expected: PrivateBasicRule,
},
{
acl: ReadOnlyBasicName,
expected: ReadOnlyBasicRule,
},
{
acl: PublicAppendName,
expected: PublicAppendRule,
},
{
acl: EACLPublicBasicName,
expected: EACLPublicBasicRule,
},
{
acl: EACLPrivateBasicName,
expected: EACLPrivateBasicRule,
},
{
acl: EACLReadOnlyBasicName,
expected: EACLReadOnlyBasicRule,
},
{
acl: EACLPublicAppendName,
expected: EACLPublicAppendRule,
},
{
acl: "0x1C8C8CCC",
expected: 0x1C8C8CCC,
},
{
acl: "1C8C8CCC",
expected: 0x1C8C8CCC,
},
{
acl: "123456789",
err: true,
},
{
acl: "0x1C8C8CCG",
err: true,
},
} {
actual, err := ParseBasicACL(tc.acl)
if tc.err {
require.Error(t, err)
continue
}
require.NoError(t, err)
require.Equal(t, tc.expected, actual)
}
}
func TestString(t *testing.T) {
acl := BasicACL(0x1fbfbfff)
require.Equal(t, "0x1fbfbfff", acl.String())
acl2, err := ParseBasicACL(PrivateBasicName)
require.NoError(t, err)
require.Equal(t, "0x1c8c8ccc", acl2.String())
}

52
ape/chain.go Normal file
View file

@ -0,0 +1,52 @@
package ape
import (
"errors"
"fmt"
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
)
var (
ErrInvalidChainRepresentation = errors.New("invalid chain representation")
)
// ChainID is Chain's identifier.
type ChainID []byte
// Chain is an SDK representation for v2's Chain.
//
// Note that Chain (as well as v2's Chain) and all related entities
// are NOT operated by Access-Policy-Engine (APE). The client is responsible
// to convert these types to policy-engine entities.
type Chain struct {
// Raw is the encoded chain kind.
// It assumes that Raw's bytes are the result of encoding provided by
// policy-engine package.
Raw []byte
}
// ToV2 converts Chain to v2.
func (c *Chain) ToV2() *apeV2.Chain {
v2ct := new(apeV2.Chain)
if c.Raw != nil {
v2Raw := new(apeV2.ChainRaw)
v2Raw.SetRaw(c.Raw)
v2ct.SetKind(v2Raw)
}
return v2ct
}
// ReadFromV2 fills Chain from v2.
func (c *Chain) ReadFromV2(v2ct *apeV2.Chain) error {
switch v := v2ct.GetKind().(type) {
default:
return fmt.Errorf("unsupported chain kind: %T", v)
case *apeV2.ChainRaw:
raw := v.GetRaw()
c.Raw = raw
}
return nil
}

53
ape/chain_target.go Normal file
View file

@ -0,0 +1,53 @@
package ape
import (
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
)
// TargetType is an SDK representation for v2's TargetType.
type TargetType apeV2.TargetType
const (
TargetTypeUndefined TargetType = iota
TargetTypeNamespace
TargetTypeContainer
TargetTypeUser
TargetTypeGroup
)
// ToV2 converts TargetType to v2.
func (targetType TargetType) ToV2() apeV2.TargetType {
return apeV2.TargetType(targetType)
}
// FromV2 reads TargetType to v2.
func (targetType *TargetType) FromV2(v2targetType apeV2.TargetType) {
*targetType = TargetType(v2targetType)
}
// ChainTarget is an SDK representation for v2's ChainTarget.
//
// Note that ChainTarget (as well as v2's ChainTarget) and all related entities
// are NOT operated by Access-Policy-Engine (APE). The client is responsible
// to convert these types to policy-engine entities.
type ChainTarget struct {
TargetType TargetType
Name string
}
// ToV2 converts ChainTarget to v2.
func (ct *ChainTarget) ToV2() *apeV2.ChainTarget {
v2ct := new(apeV2.ChainTarget)
v2ct.SetTargetType(ct.TargetType.ToV2())
v2ct.SetName(ct.Name)
return v2ct
}
// FromV2 reads ChainTarget frpm v2.
func (ct *ChainTarget) FromV2(v2ct *apeV2.ChainTarget) {
ct.TargetType.FromV2(v2ct.GetTargetType())
ct.Name = v2ct.GetName()
}

65
ape/chain_target_test.go Normal file
View file

@ -0,0 +1,65 @@
package ape_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
"github.com/stretchr/testify/require"
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
)
var (
m = map[ape.TargetType]apeV2.TargetType{
ape.TargetTypeUndefined: apeV2.TargetTypeUndefined,
ape.TargetTypeNamespace: apeV2.TargetTypeNamespace,
ape.TargetTypeContainer: apeV2.TargetTypeContainer,
ape.TargetTypeUser: apeV2.TargetTypeUser,
ape.TargetTypeGroup: apeV2.TargetTypeGroup,
}
)
func TestTargetType(t *testing.T) {
for typesdk, typev2 := range m {
t.Run("from sdk to v2 "+typev2.String(), func(t *testing.T) {
v2 := typesdk.ToV2()
require.Equal(t, v2, typev2)
})
t.Run("from v2 to sdk "+typev2.String(), func(t *testing.T) {
var typ ape.TargetType
typ.FromV2(typev2)
require.Equal(t, typesdk, typ)
})
}
}
func TestChainTarget(t *testing.T) {
var (
typ = ape.TargetTypeNamespace
name = "namespaceXXYYZZ"
)
t.Run("from sdk to v2", func(t *testing.T) {
ct := ape.ChainTarget{
TargetType: typ,
Name: name,
}
v2 := ct.ToV2()
require.Equal(t, m[typ], v2.GetTargetType())
require.Equal(t, name, v2.GetName())
})
t.Run("from v2 to sdk", func(t *testing.T) {
v2 := &apeV2.ChainTarget{}
v2.SetTargetType(m[typ])
v2.SetName(name)
var ct ape.ChainTarget
ct.FromV2(v2)
require.Equal(t, typ, ct.TargetType)
require.Equal(t, name, ct.Name)
})
}

43
ape/chain_test.go Normal file
View file

@ -0,0 +1,43 @@
package ape_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
"github.com/stretchr/testify/require"
apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
)
const (
encoded = `{"ID":"","Rules":[{"Status":"Allow","Actions":{"Inverted":false,"Names":["GetObject"]},"Resources":{"Inverted":false,"Names":["native:object/*"]},"Any":false,"Condition":[{"Op":"StringEquals","Object":"Resource","Key":"Department","Value":"HR"}]}],"MatchType":"DenyPriority"}`
)
func TestChainData(t *testing.T) {
t.Run("raw chain", func(t *testing.T) {
var c ape.Chain
b := []byte(encoded)
c.Raw = b
v2, ok := c.ToV2().GetKind().(*apeV2.ChainRaw)
require.True(t, ok)
require.Equal(t, b, v2.Raw)
})
}
func TestChainMessageV2(t *testing.T) {
b := []byte(encoded)
v2Raw := &apeV2.ChainRaw{}
v2Raw.SetRaw(b)
v2 := &apeV2.Chain{}
v2.SetKind(v2Raw)
var c ape.Chain
c.ReadFromV2(v2)
require.NotNil(t, c.Raw)
require.Equal(t, b, c.Raw)
}

BIN
ape/grpc/types_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,45 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package ape
func DoFuzzProtoChainTarget(data []byte) int {
msg := new(ChainTarget)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONChainTarget(data []byte) int {
msg := new(ChainTarget)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoChain(data []byte) int {
msg := new(Chain)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONChain(data []byte) int {
msg := new(Chain)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,31 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package ape
import (
testing "testing"
)
func FuzzProtoChainTarget(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoChainTarget(data)
})
}
func FuzzJSONChainTarget(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONChainTarget(data)
})
}
func FuzzProtoChain(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoChain(data)
})
}
func FuzzJSONChain(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONChain(data)
})
}

View file

@ -0,0 +1,104 @@
package accounting
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session"
)
type BalanceRequestBody struct {
ownerID *refs.OwnerID
}
type BalanceResponseBody struct {
bal *Decimal
}
type Decimal struct {
val int64
prec uint32
}
type BalanceRequest struct {
body *BalanceRequestBody
session.RequestHeaders
}
type BalanceResponse struct {
body *BalanceResponseBody
session.ResponseHeaders
}
func (b *BalanceRequestBody) GetOwnerID() *refs.OwnerID {
if b != nil {
return b.ownerID
}
return nil
}
func (b *BalanceRequestBody) SetOwnerID(v *refs.OwnerID) {
b.ownerID = v
}
func (b *BalanceRequest) GetBody() *BalanceRequestBody {
if b != nil {
return b.body
}
return nil
}
func (b *BalanceRequest) SetBody(v *BalanceRequestBody) {
b.body = v
}
func (d *Decimal) GetValue() int64 {
if d != nil {
return d.val
}
return 0
}
func (d *Decimal) SetValue(v int64) {
d.val = v
}
func (d *Decimal) GetPrecision() uint32 {
if d != nil {
return d.prec
}
return 0
}
func (d *Decimal) SetPrecision(v uint32) {
d.prec = v
}
func (br *BalanceResponseBody) GetBalance() *Decimal {
if br != nil {
return br.bal
}
return nil
}
func (br *BalanceResponseBody) SetBalance(v *Decimal) {
br.bal = v
}
func (br *BalanceResponse) GetBody() *BalanceResponseBody {
if br != nil {
return br.body
}
return nil
}
func (br *BalanceResponse) SetBody(v *BalanceResponseBody) {
br.body = v
}

178
api/accounting/convert.go Normal file
View file

@ -0,0 +1,178 @@
package accounting
import (
accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (b *BalanceRequestBody) ToGRPCMessage() grpc.Message {
var m *accounting.BalanceRequest_Body
if b != nil {
m = new(accounting.BalanceRequest_Body)
m.SetOwnerId(b.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID))
}
return m
}
func (b *BalanceRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*accounting.BalanceRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
ownerID := v.GetOwnerId()
if ownerID == nil {
b.ownerID = nil
} else {
if b.ownerID == nil {
b.ownerID = new(refs.OwnerID)
}
err = b.ownerID.FromGRPCMessage(ownerID)
}
return err
}
func (b *BalanceRequest) ToGRPCMessage() grpc.Message {
var m *accounting.BalanceRequest
if b != nil {
m = new(accounting.BalanceRequest)
m.SetBody(b.body.ToGRPCMessage().(*accounting.BalanceRequest_Body))
b.RequestHeaders.ToMessage(m)
}
return m
}
func (b *BalanceRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*accounting.BalanceRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
b.body = nil
} else {
if b.body == nil {
b.body = new(BalanceRequestBody)
}
err = b.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return b.RequestHeaders.FromMessage(v)
}
func (d *Decimal) ToGRPCMessage() grpc.Message {
var m *accounting.Decimal
if d != nil {
m = new(accounting.Decimal)
m.SetValue(d.val)
m.SetPrecision(d.prec)
}
return m
}
func (d *Decimal) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*accounting.Decimal)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
d.val = v.GetValue()
d.prec = v.GetPrecision()
return nil
}
func (br *BalanceResponseBody) ToGRPCMessage() grpc.Message {
var m *accounting.BalanceResponse_Body
if br != nil {
m = new(accounting.BalanceResponse_Body)
m.SetBalance(br.bal.ToGRPCMessage().(*accounting.Decimal))
}
return m
}
func (br *BalanceResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*accounting.BalanceResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
bal := v.GetBalance()
if bal == nil {
br.bal = nil
} else {
if br.bal == nil {
br.bal = new(Decimal)
}
err = br.bal.FromGRPCMessage(bal)
}
return err
}
func (br *BalanceResponse) ToGRPCMessage() grpc.Message {
var m *accounting.BalanceResponse
if br != nil {
m = new(accounting.BalanceResponse)
m.SetBody(br.body.ToGRPCMessage().(*accounting.BalanceResponse_Body))
br.ResponseHeaders.ToMessage(m)
}
return m
}
func (br *BalanceResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*accounting.BalanceResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
br.body = nil
} else {
if br.body == nil {
br.body = new(BalanceResponseBody)
}
err = br.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return br.ResponseHeaders.FromMessage(v)
}

BIN
api/accounting/grpc/service_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,45 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package accounting
func DoFuzzProtoBalanceRequest(data []byte) int {
msg := new(BalanceRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONBalanceRequest(data []byte) int {
msg := new(BalanceRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoBalanceResponse(data []byte) int {
msg := new(BalanceResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONBalanceResponse(data []byte) int {
msg := new(BalanceResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,31 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package accounting
import (
testing "testing"
)
func FuzzProtoBalanceRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoBalanceRequest(data)
})
}
func FuzzJSONBalanceRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONBalanceRequest(data)
})
}
func FuzzProtoBalanceResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoBalanceResponse(data)
})
}
func FuzzJSONBalanceResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONBalanceResponse(data)
})
}

BIN
api/accounting/grpc/service_grpc.pb.go generated Normal file

Binary file not shown.

BIN
api/accounting/grpc/types_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,26 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package accounting
func DoFuzzProtoDecimal(data []byte) int {
msg := new(Decimal)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONDecimal(data []byte) int {
msg := new(Decimal)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,21 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package accounting
import (
testing "testing"
)
func FuzzProtoDecimal(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoDecimal(data)
})
}
func FuzzJSONDecimal(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONDecimal(data)
})
}

14
api/accounting/json.go Normal file
View file

@ -0,0 +1,14 @@
package accounting
import (
accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (d *Decimal) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(d)
}
func (d *Decimal) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(d, data, new(accounting.Decimal))
}

104
api/accounting/marshal.go Normal file
View file

@ -0,0 +1,104 @@
package accounting
import (
accounting "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto"
)
const (
decimalValueField = 1
decimalPrecisionField = 2
balanceReqBodyOwnerField = 1
balanceRespBodyDecimalField = 1
)
func (d *Decimal) StableMarshal(buf []byte) []byte {
if d == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, d.StableSize())
}
var offset int
offset += protoutil.Int64Marshal(decimalValueField, buf[offset:], d.val)
protoutil.UInt32Marshal(decimalPrecisionField, buf[offset:], d.prec)
return buf
}
func (d *Decimal) StableSize() (size int) {
if d == nil {
return 0
}
size += protoutil.Int64Size(decimalValueField, d.val)
size += protoutil.UInt32Size(decimalPrecisionField, d.prec)
return size
}
func (d *Decimal) Unmarshal(data []byte) error {
return message.Unmarshal(d, data, new(accounting.Decimal))
}
func (b *BalanceRequestBody) StableMarshal(buf []byte) []byte {
if b == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, b.StableSize())
}
protoutil.NestedStructureMarshal(balanceReqBodyOwnerField, buf, b.ownerID)
return buf
}
func (b *BalanceRequestBody) StableSize() (size int) {
if b == nil {
return 0
}
size = protoutil.NestedStructureSize(balanceReqBodyOwnerField, b.ownerID)
return size
}
func (b *BalanceRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(b, data, new(accounting.BalanceRequest_Body))
}
func (br *BalanceResponseBody) StableMarshal(buf []byte) []byte {
if br == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, br.StableSize())
}
protoutil.NestedStructureMarshal(balanceRespBodyDecimalField, buf, br.bal)
return buf
}
func (br *BalanceResponseBody) StableSize() (size int) {
if br == nil {
return 0
}
size = protoutil.NestedStructureSize(balanceRespBodyDecimalField, br.bal)
return size
}
func (br *BalanceResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(br, data, new(accounting.BalanceResponse_Body))
}

View file

@ -0,0 +1,19 @@
package accounting_test
import (
"testing"
accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test"
)
func TestMessage(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return accountingtest.GenerateDecimal(empty) },
func(empty bool) message.Message { return accountingtest.GenerateBalanceRequestBody(empty) },
func(empty bool) message.Message { return accountingtest.GenerateBalanceRequest(empty) },
func(empty bool) message.Message { return accountingtest.GenerateBalanceResponseBody(empty) },
func(empty bool) message.Message { return accountingtest.GenerateBalanceResponse(empty) },
)
}

View file

@ -0,0 +1,64 @@
package accountingtest
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting"
accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test"
sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test"
)
func GenerateBalanceRequest(empty bool) *accounting.BalanceRequest {
m := new(accounting.BalanceRequest)
if !empty {
m.SetBody(GenerateBalanceRequestBody(false))
}
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
return m
}
func GenerateBalanceRequestBody(empty bool) *accounting.BalanceRequestBody {
m := new(accounting.BalanceRequestBody)
if !empty {
m.SetOwnerID(accountingtest.GenerateOwnerID(false))
}
return m
}
func GenerateBalanceResponse(empty bool) *accounting.BalanceResponse {
m := new(accounting.BalanceResponse)
if !empty {
m.SetBody(GenerateBalanceResponseBody(false))
}
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m
}
func GenerateBalanceResponseBody(empty bool) *accounting.BalanceResponseBody {
m := new(accounting.BalanceResponseBody)
if !empty {
m.SetBalance(GenerateDecimal(false))
}
return m
}
func GenerateDecimal(empty bool) *accounting.Decimal {
m := new(accounting.Decimal)
if !empty {
m.SetValue(1)
m.SetPrecision(2)
}
return m
}

51
api/acl/bench_test.go Normal file
View file

@ -0,0 +1,51 @@
package acl_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl"
aclGrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc"
acltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/test"
)
func BenchmarkTable_ToGRPCMessage(b *testing.B) {
const size = 4
tb := new(acl.Table)
rs := make([]acl.Record, size)
for i := range rs {
fs := make([]acl.HeaderFilter, size)
for j := range fs {
fs[j] = *acltest.GenerateFilter(false)
}
ts := make([]acl.Target, size)
for j := range ts {
ts[j] = *acltest.GenerateTarget(false)
}
rs[i].SetFilters(fs)
rs[i].SetTargets(ts)
}
tb.SetRecords(rs)
raw := tb.ToGRPCMessage()
b.Run("to grpc message", func(b *testing.B) {
b.ReportAllocs()
for range b.N {
raw := tb.ToGRPCMessage()
if len(tb.GetRecords()) != len(raw.(*aclGrpc.EACLTable).Records) {
b.FailNow()
}
}
})
b.Run("from grpc message", func(b *testing.B) {
b.ReportAllocs()
for range b.N {
tb := new(acl.Table)
if tb.FromGRPCMessage(raw) != nil {
b.FailNow()
}
}
})
}

592
api/acl/convert.go Normal file
View file

@ -0,0 +1,592 @@
package acl
import (
acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
apeGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
// RoleToGRPCField converts unified role enum into grpc enum.
func RoleToGRPCField(t Role) acl.Role {
switch t {
case RoleUser:
return acl.Role_USER
case RoleSystem:
return acl.Role_SYSTEM
case RoleOthers:
return acl.Role_OTHERS
default:
return acl.Role_ROLE_UNSPECIFIED
}
}
// RoleFromGRPCField converts grpc enum into unified role enum.
func RoleFromGRPCField(t acl.Role) Role {
switch t {
case acl.Role_USER:
return RoleUser
case acl.Role_SYSTEM:
return RoleSystem
case acl.Role_OTHERS:
return RoleOthers
default:
return RoleUnknown
}
}
// OperationToGRPCField converts unified operation enum into grpc enum.
func OperationToGRPCField(t Operation) acl.Operation {
switch t {
case OperationPut:
return acl.Operation_PUT
case OperationDelete:
return acl.Operation_DELETE
case OperationGet:
return acl.Operation_GET
case OperationHead:
return acl.Operation_HEAD
case OperationSearch:
return acl.Operation_SEARCH
case OperationRange:
return acl.Operation_GETRANGE
case OperationRangeHash:
return acl.Operation_GETRANGEHASH
default:
return acl.Operation_OPERATION_UNSPECIFIED
}
}
// OperationFromGRPCField converts grpc enum into unified operation enum.
func OperationFromGRPCField(t acl.Operation) Operation {
switch t {
case acl.Operation_PUT:
return OperationPut
case acl.Operation_DELETE:
return OperationDelete
case acl.Operation_GET:
return OperationGet
case acl.Operation_HEAD:
return OperationHead
case acl.Operation_SEARCH:
return OperationSearch
case acl.Operation_GETRANGE:
return OperationRange
case acl.Operation_GETRANGEHASH:
return OperationRangeHash
default:
return OperationUnknown
}
}
// ActionToGRPCField converts unified action enum into grpc enum.
func ActionToGRPCField(t Action) acl.Action {
switch t {
case ActionDeny:
return acl.Action_DENY
case ActionAllow:
return acl.Action_ALLOW
default:
return acl.Action_ACTION_UNSPECIFIED
}
}
// ActionFromGRPCField converts grpc enum into unified action enum.
func ActionFromGRPCField(t acl.Action) Action {
switch t {
case acl.Action_DENY:
return ActionDeny
case acl.Action_ALLOW:
return ActionAllow
default:
return ActionUnknown
}
}
// HeaderTypeToGRPCField converts unified header type enum into grpc enum.
func HeaderTypeToGRPCField(t HeaderType) acl.HeaderType {
switch t {
case HeaderTypeRequest:
return acl.HeaderType_REQUEST
case HeaderTypeObject:
return acl.HeaderType_OBJECT
case HeaderTypeService:
return acl.HeaderType_SERVICE
default:
return acl.HeaderType_HEADER_UNSPECIFIED
}
}
// HeaderTypeFromGRPCField converts grpc enum into unified header type enum.
func HeaderTypeFromGRPCField(t acl.HeaderType) HeaderType {
switch t {
case acl.HeaderType_REQUEST:
return HeaderTypeRequest
case acl.HeaderType_OBJECT:
return HeaderTypeObject
case acl.HeaderType_SERVICE:
return HeaderTypeService
default:
return HeaderTypeUnknown
}
}
// MatchTypeToGRPCField converts unified match type enum into grpc enum.
func MatchTypeToGRPCField(t MatchType) acl.MatchType {
switch t {
case MatchTypeStringEqual:
return acl.MatchType_STRING_EQUAL
case MatchTypeStringNotEqual:
return acl.MatchType_STRING_NOT_EQUAL
default:
return acl.MatchType_MATCH_TYPE_UNSPECIFIED
}
}
// MatchTypeFromGRPCField converts grpc enum into unified match type enum.
func MatchTypeFromGRPCField(t acl.MatchType) MatchType {
switch t {
case acl.MatchType_STRING_EQUAL:
return MatchTypeStringEqual
case acl.MatchType_STRING_NOT_EQUAL:
return MatchTypeStringNotEqual
default:
return MatchTypeUnknown
}
}
func (f *HeaderFilter) ToGRPCMessage() grpc.Message {
var m *acl.EACLRecord_Filter
if f != nil {
m = new(acl.EACLRecord_Filter)
m.SetKey(f.key)
m.SetValue(f.value)
m.SetHeaderType(HeaderTypeToGRPCField(f.hdrType))
m.SetMatchType(MatchTypeToGRPCField(f.matchType))
}
return m
}
func (f *HeaderFilter) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.EACLRecord_Filter)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
f.key = v.GetKey()
f.value = v.GetValue()
f.hdrType = HeaderTypeFromGRPCField(v.GetHeaderType())
f.matchType = MatchTypeFromGRPCField(v.GetMatchType())
return nil
}
func HeaderFiltersToGRPC(fs []HeaderFilter) (res []acl.EACLRecord_Filter) {
if fs != nil {
res = make([]acl.EACLRecord_Filter, 0, len(fs))
for i := range fs {
res = append(res, *fs[i].ToGRPCMessage().(*acl.EACLRecord_Filter))
}
}
return
}
func HeaderFiltersFromGRPC(fs []acl.EACLRecord_Filter) (res []HeaderFilter, err error) {
if fs != nil {
res = make([]HeaderFilter, len(fs))
for i := range fs {
err = res[i].FromGRPCMessage(&fs[i])
if err != nil {
return
}
}
}
return
}
func (t *Target) ToGRPCMessage() grpc.Message {
var m *acl.EACLRecord_Target
if t != nil {
m = new(acl.EACLRecord_Target)
m.SetRole(RoleToGRPCField(t.role))
m.SetKeys(t.keys)
}
return m
}
func (t *Target) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.EACLRecord_Target)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
t.role = RoleFromGRPCField(v.GetRole())
t.keys = v.GetKeys()
return nil
}
func TargetsToGRPC(ts []Target) (res []acl.EACLRecord_Target) {
if ts != nil {
res = make([]acl.EACLRecord_Target, 0, len(ts))
for i := range ts {
res = append(res, *ts[i].ToGRPCMessage().(*acl.EACLRecord_Target))
}
}
return
}
func TargetsFromGRPC(fs []acl.EACLRecord_Target) (res []Target, err error) {
if fs != nil {
res = make([]Target, len(fs))
for i := range fs {
err = res[i].FromGRPCMessage(&fs[i])
if err != nil {
return
}
}
}
return
}
func (r *Record) ToGRPCMessage() grpc.Message {
var m *acl.EACLRecord
if r != nil {
m = new(acl.EACLRecord)
m.SetOperation(OperationToGRPCField(r.op))
m.SetAction(ActionToGRPCField(r.action))
m.SetFilters(HeaderFiltersToGRPC(r.filters))
m.SetTargets(TargetsToGRPC(r.targets))
}
return m
}
func (r *Record) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.EACLRecord)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
r.filters, err = HeaderFiltersFromGRPC(v.GetFilters())
if err != nil {
return err
}
r.targets, err = TargetsFromGRPC(v.GetTargets())
if err != nil {
return err
}
r.op = OperationFromGRPCField(v.GetOperation())
r.action = ActionFromGRPCField(v.GetAction())
return nil
}
func RecordsToGRPC(ts []Record) (res []acl.EACLRecord) {
if ts != nil {
res = make([]acl.EACLRecord, 0, len(ts))
for i := range ts {
res = append(res, *ts[i].ToGRPCMessage().(*acl.EACLRecord))
}
}
return
}
func RecordsFromGRPC(fs []acl.EACLRecord) (res []Record, err error) {
if fs != nil {
res = make([]Record, len(fs))
for i := range fs {
err = res[i].FromGRPCMessage(&fs[i])
if err != nil {
return
}
}
}
return
}
func (t *Table) ToGRPCMessage() grpc.Message {
var m *acl.EACLTable
if t != nil {
m = new(acl.EACLTable)
m.SetVersion(t.version.ToGRPCMessage().(*refsGRPC.Version))
m.SetContainerId(t.cid.ToGRPCMessage().(*refsGRPC.ContainerID))
m.SetRecords(RecordsToGRPC(t.records))
}
return m
}
func (t *Table) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.EACLTable)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
cid := v.GetContainerId()
if cid == nil {
t.cid = nil
} else {
if t.cid == nil {
t.cid = new(refs.ContainerID)
}
err = t.cid.FromGRPCMessage(cid)
if err != nil {
return err
}
}
version := v.GetVersion()
if version == nil {
t.version = nil
} else {
if t.version == nil {
t.version = new(refs.Version)
}
err = t.version.FromGRPCMessage(version)
if err != nil {
return err
}
}
t.records, err = RecordsFromGRPC(v.GetRecords())
return err
}
func (l *TokenLifetime) ToGRPCMessage() grpc.Message {
var m *acl.BearerToken_Body_TokenLifetime
if l != nil {
m = new(acl.BearerToken_Body_TokenLifetime)
m.SetExp(l.exp)
m.SetIat(l.iat)
m.SetNbf(l.nbf)
}
return m
}
func (l *TokenLifetime) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.BearerToken_Body_TokenLifetime)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
l.exp = v.GetExp()
l.iat = v.GetIat()
l.nbf = v.GetNbf()
return nil
}
func (c *APEOverride) ToGRPCMessage() grpc.Message {
var m *acl.BearerToken_Body_APEOverride
if c != nil {
m = new(acl.BearerToken_Body_APEOverride)
m.SetTarget(c.target.ToGRPCMessage().(*apeGRPC.ChainTarget))
if len(c.chains) > 0 {
apeChains := make([]apeGRPC.Chain, len(c.chains))
for i := range c.chains {
apeChains[i] = *c.chains[i].ToGRPCMessage().(*apeGRPC.Chain)
}
m.SetChains(apeChains)
}
}
return m
}
func (c *APEOverride) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.BearerToken_Body_APEOverride)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
if targetGRPC := v.GetTarget(); targetGRPC != nil {
if c.target == nil {
c.target = new(ape.ChainTarget)
}
if err := c.target.FromGRPCMessage(v.GetTarget()); err != nil {
return err
}
}
if apeChains := v.GetChains(); len(apeChains) > 0 {
c.chains = make([]*ape.Chain, len(apeChains))
for i := range apeChains {
c.chains[i] = new(ape.Chain)
if err := c.chains[i].FromGRPCMessage(&apeChains[i]); err != nil {
return err
}
}
}
return nil
}
func (bt *BearerTokenBody) ToGRPCMessage() grpc.Message {
var m *acl.BearerToken_Body
if bt != nil {
m = new(acl.BearerToken_Body)
m.SetOwnerId(bt.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID))
m.SetLifetime(bt.lifetime.ToGRPCMessage().(*acl.BearerToken_Body_TokenLifetime))
m.SetEaclTable(bt.eacl.ToGRPCMessage().(*acl.EACLTable))
m.SetAllowImpersonate(bt.impersonate)
m.SetApeOverride(bt.apeOverride.ToGRPCMessage().(*acl.BearerToken_Body_APEOverride))
}
return m
}
func (bt *BearerTokenBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.BearerToken_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
ownerID := v.GetOwnerId()
if ownerID == nil {
bt.ownerID = nil
} else {
if bt.ownerID == nil {
bt.ownerID = new(refs.OwnerID)
}
err = bt.ownerID.FromGRPCMessage(ownerID)
if err != nil {
return err
}
}
lifetime := v.GetLifetime()
if lifetime == nil {
bt.lifetime = nil
} else {
if bt.lifetime == nil {
bt.lifetime = new(TokenLifetime)
}
err = bt.lifetime.FromGRPCMessage(lifetime)
if err != nil {
return err
}
}
eacl := v.GetEaclTable()
if eacl == nil {
bt.eacl = nil
} else {
if bt.eacl == nil {
bt.eacl = new(Table)
}
if err = bt.eacl.FromGRPCMessage(eacl); err != nil {
return err
}
}
if apeOverrideGRPC := v.GetApeOverride(); apeOverrideGRPC != nil {
if bt.apeOverride == nil {
bt.apeOverride = new(APEOverride)
}
err = bt.apeOverride.FromGRPCMessage(apeOverrideGRPC)
if err != nil {
return err
}
}
bt.impersonate = v.GetAllowImpersonate()
return err
}
func (bt *BearerToken) ToGRPCMessage() grpc.Message {
var m *acl.BearerToken
if bt != nil {
m = new(acl.BearerToken)
m.SetBody(bt.body.ToGRPCMessage().(*acl.BearerToken_Body))
m.SetSignature(bt.sig.ToGRPCMessage().(*refsGRPC.Signature))
}
return m
}
func (bt *BearerToken) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*acl.BearerToken)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
bt.body = nil
} else {
if bt.body == nil {
bt.body = new(BearerTokenBody)
}
err = bt.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
sig := v.GetSignature()
if sig == nil {
bt.sig = nil
} else {
if bt.sig == nil {
bt.sig = new(refs.Signature)
}
err = bt.sig.FromGRPCMessage(sig)
}
return err
}

33
api/acl/filters.go Normal file
View file

@ -0,0 +1,33 @@
package acl
// ObjectFilterPrefix is a prefix of key to object header value or property.
const ObjectFilterPrefix = "$Object:"
const (
// FilterObjectVersion is a filter key to "version" field of the object header.
FilterObjectVersion = ObjectFilterPrefix + "version"
// FilterObjectID is a filter key to "object_id" field of the object.
FilterObjectID = ObjectFilterPrefix + "objectID"
// FilterObjectContainerID is a filter key to "container_id" field of the object header.
FilterObjectContainerID = ObjectFilterPrefix + "containerID"
// FilterObjectOwnerID is a filter key to "owner_id" field of the object header.
FilterObjectOwnerID = ObjectFilterPrefix + "ownerID"
// FilterObjectCreationEpoch is a filter key to "creation_epoch" field of the object header.
FilterObjectCreationEpoch = ObjectFilterPrefix + "creationEpoch"
// FilterObjectPayloadLength is a filter key to "payload_length" field of the object header.
FilterObjectPayloadLength = ObjectFilterPrefix + "payloadLength"
// FilterObjectPayloadHash is a filter key to "payload_hash" field of the object header.
FilterObjectPayloadHash = ObjectFilterPrefix + "payloadHash"
// FilterObjectType is a filter key to "object_type" field of the object header.
FilterObjectType = ObjectFilterPrefix + "objectType"
// FilterObjectHomomorphicHash is a filter key to "homomorphic_hash" field of the object header.
FilterObjectHomomorphicHash = ObjectFilterPrefix + "homomorphicHash"
)

BIN
api/acl/grpc/types_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,64 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package acl
func DoFuzzProtoEACLRecord(data []byte) int {
msg := new(EACLRecord)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONEACLRecord(data []byte) int {
msg := new(EACLRecord)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoEACLTable(data []byte) int {
msg := new(EACLTable)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONEACLTable(data []byte) int {
msg := new(EACLTable)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoBearerToken(data []byte) int {
msg := new(BearerToken)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONBearerToken(data []byte) int {
msg := new(BearerToken)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,41 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package acl
import (
testing "testing"
)
func FuzzProtoEACLRecord(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoEACLRecord(data)
})
}
func FuzzJSONEACLRecord(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONEACLRecord(data)
})
}
func FuzzProtoEACLTable(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoEACLTable(data)
})
}
func FuzzJSONEACLTable(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONEACLTable(data)
})
}
func FuzzProtoBearerToken(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoBearerToken(data)
})
}
func FuzzJSONBearerToken(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONBearerToken(data)
})
}

70
api/acl/json.go Normal file
View file

@ -0,0 +1,70 @@
package acl
import (
acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (f *HeaderFilter) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(f)
}
func (f *HeaderFilter) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(f, data, new(acl.EACLRecord_Filter))
}
func (t *Target) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(t)
}
func (t *Target) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(t, data, new(acl.EACLRecord_Target))
}
func (a *APEOverride) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(a)
}
func (a *APEOverride) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(a, data, new(acl.BearerToken_Body_APEOverride))
}
func (r *Record) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(r)
}
func (r *Record) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(r, data, new(acl.EACLRecord))
}
func (t *Table) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(t)
}
func (t *Table) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(t, data, new(acl.EACLTable))
}
func (l *TokenLifetime) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(l)
}
func (l *TokenLifetime) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(l, data, new(acl.BearerToken_Body_TokenLifetime))
}
func (bt *BearerTokenBody) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(bt)
}
func (bt *BearerTokenBody) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(bt, data, new(acl.BearerToken_Body))
}
func (bt *BearerToken) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(bt)
}
func (bt *BearerToken) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(bt, data, new(acl.BearerToken))
}

350
api/acl/marshal.go Normal file
View file

@ -0,0 +1,350 @@
package acl
import (
acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto"
)
const (
filterHeaderTypeField = 1
filterMatchTypeField = 2
filterNameField = 3
filterValueField = 4
targetTypeField = 1
targetKeysField = 2
recordOperationField = 1
recordActionField = 2
recordFiltersField = 3
recordTargetsField = 4
tableVersionField = 1
tableContainerIDField = 2
tableRecordsField = 3
lifetimeExpirationField = 1
lifetimeNotValidBeforeField = 2
lifetimeIssuedAtField = 3
tokenAPEChainsTargetField = 1
tokenAPEChainsChainsField = 2
bearerTokenBodyACLField = 1
bearerTokenBodyOwnerField = 2
bearerTokenBodyLifetimeField = 3
bearerTokenBodyImpersonate = 4
bearerTokenTokenAPEChainsField = 5
bearerTokenBodyField = 1
bearerTokenSignatureField = 2
)
// StableMarshal marshals unified acl table structure in a protobuf
// compatible way without field order shuffle.
func (t *Table) StableMarshal(buf []byte) []byte {
if t == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, t.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(tableVersionField, buf[offset:], t.version)
offset += protoutil.NestedStructureMarshal(tableContainerIDField, buf[offset:], t.cid)
for i := range t.records {
offset += protoutil.NestedStructureMarshal(tableRecordsField, buf[offset:], &t.records[i])
}
return buf
}
// StableSize of acl table structure marshalled by StableMarshal function.
func (t *Table) StableSize() (size int) {
if t == nil {
return 0
}
size += protoutil.NestedStructureSize(tableVersionField, t.version)
size += protoutil.NestedStructureSize(tableContainerIDField, t.cid)
for i := range t.records {
size += protoutil.NestedStructureSize(tableRecordsField, &t.records[i])
}
return size
}
func (t *Table) Unmarshal(data []byte) error {
return message.Unmarshal(t, data, new(acl.EACLTable))
}
// StableMarshal marshals unified acl record structure in a protobuf
// compatible way without field order shuffle.
func (r *Record) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
var offset int
offset += protoutil.EnumMarshal(recordOperationField, buf[offset:], int32(r.op))
offset += protoutil.EnumMarshal(recordActionField, buf[offset:], int32(r.action))
for i := range r.filters {
offset += protoutil.NestedStructureMarshal(recordFiltersField, buf[offset:], &r.filters[i])
}
for i := range r.targets {
offset += protoutil.NestedStructureMarshal(recordTargetsField, buf[offset:], &r.targets[i])
}
return buf
}
// StableSize of acl record structure marshalled by StableMarshal function.
func (r *Record) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.EnumSize(recordOperationField, int32(r.op))
size += protoutil.EnumSize(recordActionField, int32(r.action))
for i := range r.filters {
size += protoutil.NestedStructureSize(recordFiltersField, &r.filters[i])
}
for i := range r.targets {
size += protoutil.NestedStructureSize(recordTargetsField, &r.targets[i])
}
return size
}
func (r *Record) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(acl.EACLRecord))
}
// StableMarshal marshals unified header filter structure in a protobuf
// compatible way without field order shuffle.
func (f *HeaderFilter) StableMarshal(buf []byte) []byte {
if f == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, f.StableSize())
}
var offset int
offset += protoutil.EnumMarshal(filterHeaderTypeField, buf[offset:], int32(f.hdrType))
offset += protoutil.EnumMarshal(filterMatchTypeField, buf[offset:], int32(f.matchType))
offset += protoutil.StringMarshal(filterNameField, buf[offset:], f.key)
protoutil.StringMarshal(filterValueField, buf[offset:], f.value)
return buf
}
// StableSize of header filter structure marshalled by StableMarshal function.
func (f *HeaderFilter) StableSize() (size int) {
if f == nil {
return 0
}
size += protoutil.EnumSize(filterHeaderTypeField, int32(f.hdrType))
size += protoutil.EnumSize(filterMatchTypeField, int32(f.matchType))
size += protoutil.StringSize(filterNameField, f.key)
size += protoutil.StringSize(filterValueField, f.value)
return size
}
func (f *HeaderFilter) Unmarshal(data []byte) error {
return message.Unmarshal(f, data, new(acl.EACLRecord_Filter))
}
// StableMarshal marshals unified role info structure in a protobuf
// compatible way without field order shuffle.
func (t *Target) StableMarshal(buf []byte) []byte {
if t == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, t.StableSize())
}
var offset int
offset += protoutil.EnumMarshal(targetTypeField, buf[offset:], int32(t.role))
protoutil.RepeatedBytesMarshal(targetKeysField, buf[offset:], t.keys)
return buf
}
// StableSize of role info structure marshalled by StableMarshal function.
func (t *Target) StableSize() (size int) {
if t == nil {
return 0
}
size += protoutil.EnumSize(targetTypeField, int32(t.role))
size += protoutil.RepeatedBytesSize(targetKeysField, t.keys)
return size
}
func (t *Target) Unmarshal(data []byte) error {
return message.Unmarshal(t, data, new(acl.EACLRecord_Target))
}
func (l *TokenLifetime) StableMarshal(buf []byte) []byte {
if l == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, l.StableSize())
}
var offset int
offset += protoutil.UInt64Marshal(lifetimeExpirationField, buf[offset:], l.exp)
offset += protoutil.UInt64Marshal(lifetimeNotValidBeforeField, buf[offset:], l.nbf)
protoutil.UInt64Marshal(lifetimeIssuedAtField, buf[offset:], l.iat)
return buf
}
func (l *TokenLifetime) StableSize() (size int) {
if l == nil {
return 0
}
size += protoutil.UInt64Size(lifetimeExpirationField, l.exp)
size += protoutil.UInt64Size(lifetimeNotValidBeforeField, l.nbf)
size += protoutil.UInt64Size(lifetimeIssuedAtField, l.iat)
return size
}
func (l *TokenLifetime) Unmarshal(data []byte) error {
return message.Unmarshal(l, data, new(acl.BearerToken_Body_TokenLifetime))
}
func (c *APEOverride) StableMarshal(buf []byte) []byte {
if c == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, c.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(tokenAPEChainsTargetField, buf[offset:], c.target)
for i := range c.chains {
offset += protoutil.NestedStructureMarshal(tokenAPEChainsChainsField, buf[offset:], c.chains[i])
}
return buf
}
func (c *APEOverride) StableSize() (size int) {
if c == nil {
return 0
}
size += protoutil.NestedStructureSize(tokenAPEChainsTargetField, c.target)
for i := range c.chains {
size += protoutil.NestedStructureSize(tokenAPEChainsChainsField, c.chains[i])
}
return size
}
func (c *APEOverride) Unmarshal(data []byte) error {
return message.Unmarshal(c, data, new(acl.BearerToken_Body_APEOverride))
}
func (bt *BearerTokenBody) StableMarshal(buf []byte) []byte {
if bt == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, bt.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(bearerTokenBodyACLField, buf[offset:], bt.eacl)
offset += protoutil.NestedStructureMarshal(bearerTokenBodyOwnerField, buf[offset:], bt.ownerID)
offset += protoutil.NestedStructureMarshal(bearerTokenBodyLifetimeField, buf[offset:], bt.lifetime)
offset += protoutil.BoolMarshal(bearerTokenBodyImpersonate, buf[offset:], bt.impersonate)
protoutil.NestedStructureMarshal(bearerTokenTokenAPEChainsField, buf[offset:], bt.apeOverride)
return buf
}
func (bt *BearerTokenBody) StableSize() (size int) {
if bt == nil {
return 0
}
size += protoutil.NestedStructureSize(bearerTokenBodyACLField, bt.eacl)
size += protoutil.NestedStructureSize(bearerTokenBodyOwnerField, bt.ownerID)
size += protoutil.NestedStructureSize(bearerTokenBodyLifetimeField, bt.lifetime)
size += protoutil.BoolSize(bearerTokenBodyImpersonate, bt.impersonate)
size += protoutil.NestedStructureSize(bearerTokenTokenAPEChainsField, bt.apeOverride)
return size
}
func (bt *BearerTokenBody) Unmarshal(data []byte) error {
return message.Unmarshal(bt, data, new(acl.BearerToken_Body))
}
func (bt *BearerToken) StableMarshal(buf []byte) []byte {
if bt == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, bt.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(bearerTokenBodyField, buf[offset:], bt.body)
protoutil.NestedStructureMarshal(bearerTokenSignatureField, buf[offset:], bt.sig)
return buf
}
func (bt *BearerToken) StableSize() (size int) {
if bt == nil {
return 0
}
size += protoutil.NestedStructureSize(bearerTokenBodyField, bt.body)
size += protoutil.NestedStructureSize(bearerTokenSignatureField, bt.sig)
return size
}
func (bt *BearerToken) Unmarshal(data []byte) error {
return message.Unmarshal(bt, data, new(acl.BearerToken))
}

21
api/acl/message_test.go Normal file
View file

@ -0,0 +1,21 @@
package acl_test
import (
"testing"
acltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test"
)
func TestMessageConvert(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return acltest.GenerateFilter(empty) },
func(empty bool) message.Message { return acltest.GenerateTarget(empty) },
func(empty bool) message.Message { return acltest.GenerateRecord(empty) },
func(empty bool) message.Message { return acltest.GenerateTable(empty) },
func(empty bool) message.Message { return acltest.GenerateTokenLifetime(empty) },
func(empty bool) message.Message { return acltest.GenerateBearerTokenBody(empty) },
func(empty bool) message.Message { return acltest.GenerateBearerToken(empty) },
)
}

110
api/acl/string.go Normal file
View file

@ -0,0 +1,110 @@
package acl
import (
acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl/grpc"
)
// String returns string representation of Action.
func (x Action) String() string {
return ActionToGRPCField(x).String()
}
// FromString parses Action from a string representation.
// It is a reverse action to String().
//
// Returns true if s was parsed successfully.
func (x *Action) FromString(s string) bool {
var g acl.Action
ok := g.FromString(s)
if ok {
*x = ActionFromGRPCField(g)
}
return ok
}
// String returns string representation of Role.
func (x Role) String() string {
return RoleToGRPCField(x).String()
}
// FromString parses Role from a string representation.
// It is a reverse action to String().
//
// Returns true if s was parsed successfully.
func (x *Role) FromString(s string) bool {
var g acl.Role
ok := g.FromString(s)
if ok {
*x = RoleFromGRPCField(g)
}
return ok
}
// String returns string representation of Operation.
func (x Operation) String() string {
return OperationToGRPCField(x).String()
}
// FromString parses Operation from a string representation.
// It is a reverse action to String().
//
// Returns true if s was parsed successfully.
func (x *Operation) FromString(s string) bool {
var g acl.Operation
ok := g.FromString(s)
if ok {
*x = OperationFromGRPCField(g)
}
return ok
}
// String returns string representation of MatchType.
func (x MatchType) String() string {
return MatchTypeToGRPCField(x).String()
}
// FromString parses MatchType from a string representation.
// It is a reverse action to String().
//
// Returns true if s was parsed successfully.
func (x *MatchType) FromString(s string) bool {
var g acl.MatchType
ok := g.FromString(s)
if ok {
*x = MatchTypeFromGRPCField(g)
}
return ok
}
// String returns string representation of HeaderType.
func (x HeaderType) String() string {
return HeaderTypeToGRPCField(x).String()
}
// FromString parses HeaderType from a string representation.
// It is a reverse action to String().
//
// Returns true if s was parsed successfully.
func (x *HeaderType) FromString(s string) bool {
var g acl.HeaderType
ok := g.FromString(s)
if ok {
*x = HeaderTypeFromGRPCField(g)
}
return ok
}

144
api/acl/test/generate.go Normal file
View file

@ -0,0 +1,144 @@
package acltest
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl"
apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/test"
accountingtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test"
)
func GenerateBearerToken(empty bool) *acl.BearerToken {
m := new(acl.BearerToken)
if !empty {
m.SetBody(GenerateBearerTokenBody(false))
}
m.SetSignature(accountingtest.GenerateSignature(empty))
return m
}
func GenerateBearerTokenBody(empty bool) *acl.BearerTokenBody {
m := new(acl.BearerTokenBody)
if !empty {
m.SetOwnerID(accountingtest.GenerateOwnerID(false))
m.SetLifetime(GenerateTokenLifetime(false))
m.SetAPEOverride(GenerateAPEOverride(empty))
}
return m
}
func GenerateAPEOverride(empty bool) *acl.APEOverride {
var m *acl.APEOverride
if !empty {
m = new(acl.APEOverride)
m.SetTarget(apetest.GenerateChainTarget(empty))
m.SetChains(apetest.GenerateRawChains(false, 3))
}
return m
}
func GenerateTable(empty bool) *acl.Table {
m := new(acl.Table)
if !empty {
m.SetRecords(GenerateRecords(false))
m.SetContainerID(accountingtest.GenerateContainerID(false))
}
m.SetVersion(accountingtest.GenerateVersion(empty))
return m
}
func GenerateRecords(empty bool) []acl.Record {
var rs []acl.Record
if !empty {
rs = append(rs,
*GenerateRecord(false),
*GenerateRecord(false),
)
}
return rs
}
func GenerateRecord(empty bool) *acl.Record {
m := new(acl.Record)
if !empty {
m.SetAction(acl.ActionAllow)
m.SetOperation(acl.OperationGet)
m.SetFilters(GenerateFilters(false))
m.SetTargets(GenerateTargets(false))
}
return m
}
func GenerateFilters(empty bool) []acl.HeaderFilter {
var fs []acl.HeaderFilter
if !empty {
fs = append(fs,
*GenerateFilter(false),
*GenerateFilter(false),
)
}
return fs
}
func GenerateFilter(empty bool) *acl.HeaderFilter {
m := new(acl.HeaderFilter)
if !empty {
m.SetKey("key")
m.SetValue("val")
m.SetHeaderType(acl.HeaderTypeRequest)
m.SetMatchType(acl.MatchTypeStringEqual)
}
return m
}
func GenerateTargets(empty bool) []acl.Target {
var ts []acl.Target
if !empty {
ts = append(ts,
*GenerateTarget(false),
*GenerateTarget(false),
)
}
return ts
}
func GenerateTarget(empty bool) *acl.Target {
m := new(acl.Target)
if !empty {
m.SetRole(acl.RoleSystem)
m.SetKeys([][]byte{{1}, {2}})
}
return m
}
func GenerateTokenLifetime(empty bool) *acl.TokenLifetime {
m := new(acl.TokenLifetime)
if !empty {
m.SetExp(1)
m.SetIat(2)
m.SetExp(3)
}
return m
}

426
api/acl/types.go Normal file
View file

@ -0,0 +1,426 @@
package acl
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
)
// HeaderFilter is a unified structure of FilterInfo
// message from proto definition.
type HeaderFilter struct {
hdrType HeaderType
matchType MatchType
key, value string
}
// Target is a unified structure of Target
// message from proto definition.
type Target struct {
role Role
keys [][]byte
}
// Record is a unified structure of EACLRecord
// message from proto definition.
type Record struct {
op Operation
action Action
filters []HeaderFilter
targets []Target
}
// Table is a unified structure of EACLTable
// message from proto definition.
type Table struct {
version *refs.Version
cid *refs.ContainerID
records []Record
}
type TokenLifetime struct {
exp, nbf, iat uint64
}
type APEOverride struct {
target *ape.ChainTarget
chains []*ape.Chain
}
type BearerTokenBody struct {
eacl *Table
ownerID *refs.OwnerID
lifetime *TokenLifetime
apeOverride *APEOverride
impersonate bool
}
type BearerToken struct {
body *BearerTokenBody
sig *refs.Signature
}
// Target is a unified enum of MatchType enum from proto definition.
type MatchType uint32
// HeaderType is a unified enum of HeaderType enum from proto definition.
type HeaderType uint32
// Action is a unified enum of Action enum from proto definition.
type Action uint32
// Operation is a unified enum of Operation enum from proto definition.
type Operation uint32
// Role is a unified enum of Role enum from proto definition.
type Role uint32
const (
MatchTypeUnknown MatchType = iota
MatchTypeStringEqual
MatchTypeStringNotEqual
)
const (
HeaderTypeUnknown HeaderType = iota
HeaderTypeRequest
HeaderTypeObject
HeaderTypeService
)
const (
ActionUnknown Action = iota
ActionAllow
ActionDeny
)
const (
OperationUnknown Operation = iota
OperationGet
OperationHead
OperationPut
OperationDelete
OperationSearch
OperationRange
OperationRangeHash
)
const (
RoleUnknown Role = iota
RoleUser
RoleSystem
RoleOthers
)
func (f *HeaderFilter) GetHeaderType() HeaderType {
if f != nil {
return f.hdrType
}
return HeaderTypeUnknown
}
func (f *HeaderFilter) SetHeaderType(v HeaderType) {
f.hdrType = v
}
func (f *HeaderFilter) GetMatchType() MatchType {
if f != nil {
return f.matchType
}
return MatchTypeUnknown
}
func (f *HeaderFilter) SetMatchType(v MatchType) {
f.matchType = v
}
func (f *HeaderFilter) GetKey() string {
if f != nil {
return f.key
}
return ""
}
func (f *HeaderFilter) SetKey(v string) {
f.key = v
}
func (f *HeaderFilter) GetValue() string {
if f != nil {
return f.value
}
return ""
}
func (f *HeaderFilter) SetValue(v string) {
f.value = v
}
func (t *Target) GetRole() Role {
if t != nil {
return t.role
}
return RoleUnknown
}
func (t *Target) SetRole(v Role) {
t.role = v
}
func (t *Target) GetKeys() [][]byte {
if t != nil {
return t.keys
}
return nil
}
func (t *Target) SetKeys(v [][]byte) {
t.keys = v
}
func (r *Record) GetOperation() Operation {
if r != nil {
return r.op
}
return OperationUnknown
}
func (r *Record) SetOperation(v Operation) {
r.op = v
}
func (r *Record) GetAction() Action {
if r != nil {
return r.action
}
return ActionUnknown
}
func (r *Record) SetAction(v Action) {
r.action = v
}
func (r *Record) GetFilters() []HeaderFilter {
if r != nil {
return r.filters
}
return nil
}
func (r *Record) SetFilters(v []HeaderFilter) {
r.filters = v
}
func (r *Record) GetTargets() []Target {
if r != nil {
return r.targets
}
return nil
}
func (r *Record) SetTargets(v []Target) {
r.targets = v
}
func (t *Table) GetVersion() *refs.Version {
if t != nil {
return t.version
}
return nil
}
func (t *Table) SetVersion(v *refs.Version) {
t.version = v
}
func (t *Table) GetContainerID() *refs.ContainerID {
if t != nil {
return t.cid
}
return nil
}
func (t *Table) SetContainerID(v *refs.ContainerID) {
t.cid = v
}
func (t *Table) GetRecords() []Record {
if t != nil {
return t.records
}
return nil
}
func (t *Table) SetRecords(v []Record) {
t.records = v
}
func (l *TokenLifetime) GetExp() uint64 {
if l != nil {
return l.exp
}
return 0
}
func (l *TokenLifetime) SetExp(v uint64) {
l.exp = v
}
func (l *TokenLifetime) GetNbf() uint64 {
if l != nil {
return l.nbf
}
return 0
}
func (l *TokenLifetime) SetNbf(v uint64) {
l.nbf = v
}
func (l *TokenLifetime) GetIat() uint64 {
if l != nil {
return l.iat
}
return 0
}
func (l *TokenLifetime) SetIat(v uint64) {
l.iat = v
}
func (bt *BearerTokenBody) GetEACL() *Table {
if bt != nil {
return bt.eacl
}
return nil
}
func (bt *BearerTokenBody) SetEACL(v *Table) {
bt.eacl = v
}
func (t *APEOverride) GetTarget() *ape.ChainTarget {
if t == nil {
return nil
}
return t.target
}
func (t *APEOverride) GetChains() []*ape.Chain {
if t == nil {
return nil
}
return t.chains
}
func (t *APEOverride) SetTarget(v *ape.ChainTarget) {
t.target = v
}
func (t *APEOverride) SetChains(v []*ape.Chain) {
t.chains = v
}
func (bt *BearerTokenBody) GetAPEOverride() *APEOverride {
if bt != nil {
return bt.apeOverride
}
return nil
}
func (bt *BearerTokenBody) SetAPEOverride(v *APEOverride) {
bt.apeOverride = v
}
func (bt *BearerTokenBody) GetOwnerID() *refs.OwnerID {
if bt != nil {
return bt.ownerID
}
return nil
}
func (bt *BearerTokenBody) SetOwnerID(v *refs.OwnerID) {
bt.ownerID = v
}
func (bt *BearerTokenBody) GetLifetime() *TokenLifetime {
if bt != nil {
return bt.lifetime
}
return nil
}
func (bt *BearerTokenBody) SetLifetime(v *TokenLifetime) {
bt.lifetime = v
}
func (bt *BearerTokenBody) GetImpersonate() bool {
if bt != nil {
return bt.impersonate
}
return false
}
func (bt *BearerTokenBody) SetImpersonate(v bool) {
bt.impersonate = v
}
func (bt *BearerToken) GetBody() *BearerTokenBody {
if bt != nil {
return bt.body
}
return nil
}
func (bt *BearerToken) SetBody(v *BearerTokenBody) {
bt.body = v
}
func (bt *BearerToken) GetSignature() *refs.Signature {
if bt != nil {
return bt.sig
}
return nil
}
func (bt *BearerToken) SetSignature(v *refs.Signature) {
bt.sig = v
}

132
api/ape/convert.go Normal file
View file

@ -0,0 +1,132 @@
package ape
import (
"fmt"
ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func TargetTypeToGRPCField(typ TargetType) ape.TargetType {
switch typ {
case TargetTypeNamespace:
return ape.TargetType_NAMESPACE
case TargetTypeContainer:
return ape.TargetType_CONTAINER
case TargetTypeUser:
return ape.TargetType_USER
case TargetTypeGroup:
return ape.TargetType_GROUP
default:
return ape.TargetType_UNDEFINED
}
}
func TargetTypeFromGRPCField(typ ape.TargetType) TargetType {
switch typ {
case ape.TargetType_NAMESPACE:
return TargetTypeNamespace
case ape.TargetType_CONTAINER:
return TargetTypeContainer
case ape.TargetType_USER:
return TargetTypeUser
case ape.TargetType_GROUP:
return TargetTypeGroup
default:
return TargetTypeUndefined
}
}
func TargetTypeToGRPC(typ TargetType) ape.TargetType {
return ape.TargetType(typ)
}
func TargetTypeFromGRPC(typ ape.TargetType) TargetType {
return TargetType(typ)
}
func (v2 *ChainTarget) ToGRPCMessage() grpc.Message {
var mgrpc *ape.ChainTarget
if v2 != nil {
mgrpc = new(ape.ChainTarget)
mgrpc.SetType(TargetTypeToGRPC(v2.GetTargetType()))
mgrpc.SetName(v2.GetName())
}
return mgrpc
}
func (v2 *ChainTarget) FromGRPCMessage(m grpc.Message) error {
mgrpc, ok := m.(*ape.ChainTarget)
if !ok {
return message.NewUnexpectedMessageType(m, mgrpc)
}
v2.SetTargetType(TargetTypeFromGRPC(mgrpc.GetType()))
v2.SetName(mgrpc.GetName())
return nil
}
func (v2 *ChainRaw) ToGRPCMessage() grpc.Message {
var mgrpc *ape.Chain_Raw
if v2 != nil {
mgrpc = new(ape.Chain_Raw)
mgrpc.SetRaw(v2.GetRaw())
}
return mgrpc
}
func (v2 *ChainRaw) FromGRPCMessage(m grpc.Message) error {
mgrpc, ok := m.(*ape.Chain_Raw)
if !ok {
return message.NewUnexpectedMessageType(m, mgrpc)
}
v2.SetRaw(mgrpc.GetRaw())
return nil
}
func (v2 *Chain) ToGRPCMessage() grpc.Message {
var mgrpc *ape.Chain
if v2 != nil {
mgrpc = new(ape.Chain)
switch chainKind := v2.GetKind().(type) {
default:
panic(fmt.Sprintf("unsupported chain kind: %T", chainKind))
case *ChainRaw:
mgrpc.SetKind(chainKind.ToGRPCMessage().(*ape.Chain_Raw))
}
}
return mgrpc
}
func (v2 *Chain) FromGRPCMessage(m grpc.Message) error {
mgrpc, ok := m.(*ape.Chain)
if !ok {
return message.NewUnexpectedMessageType(m, mgrpc)
}
switch chainKind := mgrpc.GetKind().(type) {
default:
return fmt.Errorf("unsupported chain kind: %T", chainKind)
case *ape.Chain_Raw:
chainRaw := new(ChainRaw)
if err := chainRaw.FromGRPCMessage(chainKind); err != nil {
return err
}
v2.SetKind(chainRaw)
}
return nil
}

BIN
api/ape/grpc/types_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,45 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package ape
func DoFuzzProtoChainTarget(data []byte) int {
msg := new(ChainTarget)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONChainTarget(data []byte) int {
msg := new(ChainTarget)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoChain(data []byte) int {
msg := new(Chain)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONChain(data []byte) int {
msg := new(Chain)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,31 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package ape
import (
testing "testing"
)
func FuzzProtoChainTarget(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoChainTarget(data)
})
}
func FuzzJSONChainTarget(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONChainTarget(data)
})
}
func FuzzProtoChain(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoChain(data)
})
}
func FuzzJSONChain(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONChain(data)
})
}

14
api/ape/json.go Normal file
View file

@ -0,0 +1,14 @@
package ape
import (
ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (t *ChainTarget) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(t)
}
func (t *ChainTarget) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(t, data, new(ape.ChainTarget))
}

92
api/ape/marshal.go Normal file
View file

@ -0,0 +1,92 @@
package ape
import (
"fmt"
ape "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto"
)
const (
chainTargetTargetTypeField = 1
chainTargetNameField = 2
chainRawField = 1
)
func (t *ChainTarget) StableSize() (size int) {
if t == nil {
return 0
}
size += proto.EnumSize(chainTargetTargetTypeField, int32(t.targeType))
size += proto.StringSize(chainTargetNameField, t.name)
return size
}
func (t *ChainTarget) StableMarshal(buf []byte) []byte {
if t == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, t.StableSize())
}
var offset int
offset += proto.EnumMarshal(chainTargetTargetTypeField, buf[offset:], int32(t.targeType))
proto.StringMarshal(chainTargetNameField, buf[offset:], t.name)
return buf
}
func (t *ChainTarget) Unmarshal(data []byte) error {
return message.Unmarshal(t, data, new(ape.ChainTarget))
}
func (c *Chain) StableSize() (size int) {
if c == nil {
return 0
}
switch v := c.GetKind().(type) {
case *ChainRaw:
if v != nil {
size += proto.BytesSize(chainRawField, v.GetRaw())
}
default:
panic(fmt.Sprintf("unsupported chain kind: %T", v))
}
return size
}
func (c *Chain) StableMarshal(buf []byte) []byte {
if c == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, c.StableSize())
}
var offset int
switch v := c.GetKind().(type) {
case *ChainRaw:
if v != nil {
proto.BytesMarshal(chainRawField, buf[offset:], v.GetRaw())
}
default:
panic(fmt.Sprintf("unsupported chain kind: %T", v))
}
return buf
}
func (c *Chain) Unmarshal(data []byte) error {
return message.Unmarshal(c, data, new(ape.Chain))
}

15
api/ape/message_test.go Normal file
View file

@ -0,0 +1,15 @@
package ape_test
import (
"testing"
apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test"
)
func TestMessageConvert(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return apetest.GenerateChainTarget(empty) },
)
}

18
api/ape/string.go Normal file
View file

@ -0,0 +1,18 @@
package ape
import (
apegrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc"
)
func (tt TargetType) String() string {
return TargetTypeToGRPCField(tt).String()
}
func (tt *TargetType) FromString(s string) bool {
i, ok := apegrpc.TargetType_value[s]
if ok {
*tt = TargetType(i)
}
return ok
}

71
api/ape/test/generate.go Normal file
View file

@ -0,0 +1,71 @@
package test
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
)
func GenerateRawChains(empty bool, n int) []*ape.Chain {
if empty {
return []*ape.Chain{}
}
res := make([]*ape.Chain, n)
for i := range res {
res[i] = GenerateRawChain(empty)
}
return res
}
func GenerateRawChain(empty bool) *ape.Chain {
chRaw := new(ape.ChainRaw)
if empty {
chRaw.SetRaw([]byte("{}"))
} else {
chRaw.SetRaw([]byte(`{
"ID": "",
"Rules": [
{
"Status": "Allow",
"Actions": {
"Inverted": false,
"Names": [
"GetObject"
]
},
"Resources": {
"Inverted": false,
"Names": [
"native:object/*"
]
},
"Any": false,
"Condition": [
{
"Op": "StringEquals",
"Object": "Resource",
"Key": "Department",
"Value": "HR"
}
]
}
],
"MatchType": "DenyPriority"
}`))
}
ch := new(ape.Chain)
ch.SetKind(chRaw)
return ch
}
func GenerateChainTarget(empty bool) *ape.ChainTarget {
m := new(ape.ChainTarget)
if !empty {
m.SetTargetType(ape.TargetTypeContainer)
m.SetName("BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R")
}
return m
}

79
api/ape/types.go Normal file
View file

@ -0,0 +1,79 @@
package ape
type TargetType uint32
const (
TargetTypeUndefined TargetType = iota
TargetTypeNamespace
TargetTypeContainer
TargetTypeUser
TargetTypeGroup
)
type ChainTarget struct {
targeType TargetType
name string
}
func (ct *ChainTarget) SetTargetType(targeType TargetType) {
ct.targeType = targeType
}
func (ct *ChainTarget) SetName(name string) {
ct.name = name
}
func (ct *ChainTarget) GetTargetType() TargetType {
if ct != nil {
return ct.targeType
}
return 0
}
func (ct *ChainTarget) GetName() string {
if ct != nil {
return ct.name
}
return ""
}
type chainKind interface {
isChainKind()
}
type Chain struct {
kind chainKind
}
func (c *Chain) SetKind(kind chainKind) {
c.kind = kind
}
func (c *Chain) GetKind() chainKind {
if c == nil {
return nil
}
return c.kind
}
type ChainRaw struct {
Raw []byte
}
func (*ChainRaw) isChainKind() {}
func (c *ChainRaw) SetRaw(raw []byte) {
c.Raw = raw
}
func (c *ChainRaw) GetRaw() []byte {
if c == nil {
return nil
}
return c.Raw
}

358
api/apemanager/convert.go Normal file
View file

@ -0,0 +1,358 @@
package apemanager
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
apeGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/grpc"
apemanager "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (reqBody *AddChainRequestBody) ToGRPCMessage() grpc.Message {
var reqBodygrpc *apemanager.AddChainRequest_Body
if reqBody != nil {
reqBodygrpc = new(apemanager.AddChainRequest_Body)
reqBodygrpc.SetTarget(reqBody.GetTarget().ToGRPCMessage().(*apeGRPC.ChainTarget))
reqBodygrpc.SetChain(reqBody.GetChain().ToGRPCMessage().(*apeGRPC.Chain))
}
return reqBodygrpc
}
func (reqBody *AddChainRequestBody) FromGRPCMessage(m grpc.Message) error {
reqBodygrpc, ok := m.(*apemanager.AddChainRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, reqBodygrpc)
}
if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil {
reqBody.target = new(ape.ChainTarget)
if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil {
return err
}
}
if chaingrpc := reqBodygrpc.GetChain(); chaingrpc != nil {
reqBody.chain = new(ape.Chain)
if err := reqBody.GetChain().FromGRPCMessage(chaingrpc); err != nil {
return err
}
}
return nil
}
func (req *AddChainRequest) ToGRPCMessage() grpc.Message {
var reqgrpc *apemanager.AddChainRequest
if req != nil {
reqgrpc = new(apemanager.AddChainRequest)
reqgrpc.SetBody(req.GetBody().ToGRPCMessage().(*apemanager.AddChainRequest_Body))
req.RequestHeaders.ToMessage(reqgrpc)
}
return reqgrpc
}
func (req *AddChainRequest) FromGRPCMessage(m grpc.Message) error {
reqgrpc, ok := m.(*apemanager.AddChainRequest)
if !ok {
return message.NewUnexpectedMessageType(m, reqgrpc)
}
if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil {
req.body = new(AddChainRequestBody)
if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil {
return err
}
}
return req.RequestHeaders.FromMessage(reqgrpc)
}
func (respBody *AddChainResponseBody) ToGRPCMessage() grpc.Message {
var respBodygrpc *apemanager.AddChainResponse_Body
if respBody != nil {
respBodygrpc = new(apemanager.AddChainResponse_Body)
respBodygrpc.SetChainId(respBody.GetChainID())
}
return respBodygrpc
}
func (respBody *AddChainResponseBody) FromGRPCMessage(m grpc.Message) error {
respBodygrpc, ok := m.(*apemanager.AddChainResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, respBodygrpc)
}
respBody.SetChainID(respBodygrpc.GetChainId())
return nil
}
func (resp *AddChainResponse) ToGRPCMessage() grpc.Message {
var respgrpc *apemanager.AddChainResponse
if resp != nil {
respgrpc = new(apemanager.AddChainResponse)
respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.AddChainResponse_Body))
resp.ResponseHeaders.ToMessage(respgrpc)
}
return respgrpc
}
func (resp *AddChainResponse) FromGRPCMessage(m grpc.Message) error {
respgrpc, ok := m.(*apemanager.AddChainResponse)
if !ok {
return message.NewUnexpectedMessageType(m, respgrpc)
}
if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil {
resp.body = new(AddChainResponseBody)
if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil {
return err
}
}
return resp.ResponseHeaders.FromMessage(respgrpc)
}
func (reqBody *RemoveChainRequestBody) ToGRPCMessage() grpc.Message {
var reqBodygrpc *apemanager.RemoveChainRequest_Body
if reqBody != nil {
reqBodygrpc = new(apemanager.RemoveChainRequest_Body)
reqBodygrpc.SetTarget(reqBody.target.ToGRPCMessage().(*apeGRPC.ChainTarget))
reqBodygrpc.SetChainId(reqBody.GetChainID())
}
return reqBodygrpc
}
func (reqBody *RemoveChainRequestBody) FromGRPCMessage(m grpc.Message) error {
reqBodygrpc, ok := m.(*apemanager.RemoveChainRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, reqBodygrpc)
}
if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil {
reqBody.target = new(ape.ChainTarget)
if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil {
return err
}
}
reqBody.SetChainID(reqBodygrpc.GetChainId())
return nil
}
func (req *RemoveChainRequest) ToGRPCMessage() grpc.Message {
var reqgrpc *apemanager.RemoveChainRequest
if req != nil {
reqgrpc = new(apemanager.RemoveChainRequest)
reqgrpc.SetBody(req.body.ToGRPCMessage().(*apemanager.RemoveChainRequest_Body))
req.RequestHeaders.ToMessage(reqgrpc)
}
return reqgrpc
}
func (req *RemoveChainRequest) FromGRPCMessage(m grpc.Message) error {
reqgrpc, ok := m.(*apemanager.RemoveChainRequest)
if !ok {
return message.NewUnexpectedMessageType(m, reqgrpc)
}
if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil {
req.body = new(RemoveChainRequestBody)
if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil {
return err
}
}
return req.RequestHeaders.FromMessage(reqgrpc)
}
func (respBody *RemoveChainResponseBody) ToGRPCMessage() grpc.Message {
var respBodygrpc *apemanager.RemoveChainResponse_Body
if respBody != nil {
respBodygrpc = new(apemanager.RemoveChainResponse_Body)
}
return respBodygrpc
}
func (respBody *RemoveChainResponseBody) FromGRPCMessage(m grpc.Message) error {
respBodygrpc, ok := m.(*apemanager.RemoveChainResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, respBodygrpc)
}
return nil
}
func (resp *RemoveChainResponse) ToGRPCMessage() grpc.Message {
var respgrpc *apemanager.RemoveChainResponse
if resp != nil {
respgrpc = new(apemanager.RemoveChainResponse)
respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.RemoveChainResponse_Body))
resp.ResponseHeaders.ToMessage(respgrpc)
}
return respgrpc
}
func (resp *RemoveChainResponse) FromGRPCMessage(m grpc.Message) error {
respgrpc, ok := m.(*apemanager.RemoveChainResponse)
if !ok {
return message.NewUnexpectedMessageType(m, respgrpc)
}
if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil {
resp.body = new(RemoveChainResponseBody)
if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil {
return err
}
}
return resp.ResponseHeaders.FromMessage(respgrpc)
}
func (reqBody *ListChainsRequestBody) ToGRPCMessage() grpc.Message {
var reqBodygrpc *apemanager.ListChainsRequest_Body
if reqBody != nil {
reqBodygrpc = new(apemanager.ListChainsRequest_Body)
reqBodygrpc.SetTarget(reqBody.target.ToGRPCMessage().(*apeGRPC.ChainTarget))
}
return reqBodygrpc
}
func (reqBody *ListChainsRequestBody) FromGRPCMessage(m grpc.Message) error {
reqBodygrpc, ok := m.(*apemanager.ListChainsRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, reqBodygrpc)
}
if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil {
reqBody.target = new(ape.ChainTarget)
if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil {
return err
}
}
return nil
}
func (req *ListChainsRequest) ToGRPCMessage() grpc.Message {
var reqgrpc *apemanager.ListChainsRequest
if req != nil {
reqgrpc = new(apemanager.ListChainsRequest)
reqgrpc.SetBody(req.body.ToGRPCMessage().(*apemanager.ListChainsRequest_Body))
req.RequestHeaders.ToMessage(reqgrpc)
}
return reqgrpc
}
func (req *ListChainsRequest) FromGRPCMessage(m grpc.Message) error {
reqgrpc, ok := m.(*apemanager.ListChainsRequest)
if !ok {
return message.NewUnexpectedMessageType(m, reqgrpc)
}
if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil {
req.body = new(ListChainsRequestBody)
if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil {
return err
}
}
return req.RequestHeaders.FromMessage(reqgrpc)
}
func (respBody *ListChainsResponseBody) ToGRPCMessage() grpc.Message {
var respBodygrpc *apemanager.ListChainsResponse_Body
if respBody != nil {
respBodygrpc = new(apemanager.ListChainsResponse_Body)
chainsgrpc := make([]apeGRPC.Chain, 0, len(respBody.GetChains()))
for _, chain := range respBody.GetChains() {
chainsgrpc = append(chainsgrpc, *chain.ToGRPCMessage().(*apeGRPC.Chain))
}
respBodygrpc.SetChains(chainsgrpc)
}
return respBodygrpc
}
func (respBody *ListChainsResponseBody) FromGRPCMessage(m grpc.Message) error {
respBodygrpc, ok := m.(*apemanager.ListChainsResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, respBodygrpc)
}
chains := make([]*ape.Chain, 0, len(respBodygrpc.GetChains()))
for _, chaingrpc := range respBodygrpc.GetChains() {
chain := new(ape.Chain)
if err := chain.FromGRPCMessage(&chaingrpc); err != nil {
return err
}
chains = append(chains, chain)
}
respBody.SetChains(chains)
return nil
}
func (resp *ListChainsResponse) ToGRPCMessage() grpc.Message {
var respgrpc *apemanager.ListChainsResponse
if resp != nil {
respgrpc = new(apemanager.ListChainsResponse)
respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.ListChainsResponse_Body))
resp.ResponseHeaders.ToMessage(respgrpc)
}
return respgrpc
}
func (resp *ListChainsResponse) FromGRPCMessage(m grpc.Message) error {
respgrpc, ok := m.(*apemanager.ListChainsResponse)
if !ok {
return message.NewUnexpectedMessageType(m, respgrpc)
}
if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil {
resp.body = new(ListChainsResponseBody)
if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil {
return err
}
}
return resp.ResponseHeaders.FromMessage(respgrpc)
}

BIN
api/apemanager/grpc/service_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,121 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package apemanager
func DoFuzzProtoAddChainRequest(data []byte) int {
msg := new(AddChainRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONAddChainRequest(data []byte) int {
msg := new(AddChainRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoAddChainResponse(data []byte) int {
msg := new(AddChainResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONAddChainResponse(data []byte) int {
msg := new(AddChainResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoRemoveChainRequest(data []byte) int {
msg := new(RemoveChainRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONRemoveChainRequest(data []byte) int {
msg := new(RemoveChainRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoRemoveChainResponse(data []byte) int {
msg := new(RemoveChainResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONRemoveChainResponse(data []byte) int {
msg := new(RemoveChainResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoListChainsRequest(data []byte) int {
msg := new(ListChainsRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONListChainsRequest(data []byte) int {
msg := new(ListChainsRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoListChainsResponse(data []byte) int {
msg := new(ListChainsResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONListChainsResponse(data []byte) int {
msg := new(ListChainsResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,71 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package apemanager
import (
testing "testing"
)
func FuzzProtoAddChainRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoAddChainRequest(data)
})
}
func FuzzJSONAddChainRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONAddChainRequest(data)
})
}
func FuzzProtoAddChainResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoAddChainResponse(data)
})
}
func FuzzJSONAddChainResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONAddChainResponse(data)
})
}
func FuzzProtoRemoveChainRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoRemoveChainRequest(data)
})
}
func FuzzJSONRemoveChainRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONRemoveChainRequest(data)
})
}
func FuzzProtoRemoveChainResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoRemoveChainResponse(data)
})
}
func FuzzJSONRemoveChainResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONRemoveChainResponse(data)
})
}
func FuzzProtoListChainsRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoListChainsRequest(data)
})
}
func FuzzJSONListChainsRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONListChainsRequest(data)
})
}
func FuzzProtoListChainsResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoListChainsResponse(data)
})
}
func FuzzJSONListChainsResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONListChainsResponse(data)
})
}

BIN
api/apemanager/grpc/service_grpc.pb.go generated Normal file

Binary file not shown.

205
api/apemanager/marshal.go Normal file
View file

@ -0,0 +1,205 @@
package apemanager
import (
apemanager "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto"
)
const (
addChainReqBodyTargetField = 1
addChainReqBodyChainField = 2
addChainRespBodyChainIDField = 1
removeChainReqBodyTargetField = 1
removeChainReqBodyChainField = 2
/*
Fields for RemoveResponseBody are missed since RemoveResponseBody is empty.
*/
listChainsReqBodyTargetField = 1
listChainsRespBodyChainsField = 1
)
func (rb *AddChainRequestBody) StableSize() (size int) {
if rb == nil {
return 0
}
size += proto.NestedStructureSize(addChainReqBodyTargetField, rb.target)
size += proto.NestedStructureSize(addChainReqBodyChainField, rb.chain)
return size
}
func (rb *AddChainRequestBody) StableMarshal(buf []byte) []byte {
if rb == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, rb.StableSize())
}
var offset int
offset += proto.NestedStructureMarshal(addChainReqBodyTargetField, buf[offset:], rb.target)
proto.NestedStructureMarshal(addChainReqBodyChainField, buf[offset:], rb.chain)
return buf
}
func (rb *AddChainRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(rb, data, new(apemanager.AddChainRequest_Body))
}
func (rb *AddChainResponseBody) StableSize() (size int) {
if rb == nil {
return 0
}
size += proto.BytesSize(addChainRespBodyChainIDField, rb.chainID)
return size
}
func (rb *AddChainResponseBody) StableMarshal(buf []byte) []byte {
if rb == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, rb.StableSize())
}
var offset int
proto.BytesMarshal(addChainRespBodyChainIDField, buf[offset:], rb.chainID)
return buf
}
func (rb *AddChainResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(rb, data, new(apemanager.AddChainResponse_Body))
}
func (rb *RemoveChainRequestBody) StableSize() (size int) {
if rb == nil {
return 0
}
size += proto.NestedStructureSize(addChainReqBodyTargetField, rb.target)
size += proto.BytesSize(addChainReqBodyChainField, rb.chainID)
return size
}
func (rb *RemoveChainRequestBody) StableMarshal(buf []byte) []byte {
if rb == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, rb.StableSize())
}
var offset int
offset += proto.NestedStructureMarshal(removeChainReqBodyTargetField, buf[offset:], rb.target)
proto.BytesMarshal(removeChainReqBodyChainField, buf[offset:], rb.chainID)
return buf
}
func (rb *RemoveChainRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(rb, data, new(apemanager.RemoveChainRequest_Body))
}
func (rb *RemoveChainResponseBody) StableSize() (size int) {
if rb == nil {
return 0
}
return size
}
func (rb *RemoveChainResponseBody) StableMarshal(buf []byte) []byte {
if rb == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, rb.StableSize())
}
return buf
}
func (rb *RemoveChainResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(rb, data, new(apemanager.RemoveChainResponse_Body))
}
func (rb *ListChainsRequestBody) StableSize() (size int) {
if rb == nil {
return 0
}
size += proto.NestedStructureSize(listChainsReqBodyTargetField, rb.target)
return size
}
func (rb *ListChainsRequestBody) StableMarshal(buf []byte) []byte {
if rb == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, rb.StableSize())
}
var offset int
proto.NestedStructureMarshal(addChainReqBodyTargetField, buf[offset:], rb.target)
return buf
}
func (rb *ListChainsRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(rb, data, new(apemanager.ListChainsRequest_Body))
}
func (rb *ListChainsResponseBody) StableSize() (size int) {
if rb == nil {
return 0
}
for _, chain := range rb.GetChains() {
size += proto.NestedStructureSize(listChainsRespBodyChainsField, chain)
}
return size
}
func (rb *ListChainsResponseBody) StableMarshal(buf []byte) []byte {
if rb == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, rb.StableSize())
}
var offset int
for _, chain := range rb.GetChains() {
offset += proto.NestedStructureMarshal(listChainsRespBodyChainsField, buf[offset:], chain)
}
return buf
}
func (rb *ListChainsResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(rb, data, new(apemanager.ListChainsResponse_Body))
}

View file

@ -0,0 +1,26 @@
package apemanager_test
import (
"testing"
apemanagertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test"
)
func TestMessageConvert(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return apemanagertest.GenerateAddChainRequestBody(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateAddChainRequest(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateAddChainResponseBody(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateAddChainResponse(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainRequestBody(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainRequest(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainResponseBody(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateRemoveChainResponse(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateListChainsRequestBody(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateListChainsRequest(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateListChainsResponseBody(empty) },
func(empty bool) message.Message { return apemanagertest.GenerateListChainsResponse(empty) },
)
}

76
api/apemanager/status.go Normal file
View file

@ -0,0 +1,76 @@
package apemanager
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status"
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc"
)
// LocalizeFailStatus checks if passed global status.Code is related to ape manager failure and:
//
// then localizes the code and returns true,
// else leaves the code unchanged and returns false.
//
// Arg must be non-nil.
func LocalizeFailStatus(c *status.Code) bool {
return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_APE_MANAGER))
}
// GlobalizeFail globalizes local code of ape manager failure.
//
// Arg must be non-nil.
func GlobalizeFail(c *status.Code) {
c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_APE_MANAGER))
}
const (
// StatusAPEManagerAccessDenied is a local status.Code value for
// ACCESS_DENIED ape manager failure.
StatusAPEManagerAccessDenied status.Code = iota
)
const (
// detailAccessDeniedDesc is a StatusAccessDenied detail ID for
// human-readable description.
detailAccessDeniedDesc = iota
)
// WriteAccessDeniedDesc writes human-readable description of StatusAccessDenied
// into status.Status as a detail. The status must not be nil.
//
// Existing details are expected to be ID-unique, otherwise undefined behavior.
func WriteAccessDeniedDesc(st *status.Status, desc string) {
var found bool
st.IterateDetails(func(d *status.Detail) bool {
if d.ID() == detailAccessDeniedDesc {
found = true
d.SetValue([]byte(desc))
}
return found
})
if !found {
var d status.Detail
d.SetID(detailAccessDeniedDesc)
d.SetValue([]byte(desc))
st.AppendDetails(d)
}
}
// ReadAccessDeniedDesc looks up for status detail with human-readable description
// of StatusAccessDenied. Returns empty string if detail is missing.
func ReadAccessDeniedDesc(st status.Status) (desc string) {
st.IterateDetails(func(d *status.Detail) bool {
if d.ID() == detailAccessDeniedDesc {
desc = string(d.Value())
return true
}
return false
})
return
}

View file

@ -0,0 +1,30 @@
package apemanager_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status"
statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test"
"github.com/stretchr/testify/require"
)
func TestStatusCodes(t *testing.T) {
statustest.TestCodes(t, apemanager.LocalizeFailStatus, apemanager.GlobalizeFail,
apemanager.StatusAPEManagerAccessDenied, 5120,
)
}
func TestAccessDeniedDesc(t *testing.T) {
var st status.Status
require.Empty(t, apemanager.ReadAccessDeniedDesc(st))
const desc = "some description"
apemanager.WriteAccessDeniedDesc(&st, desc)
require.Equal(t, desc, apemanager.ReadAccessDeniedDesc(st))
apemanager.WriteAccessDeniedDesc(&st, desc+"1")
require.Equal(t, desc+"1", apemanager.ReadAccessDeniedDesc(st))
}

View file

@ -0,0 +1,143 @@
package apemanagertest
import (
apetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager"
sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test"
)
func generateChainID(empty bool) []byte {
if empty {
return []byte{}
}
return []byte("616c6c6f774f626a476574436e72")
}
func GenerateAddChainRequestBody(empty bool) *apemanager.AddChainRequestBody {
m := new(apemanager.AddChainRequestBody)
if !empty {
m.SetTarget(apetest.GenerateChainTarget(empty))
m.SetChain(apetest.GenerateRawChain(empty))
}
return m
}
func GenerateAddChainRequest(empty bool) *apemanager.AddChainRequest {
m := new(apemanager.AddChainRequest)
if !empty {
m.SetBody(GenerateAddChainRequestBody(empty))
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
}
return m
}
func GenerateAddChainResponseBody(empty bool) *apemanager.AddChainResponseBody {
m := new(apemanager.AddChainResponseBody)
if !empty {
m.SetChainID(generateChainID(empty))
}
return m
}
func GenerateAddChainResponse(empty bool) *apemanager.AddChainResponse {
m := new(apemanager.AddChainResponse)
if !empty {
m.SetBody(GenerateAddChainResponseBody(empty))
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
}
return m
}
func GenerateRemoveChainRequestBody(empty bool) *apemanager.RemoveChainRequestBody {
m := new(apemanager.RemoveChainRequestBody)
if !empty {
m.SetChainID(generateChainID(empty))
m.SetTarget(apetest.GenerateChainTarget(empty))
}
return m
}
func GenerateRemoveChainRequest(empty bool) *apemanager.RemoveChainRequest {
m := new(apemanager.RemoveChainRequest)
if !empty {
m.SetBody(GenerateRemoveChainRequestBody(empty))
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
}
return m
}
func GenerateRemoveChainResponseBody(_ bool) *apemanager.RemoveChainResponseBody {
return new(apemanager.RemoveChainResponseBody)
}
func GenerateRemoveChainResponse(empty bool) *apemanager.RemoveChainResponse {
m := new(apemanager.RemoveChainResponse)
if !empty {
m.SetBody(GenerateRemoveChainResponseBody(empty))
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
}
return m
}
func GenerateListChainsRequestBody(empty bool) *apemanager.ListChainsRequestBody {
m := new(apemanager.ListChainsRequestBody)
if !empty {
m.SetTarget(apetest.GenerateChainTarget(empty))
}
return m
}
func GenerateListChainsRequest(empty bool) *apemanager.ListChainsRequest {
m := new(apemanager.ListChainsRequest)
if !empty {
m.SetBody(GenerateListChainsRequestBody(empty))
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
}
return m
}
func GenerateListChainsResponseBody(empty bool) *apemanager.ListChainsResponseBody {
m := new(apemanager.ListChainsResponseBody)
if !empty {
m.SetChains(apetest.GenerateRawChains(empty, 10))
}
return m
}
func GenerateListChainsResponse(empty bool) *apemanager.ListChainsResponse {
m := new(apemanager.ListChainsResponse)
if !empty {
m.SetBody(GenerateListChainsResponseBody(empty))
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
}
return m
}

226
api/apemanager/types.go Normal file
View file

@ -0,0 +1,226 @@
package apemanager
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session"
)
type AddChainRequest struct {
body *AddChainRequestBody
session.RequestHeaders
}
func (r *AddChainRequest) SetBody(body *AddChainRequestBody) {
r.body = body
}
func (r *AddChainRequest) GetBody() *AddChainRequestBody {
if r == nil {
return nil
}
return r.body
}
type AddChainRequestBody struct {
target *ape.ChainTarget
chain *ape.Chain
}
func (rb *AddChainRequestBody) SetTarget(target *ape.ChainTarget) {
rb.target = target
}
func (rb *AddChainRequestBody) GetTarget() *ape.ChainTarget {
if rb == nil {
return nil
}
return rb.target
}
func (rb *AddChainRequestBody) SetChain(chain *ape.Chain) {
rb.chain = chain
}
func (rb *AddChainRequestBody) GetChain() *ape.Chain {
if rb == nil {
return nil
}
return rb.chain
}
type AddChainResponse struct {
body *AddChainResponseBody
session.ResponseHeaders
}
func (r *AddChainResponse) SetBody(body *AddChainResponseBody) {
r.body = body
}
func (r *AddChainResponse) GetBody() *AddChainResponseBody {
if r == nil {
return nil
}
return r.body
}
type AddChainResponseBody struct {
chainID []byte
}
func (rb *AddChainResponseBody) SetChainID(chainID []byte) {
rb.chainID = chainID
}
func (rb *AddChainResponseBody) GetChainID() []byte {
if rb == nil {
return nil
}
return rb.chainID
}
type RemoveChainRequest struct {
body *RemoveChainRequestBody
session.RequestHeaders
}
func (r *RemoveChainRequest) SetBody(body *RemoveChainRequestBody) {
r.body = body
}
func (r *RemoveChainRequest) GetBody() *RemoveChainRequestBody {
if r == nil {
return nil
}
return r.body
}
type RemoveChainRequestBody struct {
target *ape.ChainTarget
chainID []byte
}
func (rb *RemoveChainRequestBody) SetTarget(target *ape.ChainTarget) {
rb.target = target
}
func (rb *RemoveChainRequestBody) GetTarget() *ape.ChainTarget {
if rb == nil {
return nil
}
return rb.target
}
func (rb *RemoveChainRequestBody) SetChainID(chainID []byte) {
rb.chainID = chainID
}
func (rb *RemoveChainRequestBody) GetChainID() []byte {
if rb == nil {
return nil
}
return rb.chainID
}
type RemoveChainResponse struct {
body *RemoveChainResponseBody
session.ResponseHeaders
}
type RemoveChainResponseBody struct{}
func (r *RemoveChainResponse) SetBody(body *RemoveChainResponseBody) {
r.body = body
}
func (r *RemoveChainResponse) GetBody() *RemoveChainResponseBody {
if r == nil {
return nil
}
return r.body
}
type ListChainsRequest struct {
body *ListChainsRequestBody
session.RequestHeaders
}
func (r *ListChainsRequest) SetBody(body *ListChainsRequestBody) {
r.body = body
}
func (r *ListChainsRequest) GetBody() *ListChainsRequestBody {
if r == nil {
return nil
}
return r.body
}
type ListChainsRequestBody struct {
target *ape.ChainTarget
}
func (rb *ListChainsRequestBody) SetTarget(target *ape.ChainTarget) {
rb.target = target
}
func (rb *ListChainsRequestBody) GetTarget() *ape.ChainTarget {
if rb == nil {
return nil
}
return rb.target
}
type ListChainsResponse struct {
body *ListChainsResponseBody
session.ResponseHeaders
}
func (r *ListChainsResponse) SetBody(body *ListChainsResponseBody) {
r.body = body
}
func (r *ListChainsResponse) GetBody() *ListChainsResponseBody {
if r == nil {
return nil
}
return r.body
}
type ListChainsResponseBody struct {
chains []*ape.Chain
session.RequestHeaders
}
func (r *ListChainsResponseBody) SetChains(chains []*ape.Chain) {
r.chains = chains
}
func (r *ListChainsResponseBody) GetChains() []*ape.Chain {
if r == nil {
return nil
}
return r.chains
}

View file

@ -0,0 +1,90 @@
package container
// SysAttributePrefix is a prefix of key to system attribute.
const SysAttributePrefix = "__SYSTEM__"
const (
// SysAttributeName is a string of human-friendly container name registered as the domain in NNS contract.
SysAttributeName = SysAttributePrefix + "NAME"
// SysAttributeZone is a string of zone for container name.
SysAttributeZone = SysAttributePrefix + "ZONE"
// SysAttributeHomomorphicHashing is a container's homomorphic hashing state.
SysAttributeHomomorphicHashing = SysAttributePrefix + "DISABLE_HOMOMORPHIC_HASHING"
)
// SysAttributePrefixNeoFS is a prefix of key to system attribute.
// Deprecated: use SysAttributePrefix.
const SysAttributePrefixNeoFS = "__NEOFS__"
const (
// SysAttributeNameNeoFS is a string of human-friendly container name registered as the domain in NNS contract.
// Deprecated: use SysAttributeName.
SysAttributeNameNeoFS = SysAttributePrefixNeoFS + "NAME"
// SysAttributeZoneNeoFS is a string of zone for container name.
// Deprecated: use SysAttributeZone.
SysAttributeZoneNeoFS = SysAttributePrefixNeoFS + "ZONE"
// SysAttributeHomomorphicHashingNeoFS is a container's homomorphic hashing state.
// Deprecated: use SysAttributeHomomorphicHashing.
SysAttributeHomomorphicHashingNeoFS = SysAttributePrefixNeoFS + "DISABLE_HOMOMORPHIC_HASHING"
)
// SysAttributeZoneDefault is a default value for SysAttributeZone attribute.
const SysAttributeZoneDefault = "container"
const disabledHomomorphicHashingValue = "true"
// HomomorphicHashingState returns container's homomorphic
// hashing state:
// - true if hashing is enabled;
// - false if hashing is disabled.
//
// All container's attributes must be unique, otherwise behavior
// is undefined.
//
// See also SetHomomorphicHashingState.
func (c Container) HomomorphicHashingState() bool {
for i := range c.attr {
if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS {
return c.attr[i].GetValue() != disabledHomomorphicHashingValue
}
}
return true
}
// SetHomomorphicHashingState sets homomorphic hashing state for
// container.
//
// All container's attributes must be unique, otherwise behavior
// is undefined.
//
// See also HomomorphicHashingState.
func (c *Container) SetHomomorphicHashingState(enable bool) {
for i := range c.attr {
if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS {
if enable {
// approach without allocation/waste
// coping works since the attributes
// order is not important
c.attr[i] = c.attr[len(c.attr)-1]
c.attr = c.attr[:len(c.attr)-1]
} else {
c.attr[i].SetValue(disabledHomomorphicHashingValue)
}
return
}
}
if !enable {
attr := Attribute{}
attr.SetKey(SysAttributeHomomorphicHashing)
attr.SetValue(disabledHomomorphicHashingValue)
c.attr = append(c.attr, attr)
}
}

View file

@ -0,0 +1,59 @@
package container_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/test"
"github.com/stretchr/testify/require"
)
func TestContainer_HomomorphicHashingDisabled(t *testing.T) {
cnr := containertest.GenerateContainer(false)
t.Run("defaults", func(t *testing.T) {
require.True(t, cnr.HomomorphicHashingState())
})
t.Run("disabled", func(t *testing.T) {
attr := container.Attribute{}
attr.SetKey(container.SysAttributeHomomorphicHashing)
attr.SetValue("NOT_true")
cnr.SetAttributes(append(cnr.GetAttributes(), attr))
require.True(t, cnr.HomomorphicHashingState())
attr.SetValue("true")
cnr.SetAttributes([]container.Attribute{attr})
require.False(t, cnr.HomomorphicHashingState())
})
}
func TestContainer_SetHomomorphicHashingState(t *testing.T) {
cnr := containertest.GenerateContainer(false)
attrs := cnr.GetAttributes()
attrLen := len(attrs)
cnr.SetHomomorphicHashingState(true)
// enabling hashing should not add any new attributes
require.Equal(t, attrLen, len(cnr.GetAttributes()))
require.True(t, cnr.HomomorphicHashingState())
cnr.SetHomomorphicHashingState(false)
// disabling hashing should add exactly one attribute
require.Equal(t, attrLen+1, len(cnr.GetAttributes()))
require.False(t, cnr.HomomorphicHashingState())
cnr.SetHomomorphicHashingState(true)
// enabling hashing should remove 1 attribute if
// hashing was disabled before
require.Equal(t, attrLen, len(cnr.GetAttributes()))
require.True(t, cnr.HomomorphicHashingState())
// hashing operations should not change any other attributes
require.ElementsMatch(t, attrs, cnr.GetAttributes())
}

899
api/container/convert.go Normal file
View file

@ -0,0 +1,899 @@
package container
import (
container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap"
netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session"
sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc"
)
func (a *Attribute) ToGRPCMessage() grpc.Message {
var m *container.Container_Attribute
if a != nil {
m = new(container.Container_Attribute)
m.SetKey(a.key)
m.SetValue(a.val)
}
return m
}
func (a *Attribute) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.Container_Attribute)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
a.key = v.GetKey()
a.val = v.GetValue()
return nil
}
func AttributesToGRPC(xs []Attribute) (res []container.Container_Attribute) {
if xs != nil {
res = make([]container.Container_Attribute, 0, len(xs))
for i := range xs {
res = append(res, *xs[i].ToGRPCMessage().(*container.Container_Attribute))
}
}
return
}
func AttributesFromGRPC(xs []container.Container_Attribute) (res []Attribute, err error) {
if xs != nil {
res = make([]Attribute, len(xs))
for i := range xs {
err = res[i].FromGRPCMessage(&xs[i])
if err != nil {
return
}
}
}
return
}
func (c *Container) ToGRPCMessage() grpc.Message {
var m *container.Container
if c != nil {
m = new(container.Container)
m.SetVersion(c.version.ToGRPCMessage().(*refsGRPC.Version))
m.SetOwnerId(c.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID))
m.SetPlacementPolicy(c.policy.ToGRPCMessage().(*netmapGRPC.PlacementPolicy))
m.SetAttributes(AttributesToGRPC(c.attr))
m.SetBasicAcl(c.basicACL)
m.SetNonce(c.nonce)
}
return m
}
func (c *Container) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.Container)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
version := v.GetVersion()
if version == nil {
c.version = nil
} else {
if c.version == nil {
c.version = new(refs.Version)
}
err = c.version.FromGRPCMessage(version)
if err != nil {
return err
}
}
ownerID := v.GetOwnerId()
if ownerID == nil {
c.ownerID = nil
} else {
if c.ownerID == nil {
c.ownerID = new(refs.OwnerID)
}
err = c.ownerID.FromGRPCMessage(ownerID)
if err != nil {
return err
}
}
policy := v.GetPlacementPolicy()
if policy == nil {
c.policy = nil
} else {
if c.policy == nil {
c.policy = new(netmap.PlacementPolicy)
}
err = c.policy.FromGRPCMessage(policy)
if err != nil {
return err
}
}
c.attr, err = AttributesFromGRPC(v.GetAttributes())
if err != nil {
return err
}
c.basicACL = v.GetBasicAcl()
c.nonce = v.GetNonce()
return nil
}
func toSignatureRFC6979(s *refs.Signature) *refsGRPC.SignatureRFC6979 {
var res *refsGRPC.SignatureRFC6979
if s != nil {
res = new(refsGRPC.SignatureRFC6979)
res.SetKey(s.GetKey())
res.SetSign(s.GetSign())
}
return res
}
func (r *PutRequestBody) ToGRPCMessage() grpc.Message {
var m *container.PutRequest_Body
if r != nil {
m = new(container.PutRequest_Body)
m.SetContainer(r.cnr.ToGRPCMessage().(*container.Container))
m.SetSignature(toSignatureRFC6979(r.sig))
}
return m
}
func (r *PutRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.PutRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
cnr := v.GetContainer()
if cnr == nil {
r.cnr = nil
} else {
if r.cnr == nil {
r.cnr = new(Container)
}
err = r.cnr.FromGRPCMessage(cnr)
if err != nil {
return err
}
}
sig := v.GetSignature()
if sig == nil {
r.sig = nil
} else {
if r.sig == nil {
r.sig = new(refs.Signature)
}
r.sig.SetKey(sig.GetKey())
r.sig.SetSign(sig.GetSign())
}
return err
}
func (r *PutRequest) ToGRPCMessage() grpc.Message {
var m *container.PutRequest
if r != nil {
m = new(container.PutRequest)
m.SetBody(r.body.ToGRPCMessage().(*container.PutRequest_Body))
r.RequestHeaders.ToMessage(m)
}
return m
}
func (r *PutRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.PutRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(PutRequestBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.RequestHeaders.FromMessage(v)
}
func (r *PutResponseBody) ToGRPCMessage() grpc.Message {
var m *container.PutResponse_Body
if r != nil {
m = new(container.PutResponse_Body)
m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID))
}
return m
}
func (r *PutResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.PutResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
cid := v.GetContainerId()
if cid == nil {
r.cid = nil
} else {
if r.cid == nil {
r.cid = new(refs.ContainerID)
}
err = r.cid.FromGRPCMessage(cid)
}
return err
}
func (r *PutResponse) ToGRPCMessage() grpc.Message {
var m *container.PutResponse
if r != nil {
m = new(container.PutResponse)
m.SetBody(r.body.ToGRPCMessage().(*container.PutResponse_Body))
r.ResponseHeaders.ToMessage(m)
}
return m
}
func (r *PutResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.PutResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(PutResponseBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.ResponseHeaders.FromMessage(v)
}
func (r *GetRequestBody) ToGRPCMessage() grpc.Message {
var m *container.GetRequest_Body
if r != nil {
m = new(container.GetRequest_Body)
m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID))
}
return m
}
func (r *GetRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.GetRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
cid := v.GetContainerId()
if cid == nil {
r.cid = nil
} else {
if r.cid == nil {
r.cid = new(refs.ContainerID)
}
err = r.cid.FromGRPCMessage(cid)
}
return err
}
func (r *GetRequest) ToGRPCMessage() grpc.Message {
var m *container.GetRequest
if r != nil {
m = new(container.GetRequest)
m.SetBody(r.body.ToGRPCMessage().(*container.GetRequest_Body))
r.RequestHeaders.ToMessage(m)
}
return m
}
func (r *GetRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.GetRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(GetRequestBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.RequestHeaders.FromMessage(v)
}
func (r *GetResponseBody) ToGRPCMessage() grpc.Message {
var m *container.GetResponse_Body
if r != nil {
m = new(container.GetResponse_Body)
m.SetContainer(r.cnr.ToGRPCMessage().(*container.Container))
m.SetSessionToken(r.token.ToGRPCMessage().(*sessionGRPC.SessionToken))
m.SetSignature(toSignatureRFC6979(r.sig))
}
return m
}
func (r *GetResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.GetResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
cnr := v.GetContainer()
if cnr == nil {
r.cnr = nil
} else {
if r.cnr == nil {
r.cnr = new(Container)
}
err = r.cnr.FromGRPCMessage(cnr)
}
sig := v.GetSignature()
if sig == nil {
r.sig = nil
} else {
if r.sig == nil {
r.sig = new(refs.Signature)
}
r.sig.SetKey(sig.GetKey())
r.sig.SetSign(sig.GetSign())
}
token := v.GetSessionToken()
if token == nil {
r.token = nil
} else {
if r.token == nil {
r.token = new(session.Token)
}
err = r.token.FromGRPCMessage(token)
}
return err
}
func (r *GetResponse) ToGRPCMessage() grpc.Message {
var m *container.GetResponse
if r != nil {
m = new(container.GetResponse)
m.SetBody(r.body.ToGRPCMessage().(*container.GetResponse_Body))
r.ResponseHeaders.ToMessage(m)
}
return m
}
func (r *GetResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.GetResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(GetResponseBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.ResponseHeaders.FromMessage(v)
}
func (r *DeleteRequestBody) ToGRPCMessage() grpc.Message {
var m *container.DeleteRequest_Body
if r != nil {
m = new(container.DeleteRequest_Body)
m.SetContainerId(r.cid.ToGRPCMessage().(*refsGRPC.ContainerID))
m.SetSignature(toSignatureRFC6979(r.sig))
}
return m
}
func (r *DeleteRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.DeleteRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
cid := v.GetContainerId()
if cid == nil {
r.cid = nil
} else {
if r.cid == nil {
r.cid = new(refs.ContainerID)
}
err = r.cid.FromGRPCMessage(cid)
if err != nil {
return err
}
}
sig := v.GetSignature()
if sig == nil {
r.sig = nil
} else {
if r.sig == nil {
r.sig = new(refs.Signature)
}
r.sig.SetKey(sig.GetKey())
r.sig.SetSign(sig.GetSign())
}
return err
}
func (r *DeleteRequest) ToGRPCMessage() grpc.Message {
var m *container.DeleteRequest
if r != nil {
m = new(container.DeleteRequest)
m.SetBody(r.body.ToGRPCMessage().(*container.DeleteRequest_Body))
r.RequestHeaders.ToMessage(m)
}
return m
}
func (r *DeleteRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.DeleteRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(DeleteRequestBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.RequestHeaders.FromMessage(v)
}
func (r *DeleteResponseBody) ToGRPCMessage() grpc.Message {
var m *container.DeleteResponse_Body
if r != nil {
m = new(container.DeleteResponse_Body)
}
return m
}
func (r *DeleteResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.DeleteResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
return nil
}
func (r *DeleteResponse) ToGRPCMessage() grpc.Message {
var m *container.DeleteResponse
if r != nil {
m = new(container.DeleteResponse)
m.SetBody(r.body.ToGRPCMessage().(*container.DeleteResponse_Body))
r.ResponseHeaders.ToMessage(m)
}
return m
}
func (r *DeleteResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.DeleteResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(DeleteResponseBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.ResponseHeaders.FromMessage(v)
}
func (r *ListRequestBody) ToGRPCMessage() grpc.Message {
var m *container.ListRequest_Body
if r != nil {
m = new(container.ListRequest_Body)
m.SetOwnerId(r.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID))
}
return m
}
func (r *ListRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
ownerID := v.GetOwnerId()
if ownerID == nil {
r.ownerID = nil
} else {
if r.ownerID == nil {
r.ownerID = new(refs.OwnerID)
}
err = r.ownerID.FromGRPCMessage(ownerID)
}
return err
}
func (r *ListRequest) ToGRPCMessage() grpc.Message {
var m *container.ListRequest
if r != nil {
m = new(container.ListRequest)
m.SetBody(r.body.ToGRPCMessage().(*container.ListRequest_Body))
r.RequestHeaders.ToMessage(m)
}
return m
}
func (r *ListRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(ListRequestBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.RequestHeaders.FromMessage(v)
}
func (r *ListResponseBody) ToGRPCMessage() grpc.Message {
var m *container.ListResponse_Body
if r != nil {
m = new(container.ListResponse_Body)
m.SetContainerIds(refs.ContainerIDsToGRPCMessage(r.cidList))
}
return m
}
func (r *ListResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
r.cidList, err = refs.ContainerIDsFromGRPCMessage(v.GetContainerIds())
return err
}
func (r *ListResponse) ToGRPCMessage() grpc.Message {
var m *container.ListResponse
if r != nil {
m = new(container.ListResponse)
m.SetBody(r.body.ToGRPCMessage().(*container.ListResponse_Body))
r.ResponseHeaders.ToMessage(m)
}
return m
}
func (r *ListResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(ListResponseBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.ResponseHeaders.FromMessage(v)
}
func (r *ListStreamRequestBody) ToGRPCMessage() grpc.Message {
var m *container.ListStreamRequest_Body
if r != nil {
m = new(container.ListStreamRequest_Body)
m.SetOwnerId(r.ownerID.ToGRPCMessage().(*refsGRPC.OwnerID))
}
return m
}
func (r *ListStreamRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListStreamRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
ownerID := v.GetOwnerId()
if ownerID == nil {
r.ownerID = nil
} else {
if r.ownerID == nil {
r.ownerID = new(refs.OwnerID)
}
err = r.ownerID.FromGRPCMessage(ownerID)
}
return err
}
func (r *ListStreamRequest) ToGRPCMessage() grpc.Message {
var m *container.ListStreamRequest
if r != nil {
m = new(container.ListStreamRequest)
m.SetBody(r.body.ToGRPCMessage().(*container.ListStreamRequest_Body))
r.RequestHeaders.ToMessage(m)
}
return m
}
func (r *ListStreamRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListStreamRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(ListStreamRequestBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.RequestHeaders.FromMessage(v)
}
func (r *ListStreamResponseBody) ToGRPCMessage() grpc.Message {
var m *container.ListStreamResponse_Body
if r != nil {
m = new(container.ListStreamResponse_Body)
m.SetContainerIds(refs.ContainerIDsToGRPCMessage(r.cidList))
}
return m
}
func (r *ListStreamResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListStreamResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
r.cidList, err = refs.ContainerIDsFromGRPCMessage(v.GetContainerIds())
return err
}
func (r *ListStreamResponse) ToGRPCMessage() grpc.Message {
var m *container.ListStreamResponse
if r != nil {
m = new(container.ListStreamResponse)
m.SetBody(r.body.ToGRPCMessage().(*container.ListStreamResponse_Body))
r.ResponseHeaders.ToMessage(m)
}
return m
}
func (r *ListStreamResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*container.ListStreamResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
r.body = nil
} else {
if r.body == nil {
r.body = new(ListStreamResponseBody)
}
err = r.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return r.ResponseHeaders.FromMessage(v)
}

BIN
api/container/grpc/service_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,197 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package container
func DoFuzzProtoPutRequest(data []byte) int {
msg := new(PutRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONPutRequest(data []byte) int {
msg := new(PutRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoPutResponse(data []byte) int {
msg := new(PutResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONPutResponse(data []byte) int {
msg := new(PutResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoDeleteRequest(data []byte) int {
msg := new(DeleteRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONDeleteRequest(data []byte) int {
msg := new(DeleteRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoDeleteResponse(data []byte) int {
msg := new(DeleteResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONDeleteResponse(data []byte) int {
msg := new(DeleteResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoGetRequest(data []byte) int {
msg := new(GetRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONGetRequest(data []byte) int {
msg := new(GetRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoGetResponse(data []byte) int {
msg := new(GetResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONGetResponse(data []byte) int {
msg := new(GetResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoListRequest(data []byte) int {
msg := new(ListRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONListRequest(data []byte) int {
msg := new(ListRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoListResponse(data []byte) int {
msg := new(ListResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONListResponse(data []byte) int {
msg := new(ListResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoListStreamRequest(data []byte) int {
msg := new(ListStreamRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONListStreamRequest(data []byte) int {
msg := new(ListStreamRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoListStreamResponse(data []byte) int {
msg := new(ListStreamResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONListStreamResponse(data []byte) int {
msg := new(ListStreamResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,111 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package container
import (
testing "testing"
)
func FuzzProtoPutRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoPutRequest(data)
})
}
func FuzzJSONPutRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONPutRequest(data)
})
}
func FuzzProtoPutResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoPutResponse(data)
})
}
func FuzzJSONPutResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONPutResponse(data)
})
}
func FuzzProtoDeleteRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoDeleteRequest(data)
})
}
func FuzzJSONDeleteRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONDeleteRequest(data)
})
}
func FuzzProtoDeleteResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoDeleteResponse(data)
})
}
func FuzzJSONDeleteResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONDeleteResponse(data)
})
}
func FuzzProtoGetRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoGetRequest(data)
})
}
func FuzzJSONGetRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONGetRequest(data)
})
}
func FuzzProtoGetResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoGetResponse(data)
})
}
func FuzzJSONGetResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONGetResponse(data)
})
}
func FuzzProtoListRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoListRequest(data)
})
}
func FuzzJSONListRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONListRequest(data)
})
}
func FuzzProtoListResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoListResponse(data)
})
}
func FuzzJSONListResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONListResponse(data)
})
}
func FuzzProtoListStreamRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoListStreamRequest(data)
})
}
func FuzzJSONListStreamRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONListStreamRequest(data)
})
}
func FuzzProtoListStreamResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoListStreamResponse(data)
})
}
func FuzzJSONListStreamResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONListStreamResponse(data)
})
}

BIN
api/container/grpc/service_grpc.pb.go generated Normal file

Binary file not shown.

BIN
api/container/grpc/types_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,26 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package container
func DoFuzzProtoContainer(data []byte) int {
msg := new(Container)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONContainer(data []byte) int {
msg := new(Container)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,21 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package container
import (
testing "testing"
)
func FuzzProtoContainer(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoContainer(data)
})
}
func FuzzJSONContainer(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONContainer(data)
})
}

22
api/container/json.go Normal file
View file

@ -0,0 +1,22 @@
package container
import (
container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (a *Attribute) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(a)
}
func (a *Attribute) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(a, data, new(container.Container_Attribute))
}
func (c *Container) MarshalJSON() ([]byte, error) {
return message.MarshalJSON(c)
}
func (c *Container) UnmarshalJSON(data []byte) error {
return message.UnmarshalJSON(c, data, new(container.Container))
}

407
api/container/marshal.go Normal file
View file

@ -0,0 +1,407 @@
package container
import (
container "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
protoutil "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto"
)
const (
attributeKeyField = 1
attributeValueField = 2
containerVersionField = 1
containerOwnerField = 2
containerNonceField = 3
containerBasicACLField = 4
containerAttributesField = 5
containerPlacementField = 6
putReqBodyContainerField = 1
putReqBodySignatureField = 2
putRespBodyIDField = 1
deleteReqBodyIDField = 1
deleteReqBodySignatureField = 2
getReqBodyIDField = 1
getRespBodyContainerField = 1
getRespBodySignatureField = 2
getRespBodyTokenField = 3
listReqBodyOwnerField = 1
listRespBodyIDsField = 1
)
func (a *Attribute) StableMarshal(buf []byte) []byte {
if a == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, a.StableSize())
}
var offset int
offset += protoutil.StringMarshal(attributeKeyField, buf[offset:], a.key)
protoutil.StringMarshal(attributeValueField, buf[offset:], a.val)
return buf
}
func (a *Attribute) StableSize() (size int) {
if a == nil {
return 0
}
size += protoutil.StringSize(attributeKeyField, a.key)
size += protoutil.StringSize(attributeValueField, a.val)
return size
}
func (a *Attribute) Unmarshal(data []byte) error {
return message.Unmarshal(a, data, new(container.Container_Attribute))
}
func (c *Container) StableMarshal(buf []byte) []byte {
if c == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, c.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(containerVersionField, buf[offset:], c.version)
offset += protoutil.NestedStructureMarshal(containerOwnerField, buf[offset:], c.ownerID)
offset += protoutil.BytesMarshal(containerNonceField, buf[offset:], c.nonce)
offset += protoutil.UInt32Marshal(containerBasicACLField, buf[offset:], c.basicACL)
for i := range c.attr {
offset += protoutil.NestedStructureMarshal(containerAttributesField, buf[offset:], &c.attr[i])
}
protoutil.NestedStructureMarshal(containerPlacementField, buf[offset:], c.policy)
return buf
}
func (c *Container) StableSize() (size int) {
if c == nil {
return 0
}
size += protoutil.NestedStructureSize(containerVersionField, c.version)
size += protoutil.NestedStructureSize(containerOwnerField, c.ownerID)
size += protoutil.BytesSize(containerNonceField, c.nonce)
size += protoutil.UInt32Size(containerBasicACLField, c.basicACL)
for i := range c.attr {
size += protoutil.NestedStructureSize(containerAttributesField, &c.attr[i])
}
size += protoutil.NestedStructureSize(containerPlacementField, c.policy)
return size
}
func (c *Container) Unmarshal(data []byte) error {
return message.Unmarshal(c, data, new(container.Container))
}
func (r *PutRequestBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(putReqBodyContainerField, buf[offset:], r.cnr)
protoutil.NestedStructureMarshal(putReqBodySignatureField, buf[offset:], r.sig)
return buf
}
func (r *PutRequestBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(putReqBodyContainerField, r.cnr)
size += protoutil.NestedStructureSize(putReqBodySignatureField, r.sig)
return size
}
func (r *PutRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.PutRequest_Body))
}
func (r *PutResponseBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
protoutil.NestedStructureMarshal(putRespBodyIDField, buf, r.cid)
return buf
}
func (r *PutResponseBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(putRespBodyIDField, r.cid)
return size
}
func (r *PutResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.PutResponse_Body))
}
func (r *DeleteRequestBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(deleteReqBodyIDField, buf[offset:], r.cid)
protoutil.NestedStructureMarshal(deleteReqBodySignatureField, buf[offset:], r.sig)
return buf
}
func (r *DeleteRequestBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(deleteReqBodyIDField, r.cid)
size += protoutil.NestedStructureSize(deleteReqBodySignatureField, r.sig)
return size
}
func (r *DeleteRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.DeleteRequest_Body))
}
func (r *DeleteResponseBody) StableMarshal(_ []byte) []byte {
return nil
}
func (r *DeleteResponseBody) StableSize() (size int) {
return 0
}
func (r *DeleteResponseBody) Unmarshal([]byte) error {
return nil
}
func (r *GetRequestBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
protoutil.NestedStructureMarshal(getReqBodyIDField, buf, r.cid)
return buf
}
func (r *GetRequestBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(getReqBodyIDField, r.cid)
return size
}
func (r *GetRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.GetRequest_Body))
}
func (r *GetResponseBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
var offset int
offset += protoutil.NestedStructureMarshal(getRespBodyContainerField, buf, r.cnr)
offset += protoutil.NestedStructureMarshal(getRespBodySignatureField, buf[offset:], r.sig)
protoutil.NestedStructureMarshal(getRespBodyTokenField, buf[offset:], r.token)
return buf
}
func (r *GetResponseBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(getRespBodyContainerField, r.cnr)
size += protoutil.NestedStructureSize(getRespBodySignatureField, r.sig)
size += protoutil.NestedStructureSize(getRespBodyTokenField, r.token)
return size
}
func (r *GetResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.GetResponse_Body))
}
func (r *ListRequestBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
protoutil.NestedStructureMarshal(listReqBodyOwnerField, buf, r.ownerID)
return buf
}
func (r *ListRequestBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(listReqBodyOwnerField, r.ownerID)
return size
}
func (r *ListRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.ListRequest_Body))
}
func (r *ListResponseBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
var offset int
for i := range r.cidList {
offset += protoutil.NestedStructureMarshal(listRespBodyIDsField, buf[offset:], &r.cidList[i])
}
return buf
}
func (r *ListResponseBody) StableSize() (size int) {
if r == nil {
return 0
}
for i := range r.cidList {
size += protoutil.NestedStructureSize(listRespBodyIDsField, &r.cidList[i])
}
return size
}
func (r *ListResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.ListResponse_Body))
}
func (r *ListStreamRequestBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
protoutil.NestedStructureMarshal(listReqBodyOwnerField, buf, r.ownerID)
return buf
}
func (r *ListStreamRequestBody) StableSize() (size int) {
if r == nil {
return 0
}
size += protoutil.NestedStructureSize(listReqBodyOwnerField, r.ownerID)
return size
}
func (r *ListStreamRequestBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.ListStreamRequest_Body))
}
func (r *ListStreamResponseBody) StableMarshal(buf []byte) []byte {
if r == nil {
return []byte{}
}
if buf == nil {
buf = make([]byte, r.StableSize())
}
var offset int
for i := range r.cidList {
offset += protoutil.NestedStructureMarshal(listRespBodyIDsField, buf[offset:], &r.cidList[i])
}
return buf
}
func (r *ListStreamResponseBody) StableSize() (size int) {
if r == nil {
return 0
}
for i := range r.cidList {
size += protoutil.NestedStructureSize(listRespBodyIDsField, &r.cidList[i])
}
return size
}
func (r *ListStreamResponseBody) Unmarshal(data []byte) error {
return message.Unmarshal(r, data, new(container.ListStreamResponse_Body))
}

View file

@ -0,0 +1,36 @@
package container_test
import (
"testing"
containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
messagetest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message/test"
)
func TestMessageConvert(t *testing.T) {
messagetest.TestRPCMessage(t,
func(empty bool) message.Message { return containertest.GenerateAttribute(empty) },
func(empty bool) message.Message { return containertest.GenerateContainer(empty) },
func(empty bool) message.Message { return containertest.GeneratePutRequestBody(empty) },
func(empty bool) message.Message { return containertest.GeneratePutRequest(empty) },
func(empty bool) message.Message { return containertest.GeneratePutResponseBody(empty) },
func(empty bool) message.Message { return containertest.GeneratePutResponse(empty) },
func(empty bool) message.Message { return containertest.GenerateGetRequestBody(empty) },
func(empty bool) message.Message { return containertest.GenerateGetRequest(empty) },
func(empty bool) message.Message { return containertest.GenerateGetResponseBody(empty) },
func(empty bool) message.Message { return containertest.GenerateGetResponse(empty) },
func(empty bool) message.Message { return containertest.GenerateDeleteRequestBody(empty) },
func(empty bool) message.Message { return containertest.GenerateDeleteRequest(empty) },
func(empty bool) message.Message { return containertest.GenerateDeleteResponseBody(empty) },
func(empty bool) message.Message { return containertest.GenerateDeleteResponse(empty) },
func(empty bool) message.Message { return containertest.GenerateListRequestBody(empty) },
func(empty bool) message.Message { return containertest.GenerateListRequest(empty) },
func(empty bool) message.Message { return containertest.GenerateListResponseBody(empty) },
func(empty bool) message.Message { return containertest.GenerateListResponse(empty) },
func(empty bool) message.Message { return containertest.GenerateGetRequestBody(empty) },
func(empty bool) message.Message { return containertest.GenerateGetRequest(empty) },
func(empty bool) message.Message { return containertest.GenerateGetResponseBody(empty) },
func(empty bool) message.Message { return containertest.GenerateGetResponse(empty) },
)
}

33
api/container/status.go Normal file
View file

@ -0,0 +1,33 @@
package container
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status"
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/grpc"
)
// LocalizeFailStatus checks if passed global status.Code is related to container failure and:
//
// then localizes the code and returns true,
// else leaves the code unchanged and returns false.
//
// Arg must not be nil.
func LocalizeFailStatus(c *status.Code) bool {
return status.LocalizeIfInSection(c, uint32(statusgrpc.Section_SECTION_CONTAINER))
}
// GlobalizeFail globalizes local code of container failure.
//
// Arg must not be nil.
func GlobalizeFail(c *status.Code) {
c.GlobalizeSection(uint32(statusgrpc.Section_SECTION_CONTAINER))
}
const (
// StatusNotFound is a local status.Code value for
// CONTAINER_NOT_FOUND container failure.
StatusNotFound status.Code = iota
// StatusEACLNotFound is a local status.Code value for
// EACL_NOT_FOUND failure.
StatusEACLNotFound
)

View file

@ -0,0 +1,15 @@
package container_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
statustest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status/test"
)
func TestStatusCodes(t *testing.T) {
statustest.TestCodes(t, container.LocalizeFailStatus, container.GlobalizeFail,
container.StatusNotFound, 3072,
container.StatusEACLNotFound, 3073,
)
}

View file

@ -0,0 +1,240 @@
package containertest
import (
"crypto/rand"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/test"
refstest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/test"
sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/test"
)
func GenerateAttribute(empty bool) *container.Attribute {
m := new(container.Attribute)
if !empty {
m.SetKey("key")
m.SetValue("val")
}
return m
}
func GenerateAttributes(empty bool) []container.Attribute {
var res []container.Attribute
if !empty {
res = append(res,
*GenerateAttribute(false),
*GenerateAttribute(false),
)
}
return res
}
func GenerateContainer(empty bool) *container.Container {
m := new(container.Container)
if !empty {
nonce := make([]byte, 16)
_, _ = rand.Read(nonce)
m.SetBasicACL(12)
m.SetNonce(nonce)
m.SetOwnerID(refstest.GenerateOwnerID(false))
m.SetAttributes(GenerateAttributes(false))
m.SetPlacementPolicy(netmaptest.GeneratePlacementPolicy(false))
}
m.SetVersion(refstest.GenerateVersion(empty))
return m
}
func GeneratePutRequestBody(empty bool) *container.PutRequestBody {
m := new(container.PutRequestBody)
if !empty {
m.SetContainer(GenerateContainer(false))
}
m.SetSignature(refstest.GenerateSignature(empty))
return m
}
func GeneratePutRequest(empty bool) *container.PutRequest {
m := new(container.PutRequest)
if !empty {
m.SetBody(GeneratePutRequestBody(false))
}
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
return m
}
func GeneratePutResponseBody(empty bool) *container.PutResponseBody {
m := new(container.PutResponseBody)
if !empty {
m.SetContainerID(refstest.GenerateContainerID(false))
}
return m
}
func GeneratePutResponse(empty bool) *container.PutResponse {
m := new(container.PutResponse)
if !empty {
m.SetBody(GeneratePutResponseBody(false))
}
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m
}
func GenerateGetRequestBody(empty bool) *container.GetRequestBody {
m := new(container.GetRequestBody)
if !empty {
m.SetContainerID(refstest.GenerateContainerID(false))
}
return m
}
func GenerateGetRequest(empty bool) *container.GetRequest {
m := new(container.GetRequest)
if !empty {
m.SetBody(GenerateGetRequestBody(false))
}
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
return m
}
func GenerateGetResponseBody(empty bool) *container.GetResponseBody {
m := new(container.GetResponseBody)
if !empty {
m.SetContainer(GenerateContainer(false))
}
m.SetSignature(refstest.GenerateSignature(empty))
m.SetSessionToken(sessiontest.GenerateSessionToken(empty))
return m
}
func GenerateGetResponse(empty bool) *container.GetResponse {
m := new(container.GetResponse)
if !empty {
m.SetBody(GenerateGetResponseBody(false))
}
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m
}
func GenerateDeleteRequestBody(empty bool) *container.DeleteRequestBody {
m := new(container.DeleteRequestBody)
if !empty {
m.SetContainerID(refstest.GenerateContainerID(false))
}
m.SetSignature(refstest.GenerateSignature(empty))
return m
}
func GenerateDeleteRequest(empty bool) *container.DeleteRequest {
m := new(container.DeleteRequest)
if !empty {
m.SetBody(GenerateDeleteRequestBody(false))
}
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
return m
}
func GenerateDeleteResponseBody(_ bool) *container.DeleteResponseBody {
m := new(container.DeleteResponseBody)
return m
}
func GenerateDeleteResponse(empty bool) *container.DeleteResponse {
m := new(container.DeleteResponse)
if !empty {
m.SetBody(GenerateDeleteResponseBody(false))
}
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m
}
func GenerateListRequestBody(empty bool) *container.ListRequestBody {
m := new(container.ListRequestBody)
if !empty {
m.SetOwnerID(refstest.GenerateOwnerID(false))
}
return m
}
func GenerateListRequest(empty bool) *container.ListRequest {
m := new(container.ListRequest)
if !empty {
m.SetBody(GenerateListRequestBody(false))
}
m.SetMetaHeader(sessiontest.GenerateRequestMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateRequestVerificationHeader(empty))
return m
}
func GenerateListResponseBody(empty bool) *container.ListResponseBody {
m := new(container.ListResponseBody)
if !empty {
m.SetContainerIDs(refstest.GenerateContainerIDs(false))
}
return m
}
func GenerateListResponse(empty bool) *container.ListResponse {
m := new(container.ListResponse)
if !empty {
m.SetBody(GenerateListResponseBody(false))
}
m.SetMetaHeader(sessiontest.GenerateResponseMetaHeader(empty))
m.SetVerificationHeader(sessiontest.GenerateResponseVerificationHeader(empty))
return m
}

514
api/container/types.go Normal file
View file

@ -0,0 +1,514 @@
package container
import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session"
)
type Attribute struct {
key, val string
}
type Container struct {
version *refs.Version
ownerID *refs.OwnerID
nonce []byte
basicACL uint32
attr []Attribute
policy *netmap.PlacementPolicy
}
type PutRequestBody struct {
cnr *Container
sig *refs.Signature
}
type PutRequest struct {
body *PutRequestBody
session.RequestHeaders
}
type PutResponseBody struct {
cid *refs.ContainerID
}
type PutResponse struct {
body *PutResponseBody
session.ResponseHeaders
}
type GetRequestBody struct {
cid *refs.ContainerID
}
type GetRequest struct {
body *GetRequestBody
session.RequestHeaders
}
type GetResponseBody struct {
cnr *Container
token *session.Token
sig *refs.Signature
}
type GetResponse struct {
body *GetResponseBody
session.ResponseHeaders
}
type DeleteRequestBody struct {
cid *refs.ContainerID
sig *refs.Signature
}
type DeleteRequest struct {
body *DeleteRequestBody
session.RequestHeaders
}
type DeleteResponseBody struct{}
type DeleteResponse struct {
body *DeleteResponseBody
session.ResponseHeaders
}
type ListRequestBody struct {
ownerID *refs.OwnerID
}
type ListRequest struct {
body *ListRequestBody
session.RequestHeaders
}
type ListResponseBody struct {
cidList []refs.ContainerID
}
type ListResponse struct {
body *ListResponseBody
session.ResponseHeaders
}
type ListStreamRequestBody struct {
ownerID *refs.OwnerID
}
type ListStreamRequest struct {
body *ListStreamRequestBody
session.RequestHeaders
}
type ListStreamResponseBody struct {
cidList []refs.ContainerID
}
type ListStreamResponse struct {
body *ListStreamResponseBody
session.ResponseHeaders
}
func (a *Attribute) GetKey() string {
if a != nil {
return a.key
}
return ""
}
func (a *Attribute) SetKey(v string) {
a.key = v
}
func (a *Attribute) GetValue() string {
if a != nil {
return a.val
}
return ""
}
func (a *Attribute) SetValue(v string) {
a.val = v
}
func (c *Container) GetVersion() *refs.Version {
if c != nil {
return c.version
}
return nil
}
func (c *Container) SetVersion(v *refs.Version) {
c.version = v
}
func (c *Container) GetOwnerID() *refs.OwnerID {
if c != nil {
return c.ownerID
}
return nil
}
func (c *Container) SetOwnerID(v *refs.OwnerID) {
c.ownerID = v
}
func (c *Container) GetNonce() []byte {
if c != nil {
return c.nonce
}
return nil
}
func (c *Container) SetNonce(v []byte) {
c.nonce = v
}
func (c *Container) GetBasicACL() uint32 {
if c != nil {
return c.basicACL
}
return 0
}
func (c *Container) SetBasicACL(v uint32) {
c.basicACL = v
}
func (c *Container) GetAttributes() []Attribute {
if c != nil {
return c.attr
}
return nil
}
func (c *Container) SetAttributes(v []Attribute) {
c.attr = v
}
func (c *Container) GetPlacementPolicy() *netmap.PlacementPolicy {
if c != nil {
return c.policy
}
return nil
}
func (c *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) {
c.policy = v
}
func (r *PutRequestBody) GetContainer() *Container {
if r != nil {
return r.cnr
}
return nil
}
func (r *PutRequestBody) SetContainer(v *Container) {
r.cnr = v
}
func (r *PutRequestBody) GetSignature() *refs.Signature {
if r != nil {
return r.sig
}
return nil
}
func (r *PutRequestBody) SetSignature(v *refs.Signature) {
// TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type)
v.SetScheme(0)
r.sig = v
}
func (r *PutRequest) GetBody() *PutRequestBody {
if r != nil {
return r.body
}
return nil
}
func (r *PutRequest) SetBody(v *PutRequestBody) {
r.body = v
}
func (r *PutResponseBody) GetContainerID() *refs.ContainerID {
if r != nil {
return r.cid
}
return nil
}
func (r *PutResponseBody) SetContainerID(v *refs.ContainerID) {
r.cid = v
}
func (r *PutResponse) GetBody() *PutResponseBody {
if r != nil {
return r.body
}
return nil
}
func (r *PutResponse) SetBody(v *PutResponseBody) {
r.body = v
}
func (r *GetRequestBody) GetContainerID() *refs.ContainerID {
if r != nil {
return r.cid
}
return nil
}
func (r *GetRequestBody) SetContainerID(v *refs.ContainerID) {
r.cid = v
}
func (r *GetRequest) GetBody() *GetRequestBody {
if r != nil {
return r.body
}
return nil
}
func (r *GetRequest) SetBody(v *GetRequestBody) {
r.body = v
}
func (r *GetResponseBody) GetContainer() *Container {
if r != nil {
return r.cnr
}
return nil
}
func (r *GetResponseBody) SetContainer(v *Container) {
r.cnr = v
}
// GetSessionToken returns token of the session within which requested
// container was created.
func (r *GetResponseBody) GetSessionToken() *session.Token {
if r != nil {
return r.token
}
return nil
}
// SetSessionToken sets token of the session within which requested
// container was created.
func (r *GetResponseBody) SetSessionToken(v *session.Token) {
r.token = v
}
// GetSignature returns signature of the requested container.
func (r *GetResponseBody) GetSignature() *refs.Signature {
if r != nil {
return r.sig
}
return nil
}
// SetSignature sets signature of the requested container.
func (r *GetResponseBody) SetSignature(v *refs.Signature) {
// TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type)
v.SetScheme(0)
r.sig = v
}
func (r *GetResponse) GetBody() *GetResponseBody {
if r != nil {
return r.body
}
return nil
}
func (r *GetResponse) SetBody(v *GetResponseBody) {
r.body = v
}
func (r *DeleteRequestBody) GetContainerID() *refs.ContainerID {
if r != nil {
return r.cid
}
return nil
}
func (r *DeleteRequestBody) SetContainerID(v *refs.ContainerID) {
r.cid = v
}
func (r *DeleteRequestBody) GetSignature() *refs.Signature {
if r != nil {
return r.sig
}
return nil
}
func (r *DeleteRequestBody) SetSignature(v *refs.Signature) {
// TODO: (neofs-api-go#381) avoid this hack (e.g. create refs.SignatureRFC6979 type)
v.SetScheme(0)
r.sig = v
}
func (r *DeleteRequest) GetBody() *DeleteRequestBody {
if r != nil {
return r.body
}
return nil
}
func (r *DeleteRequest) SetBody(v *DeleteRequestBody) {
r.body = v
}
func (r *DeleteResponse) GetBody() *DeleteResponseBody {
if r != nil {
return r.body
}
return nil
}
func (r *DeleteResponse) SetBody(v *DeleteResponseBody) {
r.body = v
}
func (r *ListRequestBody) GetOwnerID() *refs.OwnerID {
if r != nil {
return r.ownerID
}
return nil
}
func (r *ListRequestBody) SetOwnerID(v *refs.OwnerID) {
r.ownerID = v
}
func (r *ListRequest) GetBody() *ListRequestBody {
if r != nil {
return r.body
}
return nil
}
func (r *ListRequest) SetBody(v *ListRequestBody) {
r.body = v
}
func (r *ListResponseBody) GetContainerIDs() []refs.ContainerID {
if r != nil {
return r.cidList
}
return nil
}
func (r *ListResponseBody) SetContainerIDs(v []refs.ContainerID) {
r.cidList = v
}
func (r *ListResponse) GetBody() *ListResponseBody {
if r != nil {
return r.body
}
return nil
}
func (r *ListResponse) SetBody(v *ListResponseBody) {
r.body = v
}
func (r *ListStreamRequestBody) GetOwnerID() *refs.OwnerID {
if r != nil {
return r.ownerID
}
return nil
}
func (r *ListStreamRequestBody) SetOwnerID(v *refs.OwnerID) {
r.ownerID = v
}
func (r *ListStreamRequest) GetBody() *ListStreamRequestBody {
if r != nil {
return r.body
}
return nil
}
func (r *ListStreamRequest) SetBody(v *ListStreamRequestBody) {
r.body = v
}
func (r *ListStreamResponseBody) GetContainerIDs() []refs.ContainerID {
if r != nil {
return r.cidList
}
return nil
}
func (r *ListStreamResponseBody) SetContainerIDs(v []refs.ContainerID) {
r.cidList = v
}
func (r *ListStreamResponse) GetBody() *ListStreamResponseBody {
if r != nil {
return r.body
}
return nil
}
func (r *ListStreamResponse) SetBody(v *ListStreamResponseBody) {
r.body = v
}

BIN
api/lock/grpc/types_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,26 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package lock
func DoFuzzProtoLock(data []byte) int {
msg := new(Lock)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONLock(data []byte) int {
msg := new(Lock)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,21 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package lock
import (
testing "testing"
)
func FuzzProtoLock(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoLock(data)
})
}
func FuzzJSONLock(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONLock(data)
})
}

916
api/netmap/convert.go Normal file
View file

@ -0,0 +1,916 @@
package netmap
import (
netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
refsGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message"
)
func (f *Filter) ToGRPCMessage() grpc.Message {
var m *netmap.Filter
if f != nil {
m = new(netmap.Filter)
m.SetKey(f.key)
m.SetValue(f.value)
m.SetName(f.name)
m.SetOp(OperationToGRPCMessage(f.op))
m.SetFilters(FiltersToGRPC(f.filters))
}
return m
}
func (f *Filter) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.Filter)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
f.filters, err = FiltersFromGRPC(v.GetFilters())
if err != nil {
return err
}
f.key = v.GetKey()
f.value = v.GetValue()
f.name = v.GetName()
f.op = OperationFromGRPCMessage(v.GetOp())
return nil
}
func FiltersToGRPC(fs []Filter) (res []netmap.Filter) {
if fs != nil {
res = make([]netmap.Filter, 0, len(fs))
for i := range fs {
res = append(res, *fs[i].ToGRPCMessage().(*netmap.Filter))
}
}
return
}
func FiltersFromGRPC(fs []netmap.Filter) (res []Filter, err error) {
if fs != nil {
res = make([]Filter, len(fs))
for i := range fs {
err = res[i].FromGRPCMessage(&fs[i])
if err != nil {
return
}
}
}
return
}
func (s *Selector) ToGRPCMessage() grpc.Message {
var m *netmap.Selector
if s != nil {
m = new(netmap.Selector)
m.SetName(s.name)
m.SetAttribute(s.attribute)
m.SetFilter(s.filter)
m.SetCount(s.count)
m.SetClause(ClauseToGRPCMessage(s.clause))
}
return m
}
func (s *Selector) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.Selector)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
s.name = v.GetName()
s.attribute = v.GetAttribute()
s.filter = v.GetFilter()
s.count = v.GetCount()
s.clause = ClauseFromGRPCMessage(v.GetClause())
return nil
}
func SelectorsToGRPC(ss []Selector) (res []netmap.Selector) {
if ss != nil {
res = make([]netmap.Selector, 0, len(ss))
for i := range ss {
res = append(res, *ss[i].ToGRPCMessage().(*netmap.Selector))
}
}
return
}
func SelectorsFromGRPC(ss []netmap.Selector) (res []Selector, err error) {
if ss != nil {
res = make([]Selector, len(ss))
for i := range ss {
err = res[i].FromGRPCMessage(&ss[i])
if err != nil {
return
}
}
}
return
}
func (r *Replica) ToGRPCMessage() grpc.Message {
var m *netmap.Replica
if r != nil {
m = new(netmap.Replica)
m.SetSelector(r.selector)
m.SetCount(r.count)
m.EcDataCount = r.ecDataCount
m.EcParityCount = r.ecParityCount
}
return m
}
func (r *Replica) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.Replica)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
r.selector = v.GetSelector()
r.count = v.GetCount()
r.ecDataCount = v.GetEcDataCount()
r.ecParityCount = v.GetEcParityCount()
return nil
}
func ReplicasToGRPC(rs []Replica) (res []netmap.Replica) {
if rs != nil {
res = make([]netmap.Replica, 0, len(rs))
for i := range rs {
res = append(res, *rs[i].ToGRPCMessage().(*netmap.Replica))
}
}
return
}
func ReplicasFromGRPC(rs []netmap.Replica) (res []Replica, err error) {
if rs != nil {
res = make([]Replica, len(rs))
for i := range rs {
err = res[i].FromGRPCMessage(&rs[i])
if err != nil {
return
}
}
}
return
}
func (p *PlacementPolicy) ToGRPCMessage() grpc.Message {
var m *netmap.PlacementPolicy
if p != nil {
m = new(netmap.PlacementPolicy)
m.SetFilters(FiltersToGRPC(p.filters))
m.SetSelectors(SelectorsToGRPC(p.selectors))
m.SetReplicas(ReplicasToGRPC(p.replicas))
m.SetContainerBackupFactor(p.backupFactor)
m.SetUnique(p.unique)
}
return m
}
func (p *PlacementPolicy) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.PlacementPolicy)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
p.filters, err = FiltersFromGRPC(v.GetFilters())
if err != nil {
return err
}
p.selectors, err = SelectorsFromGRPC(v.GetSelectors())
if err != nil {
return err
}
p.replicas, err = ReplicasFromGRPC(v.GetReplicas())
if err != nil {
return err
}
p.backupFactor = v.GetContainerBackupFactor()
p.unique = v.GetUnique()
return nil
}
func ClauseToGRPCMessage(n Clause) netmap.Clause {
return netmap.Clause(n)
}
func ClauseFromGRPCMessage(n netmap.Clause) Clause {
return Clause(n)
}
func OperationToGRPCMessage(n Operation) netmap.Operation {
return netmap.Operation(n)
}
func OperationFromGRPCMessage(n netmap.Operation) Operation {
return Operation(n)
}
func NodeStateToGRPCMessage(n NodeState) netmap.NodeInfo_State {
return netmap.NodeInfo_State(n)
}
func NodeStateFromRPCMessage(n netmap.NodeInfo_State) NodeState {
return NodeState(n)
}
func (a *Attribute) ToGRPCMessage() grpc.Message {
var m *netmap.NodeInfo_Attribute
if a != nil {
m = new(netmap.NodeInfo_Attribute)
m.SetKey(a.key)
m.SetValue(a.value)
m.SetParents(a.parents)
}
return m
}
func (a *Attribute) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NodeInfo_Attribute)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
a.key = v.GetKey()
a.value = v.GetValue()
a.parents = v.GetParents()
return nil
}
func AttributesToGRPC(as []Attribute) (res []netmap.NodeInfo_Attribute) {
if as != nil {
res = make([]netmap.NodeInfo_Attribute, 0, len(as))
for i := range as {
res = append(res, *as[i].ToGRPCMessage().(*netmap.NodeInfo_Attribute))
}
}
return
}
func AttributesFromGRPC(as []netmap.NodeInfo_Attribute) (res []Attribute, err error) {
if as != nil {
res = make([]Attribute, len(as))
for i := range as {
err = res[i].FromGRPCMessage(&as[i])
if err != nil {
return
}
}
}
return
}
func (ni *NodeInfo) ToGRPCMessage() grpc.Message {
var m *netmap.NodeInfo
if ni != nil {
m = new(netmap.NodeInfo)
m.SetPublicKey(ni.publicKey)
m.SetAddresses(ni.addresses)
m.SetState(NodeStateToGRPCMessage(ni.state))
m.SetAttributes(AttributesToGRPC(ni.attributes))
}
return m
}
func (ni *NodeInfo) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NodeInfo)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
ni.attributes, err = AttributesFromGRPC(v.GetAttributes())
if err != nil {
return err
}
ni.publicKey = v.GetPublicKey()
ni.addresses = v.GetAddresses()
ni.state = NodeStateFromRPCMessage(v.GetState())
return nil
}
func (l *LocalNodeInfoRequestBody) ToGRPCMessage() grpc.Message {
var m *netmap.LocalNodeInfoRequest_Body
if l != nil {
m = new(netmap.LocalNodeInfoRequest_Body)
}
return m
}
func (l *LocalNodeInfoRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.LocalNodeInfoRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
return nil
}
func (l *LocalNodeInfoRequest) ToGRPCMessage() grpc.Message {
var m *netmap.LocalNodeInfoRequest
if l != nil {
m = new(netmap.LocalNodeInfoRequest)
m.SetBody(l.body.ToGRPCMessage().(*netmap.LocalNodeInfoRequest_Body))
l.RequestHeaders.ToMessage(m)
}
return m
}
func (l *LocalNodeInfoRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.LocalNodeInfoRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
l.body = nil
} else {
if l.body == nil {
l.body = new(LocalNodeInfoRequestBody)
}
err = l.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return l.RequestHeaders.FromMessage(v)
}
func (l *LocalNodeInfoResponseBody) ToGRPCMessage() grpc.Message {
var m *netmap.LocalNodeInfoResponse_Body
if l != nil {
m = new(netmap.LocalNodeInfoResponse_Body)
m.SetVersion(l.version.ToGRPCMessage().(*refsGRPC.Version))
m.SetNodeInfo(l.nodeInfo.ToGRPCMessage().(*netmap.NodeInfo))
}
return m
}
func (l *LocalNodeInfoResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.LocalNodeInfoResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
version := v.GetVersion()
if version == nil {
l.version = nil
} else {
if l.version == nil {
l.version = new(refs.Version)
}
err = l.version.FromGRPCMessage(version)
if err != nil {
return err
}
}
nodeInfo := v.GetNodeInfo()
if nodeInfo == nil {
l.nodeInfo = nil
} else {
if l.nodeInfo == nil {
l.nodeInfo = new(NodeInfo)
}
err = l.nodeInfo.FromGRPCMessage(nodeInfo)
}
return err
}
func (l *LocalNodeInfoResponse) ToGRPCMessage() grpc.Message {
var m *netmap.LocalNodeInfoResponse
if l != nil {
m = new(netmap.LocalNodeInfoResponse)
m.SetBody(l.body.ToGRPCMessage().(*netmap.LocalNodeInfoResponse_Body))
l.ResponseHeaders.ToMessage(m)
}
return m
}
func (l *LocalNodeInfoResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.LocalNodeInfoResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
l.body = nil
} else {
if l.body == nil {
l.body = new(LocalNodeInfoResponseBody)
}
err = l.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return l.ResponseHeaders.FromMessage(v)
}
func (x *NetworkParameter) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkConfig_Parameter
if x != nil {
m = new(netmap.NetworkConfig_Parameter)
m.SetKey(x.k)
m.SetValue(x.v)
}
return m
}
func (x *NetworkParameter) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkConfig_Parameter)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
x.k = v.GetKey()
x.v = v.GetValue()
return nil
}
func (x *NetworkConfig) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkConfig
if x != nil {
m = new(netmap.NetworkConfig)
var ps []netmap.NetworkConfig_Parameter
if ln := len(x.ps); ln > 0 {
ps = make([]netmap.NetworkConfig_Parameter, 0, ln)
for i := range ln {
ps = append(ps, *x.ps[i].ToGRPCMessage().(*netmap.NetworkConfig_Parameter))
}
}
m.SetParameters(ps)
}
return m
}
func (x *NetworkConfig) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkConfig)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var (
ps []NetworkParameter
psV2 = v.GetParameters()
)
if psV2 != nil {
ln := len(psV2)
ps = make([]NetworkParameter, ln)
for i := range ln {
if err := ps[i].FromGRPCMessage(&psV2[i]); err != nil {
return err
}
}
}
x.ps = ps
return nil
}
func (i *NetworkInfo) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkInfo
if i != nil {
m = new(netmap.NetworkInfo)
m.SetMagicNumber(i.magicNum)
m.SetCurrentEpoch(i.curEpoch)
m.SetMsPerBlock(i.msPerBlock)
m.SetNetworkConfig(i.netCfg.ToGRPCMessage().(*netmap.NetworkConfig))
}
return m
}
func (i *NetworkInfo) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkInfo)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
netCfg := v.GetNetworkConfig()
if netCfg == nil {
i.netCfg = nil
} else {
if i.netCfg == nil {
i.netCfg = new(NetworkConfig)
}
err = i.netCfg.FromGRPCMessage(netCfg)
if err != nil {
return err
}
}
i.magicNum = v.GetMagicNumber()
i.curEpoch = v.GetCurrentEpoch()
i.msPerBlock = v.GetMsPerBlock()
return nil
}
func (l *NetworkInfoRequestBody) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkInfoRequest_Body
if l != nil {
m = new(netmap.NetworkInfoRequest_Body)
}
return m
}
func (l *NetworkInfoRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkInfoRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
return nil
}
func (l *NetworkInfoRequest) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkInfoRequest
if l != nil {
m = new(netmap.NetworkInfoRequest)
m.SetBody(l.body.ToGRPCMessage().(*netmap.NetworkInfoRequest_Body))
l.RequestHeaders.ToMessage(m)
}
return m
}
func (l *NetworkInfoRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkInfoRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
l.body = nil
} else {
if l.body == nil {
l.body = new(NetworkInfoRequestBody)
}
err = l.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return l.RequestHeaders.FromMessage(v)
}
func (i *NetworkInfoResponseBody) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkInfoResponse_Body
if i != nil {
m = new(netmap.NetworkInfoResponse_Body)
m.SetNetworkInfo(i.netInfo.ToGRPCMessage().(*netmap.NetworkInfo))
}
return m
}
func (i *NetworkInfoResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkInfoResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
netInfo := v.GetNetworkInfo()
if netInfo == nil {
i.netInfo = nil
} else {
if i.netInfo == nil {
i.netInfo = new(NetworkInfo)
}
err = i.netInfo.FromGRPCMessage(netInfo)
}
return err
}
func (l *NetworkInfoResponse) ToGRPCMessage() grpc.Message {
var m *netmap.NetworkInfoResponse
if l != nil {
m = new(netmap.NetworkInfoResponse)
m.SetBody(l.body.ToGRPCMessage().(*netmap.NetworkInfoResponse_Body))
l.ResponseHeaders.ToMessage(m)
}
return m
}
func (l *NetworkInfoResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetworkInfoResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
l.body = nil
} else {
if l.body == nil {
l.body = new(NetworkInfoResponseBody)
}
err = l.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return l.ResponseHeaders.FromMessage(v)
}
func (x *NetMap) ToGRPCMessage() grpc.Message {
var m *netmap.Netmap
if x != nil {
m = new(netmap.Netmap)
m.SetEpoch(x.epoch)
if x.nodes != nil {
nodes := make([]netmap.NodeInfo, len(x.nodes))
for i := range x.nodes {
nodes[i] = *x.nodes[i].ToGRPCMessage().(*netmap.NodeInfo)
}
m.SetNodes(nodes)
}
}
return m
}
func (x *NetMap) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.Netmap)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
nodes := v.GetNodes()
if nodes == nil {
x.nodes = nil
} else {
x.nodes = make([]NodeInfo, len(nodes))
for i := range nodes {
err = x.nodes[i].FromGRPCMessage(&nodes[i])
if err != nil {
return err
}
}
}
x.epoch = v.GetEpoch()
return nil
}
func (x *SnapshotRequestBody) ToGRPCMessage() grpc.Message {
var m *netmap.NetmapSnapshotRequest_Body
if x != nil {
m = new(netmap.NetmapSnapshotRequest_Body)
}
return m
}
func (x *SnapshotRequestBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetmapSnapshotRequest_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
return nil
}
func (x *SnapshotRequest) ToGRPCMessage() grpc.Message {
var m *netmap.NetmapSnapshotRequest
if x != nil {
m = new(netmap.NetmapSnapshotRequest)
m.SetBody(x.body.ToGRPCMessage().(*netmap.NetmapSnapshotRequest_Body))
x.RequestHeaders.ToMessage(m)
}
return m
}
func (x *SnapshotRequest) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetmapSnapshotRequest)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
x.body = nil
} else {
if x.body == nil {
x.body = new(SnapshotRequestBody)
}
err = x.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return x.RequestHeaders.FromMessage(v)
}
func (x *SnapshotResponseBody) ToGRPCMessage() grpc.Message {
var m *netmap.NetmapSnapshotResponse_Body
if x != nil {
m = new(netmap.NetmapSnapshotResponse_Body)
m.SetNetmap(x.netMap.ToGRPCMessage().(*netmap.Netmap))
}
return m
}
func (x *SnapshotResponseBody) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetmapSnapshotResponse_Body)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
netMap := v.GetNetmap()
if netMap == nil {
x.netMap = nil
} else {
if x.netMap == nil {
x.netMap = new(NetMap)
}
err = x.netMap.FromGRPCMessage(netMap)
}
return err
}
func (x *SnapshotResponse) ToGRPCMessage() grpc.Message {
var m *netmap.NetmapSnapshotResponse
if x != nil {
m = new(netmap.NetmapSnapshotResponse)
m.SetBody(x.body.ToGRPCMessage().(*netmap.NetmapSnapshotResponse_Body))
x.ResponseHeaders.ToMessage(m)
}
return m
}
func (x *SnapshotResponse) FromGRPCMessage(m grpc.Message) error {
v, ok := m.(*netmap.NetmapSnapshotResponse)
if !ok {
return message.NewUnexpectedMessageType(m, v)
}
var err error
body := v.GetBody()
if body == nil {
x.body = nil
} else {
if x.body == nil {
x.body = new(SnapshotResponseBody)
}
err = x.body.FromGRPCMessage(body)
if err != nil {
return err
}
}
return x.ResponseHeaders.FromMessage(v)
}

BIN
api/netmap/grpc/service_frostfs.pb.go generated Normal file

Binary file not shown.

View file

@ -0,0 +1,121 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package netmap
func DoFuzzProtoLocalNodeInfoRequest(data []byte) int {
msg := new(LocalNodeInfoRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONLocalNodeInfoRequest(data []byte) int {
msg := new(LocalNodeInfoRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoLocalNodeInfoResponse(data []byte) int {
msg := new(LocalNodeInfoResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONLocalNodeInfoResponse(data []byte) int {
msg := new(LocalNodeInfoResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoNetworkInfoRequest(data []byte) int {
msg := new(NetworkInfoRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONNetworkInfoRequest(data []byte) int {
msg := new(NetworkInfoRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoNetworkInfoResponse(data []byte) int {
msg := new(NetworkInfoResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONNetworkInfoResponse(data []byte) int {
msg := new(NetworkInfoResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoNetmapSnapshotRequest(data []byte) int {
msg := new(NetmapSnapshotRequest)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONNetmapSnapshotRequest(data []byte) int {
msg := new(NetmapSnapshotRequest)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}
func DoFuzzProtoNetmapSnapshotResponse(data []byte) int {
msg := new(NetmapSnapshotResponse)
if err := msg.UnmarshalProtobuf(data); err != nil {
return 0
}
_ = msg.MarshalProtobuf(nil)
return 1
}
func DoFuzzJSONNetmapSnapshotResponse(data []byte) int {
msg := new(NetmapSnapshotResponse)
if err := msg.UnmarshalJSON(data); err != nil {
return 0
}
_, err := msg.MarshalJSON()
if err != nil {
panic(err)
}
return 1
}

View file

@ -0,0 +1,71 @@
//go:build gofuzz
// +build gofuzz
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
package netmap
import (
testing "testing"
)
func FuzzProtoLocalNodeInfoRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoLocalNodeInfoRequest(data)
})
}
func FuzzJSONLocalNodeInfoRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONLocalNodeInfoRequest(data)
})
}
func FuzzProtoLocalNodeInfoResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoLocalNodeInfoResponse(data)
})
}
func FuzzJSONLocalNodeInfoResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONLocalNodeInfoResponse(data)
})
}
func FuzzProtoNetworkInfoRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoNetworkInfoRequest(data)
})
}
func FuzzJSONNetworkInfoRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONNetworkInfoRequest(data)
})
}
func FuzzProtoNetworkInfoResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoNetworkInfoResponse(data)
})
}
func FuzzJSONNetworkInfoResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONNetworkInfoResponse(data)
})
}
func FuzzProtoNetmapSnapshotRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoNetmapSnapshotRequest(data)
})
}
func FuzzJSONNetmapSnapshotRequest(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONNetmapSnapshotRequest(data)
})
}
func FuzzProtoNetmapSnapshotResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzProtoNetmapSnapshotResponse(data)
})
}
func FuzzJSONNetmapSnapshotResponse(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
DoFuzzJSONNetmapSnapshotResponse(data)
})
}

BIN
api/netmap/grpc/service_grpc.pb.go generated Normal file

Binary file not shown.

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