forked from TrueCloudLab/frostfs-node
Compare commits
147 commits
Author | SHA1 | Date | |
---|---|---|---|
d7fcc5ce30 | |||
c0221d76e6 | |||
242f0095d0 | |||
6fe34d266a | |||
fa08bfa553 | |||
0da998ef50 | |||
e44782473a | |||
9cd1bcef06 | |||
ca0a33ea0f | |||
f6c5222952 | |||
ea868e09f8 | |||
31d3d299bf | |||
b5b4f78b49 | |||
2832f44437 | |||
7c3bcb0f44 | |||
e64871c3fd | |||
303cd35a01 | |||
bb9ba1bce2 | |||
db03742d33 | |||
148d68933b | |||
51ee132ea3 | |||
226dd25dd0 | |||
bd0197eaa8 | |||
e44b84c18c | |||
bed49e6ace | |||
df05057ed4 | |||
b6c8ebf493 | |||
6e82661c35 | |||
1a091ea7bb | |||
7ac3542714 | |||
f0c43c8d80 | |||
8ba9f31fca | |||
2af3409d39 | |||
d165ac042c | |||
7151c71d51 | |||
91d9dc2676 | |||
7853dbc315 | |||
3821645085 | |||
72470d6b48 | |||
e9837bbcf9 | |||
a641c91594 | |||
b1614a284d | |||
d0ce835fbf | |||
dfa51048a8 | |||
670305a721 | |||
1f6cf57e30 | |||
386a12eea4 | |||
15139d80c9 | |||
41da27dad5 | |||
ac0511d214 | |||
7e542906ef | |||
d1bc4351c3 | |||
1c12f23b84 | |||
a353d45742 | |||
d5c46d812a | |||
d5d5ce2074 | |||
7df3520d48 | |||
5fe78e51d1 | |||
84b4051b4d | |||
6a51086030 | |||
5c3b2d95ba | |||
2d5d4093be | |||
e3487d5af5 | |||
e37dcdf88b | |||
6c679d1535 | |||
281d65435e | |||
b348b20289 | |||
748edd1999 | |||
47dfd8840c | |||
432042c534 | |||
9cabca9dfe | |||
60feed3b5f | |||
635a292ae4 | |||
edfa3f4825 | |||
e0ac3a583f | |||
00c608c05e | |||
bba1892fa1 | |||
01acec708f | |||
aac65001e5 | |||
1170370753 | |||
9e275d44c8 | |||
2469e0c683 | |||
a6ef4ab524 | |||
49959c4166 | |||
61ee1b5610 | |||
b10c954377 | |||
1605391628 | |||
b1766e47c7 | |||
caa4253249 | |||
7eac5fb18b | |||
0e5524dac7 | |||
3ebd560f42 | |||
1ed7ab75fb | |||
99f9e59de9 | |||
256f96e252 | |||
e5ea95c045 | |||
9073e555db | |||
2771fdb8c7 | |||
efa4ce00b8 | |||
f12f04199e | |||
2e2c62147d | |||
6ae8667fb4 | |||
49a4e727fd | |||
2e974f734c | |||
3042490340 | |||
a339b52a60 | |||
4ab4ed6f96 | |||
3b1364e4cf | |||
daff77b273 | |||
7a7ee71a4d | |||
ffe9906266 | |||
ae31ef3602 | |||
e2cb0640f1 | |||
9f4ce600ac | |||
d82f0d1926 | |||
acd5babd86 | |||
b65874d1c3 | |||
69c63006da | |||
d77a218f7c | |||
44df67492f | |||
1e6f132b4e | |||
6dc0dc6691 | |||
f7cb6b4d87 | |||
7fc6101bec | |||
7ef36749d0 | |||
c6066d6ee4 | |||
612b34d570 | |||
7429553266 | |||
6921a89061 | |||
16598553d9 | |||
c139892117 | |||
62b5181618 | |||
6db46257c0 | |||
c16dae8b4d | |||
fd004add00 | |||
8ed7a676d5 | |||
b451de94c8 | |||
f1556e3c42 | |||
e122ff6013 | |||
e2658c7519 | |||
c00f4bab18 | |||
46fef276b4 | |||
9bd05e94c8 | |||
16830033f8 | |||
1cf51a8079 | |||
3324c26fd8 | |||
a692298533 |
492 changed files with 5521 additions and 5514 deletions
|
@ -1,6 +1,10 @@
|
||||||
name: Build
|
name: Build
|
||||||
|
|
||||||
on: [pull_request]
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
name: Pre-commit hooks
|
name: Pre-commit hooks
|
||||||
on: [pull_request]
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
precommit:
|
precommit:
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
name: Tests and linters
|
name: Tests and linters
|
||||||
on: [pull_request]
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
name: Vulncheck
|
name: Vulncheck
|
||||||
on: [pull_request]
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
vulncheck:
|
vulncheck:
|
||||||
|
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -9,6 +9,30 @@ Changelog for FrostFS Node
|
||||||
### Removed
|
### Removed
|
||||||
### Updated
|
### Updated
|
||||||
|
|
||||||
|
## [v0.44.0] - 2024-25-11 - Rongbuk
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Allow to prioritize nodes during GET traversal via attributes (#1439)
|
||||||
|
- Add metrics for the frostfsid cache (#1464)
|
||||||
|
- Customize constant attributes attached to every tracing span (#1488)
|
||||||
|
- Manage additional keys in the `frostfsid` contract (#1505)
|
||||||
|
- Describe `--rule` flag in detail for `frostfs-cli ape-manager` subcommands (#1519)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Support richer interaction with the console in `frostfs-cli container policy-playground` (#1396)
|
||||||
|
- Print address in base58 format in `frostfs-adm morph policy set-admin` (#1515)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix EC object search (#1408)
|
||||||
|
- Fix EC object put when one of the nodes is unavailable (#1427)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Drop most of the eACL-related code (#1425)
|
||||||
|
- Remove `--basic-acl` flag from `frostfs-cli container create` (#1483)
|
||||||
|
|
||||||
|
### Upgrading from v0.43.0
|
||||||
|
The metabase schema has changed completely, resync is required.
|
||||||
|
|
||||||
## [v0.42.0]
|
## [v0.42.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
3
CODEOWNERS
Normal file
3
CODEOWNERS
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.* @TrueCloudLab/storage-core-committers @TrueCloudLab/storage-core-developers
|
||||||
|
.forgejo/.* @potyarkin
|
||||||
|
Makefile @potyarkin
|
17
Makefile
17
Makefile
|
@ -8,8 +8,8 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs
|
||||||
HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')"
|
HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')"
|
||||||
|
|
||||||
GO_VERSION ?= 1.22
|
GO_VERSION ?= 1.22
|
||||||
LINT_VERSION ?= 1.61.0
|
LINT_VERSION ?= 1.62.0
|
||||||
TRUECLOUDLAB_LINT_VERSION ?= 0.0.7
|
TRUECLOUDLAB_LINT_VERSION ?= 0.0.8
|
||||||
PROTOC_VERSION ?= 25.0
|
PROTOC_VERSION ?= 25.0
|
||||||
PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go)
|
PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go)
|
||||||
PROTOC_OS_VERSION=osx-x86_64
|
PROTOC_OS_VERSION=osx-x86_64
|
||||||
|
@ -270,10 +270,12 @@ env-up: all
|
||||||
echo "Frostfs contracts not found"; exit 1; \
|
echo "Frostfs contracts not found"; exit 1; \
|
||||||
fi
|
fi
|
||||||
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph init --contracts ${FROSTFS_CONTRACTS_PATH}
|
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph init --contracts ${FROSTFS_CONTRACTS_PATH}
|
||||||
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet01.json --gas 10.0
|
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --gas 10.0 \
|
||||||
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet02.json --gas 10.0
|
--storage-wallet ./dev/storage/wallet01.json \
|
||||||
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet03.json --gas 10.0
|
--storage-wallet ./dev/storage/wallet02.json \
|
||||||
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet04.json --gas 10.0
|
--storage-wallet ./dev/storage/wallet03.json \
|
||||||
|
--storage-wallet ./dev/storage/wallet04.json
|
||||||
|
|
||||||
@if [ ! -f "$(LOCODE_DB_PATH)" ]; then \
|
@if [ ! -f "$(LOCODE_DB_PATH)" ]; then \
|
||||||
make locode-download; \
|
make locode-download; \
|
||||||
fi
|
fi
|
||||||
|
@ -282,7 +284,6 @@ env-up: all
|
||||||
|
|
||||||
# Shutdown dev environment
|
# Shutdown dev environment
|
||||||
env-down:
|
env-down:
|
||||||
docker compose -f dev/docker-compose.yml down
|
docker compose -f dev/docker-compose.yml down -v
|
||||||
docker volume rm -f frostfs-node_neo-go
|
|
||||||
rm -rf ./$(TMP_DIR)/state
|
rm -rf ./$(TMP_DIR)/state
|
||||||
rm -rf ./$(TMP_DIR)/storage
|
rm -rf ./$(TMP_DIR)/storage
|
||||||
|
|
|
@ -98,7 +98,7 @@ See `frostfs-contract`'s README.md for build instructions.
|
||||||
4. To create container and put object into it run (container and object IDs will be different):
|
4. To create container and put object into it run (container and object IDs will be different):
|
||||||
|
|
||||||
```
|
```
|
||||||
./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --basic-acl public-read-write --await
|
./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --await
|
||||||
Enter password > <- press ENTER, the is no password for wallet
|
Enter password > <- press ENTER, the is no password for wallet
|
||||||
CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju
|
CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
v0.42.0
|
v0.44.0
|
||||||
|
|
|
@ -20,6 +20,7 @@ const (
|
||||||
AlphabetWalletsFlagDesc = "Path to alphabet wallets dir"
|
AlphabetWalletsFlagDesc = "Path to alphabet wallets dir"
|
||||||
|
|
||||||
LocalDumpFlag = "local-dump"
|
LocalDumpFlag = "local-dump"
|
||||||
|
ProtoConfigPath = "protocol"
|
||||||
ContractsInitFlag = "contracts"
|
ContractsInitFlag = "contracts"
|
||||||
ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)"
|
ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)"
|
||||||
ContractsURLFlag = "contracts-url"
|
ContractsURLFlag = "contracts-url"
|
||||||
|
|
|
@ -135,7 +135,7 @@ func createContainerInfoProvider(cli *client.Client) (container.InfoProvider, er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("resolve container contract hash: %w", err)
|
return nil, fmt.Errorf("resolve container contract hash: %w", err)
|
||||||
}
|
}
|
||||||
cc, err := morphcontainer.NewFromMorph(cli, sh, 0, morphcontainer.TryNotary())
|
cc, err := morphcontainer.NewFromMorph(cli, sh, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("create morph container client: %w", err)
|
return nil, fmt.Errorf("create morph container client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,35 +5,19 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
namespaceTarget = "namespace"
|
jsonFlag = "json"
|
||||||
containerTarget = "container"
|
jsonFlagDesc = "Output rule chains in JSON format"
|
||||||
userTarget = "user"
|
addrAdminFlag = "addr"
|
||||||
groupTarget = "group"
|
addrAdminDesc = "The address of the admins wallet"
|
||||||
jsonFlag = "json"
|
|
||||||
jsonFlagDesc = "Output rule chains in JSON format"
|
|
||||||
chainIDFlag = "chain-id"
|
|
||||||
chainIDDesc = "Rule chain ID"
|
|
||||||
ruleFlag = "rule"
|
|
||||||
ruleFlagDesc = "Rule chain in text format"
|
|
||||||
pathFlag = "path"
|
|
||||||
pathFlagDesc = "path to encoded chain in JSON or binary format"
|
|
||||||
targetNameFlag = "target-name"
|
|
||||||
targetNameDesc = "Resource name in APE resource name format"
|
|
||||||
targetTypeFlag = "target-type"
|
|
||||||
targetTypeDesc = "Resource type(container/namespace)"
|
|
||||||
addrAdminFlag = "addr"
|
|
||||||
addrAdminDesc = "The address of the admins wallet"
|
|
||||||
chainNameFlag = "chain-name"
|
|
||||||
chainNameFlagDesc = "Chain name(ingress|s3)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -101,17 +85,17 @@ func initAddRuleChainCmd() {
|
||||||
addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||||
|
|
||||||
addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc)
|
addRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag)
|
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
addRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc)
|
addRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = addRuleChainCmd.MarkFlagRequired(targetNameFlag)
|
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag)
|
||||||
|
|
||||||
addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc)
|
addRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||||
_ = addRuleChainCmd.MarkFlagRequired(chainIDFlag)
|
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.ChainIDFlag)
|
||||||
addRuleChainCmd.Flags().StringArray(ruleFlag, []string{}, ruleFlagDesc)
|
addRuleChainCmd.Flags().StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc)
|
||||||
addRuleChainCmd.Flags().String(pathFlag, "", pathFlagDesc)
|
addRuleChainCmd.Flags().String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc)
|
||||||
addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
|
addRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
|
||||||
addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, pathFlag)
|
addRuleChainCmd.MarkFlagsMutuallyExclusive(apeCmd.RuleFlag, apeCmd.PathFlag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initRemoveRuleChainCmd() {
|
func initRemoveRuleChainCmd() {
|
||||||
|
@ -120,26 +104,25 @@ func initRemoveRuleChainCmd() {
|
||||||
removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||||
|
|
||||||
removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc)
|
removeRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag)
|
_ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc)
|
removeRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
_ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag)
|
_ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag)
|
||||||
removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc)
|
removeRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||||
removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
|
removeRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
|
||||||
removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target")
|
removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target")
|
||||||
removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, chainIDFlag)
|
removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, apeCmd.ChainIDFlag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initListRuleChainsCmd() {
|
func initListRuleChainsCmd() {
|
||||||
Cmd.AddCommand(listRuleChainsCmd)
|
Cmd.AddCommand(listRuleChainsCmd)
|
||||||
|
|
||||||
listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc)
|
listRuleChainsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag)
|
_ = listRuleChainsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc)
|
listRuleChainsCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
_ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag)
|
|
||||||
listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc)
|
listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc)
|
||||||
listRuleChainsCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
|
listRuleChainsCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initSetAdminCmd() {
|
func initSetAdminCmd() {
|
||||||
|
@ -161,15 +144,15 @@ func initListTargetsCmd() {
|
||||||
Cmd.AddCommand(listTargetsCmd)
|
Cmd.AddCommand(listTargetsCmd)
|
||||||
|
|
||||||
listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
listTargetsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc)
|
listTargetsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = listTargetsCmd.MarkFlagRequired(targetTypeFlag)
|
_ = listTargetsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRuleChain(cmd *cobra.Command, _ []string) {
|
func addRuleChain(cmd *cobra.Command, _ []string) {
|
||||||
chain := parseChain(cmd)
|
chain := apeCmd.ParseChain(cmd)
|
||||||
target := parseTarget(cmd)
|
target := parseTarget(cmd)
|
||||||
pci, ac := newPolicyContractInterface(cmd)
|
pci, ac := newPolicyContractInterface(cmd)
|
||||||
h, vub, err := pci.AddMorphRuleChain(parseChainName(cmd), target, chain)
|
h, vub, err := pci.AddMorphRuleChain(apeCmd.ParseChainName(cmd), target, chain)
|
||||||
cmd.Println("Waiting for transaction to persist...")
|
cmd.Println("Waiting for transaction to persist...")
|
||||||
_, err = ac.Wait(h, vub, err)
|
_, err = ac.Wait(h, vub, err)
|
||||||
commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err)
|
commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err)
|
||||||
|
@ -181,14 +164,14 @@ func removeRuleChain(cmd *cobra.Command, _ []string) {
|
||||||
pci, ac := newPolicyContractInterface(cmd)
|
pci, ac := newPolicyContractInterface(cmd)
|
||||||
removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag)
|
removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag)
|
||||||
if removeAll {
|
if removeAll {
|
||||||
h, vub, err := pci.RemoveMorphRuleChainsByTarget(parseChainName(cmd), target)
|
h, vub, err := pci.RemoveMorphRuleChainsByTarget(apeCmd.ParseChainName(cmd), target)
|
||||||
cmd.Println("Waiting for transaction to persist...")
|
cmd.Println("Waiting for transaction to persist...")
|
||||||
_, err = ac.Wait(h, vub, err)
|
_, err = ac.Wait(h, vub, err)
|
||||||
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
|
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
|
||||||
cmd.Println("All chains for target removed successfully")
|
cmd.Println("All chains for target removed successfully")
|
||||||
} else {
|
} else {
|
||||||
chainID := parseChainID(cmd)
|
chainID := apeCmd.ParseChainID(cmd)
|
||||||
h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID)
|
h, vub, err := pci.RemoveMorphRuleChain(apeCmd.ParseChainName(cmd), target, chainID)
|
||||||
cmd.Println("Waiting for transaction to persist...")
|
cmd.Println("Waiting for transaction to persist...")
|
||||||
_, err = ac.Wait(h, vub, err)
|
_, err = ac.Wait(h, vub, err)
|
||||||
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
|
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
|
||||||
|
@ -199,7 +182,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) {
|
||||||
func listRuleChains(cmd *cobra.Command, _ []string) {
|
func listRuleChains(cmd *cobra.Command, _ []string) {
|
||||||
target := parseTarget(cmd)
|
target := parseTarget(cmd)
|
||||||
pci, _ := newPolicyContractReaderInterface(cmd)
|
pci, _ := newPolicyContractReaderInterface(cmd)
|
||||||
chains, err := pci.ListMorphRuleChains(parseChainName(cmd), target)
|
chains, err := pci.ListMorphRuleChains(apeCmd.ParseChainName(cmd), target)
|
||||||
commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err)
|
commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err)
|
||||||
if len(chains) == 0 {
|
if len(chains) == 0 {
|
||||||
return
|
return
|
||||||
|
@ -210,14 +193,14 @@ func listRuleChains(cmd *cobra.Command, _ []string) {
|
||||||
prettyJSONFormat(cmd, chains)
|
prettyJSONFormat(cmd, chains)
|
||||||
} else {
|
} else {
|
||||||
for _, c := range chains {
|
for _, c := range chains {
|
||||||
parseutil.PrintHumanReadableAPEChain(cmd, c)
|
apeCmd.PrintHumanReadableAPEChain(cmd, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setAdmin(cmd *cobra.Command, _ []string) {
|
func setAdmin(cmd *cobra.Command, _ []string) {
|
||||||
s, _ := cmd.Flags().GetString(addrAdminFlag)
|
s, _ := cmd.Flags().GetString(addrAdminFlag)
|
||||||
addr, err := util.Uint160DecodeStringLE(s)
|
addr, err := address.StringToUint160(s)
|
||||||
commonCmd.ExitOnErr(cmd, "can't decode admin addr: %w", err)
|
commonCmd.ExitOnErr(cmd, "can't decode admin addr: %w", err)
|
||||||
pci, ac := newPolicyContractInterface(cmd)
|
pci, ac := newPolicyContractInterface(cmd)
|
||||||
h, vub, err := pci.SetAdmin(addr)
|
h, vub, err := pci.SetAdmin(addr)
|
||||||
|
@ -231,12 +214,11 @@ func getAdmin(cmd *cobra.Command, _ []string) {
|
||||||
pci, _ := newPolicyContractReaderInterface(cmd)
|
pci, _ := newPolicyContractReaderInterface(cmd)
|
||||||
addr, err := pci.GetAdmin()
|
addr, err := pci.GetAdmin()
|
||||||
commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err)
|
||||||
cmd.Println(addr.StringLE())
|
cmd.Println(address.Uint160ToString(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func listTargets(cmd *cobra.Command, _ []string) {
|
func listTargets(cmd *cobra.Command, _ []string) {
|
||||||
typ, err := parseTargetType(cmd)
|
typ := apeCmd.ParseTargetType(cmd)
|
||||||
commonCmd.ExitOnErr(cmd, "parse target type error: %w", err)
|
|
||||||
pci, inv := newPolicyContractReaderInterface(cmd)
|
pci, inv := newPolicyContractReaderInterface(cmd)
|
||||||
|
|
||||||
sid, it, err := pci.ListTargetsIterator(typ)
|
sid, it, err := pci.ListTargetsIterator(typ)
|
||||||
|
|
|
@ -2,13 +2,12 @@ package ape
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
||||||
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy"
|
morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
|
@ -18,90 +17,29 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var errUnknownTargetType = errors.New("unknown target type")
|
||||||
ingress = "ingress"
|
|
||||||
s3 = "s3"
|
|
||||||
)
|
|
||||||
|
|
||||||
var mChainName = map[string]apechain.Name{
|
|
||||||
ingress: apechain.Ingress,
|
|
||||||
s3: apechain.S3,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errUnknownTargetType = errors.New("unknown target type")
|
|
||||||
errChainIDCannotBeEmpty = errors.New("chain id cannot be empty")
|
|
||||||
errRuleIsNotParsed = errors.New("rule is not passed")
|
|
||||||
errUnsupportedChainName = errors.New("unsupported chain name")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseTarget(cmd *cobra.Command) policyengine.Target {
|
func parseTarget(cmd *cobra.Command) policyengine.Target {
|
||||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
typ := apeCmd.ParseTargetType(cmd)
|
||||||
typ, err := parseTargetType(cmd)
|
name, _ := cmd.Flags().GetString(apeCmd.TargetNameFlag)
|
||||||
|
|
||||||
// interpret "root" namespace as empty
|
|
||||||
if typ == policyengine.Namespace && name == "root" {
|
|
||||||
name = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
commonCmd.ExitOnErr(cmd, "read target type error: %w", err)
|
|
||||||
|
|
||||||
return policyengine.Target{
|
|
||||||
Name: name,
|
|
||||||
Type: typ,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseTargetType(cmd *cobra.Command) (policyengine.TargetType, error) {
|
|
||||||
typ, _ := cmd.Flags().GetString(targetTypeFlag)
|
|
||||||
switch typ {
|
switch typ {
|
||||||
case namespaceTarget:
|
case policyengine.Namespace:
|
||||||
return policyengine.Namespace, nil
|
if name == "root" {
|
||||||
case containerTarget:
|
name = ""
|
||||||
return policyengine.Container, nil
|
}
|
||||||
case userTarget:
|
return policyengine.NamespaceTarget(name)
|
||||||
return policyengine.User, nil
|
case policyengine.Container:
|
||||||
case groupTarget:
|
var cnr cid.ID
|
||||||
return policyengine.Group, nil
|
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
|
||||||
|
return policyengine.ContainerTarget(name)
|
||||||
|
case policyengine.User:
|
||||||
|
return policyengine.UserTarget(name)
|
||||||
|
case policyengine.Group:
|
||||||
|
return policyengine.GroupTarget(name)
|
||||||
|
default:
|
||||||
|
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
|
||||||
}
|
}
|
||||||
return -1, errUnknownTargetType
|
panic("unreachable")
|
||||||
}
|
|
||||||
|
|
||||||
func parseChainID(cmd *cobra.Command) apechain.ID {
|
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
|
||||||
if chainID == "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w",
|
|
||||||
errChainIDCannotBeEmpty)
|
|
||||||
}
|
|
||||||
return apechain.ID(chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseChain(cmd *cobra.Command) *apechain.Chain {
|
|
||||||
chain := new(apechain.Chain)
|
|
||||||
|
|
||||||
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules))
|
|
||||||
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath))
|
|
||||||
} else {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed)
|
|
||||||
}
|
|
||||||
|
|
||||||
chain.ID = parseChainID(cmd)
|
|
||||||
|
|
||||||
cmd.Println("Parsed chain:")
|
|
||||||
parseutil.PrintHumanReadableAPEChain(cmd, chain)
|
|
||||||
|
|
||||||
return chain
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseChainName(cmd *cobra.Command) apechain.Name {
|
|
||||||
chainName, _ := cmd.Flags().GetString(chainNameFlag)
|
|
||||||
apeChainName, ok := mChainName[strings.ToLower(chainName)]
|
|
||||||
if !ok {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName)
|
|
||||||
}
|
|
||||||
return apeChainName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// invokerAdapter adapats invoker.Invoker to ContractStorageInvoker interface.
|
// invokerAdapter adapats invoker.Invoker to ContractStorageInvoker interface.
|
||||||
|
@ -115,16 +53,15 @@ func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorageReader, *invoker.Invoker) {
|
func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorageReader, *invoker.Invoker) {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
var ch util.Uint160
|
|
||||||
r := management.NewReader(inv)
|
r := management.NewReader(inv)
|
||||||
nnsCs, err := helper.GetContractByID(r, 1)
|
nnsCs, err := helper.GetContractByID(r, 1)
|
||||||
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
|
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
|
||||||
|
|
||||||
ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract))
|
ch, err := helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract))
|
||||||
commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err)
|
||||||
|
|
||||||
invokerAdapter := &invokerAdapter{
|
invokerAdapter := &invokerAdapter{
|
||||||
|
@ -136,7 +73,7 @@ func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorag
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) {
|
func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
||||||
|
|
||||||
ac, err := helper.NewLocalActor(cmd, c, constants.ConsensusAccountName)
|
ac, err := helper.NewLocalActor(cmd, c, constants.ConsensusAccountName)
|
||||||
|
|
|
@ -51,7 +51,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
|
||||||
nmHash util.Uint160
|
nmHash util.Uint160
|
||||||
)
|
)
|
||||||
|
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
const forceConfigSet = "force"
|
const forceConfigSet = "force"
|
||||||
|
|
||||||
func dumpNetworkConfig(cmd *cobra.Command, _ []string) error {
|
func dumpNetworkConfig(cmd *cobra.Command, _ []string) error {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create N3 client: %w", err)
|
return fmt.Errorf("can't create N3 client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import "time"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ConsensusAccountName = "consensus"
|
ConsensusAccountName = "consensus"
|
||||||
ProtoConfigPath = "protocol"
|
|
||||||
|
|
||||||
// MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size
|
// MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size
|
||||||
// of the invocation script.
|
// of the invocation script.
|
||||||
|
|
|
@ -76,7 +76,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("invalid filename: %w", err)
|
return fmt.Errorf("invalid filename: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create N3 client: %w", err)
|
return fmt.Errorf("can't create N3 client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo
|
||||||
}
|
}
|
||||||
|
|
||||||
func listContainers(cmd *cobra.Command, _ []string) error {
|
func listContainers(cmd *cobra.Command, _ []string) error {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create N3 client: %w", err)
|
return fmt.Errorf("can't create N3 client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ type contractDumpInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpContractHashes(cmd *cobra.Command, _ []string) error {
|
func dumpContractHashes(cmd *cobra.Command, _ []string) error {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create N3 client: %w", err)
|
return fmt.Errorf("can't create N3 client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package frostfsid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
frostfsidAddSubjectKeyCmd = &cobra.Command{
|
||||||
|
Use: "add-subject-key",
|
||||||
|
Short: "Add a public key to the subject in frostfsid contract",
|
||||||
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
|
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
||||||
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
|
},
|
||||||
|
Run: frostfsidAddSubjectKey,
|
||||||
|
}
|
||||||
|
frostfsidRemoveSubjectKeyCmd = &cobra.Command{
|
||||||
|
Use: "remove-subject-key",
|
||||||
|
Short: "Remove a public key from the subject in frostfsid contract",
|
||||||
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
|
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
||||||
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
|
},
|
||||||
|
Run: frostfsidRemoveSubjectKey,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func initFrostfsIDAddSubjectKeyCmd() {
|
||||||
|
Cmd.AddCommand(frostfsidAddSubjectKeyCmd)
|
||||||
|
|
||||||
|
ff := frostfsidAddSubjectKeyCmd.Flags()
|
||||||
|
ff.StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
|
ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||||
|
|
||||||
|
ff.String(subjectAddressFlag, "", "Subject address")
|
||||||
|
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectAddressFlag)
|
||||||
|
|
||||||
|
ff.String(subjectKeyFlag, "", "Public key to add")
|
||||||
|
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectKeyFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initFrostfsIDRemoveSubjectKeyCmd() {
|
||||||
|
Cmd.AddCommand(frostfsidRemoveSubjectKeyCmd)
|
||||||
|
|
||||||
|
ff := frostfsidRemoveSubjectKeyCmd.Flags()
|
||||||
|
ff.StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
|
ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||||
|
|
||||||
|
ff.String(subjectAddressFlag, "", "Subject address")
|
||||||
|
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectAddressFlag)
|
||||||
|
|
||||||
|
ff.String(subjectKeyFlag, "", "Public key to remove")
|
||||||
|
_ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectKeyFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func frostfsidAddSubjectKey(cmd *cobra.Command, _ []string) {
|
||||||
|
addr := getFrostfsIDSubjectAddress(cmd)
|
||||||
|
pub := getFrostfsIDSubjectKey(cmd)
|
||||||
|
|
||||||
|
ffsid, err := newFrostfsIDClient(cmd)
|
||||||
|
commonCmd.ExitOnErr(cmd, "init contract client: %w", err)
|
||||||
|
|
||||||
|
ffsid.addCall(ffsid.roCli.AddSubjectKeyCall(addr, pub))
|
||||||
|
|
||||||
|
err = ffsid.sendWait()
|
||||||
|
commonCmd.ExitOnErr(cmd, "add subject key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func frostfsidRemoveSubjectKey(cmd *cobra.Command, _ []string) {
|
||||||
|
addr := getFrostfsIDSubjectAddress(cmd)
|
||||||
|
pub := getFrostfsIDSubjectKey(cmd)
|
||||||
|
|
||||||
|
ffsid, err := newFrostfsIDClient(cmd)
|
||||||
|
commonCmd.ExitOnErr(cmd, "init contract client: %w", err)
|
||||||
|
|
||||||
|
ffsid.addCall(ffsid.roCli.RemoveSubjectKeyCall(addr, pub))
|
||||||
|
|
||||||
|
err = ffsid.sendWait()
|
||||||
|
commonCmd.ExitOnErr(cmd, "remove subject key: %w", err)
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package frostfsid
|
package frostfsid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -61,7 +60,6 @@ var (
|
||||||
Use: "list-namespaces",
|
Use: "list-namespaces",
|
||||||
Short: "List all namespaces in frostfsid",
|
Short: "List all namespaces in frostfsid",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
|
||||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
},
|
},
|
||||||
Run: frostfsidListNamespaces,
|
Run: frostfsidListNamespaces,
|
||||||
|
@ -91,7 +89,6 @@ var (
|
||||||
Use: "list-subjects",
|
Use: "list-subjects",
|
||||||
Short: "List subjects in namespace",
|
Short: "List subjects in namespace",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
|
||||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
},
|
},
|
||||||
Run: frostfsidListSubjects,
|
Run: frostfsidListSubjects,
|
||||||
|
@ -121,7 +118,6 @@ var (
|
||||||
Use: "list-groups",
|
Use: "list-groups",
|
||||||
Short: "List groups in namespace",
|
Short: "List groups in namespace",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
|
||||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
},
|
},
|
||||||
Run: frostfsidListGroups,
|
Run: frostfsidListGroups,
|
||||||
|
@ -151,7 +147,6 @@ var (
|
||||||
Use: "list-group-subjects",
|
Use: "list-group-subjects",
|
||||||
Short: "List subjects in group",
|
Short: "List subjects in group",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
|
||||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
},
|
},
|
||||||
Run: frostfsidListGroupSubjects,
|
Run: frostfsidListGroupSubjects,
|
||||||
|
@ -169,7 +164,6 @@ func initFrostfsIDCreateNamespaceCmd() {
|
||||||
func initFrostfsIDListNamespacesCmd() {
|
func initFrostfsIDListNamespacesCmd() {
|
||||||
Cmd.AddCommand(frostfsidListNamespacesCmd)
|
Cmd.AddCommand(frostfsidListNamespacesCmd)
|
||||||
frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
frostfsidListNamespacesCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initFrostfsIDCreateSubjectCmd() {
|
func initFrostfsIDCreateSubjectCmd() {
|
||||||
|
@ -193,7 +187,6 @@ func initFrostfsIDListSubjectsCmd() {
|
||||||
frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects")
|
frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects")
|
||||||
frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
|
frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
|
||||||
frostfsidListSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initFrostfsIDCreateGroupCmd() {
|
func initFrostfsIDCreateGroupCmd() {
|
||||||
|
@ -217,7 +210,6 @@ func initFrostfsIDListGroupsCmd() {
|
||||||
Cmd.AddCommand(frostfsidListGroupsCmd)
|
Cmd.AddCommand(frostfsidListGroupsCmd)
|
||||||
frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups")
|
frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups")
|
||||||
frostfsidListGroupsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initFrostfsIDAddSubjectToGroupCmd() {
|
func initFrostfsIDAddSubjectToGroupCmd() {
|
||||||
|
@ -242,7 +234,6 @@ func initFrostfsIDListGroupSubjectsCmd() {
|
||||||
frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name")
|
frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name")
|
||||||
frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id")
|
frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id")
|
||||||
frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
|
frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
|
||||||
frostfsidListGroupSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) {
|
func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) {
|
||||||
|
@ -497,10 +488,6 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) {
|
||||||
}
|
}
|
||||||
f.bw.Reset()
|
f.bw.Reset()
|
||||||
|
|
||||||
if len(f.wCtx.SentTxs) == 0 {
|
|
||||||
return nil, errors.New("no transactions to wait")
|
|
||||||
}
|
|
||||||
|
|
||||||
f.wCtx.Command.Println("Waiting for transactions to persist...")
|
f.wCtx.Command.Println("Waiting for transactions to persist...")
|
||||||
return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil)
|
return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil)
|
||||||
}
|
}
|
||||||
|
@ -522,7 +509,7 @@ func readIterator(inv *invoker.Invoker, iter *result.Iterator, batchSize int, se
|
||||||
}
|
}
|
||||||
|
|
||||||
func initInvoker(cmd *cobra.Command) (*invoker.Invoker, *state.Contract, util.Uint160) {
|
func initInvoker(cmd *cobra.Command) (*invoker.Invoker, *state.Contract, util.Uint160) {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
|
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
|
|
|
@ -1,59 +1,12 @@
|
||||||
package frostfsid
|
package frostfsid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFrostfsIDConfig(t *testing.T) {
|
|
||||||
pks := make([]*keys.PrivateKey, 4)
|
|
||||||
for i := range pks {
|
|
||||||
pk, err := keys.NewPrivateKey()
|
|
||||||
require.NoError(t, err)
|
|
||||||
pks[i] = pk
|
|
||||||
}
|
|
||||||
|
|
||||||
fmts := []string{
|
|
||||||
pks[0].GetScriptHash().StringLE(),
|
|
||||||
address.Uint160ToString(pks[1].GetScriptHash()),
|
|
||||||
hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()),
|
|
||||||
hex.EncodeToString(pks[3].PublicKey().Bytes()),
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range fmts {
|
|
||||||
v := viper.New()
|
|
||||||
v.Set("frostfsid.admin", fmts[i])
|
|
||||||
|
|
||||||
actual, found, err := helper.GetFrostfsIDAdmin(v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.True(t, found)
|
|
||||||
require.Equal(t, pks[i].GetScriptHash(), actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("bad key", func(t *testing.T) {
|
|
||||||
v := viper.New()
|
|
||||||
v.Set("frostfsid.admin", "abc")
|
|
||||||
|
|
||||||
_, found, err := helper.GetFrostfsIDAdmin(v)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.True(t, found)
|
|
||||||
})
|
|
||||||
t.Run("missing key", func(t *testing.T) {
|
|
||||||
v := viper.New()
|
|
||||||
|
|
||||||
_, found, err := helper.GetFrostfsIDAdmin(v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.False(t, found)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNamespaceRegexp(t *testing.T) {
|
func TestNamespaceRegexp(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
@ -12,4 +12,6 @@ func init() {
|
||||||
initFrostfsIDAddSubjectToGroupCmd()
|
initFrostfsIDAddSubjectToGroupCmd()
|
||||||
initFrostfsIDRemoveSubjectFromGroupCmd()
|
initFrostfsIDRemoveSubjectFromGroupCmd()
|
||||||
initFrostfsIDListGroupSubjectsCmd()
|
initFrostfsIDListGroupSubjectsCmd()
|
||||||
|
initFrostfsIDAddSubjectKeyCmd()
|
||||||
|
initFrostfsIDRemoveSubjectKeyCmd()
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
|
@ -141,60 +140,29 @@ func addMultisigAccount(w *wallet.Wallet, m int, name, password string, pubs key
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateStorageCreds(cmd *cobra.Command, _ []string) error {
|
func generateStorageCreds(cmd *cobra.Command, _ []string) error {
|
||||||
return refillGas(cmd, storageGasConfigFlag, true)
|
walletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag)
|
||||||
}
|
w, err := wallet.NewWallet(walletPath)
|
||||||
|
if err != nil {
|
||||||
func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error) {
|
return fmt.Errorf("create wallet: %w", err)
|
||||||
// storage wallet path is not part of the config
|
|
||||||
storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag)
|
|
||||||
// wallet address is not part of the config
|
|
||||||
walletAddress, _ := cmd.Flags().GetString(walletAddressFlag)
|
|
||||||
|
|
||||||
var gasReceiver util.Uint160
|
|
||||||
|
|
||||||
if len(walletAddress) != 0 {
|
|
||||||
gasReceiver, err = address.StringToUint160(walletAddress)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if storageWalletPath == "" {
|
|
||||||
return fmt.Errorf("missing wallet path (use '--%s <out.json>')", commonflags.StorageWalletFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
var w *wallet.Wallet
|
|
||||||
|
|
||||||
if createWallet {
|
|
||||||
w, err = wallet.NewWallet(storageWalletPath)
|
|
||||||
} else {
|
|
||||||
w, err = wallet.NewWalletFromFile(storageWalletPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't create wallet: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if createWallet {
|
|
||||||
var password string
|
|
||||||
|
|
||||||
label, _ := cmd.Flags().GetString(storageWalletLabelFlag)
|
|
||||||
password, err := config.GetStoragePassword(viper.GetViper(), label)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't fetch password: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if label == "" {
|
|
||||||
label = constants.SingleAccountName
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.CreateAccount(label, password); err != nil {
|
|
||||||
return fmt.Errorf("can't create account: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gasReceiver = w.Accounts[0].Contract.ScriptHash()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label, _ := cmd.Flags().GetString(storageWalletLabelFlag)
|
||||||
|
password, err := config.GetStoragePassword(viper.GetViper(), label)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't fetch password: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if label == "" {
|
||||||
|
label = constants.SingleAccountName
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.CreateAccount(label, password); err != nil {
|
||||||
|
return fmt.Errorf("can't create account: %w", err)
|
||||||
|
}
|
||||||
|
return refillGas(cmd, storageGasConfigFlag, w.Accounts[0].ScriptHash())
|
||||||
|
}
|
||||||
|
|
||||||
|
func refillGas(cmd *cobra.Command, gasFlag string, gasReceivers ...util.Uint160) (err error) {
|
||||||
gasStr := viper.GetString(gasFlag)
|
gasStr := viper.GetString(gasFlag)
|
||||||
|
|
||||||
gasAmount, err := helper.ParseGASAmount(gasStr)
|
gasAmount, err := helper.ParseGASAmount(gasStr)
|
||||||
|
@ -208,9 +176,11 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
|
||||||
}
|
}
|
||||||
|
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All,
|
for _, gasReceiver := range gasReceivers {
|
||||||
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
|
emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All,
|
||||||
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
|
||||||
|
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
||||||
|
}
|
||||||
if bw.Err != nil {
|
if bw.Err != nil {
|
||||||
return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err)
|
return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package generate
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -33,7 +38,27 @@ var (
|
||||||
_ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag))
|
_ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag))
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return refillGas(cmd, commonflags.RefillGasAmountFlag, false)
|
storageWalletPaths, _ := cmd.Flags().GetStringArray(commonflags.StorageWalletFlag)
|
||||||
|
walletAddresses, _ := cmd.Flags().GetStringArray(walletAddressFlag)
|
||||||
|
|
||||||
|
var gasReceivers []util.Uint160
|
||||||
|
for _, walletAddress := range walletAddresses {
|
||||||
|
addr, err := address.StringToUint160(walletAddress)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gasReceivers = append(gasReceivers, addr)
|
||||||
|
}
|
||||||
|
for _, storageWalletPath := range storageWalletPaths {
|
||||||
|
w, err := wallet.NewWalletFromFile(storageWalletPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't create wallet: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gasReceivers = append(gasReceivers, w.Accounts[0].Contract.ScriptHash())
|
||||||
|
}
|
||||||
|
return refillGas(cmd, commonflags.RefillGasAmountFlag, gasReceivers...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
GenerateAlphabetCmd = &cobra.Command{
|
GenerateAlphabetCmd = &cobra.Command{
|
||||||
|
@ -50,10 +75,10 @@ var (
|
||||||
func initRefillGasCmd() {
|
func initRefillGasCmd() {
|
||||||
RefillGasCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
RefillGasCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||||
RefillGasCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
RefillGasCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
RefillGasCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet")
|
RefillGasCmd.Flags().StringArray(commonflags.StorageWalletFlag, nil, "Path to storage node wallet")
|
||||||
RefillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet")
|
RefillGasCmd.Flags().StringArray(walletAddressFlag, nil, "Address of wallet")
|
||||||
RefillGasCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Additional amount of GAS to transfer")
|
RefillGasCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Additional amount of GAS to transfer")
|
||||||
RefillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, commonflags.StorageWalletFlag)
|
RefillGasCmd.MarkFlagsOneRequired(walletAddressFlag, commonflags.StorageWalletFlag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initGenerateStorageCmd() {
|
func initGenerateStorageCmd() {
|
||||||
|
|
|
@ -38,38 +38,24 @@ func NewLocalActor(cmd *cobra.Command, c actor.RPCActor, accName string) (*Local
|
||||||
walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag))
|
walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag))
|
||||||
var act *actor.Actor
|
var act *actor.Actor
|
||||||
var accounts []*wallet.Account
|
var accounts []*wallet.Account
|
||||||
if walletDir == "" {
|
|
||||||
account, err := wallet.NewAccount()
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to create dummy account: %w", err)
|
|
||||||
act, err = actor.New(c, []actor.SignerAccount{{
|
|
||||||
Signer: transaction.Signer{
|
|
||||||
Account: account.Contract.ScriptHash(),
|
|
||||||
Scopes: transaction.Global,
|
|
||||||
},
|
|
||||||
Account: account,
|
|
||||||
}})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir)
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err)
|
|
||||||
|
|
||||||
for _, w := range wallets {
|
wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir)
|
||||||
acc, err := GetWalletAccount(w, accName)
|
commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err)
|
||||||
commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err)
|
|
||||||
accounts = append(accounts, acc)
|
for _, w := range wallets {
|
||||||
}
|
acc, err := GetWalletAccount(w, accName)
|
||||||
act, err = actor.New(c, []actor.SignerAccount{{
|
commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err)
|
||||||
Signer: transaction.Signer{
|
accounts = append(accounts, acc)
|
||||||
Account: accounts[0].Contract.ScriptHash(),
|
}
|
||||||
Scopes: transaction.Global,
|
act, err = actor.New(c, []actor.SignerAccount{{
|
||||||
},
|
Signer: transaction.Signer{
|
||||||
Account: accounts[0],
|
Account: accounts[0].Contract.ScriptHash(),
|
||||||
}})
|
Scopes: transaction.Global,
|
||||||
if err != nil {
|
},
|
||||||
return nil, err
|
Account: accounts[0],
|
||||||
}
|
}})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return &LocalActor{
|
return &LocalActor{
|
||||||
neoActor: act,
|
neoActor: act,
|
||||||
|
|
|
@ -82,7 +82,7 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any
|
||||||
h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker)
|
h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker)
|
||||||
}
|
}
|
||||||
if method != constants.UpdateMethodName || err == nil && !found {
|
if method != constants.UpdateMethodName || err == nil && !found {
|
||||||
h, found, err = GetFrostfsIDAdmin(viper.GetViper())
|
h, found, err = getFrostfsIDAdmin(viper.GetViper())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
const frostfsIDAdminConfigKey = "frostfsid.admin"
|
const frostfsIDAdminConfigKey = "frostfsid.admin"
|
||||||
|
|
||||||
func GetFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) {
|
func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) {
|
||||||
admin := v.GetString(frostfsIDAdminConfigKey)
|
admin := v.GetString(frostfsIDAdminConfigKey)
|
||||||
if admin == "" {
|
if admin == "" {
|
||||||
return util.Uint160{}, false, nil
|
return util.Uint160{}, false, nil
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFrostfsIDConfig(t *testing.T) {
|
||||||
|
pks := make([]*keys.PrivateKey, 4)
|
||||||
|
for i := range pks {
|
||||||
|
pk, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
pks[i] = pk
|
||||||
|
}
|
||||||
|
|
||||||
|
fmts := []string{
|
||||||
|
pks[0].GetScriptHash().StringLE(),
|
||||||
|
address.Uint160ToString(pks[1].GetScriptHash()),
|
||||||
|
hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()),
|
||||||
|
hex.EncodeToString(pks[3].PublicKey().Bytes()),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range fmts {
|
||||||
|
v := viper.New()
|
||||||
|
v.Set("frostfsid.admin", fmts[i])
|
||||||
|
|
||||||
|
actual, found, err := getFrostfsIDAdmin(v)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, pks[i].GetScriptHash(), actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("bad key", func(t *testing.T) {
|
||||||
|
v := viper.New()
|
||||||
|
v.Set("frostfsid.admin", "abc")
|
||||||
|
|
||||||
|
_, found, err := getFrostfsIDAdmin(v)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.True(t, found)
|
||||||
|
})
|
||||||
|
t.Run("missing key", func(t *testing.T) {
|
||||||
|
v := viper.New()
|
||||||
|
|
||||||
|
_, found, err := getFrostfsIDAdmin(v)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, found)
|
||||||
|
})
|
||||||
|
}
|
|
@ -134,12 +134,12 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
accounts, err := createWalletAccounts(wallets)
|
accounts, err := getSingleAccounts(wallets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx, err := DefaultClientContext(c, committeeAcc)
|
cliCtx, err := defaultClientContext(c, committeeAcc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("client context: %w", err)
|
return nil, fmt.Errorf("client context: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet)
|
||||||
}
|
}
|
||||||
c, err = NewLocalClient(cmd, v, wallets, ldf.Value.String())
|
c, err = NewLocalClient(cmd, v, wallets, ldf.Value.String())
|
||||||
} else {
|
} else {
|
||||||
c, err = GetN3Client(v)
|
c, err = NewRemoteClient(v)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't create N3 client: %w", err)
|
return nil, fmt.Errorf("can't create N3 client: %w", err)
|
||||||
|
@ -211,7 +211,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) {
|
||||||
return ctrPath, nil
|
return ctrPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) {
|
func getSingleAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) {
|
||||||
accounts := make([]*wallet.Account, len(wallets))
|
accounts := make([]*wallet.Account, len(wallets))
|
||||||
for i, w := range wallets {
|
for i, w := range wallets {
|
||||||
acc, err := GetWalletAccount(w, constants.SingleAccountName)
|
acc, err := GetWalletAccount(w, constants.SingleAccountName)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
|
@ -47,7 +48,7 @@ type LocalClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) {
|
func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) {
|
||||||
cfg, err := config.LoadFile(v.GetString(constants.ProtoConfigPath))
|
cfg, err := config.LoadFile(v.GetString(commonflags.ProtoConfigPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -57,17 +58,59 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ProtocolConfiguration.ValidatorsCount))
|
go bc.Run()
|
||||||
accounts := make([]*wallet.Account, len(wallets))
|
|
||||||
for i := range accounts {
|
accounts, err := getBlockSigningAccounts(cfg.ProtocolConfiguration, wallets)
|
||||||
accounts[i], err = GetWalletAccount(wallets[i], constants.ConsensusAccountName)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
|
|
||||||
|
if cmd.Name() != "init" {
|
||||||
|
if err := restoreDump(bc, dumpPath); err != nil {
|
||||||
|
return nil, fmt.Errorf("restore dump: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &LocalClient{
|
||||||
|
bc: bc,
|
||||||
|
dumpPath: dumpPath,
|
||||||
|
accounts: accounts,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func restoreDump(bc *core.Blockchain, dumpPath string) error {
|
||||||
|
f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't open local dump: %w", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
r := io.NewBinReaderFromIO(f)
|
||||||
|
|
||||||
|
var skip uint32
|
||||||
|
if bc.BlockHeight() != 0 {
|
||||||
|
skip = bc.BlockHeight() + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
count := r.ReadU32LE() - skip
|
||||||
|
if err := chaindump.Restore(bc, r, skip, count, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBlockSigningAccounts(cfg config.ProtocolConfiguration, wallets []*wallet.Wallet) ([]*wallet.Account, error) {
|
||||||
|
accounts := make([]*wallet.Account, len(wallets))
|
||||||
|
for i := range accounts {
|
||||||
|
acc, err := GetWalletAccount(wallets[i], constants.ConsensusAccountName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
accounts[i] = acc
|
||||||
|
}
|
||||||
|
|
||||||
indexMap := make(map[string]int)
|
indexMap := make(map[string]int)
|
||||||
for i, pub := range cfg.ProtocolConfiguration.StandbyCommittee {
|
for i, pub := range cfg.StandbyCommittee {
|
||||||
indexMap[pub] = i
|
indexMap[pub] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,37 +119,12 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet
|
||||||
pj := accounts[j].PrivateKey().PublicKey().Bytes()
|
pj := accounts[j].PrivateKey().PublicKey().Bytes()
|
||||||
return indexMap[string(pi)] < indexMap[string(pj)]
|
return indexMap[string(pi)] < indexMap[string(pj)]
|
||||||
})
|
})
|
||||||
sort.Slice(accounts[:cfg.ProtocolConfiguration.ValidatorsCount], func(i, j int) bool {
|
sort.Slice(accounts[:cfg.ValidatorsCount], func(i, j int) bool {
|
||||||
return accounts[i].PublicKey().Cmp(accounts[j].PublicKey()) == -1
|
return accounts[i].PublicKey().Cmp(accounts[j].PublicKey()) == -1
|
||||||
})
|
})
|
||||||
|
|
||||||
go bc.Run()
|
m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ValidatorsCount))
|
||||||
|
return accounts[:m], nil
|
||||||
if cmd.Name() != "init" {
|
|
||||||
f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("can't open local dump: %w", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
r := io.NewBinReaderFromIO(f)
|
|
||||||
|
|
||||||
var skip uint32
|
|
||||||
if bc.BlockHeight() != 0 {
|
|
||||||
skip = bc.BlockHeight() + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
count := r.ReadU32LE() - skip
|
|
||||||
if err := chaindump.Restore(bc, r, skip, count, nil); err != nil {
|
|
||||||
return nil, fmt.Errorf("can't restore local dump: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &LocalClient{
|
|
||||||
bc: bc,
|
|
||||||
dumpPath: dumpPath,
|
|
||||||
accounts: accounts[:m],
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LocalClient) GetBlockCount() (uint32, error) {
|
func (l *LocalClient) GetBlockCount() (uint32, error) {
|
||||||
|
@ -127,11 +145,6 @@ func (l *LocalClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*resul
|
||||||
return &a, nil
|
return &a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LocalClient) GetCommittee() (keys.PublicKeys, error) {
|
|
||||||
// not used by `morph init` command
|
|
||||||
panic("unexpected call")
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvokeFunction is implemented via `InvokeScript`.
|
// InvokeFunction is implemented via `InvokeScript`.
|
||||||
func (l *LocalClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) {
|
func (l *LocalClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) {
|
||||||
var err error
|
var err error
|
||||||
|
@ -295,13 +308,7 @@ func (l *LocalClient) InvokeScript(script []byte, signers []transaction.Signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) {
|
func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) {
|
||||||
// We need to test that transaction was formed correctly to catch as many errors as we can.
|
tx = tx.Copy()
|
||||||
bs := tx.Bytes()
|
|
||||||
_, err := transaction.NewTransactionFromBytes(bs)
|
|
||||||
if err != nil {
|
|
||||||
return tx.Hash(), fmt.Errorf("invalid transaction: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
l.transactions = append(l.transactions, tx)
|
l.transactions = append(l.transactions, tx)
|
||||||
return tx.Hash(), nil
|
return tx.Hash(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||||
|
@ -25,15 +24,10 @@ import (
|
||||||
// Client represents N3 client interface capable of test-invoking scripts
|
// Client represents N3 client interface capable of test-invoking scripts
|
||||||
// and sending signed transactions to chain.
|
// and sending signed transactions to chain.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
invoker.RPCInvoke
|
actor.RPCActor
|
||||||
|
|
||||||
GetBlockCount() (uint32, error)
|
|
||||||
GetNativeContracts() ([]state.Contract, error)
|
GetNativeContracts() ([]state.Contract, error)
|
||||||
GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error)
|
GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error)
|
||||||
GetVersion() (*result.Version, error)
|
|
||||||
SendRawTransaction(*transaction.Transaction) (util.Uint256, error)
|
|
||||||
GetCommittee() (keys.PublicKeys, error)
|
|
||||||
CalculateNetworkFee(tx *transaction.Transaction) (int64, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HashVUBPair struct {
|
type HashVUBPair struct {
|
||||||
|
@ -48,7 +42,7 @@ type ClientContext struct {
|
||||||
SentTxs []HashVUBPair
|
SentTxs []HashVUBPair
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetN3Client(v *viper.Viper) (Client, error) {
|
func NewRemoteClient(v *viper.Viper) (Client, error) {
|
||||||
// number of opened connections
|
// number of opened connections
|
||||||
// by neo-go client per one host
|
// by neo-go client per one host
|
||||||
const (
|
const (
|
||||||
|
@ -88,8 +82,14 @@ func GetN3Client(v *viper.Viper) (Client, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) {
|
func defaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) {
|
||||||
commAct, err := NewActor(c, committeeAcc)
|
commAct, err := actor.New(c, []actor.SignerAccount{{
|
||||||
|
Signer: transaction.Signer{
|
||||||
|
Account: committeeAcc.Contract.ScriptHash(),
|
||||||
|
Scopes: transaction.Global,
|
||||||
|
},
|
||||||
|
Account: committeeAcc,
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,8 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -87,16 +85,6 @@ func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, er
|
||||||
return wallets, nil
|
return wallets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) {
|
|
||||||
return actor.New(c, []actor.SignerAccount{{
|
|
||||||
Signer: transaction.Signer{
|
|
||||||
Account: committeeAcc.Contract.ScriptHash(),
|
|
||||||
Scopes: transaction.Global,
|
|
||||||
},
|
|
||||||
Account: committeeAcc,
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadContract(ctrPath, ctrName string) (*ContractState, error) {
|
func ReadContract(ctrPath, ctrName string) (*ContractState, error) {
|
||||||
rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef"))
|
rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -62,7 +62,7 @@ func testInitialize(t *testing.T, committeeSize int) {
|
||||||
v := viper.GetViper()
|
v := viper.GetViper()
|
||||||
|
|
||||||
require.NoError(t, generateTestData(testdataDir, committeeSize))
|
require.NoError(t, generateTestData(testdataDir, committeeSize))
|
||||||
v.Set(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName))
|
v.Set(commonflags.ProtoConfigPath, filepath.Join(testdataDir, protoFileName))
|
||||||
|
|
||||||
// Set to the path or remove the next statement to download from the network.
|
// Set to the path or remove the next statement to download from the network.
|
||||||
require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath))
|
require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath))
|
||||||
|
|
|
@ -2,7 +2,6 @@ package initialize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -32,7 +31,7 @@ var Cmd = &cobra.Command{
|
||||||
_ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag))
|
_ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag))
|
||||||
_ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag))
|
_ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag))
|
||||||
_ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag))
|
_ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag))
|
||||||
_ = viper.BindPFlag(constants.ProtoConfigPath, cmd.Flags().Lookup(constants.ProtoConfigPath))
|
_ = viper.BindPFlag(commonflags.ProtoConfigPath, cmd.Flags().Lookup(commonflags.ProtoConfigPath))
|
||||||
},
|
},
|
||||||
RunE: initializeSideChainCmd,
|
RunE: initializeSideChainCmd,
|
||||||
}
|
}
|
||||||
|
@ -48,7 +47,7 @@ func initInitCmd() {
|
||||||
// Defaults are taken from neo-preodolenie.
|
// Defaults are taken from neo-preodolenie.
|
||||||
Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee")
|
Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee")
|
||||||
Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee")
|
Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee")
|
||||||
Cmd.Flags().String(constants.ProtoConfigPath, "", "Path to the consensus node configuration")
|
Cmd.Flags().String(commonflags.ProtoConfigPath, "", "Path to the consensus node configuration")
|
||||||
Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file")
|
Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file")
|
||||||
Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag)
|
Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) {
|
func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
|
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
|
|
|
@ -12,7 +12,6 @@ var (
|
||||||
Short: "List netmap candidates nodes",
|
Short: "List netmap candidates nodes",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
|
||||||
},
|
},
|
||||||
Run: listNetmapCandidatesNodes,
|
Run: listNetmapCandidatesNodes,
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func initRegisterCmd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerDomain(cmd *cobra.Command, _ []string) {
|
func registerDomain(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
|
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
email, _ := cmd.Flags().GetString(nnsEmailFlag)
|
email, _ := cmd.Flags().GetString(nnsEmailFlag)
|
||||||
|
@ -53,7 +53,7 @@ func initDeleteCmd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteDomain(cmd *cobra.Command, _ []string) {
|
func deleteDomain(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
|
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
h, vub, err := c.DeleteDomain(name)
|
h, vub, err := c.DeleteDomain(name)
|
||||||
|
|
|
@ -5,15 +5,15 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, util.Uint160) {
|
func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) {
|
||||||
v := viper.GetViper()
|
v := viper.GetViper()
|
||||||
c, err := helper.GetN3Client(v)
|
c, err := helper.NewRemoteClient(v)
|
||||||
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
||||||
|
|
||||||
ac, err := helper.NewLocalActor(cmd, c, constants.CommitteeAccountName)
|
ac, err := helper.NewLocalActor(cmd, c, constants.CommitteeAccountName)
|
||||||
|
@ -22,5 +22,17 @@ func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, uti
|
||||||
r := management.NewReader(ac.Invoker)
|
r := management.NewReader(ac.Invoker)
|
||||||
nnsCs, err := helper.GetContractByID(r, 1)
|
nnsCs, err := helper.GetContractByID(r, 1)
|
||||||
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
|
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
|
||||||
return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash
|
return client.New(ac, nnsCs.Hash), ac
|
||||||
|
}
|
||||||
|
|
||||||
|
func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) {
|
||||||
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
|
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
|
||||||
|
|
||||||
|
inv := invoker.New(c, nil)
|
||||||
|
r := management.NewReader(inv)
|
||||||
|
nnsCs, err := helper.GetContractByID(r, 1)
|
||||||
|
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
|
||||||
|
|
||||||
|
return client.NewReader(inv, nnsCs.Hash), inv
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -29,7 +28,6 @@ func initAddRecordCmd() {
|
||||||
func initGetRecordsCmd() {
|
func initGetRecordsCmd() {
|
||||||
Cmd.AddCommand(getRecordsCmd)
|
Cmd.AddCommand(getRecordsCmd)
|
||||||
getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
getRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
|
||||||
getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc)
|
getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc)
|
||||||
getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc)
|
getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc)
|
||||||
|
|
||||||
|
@ -61,7 +59,7 @@ func initDelRecordCmd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRecord(cmd *cobra.Command, _ []string) {
|
func addRecord(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
|
data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
|
||||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||||
|
@ -77,16 +75,16 @@ func addRecord(cmd *cobra.Command, _ []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRecords(cmd *cobra.Command, _ []string) {
|
func getRecords(cmd *cobra.Command, _ []string) {
|
||||||
c, act, hash := getRPCClient(cmd)
|
c, inv := nnsReader(cmd)
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||||
if recordType == "" {
|
if recordType == "" {
|
||||||
sid, r, err := unwrap.SessionIterator(act.Invoker.Call(hash, "getAllRecords", name))
|
sid, r, err := c.GetAllRecords(name)
|
||||||
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = act.Invoker.TerminateSession(sid)
|
_ = inv.TerminateSession(sid)
|
||||||
}()
|
}()
|
||||||
items, err := act.Invoker.TraverseIterator(sid, &r, 0)
|
items, err := inv.TraverseIterator(sid, &r, 0)
|
||||||
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
||||||
for len(items) != 0 {
|
for len(items) != 0 {
|
||||||
for j := range items {
|
for j := range items {
|
||||||
|
@ -97,7 +95,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
|
||||||
recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())),
|
recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())),
|
||||||
string(bs))
|
string(bs))
|
||||||
}
|
}
|
||||||
items, err = act.Invoker.TraverseIterator(sid, &r, 0)
|
items, err = inv.TraverseIterator(sid, &r, 0)
|
||||||
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -114,7 +112,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func delRecords(cmd *cobra.Command, _ []string) {
|
func delRecords(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||||
typ, err := getRecordType(recordType)
|
typ, err := getRecordType(recordType)
|
||||||
|
@ -129,7 +127,7 @@ func delRecords(cmd *cobra.Command, _ []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func delRecord(cmd *cobra.Command, _ []string) {
|
func delRecord(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
|
data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
|
||||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||||
|
|
|
@ -14,7 +14,7 @@ func initRenewCmd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func renewDomain(cmd *cobra.Command, _ []string) {
|
func renewDomain(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
h, vub, err := c.Renew(name)
|
h, vub, err := c.Renew(name)
|
||||||
commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err)
|
||||||
|
|
|
@ -18,12 +18,11 @@ const (
|
||||||
func initTokensCmd() {
|
func initTokensCmd() {
|
||||||
Cmd.AddCommand(tokensCmd)
|
Cmd.AddCommand(tokensCmd)
|
||||||
tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||||
tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
|
||||||
tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc)
|
tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func listTokens(cmd *cobra.Command, _ []string) {
|
func listTokens(cmd *cobra.Command, _ []string) {
|
||||||
c, _, _ := getRPCClient(cmd)
|
c, _ := nnsReader(cmd)
|
||||||
it, err := c.Tokens()
|
it, err := c.Tokens()
|
||||||
commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err)
|
commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err)
|
||||||
for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) {
|
for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) {
|
||||||
|
@ -41,7 +40,7 @@ func listTokens(cmd *cobra.Command, _ []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCnameRecord(c *client.Contract, token []byte) (string, error) {
|
func getCnameRecord(c *client.ContractReader, token []byte) (string, error) {
|
||||||
items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME)))
|
items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME)))
|
||||||
|
|
||||||
// GetRecords returns the error "not an array" if the domain does not contain records.
|
// GetRecords returns the error "not an array" if the domain does not contain records.
|
||||||
|
|
|
@ -30,7 +30,7 @@ func initUpdateCmd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSOA(cmd *cobra.Command, _ []string) {
|
func updateSOA(cmd *cobra.Command, _ []string) {
|
||||||
c, actor, _ := getRPCClient(cmd)
|
c, actor := nnsWriter(cmd)
|
||||||
|
|
||||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||||
email, _ := cmd.Flags().GetString(nnsEmailFlag)
|
email, _ := cmd.Flags().GetString(nnsEmailFlag)
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
||||||
|
@ -41,7 +40,8 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
accHash := w.GetChangeAddress()
|
accHash := w.GetChangeAddress()
|
||||||
if addr, err := cmd.Flags().GetString(walletAccountFlag); err == nil {
|
addr, _ := cmd.Flags().GetString(walletAccountFlag)
|
||||||
|
if addr != "" {
|
||||||
accHash, err = address.StringToUint160(addr)
|
accHash, err = address.StringToUint160(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid address: %s", addr)
|
return fmt.Errorf("invalid address: %s", addr)
|
||||||
|
@ -53,7 +53,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("can't find account for %s", accHash)
|
return fmt.Errorf("can't find account for %s", accHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt := fmt.Sprintf("Enter password for %s >", address.Uint160ToString(accHash))
|
prompt := fmt.Sprintf("Enter password for %s > ", address.Uint160ToString(accHash))
|
||||||
pass, err := input.ReadPassword(prompt)
|
pass, err := input.ReadPassword(prompt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get password: %v", err)
|
return fmt.Errorf("can't get password: %v", err)
|
||||||
|
@ -73,23 +73,16 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
till := int64(defaultNotaryDepositLifetime)
|
till, _ := cmd.Flags().GetInt64(notaryDepositTillFlag)
|
||||||
tillStr, err := cmd.Flags().GetString(notaryDepositTillFlag)
|
if till <= 0 {
|
||||||
if err != nil {
|
return errInvalidNotaryDepositLifetime
|
||||||
return err
|
|
||||||
}
|
|
||||||
if tillStr != "" {
|
|
||||||
till, err = strconv.ParseInt(tillStr, 10, 64)
|
|
||||||
if err != nil || till <= 0 {
|
|
||||||
return errInvalidNotaryDepositLifetime
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return transferGas(cmd, acc, accHash, gasAmount, till)
|
return transferGas(cmd, acc, accHash, gasAmount, till)
|
||||||
}
|
}
|
||||||
|
|
||||||
func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error {
|
func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ func initDepositoryNotaryCmd() {
|
||||||
DepositCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet")
|
DepositCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet")
|
||||||
DepositCmd.Flags().String(walletAccountFlag, "", "Wallet account address")
|
DepositCmd.Flags().String(walletAccountFlag, "", "Wallet account address")
|
||||||
DepositCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Amount of GAS to deposit")
|
DepositCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Amount of GAS to deposit")
|
||||||
DepositCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks")
|
DepositCmd.Flags().Int64(notaryDepositTillFlag, defaultNotaryDepositLifetime, "Notary deposit duration in blocks")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -62,7 +62,7 @@ func SetPolicyCmd(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpPolicyCmd(cmd *cobra.Command, _ []string) error {
|
func dumpPolicyCmd(cmd *cobra.Command, _ []string) error {
|
||||||
c, err := helper.GetN3Client(viper.GetViper())
|
c, err := helper.NewRemoteClient(viper.GetViper())
|
||||||
commonCmd.ExitOnErr(cmd, "can't create N3 client:", err)
|
commonCmd.ExitOnErr(cmd, "can't create N3 client:", err)
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
|
|
|
@ -105,7 +105,7 @@ func storageConfig(cmd *cobra.Command, args []string) {
|
||||||
fatalOnErr(errors.New("can't find account in wallet"))
|
fatalOnErr(errors.New("can't find account in wallet"))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Account password for %s: ", c.Wallet.Account))
|
c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Enter password for %s > ", c.Wallet.Account))
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
|
|
||||||
err = acc.Decrypt(c.Wallet.Password, keys.NEP2ScryptParams())
|
err = acc.Decrypt(c.Wallet.Password, keys.NEP2ScryptParams())
|
||||||
|
|
|
@ -72,4 +72,3 @@ All other `object` sub-commands support only static sessions (2).
|
||||||
List of commands supporting sessions (static only):
|
List of commands supporting sessions (static only):
|
||||||
- `create`
|
- `create`
|
||||||
- `delete`
|
- `delete`
|
||||||
- `set-eacl`
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
|
||||||
|
@ -78,13 +77,31 @@ func ListContainers(ctx context.Context, prm ListContainersPrm) (res ListContain
|
||||||
// SortedIDList returns sorted list of identifiers of user's containers.
|
// SortedIDList returns sorted list of identifiers of user's containers.
|
||||||
func (x ListContainersRes) SortedIDList() []cid.ID {
|
func (x ListContainersRes) SortedIDList() []cid.ID {
|
||||||
list := x.cliRes.Containers()
|
list := x.cliRes.Containers()
|
||||||
sort.Slice(list, func(i, j int) bool {
|
slices.SortFunc(list, func(lhs, rhs cid.ID) int {
|
||||||
lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString()
|
return strings.Compare(lhs.EncodeToString(), rhs.EncodeToString())
|
||||||
return strings.Compare(lhs, rhs) < 0
|
|
||||||
})
|
})
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ListContainersStream(ctx context.Context, prm ListContainersPrm, processCnr func(id cid.ID) bool) (err error) {
|
||||||
|
cliPrm := &client.PrmContainerListStream{
|
||||||
|
XHeaders: prm.XHeaders,
|
||||||
|
OwnerID: prm.OwnerID,
|
||||||
|
Session: prm.Session,
|
||||||
|
}
|
||||||
|
rdr, err := prm.cli.ContainerListInit(ctx, *cliPrm)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("init container list: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rdr.Iterate(processCnr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read container list: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// PutContainerPrm groups parameters of PutContainer operation.
|
// PutContainerPrm groups parameters of PutContainer operation.
|
||||||
type PutContainerPrm struct {
|
type PutContainerPrm struct {
|
||||||
Client *client.Client
|
Client *client.Client
|
||||||
|
|
|
@ -1,44 +1,19 @@
|
||||||
package apemanager
|
package apemanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"fmt"
|
||||||
"errors"
|
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
chainIDFlag = "chain-id"
|
|
||||||
chainIDHexFlag = "chain-id-hex"
|
|
||||||
ruleFlag = "rule"
|
|
||||||
pathFlag = "path"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
targetNameFlag = "target-name"
|
|
||||||
targetNameDesc = "Resource name in APE resource name format"
|
|
||||||
targetTypeFlag = "target-type"
|
|
||||||
targetTypeDesc = "Resource type(container/namespace)"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
namespaceTarget = "namespace"
|
|
||||||
containerTarget = "container"
|
|
||||||
userTarget = "user"
|
|
||||||
groupTarget = "group"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errUnknownTargetType = errors.New("unknown target type")
|
|
||||||
|
|
||||||
var addCmd = &cobra.Command{
|
var addCmd = &cobra.Command{
|
||||||
Use: "add",
|
Use: "add",
|
||||||
Short: "Add rule chain for a target",
|
Short: "Add rule chain for a target",
|
||||||
|
@ -49,55 +24,28 @@ var addCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) {
|
func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) {
|
||||||
typ, _ := cmd.Flags().GetString(targetTypeFlag)
|
t := apeCmd.ParseTarget(cmd)
|
||||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
|
||||||
|
|
||||||
ct.Name = name
|
ct.Name = t.Name
|
||||||
|
|
||||||
switch typ {
|
switch t.Type {
|
||||||
case namespaceTarget:
|
case engine.Namespace:
|
||||||
ct.TargetType = apeSDK.TargetTypeNamespace
|
ct.TargetType = apeSDK.TargetTypeNamespace
|
||||||
case containerTarget:
|
case engine.Container:
|
||||||
var cnr cid.ID
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
|
|
||||||
ct.TargetType = apeSDK.TargetTypeContainer
|
ct.TargetType = apeSDK.TargetTypeContainer
|
||||||
case userTarget:
|
case engine.User:
|
||||||
ct.TargetType = apeSDK.TargetTypeUser
|
ct.TargetType = apeSDK.TargetTypeUser
|
||||||
case groupTarget:
|
case engine.Group:
|
||||||
ct.TargetType = apeSDK.TargetTypeGroup
|
ct.TargetType = apeSDK.TargetTypeGroup
|
||||||
default:
|
default:
|
||||||
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
|
commonCmd.ExitOnErr(cmd, "conversion error: %w", fmt.Errorf("unknown type '%c'", t.Type))
|
||||||
}
|
}
|
||||||
return ct
|
return ct
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseChain(cmd *cobra.Command) apeSDK.Chain {
|
func parseChain(cmd *cobra.Command) apeSDK.Chain {
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
c := apeCmd.ParseChain(cmd)
|
||||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
serialized := c.Bytes()
|
||||||
|
|
||||||
chainIDRaw := []byte(chainID)
|
|
||||||
|
|
||||||
if hexEncoded {
|
|
||||||
var err error
|
|
||||||
chainIDRaw, err = hex.DecodeString(chainID)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
chain := new(apechain.Chain)
|
|
||||||
chain.ID = apechain.ID(chainIDRaw)
|
|
||||||
|
|
||||||
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules))
|
|
||||||
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath))
|
|
||||||
} else {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", errors.New("rule is not passed"))
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Parsed chain:")
|
|
||||||
util.PrintHumanReadableAPEChain(cmd, chain)
|
|
||||||
|
|
||||||
serialized := chain.Bytes()
|
|
||||||
return apeSDK.Chain{
|
return apeSDK.Chain{
|
||||||
Raw: serialized,
|
Raw: serialized,
|
||||||
}
|
}
|
||||||
|
@ -126,13 +74,13 @@ func initAddCmd() {
|
||||||
commonflags.Init(addCmd)
|
commonflags.Init(addCmd)
|
||||||
|
|
||||||
ff := addCmd.Flags()
|
ff := addCmd.Flags()
|
||||||
ff.StringArray(ruleFlag, []string{}, "Rule statement")
|
ff.StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc)
|
||||||
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
|
ff.String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc)
|
||||||
ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
|
ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = addCmd.MarkFlagRequired(targetTypeFlag)
|
_ = addCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
|
||||||
|
|
||||||
addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
|
addCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -35,7 +35,7 @@ func list(cmd *cobra.Command, _ []string) {
|
||||||
for _, respChain := range resp.Chains {
|
for _, respChain := range resp.Chains {
|
||||||
var chain apechain.Chain
|
var chain apechain.Chain
|
||||||
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw))
|
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw))
|
||||||
apeutil.PrintHumanReadableAPEChain(cmd, &chain)
|
apeCmd.PrintHumanReadableAPEChain(cmd, &chain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ func initListCmd() {
|
||||||
commonflags.Init(listCmd)
|
commonflags.Init(listCmd)
|
||||||
|
|
||||||
ff := listCmd.Flags()
|
ff := listCmd.Flags()
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = listCmd.MarkFlagRequired(targetTypeFlag)
|
_ = listCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,23 @@
|
||||||
package apemanager
|
package apemanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var removeCmd = &cobra.Command{
|
||||||
errEmptyChainID = errors.New("chain id cannot be empty")
|
Use: "remove",
|
||||||
|
Short: "Remove rule chain for a target",
|
||||||
removeCmd = &cobra.Command{
|
Run: remove,
|
||||||
Use: "remove",
|
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
Short: "Remove rule chain for a target",
|
commonflags.Bind(cmd)
|
||||||
Run: remove,
|
},
|
||||||
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
|
}
|
||||||
commonflags.Bind(cmd)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func remove(cmd *cobra.Command, _ []string) {
|
func remove(cmd *cobra.Command, _ []string) {
|
||||||
target := parseTarget(cmd)
|
target := parseTarget(cmd)
|
||||||
|
@ -31,19 +25,9 @@ func remove(cmd *cobra.Command, _ []string) {
|
||||||
key := key.Get(cmd)
|
key := key.Get(cmd)
|
||||||
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
||||||
|
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
chainID := apeCmd.ParseChainID(cmd)
|
||||||
if chainID == "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
|
|
||||||
}
|
|
||||||
chainIDRaw := []byte(chainID)
|
chainIDRaw := []byte(chainID)
|
||||||
|
|
||||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
|
||||||
if hexEncoded {
|
|
||||||
var err error
|
|
||||||
chainIDRaw, err = hex.DecodeString(chainID)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := cli.APEManagerRemoveChain(cmd.Context(), client_sdk.PrmAPEManagerRemoveChain{
|
_, err := cli.APEManagerRemoveChain(cmd.Context(), client_sdk.PrmAPEManagerRemoveChain{
|
||||||
ChainTarget: target,
|
ChainTarget: target,
|
||||||
ChainID: chainIDRaw,
|
ChainID: chainIDRaw,
|
||||||
|
@ -58,9 +42,10 @@ func initRemoveCmd() {
|
||||||
commonflags.Init(removeCmd)
|
commonflags.Init(removeCmd)
|
||||||
|
|
||||||
ff := removeCmd.Flags()
|
ff := removeCmd.Flags()
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = removeCmd.MarkFlagRequired(targetTypeFlag)
|
_ = removeCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
ff.String(chainIDFlag, "", "Chain id")
|
ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
_ = removeCmd.MarkFlagRequired(apeCmd.ChainIDFlag)
|
||||||
|
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,20 @@
|
||||||
package bearer
|
package bearer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||||
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
errChainIDCannotBeEmpty = errors.New("chain id cannot be empty")
|
|
||||||
errRuleIsNotParsed = errors.New("rule is not passed")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
chainIDFlag = "chain-id"
|
outputFlag = "output"
|
||||||
chainIDHexFlag = "chain-id-hex"
|
|
||||||
ruleFlag = "rule"
|
|
||||||
pathFlag = "path"
|
|
||||||
outputFlag = "output"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var generateAPEOverrideCmd = &cobra.Command{
|
var generateAPEOverrideCmd = &cobra.Command{
|
||||||
|
@ -40,7 +29,7 @@ Generated APE override can be dumped to a file in JSON format that is passed to
|
||||||
}
|
}
|
||||||
|
|
||||||
func genereateAPEOverride(cmd *cobra.Command, _ []string) {
|
func genereateAPEOverride(cmd *cobra.Command, _ []string) {
|
||||||
c := parseChain(cmd)
|
c := apeCmd.ParseChain(cmd)
|
||||||
|
|
||||||
targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag)
|
targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag)
|
||||||
var cid cidSDK.ID
|
var cid cidSDK.ID
|
||||||
|
@ -77,39 +66,11 @@ func init() {
|
||||||
ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.")
|
ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.")
|
||||||
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag)
|
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag)
|
||||||
|
|
||||||
ff.StringArray(ruleFlag, []string{}, "Rule statement")
|
ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement")
|
||||||
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
|
ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||||
ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
|
ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain")
|
||||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||||
|
|
||||||
ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override")
|
ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override")
|
||||||
_ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag)
|
_ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseChainID(cmd *cobra.Command) apechain.ID {
|
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
|
||||||
if chainID == "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w",
|
|
||||||
errChainIDCannotBeEmpty)
|
|
||||||
}
|
|
||||||
return apechain.ID(chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseChain(cmd *cobra.Command) *apechain.Chain {
|
|
||||||
chain := new(apechain.Chain)
|
|
||||||
|
|
||||||
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules))
|
|
||||||
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath))
|
|
||||||
} else {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed)
|
|
||||||
}
|
|
||||||
|
|
||||||
chain.ID = parseChainID(cmd)
|
|
||||||
|
|
||||||
cmd.Println("Parsed chain:")
|
|
||||||
parseutil.PrintHumanReadableAPEChain(cmd, chain)
|
|
||||||
|
|
||||||
return chain
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,14 +15,12 @@ import (
|
||||||
containerApi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
|
containerApi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
containerACL string
|
|
||||||
containerPolicy string
|
containerPolicy string
|
||||||
containerAttributes []string
|
containerAttributes []string
|
||||||
containerAwait bool
|
containerAwait bool
|
||||||
|
@ -89,9 +87,6 @@ It will be stored in sidechain when inner ring will accepts it.`,
|
||||||
err = parseAttributes(&cnr, containerAttributes)
|
err = parseAttributes(&cnr, containerAttributes)
|
||||||
commonCmd.ExitOnErr(cmd, "", err)
|
commonCmd.ExitOnErr(cmd, "", err)
|
||||||
|
|
||||||
var basicACL acl.Basic
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL))
|
|
||||||
|
|
||||||
tok := getSession(cmd)
|
tok := getSession(cmd)
|
||||||
|
|
||||||
if tok != nil {
|
if tok != nil {
|
||||||
|
@ -105,7 +100,6 @@ It will be stored in sidechain when inner ring will accepts it.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
cnr.SetPlacementPolicy(*placementPolicy)
|
cnr.SetPlacementPolicy(*placementPolicy)
|
||||||
cnr.SetBasicACL(basicACL)
|
|
||||||
|
|
||||||
var syncContainerPrm internalclient.SyncContainerPrm
|
var syncContainerPrm internalclient.SyncContainerPrm
|
||||||
syncContainerPrm.SetClient(cli)
|
syncContainerPrm.SetClient(cli)
|
||||||
|
@ -163,10 +157,6 @@ func initContainerCreateCmd() {
|
||||||
flags.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage)
|
flags.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage)
|
||||||
flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
|
flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
|
||||||
flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
|
flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
|
||||||
|
|
||||||
flags.StringVar(&containerACL, "basic-acl", acl.NamePrivate, fmt.Sprintf("HEX encoded basic ACL value or keywords like '%s', '%s', '%s'",
|
|
||||||
acl.NamePublicRW, acl.NamePrivate, acl.NamePublicROExtended,
|
|
||||||
))
|
|
||||||
flags.StringVarP(&containerPolicy, "policy", "p", "", "QL-encoded or JSON-encoded placement policy or path to file with it")
|
flags.StringVarP(&containerPolicy, "policy", "p", "", "QL-encoded or JSON-encoded placement policy or path to file with it")
|
||||||
flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2")
|
flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2")
|
||||||
flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted")
|
flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted")
|
||||||
|
|
|
@ -6,8 +6,11 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// flags of list command.
|
// flags of list command.
|
||||||
|
@ -51,44 +54,60 @@ var listContainersCmd = &cobra.Command{
|
||||||
|
|
||||||
var prm internalclient.ListContainersPrm
|
var prm internalclient.ListContainersPrm
|
||||||
prm.SetClient(cli)
|
prm.SetClient(cli)
|
||||||
prm.Account = idUser
|
prm.OwnerID = idUser
|
||||||
|
|
||||||
res, err := internalclient.ListContainers(cmd.Context(), prm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
prmGet := internalclient.GetContainerPrm{
|
prmGet := internalclient.GetContainerPrm{
|
||||||
Client: cli,
|
Client: cli,
|
||||||
}
|
}
|
||||||
|
var containerIDs []cid.ID
|
||||||
|
|
||||||
|
err := internalclient.ListContainersStream(cmd.Context(), prm, func(id cid.ID) bool {
|
||||||
|
printContainer(cmd, prmGet, id)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, ok := status.FromError(err); ok && e.Code() == codes.Unimplemented {
|
||||||
|
res, err := internalclient.ListContainers(cmd.Context(), prm)
|
||||||
|
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
||||||
|
containerIDs = res.SortedIDList()
|
||||||
|
} else {
|
||||||
|
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
containerIDs := res.SortedIDList()
|
|
||||||
for _, cnrID := range containerIDs {
|
for _, cnrID := range containerIDs {
|
||||||
if flagVarListName == "" && !flagVarListPrintAttr {
|
printContainer(cmd, prmGet, cnrID)
|
||||||
cmd.Println(cnrID.String())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
prmGet.ClientParams.ContainerID = &cnrID
|
|
||||||
res, err := internalclient.GetContainer(cmd.Context(), prmGet)
|
|
||||||
if err != nil {
|
|
||||||
cmd.Printf(" failed to read attributes: %v\n", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cnr := res.Container()
|
|
||||||
if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cmd.Println(cnrID.String())
|
|
||||||
|
|
||||||
if flagVarListPrintAttr {
|
|
||||||
cnr.IterateUserAttributes(func(key, val string) {
|
|
||||||
cmd.Printf(" %s: %s\n", key, val)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printContainer(cmd *cobra.Command, prmGet internalclient.GetContainerPrm, id cid.ID) {
|
||||||
|
if flagVarListName == "" && !flagVarListPrintAttr {
|
||||||
|
cmd.Println(id.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
prmGet.ClientParams.ContainerID = &id
|
||||||
|
res, err := internalclient.GetContainer(cmd.Context(), prmGet)
|
||||||
|
if err != nil {
|
||||||
|
cmd.Printf(" failed to read attributes: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cnr := res.Container()
|
||||||
|
if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd.Println(id.String())
|
||||||
|
|
||||||
|
if flagVarListPrintAttr {
|
||||||
|
cnr.IterateUserAttributes(func(key, val string) {
|
||||||
|
cmd.Printf(" %s: %s\n", key, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func initContainerListContainersCmd() {
|
func initContainerListContainersCmd() {
|
||||||
commonflags.Init(listContainersCmd)
|
commonflags.Init(listContainersCmd)
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,14 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
ruleFlag = "rule"
|
|
||||||
pathFlag = "path"
|
|
||||||
)
|
|
||||||
|
|
||||||
var addRuleCmd = &cobra.Command{
|
var addRuleCmd = &cobra.Command{
|
||||||
Use: "add-rule",
|
Use: "add-rule",
|
||||||
Short: "Add local override",
|
Short: "Add local override",
|
||||||
|
@ -31,41 +22,12 @@ control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ..
|
||||||
Run: addRule,
|
Run: addRule,
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseChain(cmd *cobra.Command) *apechain.Chain {
|
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
|
||||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
|
||||||
|
|
||||||
chainIDRaw := []byte(chainID)
|
|
||||||
|
|
||||||
if hexEncoded {
|
|
||||||
var err error
|
|
||||||
chainIDRaw, err = hex.DecodeString(chainID)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
chain := new(apechain.Chain)
|
|
||||||
chain.ID = apechain.ID(chainIDRaw)
|
|
||||||
|
|
||||||
if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules))
|
|
||||||
} else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath))
|
|
||||||
} else {
|
|
||||||
commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed"))
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("Parsed chain:")
|
|
||||||
util.PrintHumanReadableAPEChain(cmd, chain)
|
|
||||||
|
|
||||||
return chain
|
|
||||||
}
|
|
||||||
|
|
||||||
func addRule(cmd *cobra.Command, _ []string) {
|
func addRule(cmd *cobra.Command, _ []string) {
|
||||||
pk := key.Get(cmd)
|
pk := key.Get(cmd)
|
||||||
|
|
||||||
target := parseTarget(cmd)
|
target := parseTarget(cmd)
|
||||||
|
|
||||||
parsed := parseChain(cmd)
|
parsed := apeCmd.ParseChain(cmd)
|
||||||
|
|
||||||
req := &control.AddChainLocalOverrideRequest{
|
req := &control.AddChainLocalOverrideRequest{
|
||||||
Body: &control.AddChainLocalOverrideRequest_Body{
|
Body: &control.AddChainLocalOverrideRequest_Body{
|
||||||
|
@ -94,13 +56,13 @@ func initControlAddRuleCmd() {
|
||||||
initControlFlags(addRuleCmd)
|
initControlFlags(addRuleCmd)
|
||||||
|
|
||||||
ff := addRuleCmd.Flags()
|
ff := addRuleCmd.Flags()
|
||||||
ff.StringArray(ruleFlag, []string{}, "Rule statement")
|
ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement")
|
||||||
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
|
ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||||
ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
|
ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain")
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = addRuleCmd.MarkFlagRequired(targetTypeFlag)
|
_ = addRuleCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||||
|
|
||||||
addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
|
addRuleCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
package control
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
const ignoreErrorsFlag = "no-errors"
|
|
||||||
|
|
||||||
var evacuateShardCmd = &cobra.Command{
|
|
||||||
Use: "evacuate",
|
|
||||||
Short: "Evacuate objects from shard",
|
|
||||||
Long: "Evacuate objects from shard to other shards",
|
|
||||||
Run: evacuateShard,
|
|
||||||
Deprecated: "use frostfs-cli control shards evacuation start",
|
|
||||||
}
|
|
||||||
|
|
||||||
func evacuateShard(cmd *cobra.Command, _ []string) {
|
|
||||||
pk := key.Get(cmd)
|
|
||||||
|
|
||||||
req := &control.EvacuateShardRequest{Body: new(control.EvacuateShardRequest_Body)}
|
|
||||||
req.Body.Shard_ID = getShardIDList(cmd)
|
|
||||||
req.Body.IgnoreErrors, _ = cmd.Flags().GetBool(ignoreErrorsFlag)
|
|
||||||
|
|
||||||
signRequest(cmd, pk, req)
|
|
||||||
|
|
||||||
cli := getClient(cmd, pk)
|
|
||||||
|
|
||||||
var resp *control.EvacuateShardResponse
|
|
||||||
var err error
|
|
||||||
err = cli.ExecRaw(func(client *client.Client) error {
|
|
||||||
resp, err = control.EvacuateShard(client, req)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
cmd.Printf("Objects moved: %d\n", resp.GetBody().GetCount())
|
|
||||||
|
|
||||||
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
|
|
||||||
|
|
||||||
cmd.Println("Shard has successfully been evacuated.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func initControlEvacuateShardCmd() {
|
|
||||||
initControlFlags(evacuateShardCmd)
|
|
||||||
|
|
||||||
flags := evacuateShardCmd.Flags()
|
|
||||||
flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding")
|
|
||||||
flags.Bool(shardAllFlag, false, "Process all shards")
|
|
||||||
flags.Bool(ignoreErrorsFlag, false, "Skip invalid/unreadable objects")
|
|
||||||
|
|
||||||
evacuateShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag)
|
|
||||||
}
|
|
|
@ -17,10 +17,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
awaitFlag = "await"
|
awaitFlag = "await"
|
||||||
noProgressFlag = "no-progress"
|
noProgressFlag = "no-progress"
|
||||||
scopeFlag = "scope"
|
scopeFlag = "scope"
|
||||||
repOneOnlyFlag = "rep-one-only"
|
repOneOnlyFlag = "rep-one-only"
|
||||||
|
ignoreErrorsFlag = "no-errors"
|
||||||
|
|
||||||
containerWorkerCountFlag = "container-worker-count"
|
containerWorkerCountFlag = "container-worker-count"
|
||||||
objectWorkerCountFlag = "object-worker-count"
|
objectWorkerCountFlag = "object-worker-count"
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apecmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
|
@ -24,8 +24,8 @@ func getRule(cmd *cobra.Command, _ []string) {
|
||||||
|
|
||||||
target := parseTarget(cmd)
|
target := parseTarget(cmd)
|
||||||
|
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag)
|
||||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag)
|
||||||
|
|
||||||
if hexEncoded {
|
if hexEncoded {
|
||||||
chainIDBytes, err := hex.DecodeString(chainID)
|
chainIDBytes, err := hex.DecodeString(chainID)
|
||||||
|
@ -56,16 +56,16 @@ func getRule(cmd *cobra.Command, _ []string) {
|
||||||
|
|
||||||
var chain apechain.Chain
|
var chain apechain.Chain
|
||||||
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain()))
|
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain()))
|
||||||
util.PrintHumanReadableAPEChain(cmd, &chain)
|
apecmd.PrintHumanReadableAPEChain(cmd, &chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initControGetRuleCmd() {
|
func initControGetRuleCmd() {
|
||||||
initControlFlags(getRuleCmd)
|
initControlFlags(getRuleCmd)
|
||||||
|
|
||||||
ff := getRuleCmd.Flags()
|
ff := getRuleCmd.Flags()
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc)
|
||||||
_ = getRuleCmd.MarkFlagRequired(targetTypeFlag)
|
_ = getRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag)
|
||||||
ff.String(chainIDFlag, "", "Chain id")
|
ff.String(apecmd.ChainIDFlag, "", "Chain id")
|
||||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
ff.Bool(apecmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,65 +21,25 @@ var listRulesCmd = &cobra.Command{
|
||||||
Run: listRules,
|
Run: listRules,
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
var engineToControlSvcType = map[policyengine.TargetType]control.ChainTarget_TargetType{
|
||||||
defaultNamespace = "root"
|
policyengine.Namespace: control.ChainTarget_NAMESPACE,
|
||||||
namespaceTarget = "namespace"
|
policyengine.Container: control.ChainTarget_CONTAINER,
|
||||||
containerTarget = "container"
|
policyengine.User: control.ChainTarget_USER,
|
||||||
userTarget = "user"
|
policyengine.Group: control.ChainTarget_GROUP,
|
||||||
groupTarget = "group"
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
targetNameFlag = "target-name"
|
|
||||||
targetNameDesc = "Resource name in APE resource name format"
|
|
||||||
targetTypeFlag = "target-type"
|
|
||||||
targetTypeDesc = "Resource type(container/namespace)"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errSettingDefaultValueWasDeclined = errors.New("setting default value was declined")
|
|
||||||
errUnknownTargetType = errors.New("unknown target type")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseTarget(cmd *cobra.Command) *control.ChainTarget {
|
func parseTarget(cmd *cobra.Command) *control.ChainTarget {
|
||||||
typ, _ := cmd.Flags().GetString(targetTypeFlag)
|
target := apeCmd.ParseTarget(cmd)
|
||||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
|
||||||
switch typ {
|
typ, ok := engineToControlSvcType[target.Type]
|
||||||
case namespaceTarget:
|
if !ok {
|
||||||
if name == "" {
|
commonCmd.ExitOnErr(cmd, "%w", fmt.Errorf("unknown type '%c", target.Type))
|
||||||
ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace))
|
}
|
||||||
commonCmd.ExitOnErr(cmd, "read line error: %w", err)
|
|
||||||
ln = strings.ToLower(ln)
|
return &control.ChainTarget{
|
||||||
if len(ln) > 0 && (ln[0] == 'n') {
|
Name: target.Name,
|
||||||
commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined)
|
Type: typ,
|
||||||
}
|
|
||||||
name = defaultNamespace
|
|
||||||
}
|
|
||||||
return &control.ChainTarget{
|
|
||||||
Name: name,
|
|
||||||
Type: control.ChainTarget_NAMESPACE,
|
|
||||||
}
|
|
||||||
case containerTarget:
|
|
||||||
var cnr cid.ID
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
|
|
||||||
return &control.ChainTarget{
|
|
||||||
Name: name,
|
|
||||||
Type: control.ChainTarget_CONTAINER,
|
|
||||||
}
|
|
||||||
case userTarget:
|
|
||||||
return &control.ChainTarget{
|
|
||||||
Name: name,
|
|
||||||
Type: control.ChainTarget_USER,
|
|
||||||
}
|
|
||||||
case groupTarget:
|
|
||||||
return &control.ChainTarget{
|
|
||||||
Name: name,
|
|
||||||
Type: control.ChainTarget_GROUP,
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func listRules(cmd *cobra.Command, _ []string) {
|
func listRules(cmd *cobra.Command, _ []string) {
|
||||||
|
@ -117,7 +75,7 @@ func listRules(cmd *cobra.Command, _ []string) {
|
||||||
for _, c := range chains {
|
for _, c := range chains {
|
||||||
var chain apechain.Chain
|
var chain apechain.Chain
|
||||||
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c))
|
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c))
|
||||||
util.PrintHumanReadableAPEChain(cmd, &chain)
|
apeCmd.PrintHumanReadableAPEChain(cmd, &chain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +83,7 @@ func initControlListRulesCmd() {
|
||||||
initControlFlags(listRulesCmd)
|
initControlFlags(listRulesCmd)
|
||||||
|
|
||||||
ff := listRulesCmd.Flags()
|
ff := listRulesCmd.Flags()
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||||
_ = listRulesCmd.MarkFlagRequired(targetTypeFlag)
|
_ = listRulesCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,26 +2,20 @@ package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
chainNameFlag = "chain-name"
|
|
||||||
chainNameFlagUsage = "Chain name(ingress|s3)"
|
|
||||||
)
|
|
||||||
|
|
||||||
var listTargetsCmd = &cobra.Command{
|
var listTargetsCmd = &cobra.Command{
|
||||||
Use: "list-targets",
|
Use: "list-targets",
|
||||||
Short: "List local targets",
|
Short: "List local targets",
|
||||||
|
@ -32,15 +26,11 @@ var listTargetsCmd = &cobra.Command{
|
||||||
func listTargets(cmd *cobra.Command, _ []string) {
|
func listTargets(cmd *cobra.Command, _ []string) {
|
||||||
pk := key.Get(cmd)
|
pk := key.Get(cmd)
|
||||||
|
|
||||||
var cnr cid.ID
|
chainName := apeCmd.ParseChainName(cmd)
|
||||||
chainName, _ := cmd.Flags().GetString(chainNameFlag)
|
|
||||||
|
|
||||||
rawCID := make([]byte, sha256.Size)
|
|
||||||
cnr.Encode(rawCID)
|
|
||||||
|
|
||||||
req := &control.ListTargetsLocalOverridesRequest{
|
req := &control.ListTargetsLocalOverridesRequest{
|
||||||
Body: &control.ListTargetsLocalOverridesRequest_Body{
|
Body: &control.ListTargetsLocalOverridesRequest_Body{
|
||||||
ChainName: chainName,
|
ChainName: string(chainName),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +72,7 @@ func initControlListTargetsCmd() {
|
||||||
initControlFlags(listTargetsCmd)
|
initControlFlags(listTargetsCmd)
|
||||||
|
|
||||||
ff := listTargetsCmd.Flags()
|
ff := listTargetsCmd.Flags()
|
||||||
ff.String(chainNameFlag, "", chainNameFlagUsage)
|
ff.String(apeCmd.ChainNameFlag, "", apeCmd.ChainNameFlagDesc)
|
||||||
|
|
||||||
_ = cobra.MarkFlagRequired(ff, chainNameFlag)
|
_ = cobra.MarkFlagRequired(ff, apeCmd.ChainNameFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,12 @@ import (
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apecmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
chainIDFlag = "chain-id"
|
|
||||||
chainIDHexFlag = "chain-id-hex"
|
|
||||||
allFlag = "all"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errEmptyChainID = errors.New("chain id cannot be empty")
|
errEmptyChainID = errors.New("chain id cannot be empty")
|
||||||
|
|
||||||
|
@ -30,8 +25,8 @@ var (
|
||||||
|
|
||||||
func removeRule(cmd *cobra.Command, _ []string) {
|
func removeRule(cmd *cobra.Command, _ []string) {
|
||||||
pk := key.Get(cmd)
|
pk := key.Get(cmd)
|
||||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag)
|
||||||
removeAll, _ := cmd.Flags().GetBool(allFlag)
|
removeAll, _ := cmd.Flags().GetBool(apecmd.AllFlag)
|
||||||
if removeAll {
|
if removeAll {
|
||||||
req := &control.RemoveChainLocalOverridesByTargetRequest{
|
req := &control.RemoveChainLocalOverridesByTargetRequest{
|
||||||
Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{
|
Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{
|
||||||
|
@ -52,7 +47,7 @@ func removeRule(cmd *cobra.Command, _ []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag)
|
||||||
if chainID == "" {
|
if chainID == "" {
|
||||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
|
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
|
||||||
}
|
}
|
||||||
|
@ -92,11 +87,11 @@ func initControlRemoveRuleCmd() {
|
||||||
initControlFlags(removeRuleCmd)
|
initControlFlags(removeRuleCmd)
|
||||||
|
|
||||||
ff := removeRuleCmd.Flags()
|
ff := removeRuleCmd.Flags()
|
||||||
ff.String(targetNameFlag, "", targetNameDesc)
|
ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc)
|
||||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc)
|
||||||
_ = removeRuleCmd.MarkFlagRequired(targetTypeFlag)
|
_ = removeRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag)
|
||||||
ff.String(chainIDFlag, "", "Chain id")
|
ff.String(apecmd.ChainIDFlag, "", apecmd.ChainIDFlagDesc)
|
||||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
ff.Bool(apecmd.ChainIDHexFlag, false, apecmd.ChainIDHexFlagDesc)
|
||||||
ff.Bool(allFlag, false, "Remove all chains")
|
ff.Bool(apecmd.AllFlag, false, "Remove all chains")
|
||||||
removeRuleCmd.MarkFlagsMutuallyExclusive(allFlag, chainIDFlag)
|
removeRuleCmd.MarkFlagsMutuallyExclusive(apecmd.AllFlag, apecmd.ChainIDFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ var shardsCmd = &cobra.Command{
|
||||||
func initControlShardsCmd() {
|
func initControlShardsCmd() {
|
||||||
shardsCmd.AddCommand(listShardsCmd)
|
shardsCmd.AddCommand(listShardsCmd)
|
||||||
shardsCmd.AddCommand(setShardModeCmd)
|
shardsCmd.AddCommand(setShardModeCmd)
|
||||||
shardsCmd.AddCommand(evacuateShardCmd)
|
|
||||||
shardsCmd.AddCommand(evacuationShardCmd)
|
shardsCmd.AddCommand(evacuationShardCmd)
|
||||||
shardsCmd.AddCommand(flushCacheCmd)
|
shardsCmd.AddCommand(flushCacheCmd)
|
||||||
shardsCmd.AddCommand(doctorCmd)
|
shardsCmd.AddCommand(doctorCmd)
|
||||||
|
@ -23,7 +22,6 @@ func initControlShardsCmd() {
|
||||||
|
|
||||||
initControlShardsListCmd()
|
initControlShardsListCmd()
|
||||||
initControlSetShardModeCmd()
|
initControlSetShardModeCmd()
|
||||||
initControlEvacuateShardCmd()
|
|
||||||
initControlEvacuationShardCmd()
|
initControlEvacuationShardCmd()
|
||||||
initControlFlushCacheCmd()
|
initControlFlushCacheCmd()
|
||||||
initControlDoctorCmd()
|
initControlDoctorCmd()
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -43,6 +42,8 @@ func initObjectHashCmd() {
|
||||||
_ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag)
|
_ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag)
|
||||||
|
|
||||||
flags.String("range", "", "Range to take hash from in the form offset1:length1,...")
|
flags.String("range", "", "Range to take hash from in the form offset1:length1,...")
|
||||||
|
_ = objectHashCmd.MarkFlagRequired("range")
|
||||||
|
|
||||||
flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'")
|
flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'")
|
||||||
flags.String(getRangeHashSaltFlag, "", "Salt in hex format")
|
flags.String(getRangeHashSaltFlag, "", "Salt in hex format")
|
||||||
}
|
}
|
||||||
|
@ -66,36 +67,6 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
|
||||||
pk := key.GetOrGenerate(cmd)
|
pk := key.GetOrGenerate(cmd)
|
||||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
||||||
|
|
||||||
tz := typ == hashTz
|
|
||||||
fullHash := len(ranges) == 0
|
|
||||||
if fullHash {
|
|
||||||
var headPrm internalclient.HeadObjectPrm
|
|
||||||
headPrm.SetClient(cli)
|
|
||||||
Prepare(cmd, &headPrm)
|
|
||||||
headPrm.SetAddress(objAddr)
|
|
||||||
|
|
||||||
// get hash of full payload through HEAD (may be user can do it through dedicated command?)
|
|
||||||
res, err := internalclient.HeadObject(cmd.Context(), headPrm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
var cs checksum.Checksum
|
|
||||||
var csSet bool
|
|
||||||
|
|
||||||
if tz {
|
|
||||||
cs, csSet = res.Header().PayloadHomomorphicHash()
|
|
||||||
} else {
|
|
||||||
cs, csSet = res.Header().PayloadChecksum()
|
|
||||||
}
|
|
||||||
|
|
||||||
if csSet {
|
|
||||||
cmd.Println(hex.EncodeToString(cs.Value()))
|
|
||||||
} else {
|
|
||||||
cmd.Println("Missing checksum in object header.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var hashPrm internalclient.HashPayloadRangesPrm
|
var hashPrm internalclient.HashPayloadRangesPrm
|
||||||
hashPrm.SetClient(cli)
|
hashPrm.SetClient(cli)
|
||||||
Prepare(cmd, &hashPrm)
|
Prepare(cmd, &hashPrm)
|
||||||
|
@ -104,7 +75,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
|
||||||
hashPrm.SetSalt(salt)
|
hashPrm.SetSalt(salt)
|
||||||
hashPrm.SetRanges(ranges)
|
hashPrm.SetRanges(ranges)
|
||||||
|
|
||||||
if tz {
|
if typ == hashTz {
|
||||||
hashPrm.TZ()
|
hashPrm.TZ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"cmp"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||||
|
@ -507,7 +504,6 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) {
|
func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) {
|
||||||
normilizeObjectNodesResult(objects, result)
|
|
||||||
if json, _ := cmd.Flags().GetBool(commonflags.JSON); json {
|
if json, _ := cmd.Flags().GetBool(commonflags.JSON); json {
|
||||||
printObjectNodesAsJSON(cmd, objID, objects, result)
|
printObjectNodesAsJSON(cmd, objID, objects, result)
|
||||||
} else {
|
} else {
|
||||||
|
@ -515,34 +511,6 @@ func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, resul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func normilizeObjectNodesResult(objects []phyObject, result *objectNodesResult) {
|
|
||||||
slices.SortFunc(objects, func(lhs, rhs phyObject) int {
|
|
||||||
if lhs.ecHeader == nil && rhs.ecHeader == nil {
|
|
||||||
return bytes.Compare(lhs.objectID[:], rhs.objectID[:])
|
|
||||||
}
|
|
||||||
if lhs.ecHeader == nil {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if rhs.ecHeader == nil {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
if lhs.ecHeader.parent == rhs.ecHeader.parent {
|
|
||||||
return cmp.Compare(lhs.ecHeader.index, rhs.ecHeader.index)
|
|
||||||
}
|
|
||||||
return bytes.Compare(lhs.ecHeader.parent[:], rhs.ecHeader.parent[:])
|
|
||||||
})
|
|
||||||
for _, obj := range objects {
|
|
||||||
op := result.placements[obj.objectID]
|
|
||||||
slices.SortFunc(op.confirmedNodes, func(lhs, rhs netmapSDK.NodeInfo) int {
|
|
||||||
return bytes.Compare(lhs.PublicKey(), rhs.PublicKey())
|
|
||||||
})
|
|
||||||
slices.SortFunc(op.requiredNodes, func(lhs, rhs netmapSDK.NodeInfo) int {
|
|
||||||
return bytes.Compare(lhs.PublicKey(), rhs.PublicKey())
|
|
||||||
})
|
|
||||||
result.placements[obj.objectID] = op
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printObjectNodesAsText(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) {
|
func printObjectNodesAsText(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) {
|
||||||
fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects))
|
fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects))
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
|
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape"
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -46,7 +47,7 @@ func reloadConfig() error {
|
||||||
return logPrm.Reload()
|
return logPrm.Reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
func watchForSignal(cancel func()) {
|
func watchForSignal(ctx context.Context, cancel func()) {
|
||||||
ch := make(chan os.Signal, 1)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
@ -58,49 +59,49 @@ func watchForSignal(cancel func()) {
|
||||||
// signals causing application to shut down should have priority over
|
// signals causing application to shut down should have priority over
|
||||||
// reconfiguration signal
|
// reconfiguration signal
|
||||||
case <-ch:
|
case <-ch:
|
||||||
log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
||||||
cancel()
|
cancel()
|
||||||
shutdown()
|
shutdown(ctx)
|
||||||
log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
||||||
return
|
return
|
||||||
case err := <-intErr: // internal application error
|
case err := <-intErr: // internal application error
|
||||||
log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
|
log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
|
||||||
cancel()
|
cancel()
|
||||||
shutdown()
|
shutdown(ctx)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
// block until any signal is receieved
|
// block until any signal is receieved
|
||||||
select {
|
select {
|
||||||
case <-ch:
|
case <-ch:
|
||||||
log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
||||||
cancel()
|
cancel()
|
||||||
shutdown()
|
shutdown(ctx)
|
||||||
log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
||||||
return
|
return
|
||||||
case err := <-intErr: // internal application error
|
case err := <-intErr: // internal application error
|
||||||
log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
|
log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error()))
|
||||||
cancel()
|
cancel()
|
||||||
shutdown()
|
shutdown(ctx)
|
||||||
return
|
return
|
||||||
case <-sighupCh:
|
case <-sighupCh:
|
||||||
log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
|
log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
|
||||||
if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
|
if !innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
|
||||||
log.Info(logs.FrostFSNodeSIGHUPSkip)
|
log.Info(ctx, logs.FrostFSNodeSIGHUPSkip)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
err := reloadConfig()
|
err := reloadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
|
log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err))
|
||||||
}
|
}
|
||||||
pprofCmp.reload()
|
pprofCmp.reload(ctx)
|
||||||
metricsCmp.reload()
|
metricsCmp.reload(ctx)
|
||||||
log.Info(logs.FrostFSIRReloadExtraWallets)
|
log.Info(ctx, logs.FrostFSIRReloadExtraWallets)
|
||||||
err = innerRing.SetExtraWallets(cfg)
|
err = innerRing.SetExtraWallets(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
|
log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err))
|
||||||
}
|
}
|
||||||
innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
|
innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
|
||||||
log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
|
log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -24,8 +25,8 @@ const (
|
||||||
shutdownTimeoutKeyPostfix = ".shutdown_timeout"
|
shutdownTimeoutKeyPostfix = ".shutdown_timeout"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *httpComponent) init() {
|
func (c *httpComponent) init(ctx context.Context) {
|
||||||
log.Info("init " + c.name)
|
log.Info(ctx, "init "+c.name)
|
||||||
c.enabled = cfg.GetBool(c.name + enabledKeyPostfix)
|
c.enabled = cfg.GetBool(c.name + enabledKeyPostfix)
|
||||||
c.address = cfg.GetString(c.name + addressKeyPostfix)
|
c.address = cfg.GetString(c.name + addressKeyPostfix)
|
||||||
c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix)
|
c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix)
|
||||||
|
@ -39,14 +40,14 @@ func (c *httpComponent) init() {
|
||||||
httputil.WithShutdownTimeout(c.shutdownDur),
|
httputil.WithShutdownTimeout(c.shutdownDur),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
log.Info(c.name + " is disabled, skip")
|
log.Info(ctx, c.name+" is disabled, skip")
|
||||||
c.srv = nil
|
c.srv = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpComponent) start() {
|
func (c *httpComponent) start(ctx context.Context) {
|
||||||
if c.srv != nil {
|
if c.srv != nil {
|
||||||
log.Info("start " + c.name)
|
log.Info(ctx, "start "+c.name)
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
@ -55,10 +56,10 @@ func (c *httpComponent) start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpComponent) shutdown() error {
|
func (c *httpComponent) shutdown(ctx context.Context) error {
|
||||||
if c.srv != nil {
|
if c.srv != nil {
|
||||||
log.Info("shutdown " + c.name)
|
log.Info(ctx, "shutdown "+c.name)
|
||||||
return c.srv.Shutdown()
|
return c.srv.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -70,17 +71,17 @@ func (c *httpComponent) needReload() bool {
|
||||||
return enabled != c.enabled || enabled && (address != c.address || dur != c.shutdownDur)
|
return enabled != c.enabled || enabled && (address != c.address || dur != c.shutdownDur)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpComponent) reload() {
|
func (c *httpComponent) reload(ctx context.Context) {
|
||||||
log.Info("reload " + c.name)
|
log.Info(ctx, "reload "+c.name)
|
||||||
if c.needReload() {
|
if c.needReload() {
|
||||||
log.Info(c.name + " config updated")
|
log.Info(ctx, c.name+" config updated")
|
||||||
if err := c.shutdown(); err != nil {
|
if err := c.shutdown(ctx); err != nil {
|
||||||
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
|
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
c.init()
|
c.init(ctx)
|
||||||
c.start()
|
c.start(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,48 +87,48 @@ func main() {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
pprofCmp = newPprofComponent()
|
pprofCmp = newPprofComponent()
|
||||||
pprofCmp.init()
|
pprofCmp.init(ctx)
|
||||||
|
|
||||||
metricsCmp = newMetricsComponent()
|
metricsCmp = newMetricsComponent()
|
||||||
metricsCmp.init()
|
metricsCmp.init(ctx)
|
||||||
audit.Store(cfg.GetBool("audit.enabled"))
|
audit.Store(cfg.GetBool("audit.enabled"))
|
||||||
|
|
||||||
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit)
|
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit)
|
||||||
exitErr(err)
|
exitErr(err)
|
||||||
|
|
||||||
pprofCmp.start()
|
pprofCmp.start(ctx)
|
||||||
metricsCmp.start()
|
metricsCmp.start(ctx)
|
||||||
|
|
||||||
// start inner ring
|
// start inner ring
|
||||||
err = innerRing.Start(ctx, intErr)
|
err = innerRing.Start(ctx, intErr)
|
||||||
exitErr(err)
|
exitErr(err)
|
||||||
|
|
||||||
log.Info(logs.CommonApplicationStarted,
|
log.Info(ctx, logs.CommonApplicationStarted,
|
||||||
zap.String("version", misc.Version))
|
zap.String("version", misc.Version))
|
||||||
|
|
||||||
watchForSignal(cancel)
|
watchForSignal(ctx, cancel)
|
||||||
|
|
||||||
<-ctx.Done() // graceful shutdown
|
<-ctx.Done() // graceful shutdown
|
||||||
log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop)
|
log.Debug(ctx, logs.FrostFSNodeWaitingForAllProcessesToStop)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
log.Info(logs.FrostFSIRApplicationStopped)
|
log.Info(ctx, logs.FrostFSIRApplicationStopped)
|
||||||
}
|
}
|
||||||
|
|
||||||
func shutdown() {
|
func shutdown(ctx context.Context) {
|
||||||
innerRing.Stop()
|
innerRing.Stop(ctx)
|
||||||
if err := metricsCmp.shutdown(); err != nil {
|
if err := metricsCmp.shutdown(ctx); err != nil {
|
||||||
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
|
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if err := pprofCmp.shutdown(); err != nil {
|
if err := pprofCmp.shutdown(ctx); err != nil {
|
||||||
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
|
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sdnotify.ClearStatus(); err != nil {
|
if err := sdnotify.ClearStatus(); err != nil {
|
||||||
log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err))
|
log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
|
@ -28,8 +29,8 @@ func newPprofComponent() *pprofComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *pprofComponent) init() {
|
func (c *pprofComponent) init(ctx context.Context) {
|
||||||
c.httpComponent.init()
|
c.httpComponent.init(ctx)
|
||||||
|
|
||||||
if c.enabled {
|
if c.enabled {
|
||||||
c.blockRate = cfg.GetInt(pprofBlockRateKey)
|
c.blockRate = cfg.GetInt(pprofBlockRateKey)
|
||||||
|
@ -51,17 +52,17 @@ func (c *pprofComponent) needReload() bool {
|
||||||
c.enabled && (c.blockRate != blockRate || c.mutexRate != mutexRate)
|
c.enabled && (c.blockRate != blockRate || c.mutexRate != mutexRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *pprofComponent) reload() {
|
func (c *pprofComponent) reload(ctx context.Context) {
|
||||||
log.Info("reload " + c.name)
|
log.Info(ctx, "reload "+c.name)
|
||||||
if c.needReload() {
|
if c.needReload() {
|
||||||
log.Info(c.name + " config updated")
|
log.Info(ctx, c.name+" config updated")
|
||||||
if err := c.shutdown(); err != nil {
|
if err := c.shutdown(ctx); err != nil {
|
||||||
log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer,
|
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
|
||||||
zap.String("error", err.Error()))
|
zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.init()
|
c.init(ctx)
|
||||||
c.start()
|
c.start(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) {
|
||||||
common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
|
common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
|
||||||
|
|
||||||
blz := openBlobovnicza(cmd)
|
blz := openBlobovnicza(cmd)
|
||||||
defer blz.Close()
|
defer blz.Close(cmd.Context())
|
||||||
|
|
||||||
var prm blobovnicza.GetPrm
|
var prm blobovnicza.GetPrm
|
||||||
prm.SetAddress(addr)
|
prm.SetAddress(addr)
|
||||||
|
|
|
@ -32,7 +32,7 @@ func listFunc(cmd *cobra.Command, _ []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
blz := openBlobovnicza(cmd)
|
blz := openBlobovnicza(cmd)
|
||||||
defer blz.Close()
|
defer blz.Close(cmd.Context())
|
||||||
|
|
||||||
err := blobovnicza.IterateAddresses(context.Background(), blz, wAddr)
|
err := blobovnicza.IterateAddresses(context.Background(), blz, wAddr)
|
||||||
common.ExitOnErr(cmd, common.Errf("blobovnicza iterator failure: %w", err))
|
common.ExitOnErr(cmd, common.Errf("blobovnicza iterator failure: %w", err))
|
||||||
|
|
|
@ -27,7 +27,7 @@ func openBlobovnicza(cmd *cobra.Command) *blobovnicza.Blobovnicza {
|
||||||
blobovnicza.WithPath(vPath),
|
blobovnicza.WithPath(vPath),
|
||||||
blobovnicza.WithReadOnly(true),
|
blobovnicza.WithReadOnly(true),
|
||||||
)
|
)
|
||||||
common.ExitOnErr(cmd, blz.Open())
|
common.ExitOnErr(cmd, blz.Open(cmd.Context()))
|
||||||
|
|
||||||
return blz
|
return blz
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) {
|
||||||
common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
|
common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
|
||||||
|
|
||||||
db := openMeta(cmd)
|
db := openMeta(cmd)
|
||||||
defer db.Close()
|
defer db.Close(cmd.Context())
|
||||||
|
|
||||||
storageID := meta.StorageIDPrm{}
|
storageID := meta.StorageIDPrm{}
|
||||||
storageID.SetAddress(addr)
|
storageID.SetAddress(addr)
|
||||||
|
|
|
@ -19,7 +19,7 @@ func init() {
|
||||||
|
|
||||||
func listGarbageFunc(cmd *cobra.Command, _ []string) {
|
func listGarbageFunc(cmd *cobra.Command, _ []string) {
|
||||||
db := openMeta(cmd)
|
db := openMeta(cmd)
|
||||||
defer db.Close()
|
defer db.Close(cmd.Context())
|
||||||
|
|
||||||
var garbPrm meta.GarbageIterationPrm
|
var garbPrm meta.GarbageIterationPrm
|
||||||
garbPrm.SetHandler(
|
garbPrm.SetHandler(
|
||||||
|
|
|
@ -19,7 +19,7 @@ func init() {
|
||||||
|
|
||||||
func listGraveyardFunc(cmd *cobra.Command, _ []string) {
|
func listGraveyardFunc(cmd *cobra.Command, _ []string) {
|
||||||
db := openMeta(cmd)
|
db := openMeta(cmd)
|
||||||
defer db.Close()
|
defer db.Close(cmd.Context())
|
||||||
|
|
||||||
var gravePrm meta.GraveyardIterationPrm
|
var gravePrm meta.GraveyardIterationPrm
|
||||||
gravePrm.SetHandler(
|
gravePrm.SetHandler(
|
||||||
|
|
|
@ -196,31 +196,6 @@ func (s ttlContainerStorage) DeletionInfo(cnr cid.ID) (*container.DelInfo, error
|
||||||
return s.delInfoCache.get(cnr)
|
return s.delInfoCache.get(cnr)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ttlEACLStorage struct {
|
|
||||||
*ttlNetCache[cid.ID, *container.EACL]
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCachedEACLStorage(v container.EACLSource, ttl time.Duration) ttlEACLStorage {
|
|
||||||
const eaclCacheSize = 100
|
|
||||||
|
|
||||||
lruCnrCache := newNetworkTTLCache(eaclCacheSize, ttl, func(id cid.ID) (*container.EACL, error) {
|
|
||||||
return v.GetEACL(id)
|
|
||||||
}, metrics.NewCacheMetrics("eacl"))
|
|
||||||
|
|
||||||
return ttlEACLStorage{lruCnrCache}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEACL returns eACL value from the cache. If value is missing in the cache
|
|
||||||
// or expired, then it returns value from side chain and updates cache.
|
|
||||||
func (s ttlEACLStorage) GetEACL(cnr cid.ID) (*container.EACL, error) {
|
|
||||||
return s.get(cnr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidateEACL removes cached eACL value.
|
|
||||||
func (s ttlEACLStorage) InvalidateEACL(cnr cid.ID) {
|
|
||||||
s.remove(cnr)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lruNetmapSource struct {
|
type lruNetmapSource struct {
|
||||||
netState netmap.State
|
netState netmap.State
|
||||||
|
|
||||||
|
|
|
@ -397,16 +397,16 @@ type internals struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// starts node's maintenance.
|
// starts node's maintenance.
|
||||||
func (c *cfg) startMaintenance() {
|
func (c *cfg) startMaintenance(ctx context.Context) {
|
||||||
c.isMaintenance.Store(true)
|
c.isMaintenance.Store(true)
|
||||||
c.cfgNetmap.state.setControlNetmapStatus(control.NetmapStatus_MAINTENANCE)
|
c.cfgNetmap.state.setControlNetmapStatus(control.NetmapStatus_MAINTENANCE)
|
||||||
c.log.Info(logs.FrostFSNodeStartedLocalNodesMaintenance)
|
c.log.Info(ctx, logs.FrostFSNodeStartedLocalNodesMaintenance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stops node's maintenance.
|
// stops node's maintenance.
|
||||||
func (c *internals) stopMaintenance() {
|
func (c *internals) stopMaintenance(ctx context.Context) {
|
||||||
if c.isMaintenance.CompareAndSwap(true, false) {
|
if c.isMaintenance.CompareAndSwap(true, false) {
|
||||||
c.log.Info(logs.FrostFSNodeStoppedLocalNodesMaintenance)
|
c.log.Info(ctx, logs.FrostFSNodeStoppedLocalNodesMaintenance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,8 +591,6 @@ type cfgMorph struct {
|
||||||
|
|
||||||
client *client.Client
|
client *client.Client
|
||||||
|
|
||||||
notaryEnabled bool
|
|
||||||
|
|
||||||
// TTL of Sidechain cached values. Non-positive value disables caching.
|
// TTL of Sidechain cached values. Non-positive value disables caching.
|
||||||
cacheTTL time.Duration
|
cacheTTL time.Duration
|
||||||
|
|
||||||
|
@ -608,9 +606,10 @@ type cfgAccounting struct {
|
||||||
type cfgContainer struct {
|
type cfgContainer struct {
|
||||||
scriptHash neogoutil.Uint160
|
scriptHash neogoutil.Uint160
|
||||||
|
|
||||||
parsers map[event.Type]event.NotificationParser
|
parsers map[event.Type]event.NotificationParser
|
||||||
subscribers map[event.Type][]event.Handler
|
subscribers map[event.Type][]event.Handler
|
||||||
workerPool util.WorkerPool // pool for asynchronous handlers
|
workerPool util.WorkerPool // pool for asynchronous handlers
|
||||||
|
containerBatchSize uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type cfgFrostfsID struct {
|
type cfgFrostfsID struct {
|
||||||
|
@ -642,8 +641,6 @@ type cfgObject struct {
|
||||||
|
|
||||||
cnrSource container.Source
|
cnrSource container.Source
|
||||||
|
|
||||||
eaclSource container.EACLSource
|
|
||||||
|
|
||||||
cfgAccessPolicyEngine cfgAccessPolicyEngine
|
cfgAccessPolicyEngine cfgAccessPolicyEngine
|
||||||
|
|
||||||
pool cfgObjectRoutines
|
pool cfgObjectRoutines
|
||||||
|
@ -707,7 +704,7 @@ func initCfg(appCfg *config.Config) *cfg {
|
||||||
log, err := logger.NewLogger(logPrm)
|
log, err := logger.NewLogger(logPrm)
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
if loggerconfig.ToLokiConfig(appCfg).Enabled {
|
if loggerconfig.ToLokiConfig(appCfg).Enabled {
|
||||||
log.Logger = log.Logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
|
log.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
|
||||||
lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg))
|
lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg))
|
||||||
return lokiCore
|
return lokiCore
|
||||||
}))
|
}))
|
||||||
|
@ -1091,7 +1088,7 @@ func (c *cfg) LocalAddress() network.AddressGroup {
|
||||||
func initLocalStorage(ctx context.Context, c *cfg) {
|
func initLocalStorage(ctx context.Context, c *cfg) {
|
||||||
ls := engine.New(c.engineOpts()...)
|
ls := engine.New(c.engineOpts()...)
|
||||||
|
|
||||||
addNewEpochAsyncNotificationHandler(c, func(ev event.Event) {
|
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) {
|
||||||
ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber())
|
ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1105,10 +1102,10 @@ func initLocalStorage(ctx context.Context, c *cfg) {
|
||||||
shard.WithTombstoneSource(c.createTombstoneSource()),
|
shard.WithTombstoneSource(c.createTombstoneSource()),
|
||||||
shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)))...)
|
shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)))...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
shardsAttached++
|
shardsAttached++
|
||||||
c.log.Info(logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id))
|
c.log.Info(ctx, logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if shardsAttached == 0 {
|
if shardsAttached == 0 {
|
||||||
|
@ -1118,23 +1115,23 @@ func initLocalStorage(ctx context.Context, c *cfg) {
|
||||||
c.cfgObject.cfgLocalStorage.localStorage = ls
|
c.cfgObject.cfgLocalStorage.localStorage = ls
|
||||||
|
|
||||||
c.onShutdown(func() {
|
c.onShutdown(func() {
|
||||||
c.log.Info(logs.FrostFSNodeClosingComponentsOfTheStorageEngine)
|
c.log.Info(ctx, logs.FrostFSNodeClosingComponentsOfTheStorageEngine)
|
||||||
|
|
||||||
err := ls.Close(context.WithoutCancel(ctx))
|
err := ls.Close(context.WithoutCancel(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Info(logs.FrostFSNodeStorageEngineClosingFailure,
|
c.log.Info(ctx, logs.FrostFSNodeStorageEngineClosingFailure,
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
c.log.Info(logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully)
|
c.log.Info(ctx, logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func initAccessPolicyEngine(_ context.Context, c *cfg) {
|
func initAccessPolicyEngine(ctx context.Context, c *cfg) {
|
||||||
var localOverrideDB chainbase.LocalOverrideDatabase
|
var localOverrideDB chainbase.LocalOverrideDatabase
|
||||||
if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" {
|
if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" {
|
||||||
c.log.Warn(logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed)
|
c.log.Warn(ctx, logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed)
|
||||||
localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase()
|
localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase()
|
||||||
} else {
|
} else {
|
||||||
localOverrideDB = chainbase.NewBoltLocalOverrideDatabase(
|
localOverrideDB = chainbase.NewBoltLocalOverrideDatabase(
|
||||||
|
@ -1159,7 +1156,7 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) {
|
||||||
|
|
||||||
c.onShutdown(func() {
|
c.onShutdown(func() {
|
||||||
if err := ape.LocalOverrideDatabaseCore().Close(); err != nil {
|
if err := ape.LocalOverrideDatabaseCore().Close(); err != nil {
|
||||||
c.log.Warn(logs.FrostFSNodeAccessPolicyEngineClosingFailure,
|
c.log.Warn(ctx, logs.FrostFSNodeAccessPolicyEngineClosingFailure,
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1208,12 +1205,12 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) {
|
||||||
c.cfgNetmap.state.setNodeInfo(ni)
|
c.cfgNetmap.state.setNodeInfo(ni)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) updateContractNodeInfo(epoch uint64) {
|
func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) {
|
||||||
ni, err := c.netmapLocalNodeState(epoch)
|
ni, err := c.netmapLocalNodeState(epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch,
|
c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch,
|
||||||
zap.Uint64("epoch", epoch),
|
zap.Uint64("epoch", epoch),
|
||||||
zap.String("error", err.Error()))
|
zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1223,41 +1220,37 @@ func (c *cfg) updateContractNodeInfo(epoch uint64) {
|
||||||
// bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract
|
// bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract
|
||||||
// with the binary-encoded information from the current node's configuration.
|
// with the binary-encoded information from the current node's configuration.
|
||||||
// The state is set using the provided setter which MUST NOT be nil.
|
// The state is set using the provided setter which MUST NOT be nil.
|
||||||
func (c *cfg) bootstrapWithState(stateSetter func(*netmap.NodeInfo)) error {
|
func (c *cfg) bootstrapWithState(ctx context.Context, state netmap.NodeState) error {
|
||||||
ni := c.cfgNodeInfo.localInfo
|
ni := c.cfgNodeInfo.localInfo
|
||||||
stateSetter(&ni)
|
ni.SetStatus(state)
|
||||||
|
|
||||||
prm := nmClient.AddPeerPrm{}
|
prm := nmClient.AddPeerPrm{}
|
||||||
prm.SetNodeInfo(ni)
|
prm.SetNodeInfo(ni)
|
||||||
|
|
||||||
return c.cfgNetmap.wrapper.AddPeer(prm)
|
return c.cfgNetmap.wrapper.AddPeer(ctx, prm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bootstrapOnline calls cfg.bootstrapWithState with "online" state.
|
// bootstrapOnline calls cfg.bootstrapWithState with "online" state.
|
||||||
func bootstrapOnline(c *cfg) error {
|
func bootstrapOnline(ctx context.Context, c *cfg) error {
|
||||||
return c.bootstrapWithState(func(ni *netmap.NodeInfo) {
|
return c.bootstrapWithState(ctx, netmap.Online)
|
||||||
ni.SetStatus(netmap.Online)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bootstrap calls bootstrapWithState with:
|
// bootstrap calls bootstrapWithState with:
|
||||||
// - "maintenance" state if maintenance is in progress on the current node
|
// - "maintenance" state if maintenance is in progress on the current node
|
||||||
// - "online", otherwise
|
// - "online", otherwise
|
||||||
func (c *cfg) bootstrap() error {
|
func (c *cfg) bootstrap(ctx context.Context) error {
|
||||||
// switch to online except when under maintenance
|
// switch to online except when under maintenance
|
||||||
st := c.cfgNetmap.state.controlNetmapStatus()
|
st := c.cfgNetmap.state.controlNetmapStatus()
|
||||||
if st == control.NetmapStatus_MAINTENANCE {
|
if st == control.NetmapStatus_MAINTENANCE {
|
||||||
c.log.Info(logs.FrostFSNodeBootstrappingWithTheMaintenanceState)
|
c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithTheMaintenanceState)
|
||||||
return c.bootstrapWithState(func(ni *netmap.NodeInfo) {
|
return c.bootstrapWithState(ctx, netmap.Maintenance)
|
||||||
ni.SetStatus(netmap.Maintenance)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeBootstrappingWithOnlineState,
|
c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithOnlineState,
|
||||||
zap.Stringer("previous", st),
|
zap.Stringer("previous", st),
|
||||||
)
|
)
|
||||||
|
|
||||||
return bootstrapOnline(c)
|
return bootstrapOnline(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// needBootstrap checks if local node should be registered in network on bootup.
|
// needBootstrap checks if local node should be registered in network on bootup.
|
||||||
|
@ -1282,19 +1275,19 @@ func (c *cfg) signalWatcher(ctx context.Context) {
|
||||||
// signals causing application to shut down should have priority over
|
// signals causing application to shut down should have priority over
|
||||||
// reconfiguration signal
|
// reconfiguration signal
|
||||||
case <-ch:
|
case <-ch:
|
||||||
c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
||||||
|
|
||||||
c.shutdown()
|
c.shutdown(ctx)
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
||||||
return
|
return
|
||||||
case err := <-c.internalErr: // internal application error
|
case err := <-c.internalErr: // internal application error
|
||||||
c.log.Warn(logs.FrostFSNodeInternalApplicationError,
|
c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError,
|
||||||
zap.String("message", err.Error()))
|
zap.String("message", err.Error()))
|
||||||
|
|
||||||
c.shutdown()
|
c.shutdown(ctx)
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete)
|
c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
// block until any signal is receieved
|
// block until any signal is receieved
|
||||||
|
@ -1302,19 +1295,19 @@ func (c *cfg) signalWatcher(ctx context.Context) {
|
||||||
case <-sighupCh:
|
case <-sighupCh:
|
||||||
c.reloadConfig(ctx)
|
c.reloadConfig(ctx)
|
||||||
case <-ch:
|
case <-ch:
|
||||||
c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping)
|
||||||
|
|
||||||
c.shutdown()
|
c.shutdown(ctx)
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete)
|
||||||
return
|
return
|
||||||
case err := <-c.internalErr: // internal application error
|
case err := <-c.internalErr: // internal application error
|
||||||
c.log.Warn(logs.FrostFSNodeInternalApplicationError,
|
c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError,
|
||||||
zap.String("message", err.Error()))
|
zap.String("message", err.Error()))
|
||||||
|
|
||||||
c.shutdown()
|
c.shutdown(ctx)
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete)
|
c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1322,17 +1315,17 @@ func (c *cfg) signalWatcher(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) reloadConfig(ctx context.Context) {
|
func (c *cfg) reloadConfig(ctx context.Context) {
|
||||||
c.log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
|
c.log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration)
|
||||||
|
|
||||||
if !c.compareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
|
if !c.compareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) {
|
||||||
c.log.Info(logs.FrostFSNodeSIGHUPSkip)
|
c.log.Info(ctx, logs.FrostFSNodeSIGHUPSkip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
|
defer c.compareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY)
|
||||||
|
|
||||||
err := c.reloadAppConfig()
|
err := c.reloadAppConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,7 +1336,7 @@ func (c *cfg) reloadConfig(ctx context.Context) {
|
||||||
|
|
||||||
logPrm, err := c.loggerPrm()
|
logPrm, err := c.loggerPrm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1364,25 +1357,25 @@ func (c *cfg) reloadConfig(ctx context.Context) {
|
||||||
|
|
||||||
err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg)
|
err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, component := range components {
|
for _, component := range components {
|
||||||
err = component.reloadFunc()
|
err = component.reloadFunc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeUpdatedConfigurationApplying,
|
c.log.Error(ctx, logs.FrostFSNodeUpdatedConfigurationApplying,
|
||||||
zap.String("component", component.name),
|
zap.String("component", component.name),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.dialerSource.Update(internalNetConfig(c.appCfg, c.metricsCollector.MultinetMetrics())); err != nil {
|
if err := c.dialerSource.Update(internalNetConfig(c.appCfg, c.metricsCollector.MultinetMetrics())); err != nil {
|
||||||
c.log.Error(logs.FailedToUpdateMultinetConfiguration, zap.Error(err))
|
c.log.Error(ctx, logs.FailedToUpdateMultinetConfiguration, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
|
c.log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
|
func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
|
||||||
|
@ -1390,7 +1383,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
|
||||||
|
|
||||||
components = append(components, dCmp{"logger", logPrm.Reload})
|
components = append(components, dCmp{"logger", logPrm.Reload})
|
||||||
components = append(components, dCmp{"runtime", func() error {
|
components = append(components, dCmp{"runtime", func() error {
|
||||||
setRuntimeParameters(c)
|
setRuntimeParameters(ctx, c)
|
||||||
return nil
|
return nil
|
||||||
}})
|
}})
|
||||||
components = append(components, dCmp{"audit", func() error {
|
components = append(components, dCmp{"audit", func() error {
|
||||||
|
@ -1405,7 +1398,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp {
|
||||||
}
|
}
|
||||||
updated, err := tracing.Setup(ctx, *traceConfig)
|
updated, err := tracing.Setup(ctx, *traceConfig)
|
||||||
if updated {
|
if updated {
|
||||||
c.log.Info(logs.FrostFSNodeTracingConfigationUpdated)
|
c.log.Info(ctx, logs.FrostFSNodeTracingConfigationUpdated)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}})
|
}})
|
||||||
|
@ -1440,7 +1433,7 @@ func (c *cfg) reloadPools() error {
|
||||||
func (c *cfg) reloadPool(p *ants.Pool, newSize int, name string) {
|
func (c *cfg) reloadPool(p *ants.Pool, newSize int, name string) {
|
||||||
oldSize := p.Cap()
|
oldSize := p.Cap()
|
||||||
if oldSize != newSize {
|
if oldSize != newSize {
|
||||||
c.log.Info(logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name),
|
c.log.Info(context.Background(), logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name),
|
||||||
zap.Int("old", oldSize), zap.Int("new", newSize))
|
zap.Int("old", oldSize), zap.Int("new", newSize))
|
||||||
p.Tune(newSize)
|
p.Tune(newSize)
|
||||||
}
|
}
|
||||||
|
@ -1468,7 +1461,7 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker {
|
||||||
func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider {
|
func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider {
|
||||||
return container.NewInfoProvider(func() (container.Source, error) {
|
return container.NewInfoProvider(func() (container.Source, error) {
|
||||||
c.initMorphComponents(ctx)
|
c.initMorphComponents(ctx)
|
||||||
cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary())
|
cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1476,14 +1469,14 @@ func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoPro
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) shutdown() {
|
func (c *cfg) shutdown(ctx context.Context) {
|
||||||
old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN)
|
old := c.swapHealthStatus(ctx, control.HealthStatus_SHUTTING_DOWN)
|
||||||
if old == control.HealthStatus_SHUTTING_DOWN {
|
if old == control.HealthStatus_SHUTTING_DOWN {
|
||||||
c.log.Info(logs.FrostFSNodeShutdownSkip)
|
c.log.Info(ctx, logs.FrostFSNodeShutdownSkip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if old == control.HealthStatus_STARTING {
|
if old == control.HealthStatus_STARTING {
|
||||||
c.log.Warn(logs.FrostFSNodeShutdownWhenNotReady)
|
c.log.Warn(ctx, logs.FrostFSNodeShutdownWhenNotReady)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ctxCancel()
|
c.ctxCancel()
|
||||||
|
@ -1493,6 +1486,6 @@ func (c *cfg) shutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sdnotify.ClearStatus(); err != nil {
|
if err := sdnotify.ClearStatus(); err != nil {
|
||||||
c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err))
|
c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
27
cmd/frostfs-node/config/container/container.go
Normal file
27
cmd/frostfs-node/config/container/container.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package containerconfig
|
||||||
|
|
||||||
|
import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
|
||||||
|
const (
|
||||||
|
subsection = "container"
|
||||||
|
listStreamSubsection = "list_stream"
|
||||||
|
|
||||||
|
// ContainerBatchSizeDefault represents the maximum amount of containers to send via stream at once.
|
||||||
|
ContainerBatchSizeDefault = 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContainerBatchSize returns the value of "batch_size" config parameter
|
||||||
|
// from "list_stream" subsection of "container" section.
|
||||||
|
//
|
||||||
|
// Returns ContainerBatchSizeDefault if the value is missing or if
|
||||||
|
// the value is not positive integer.
|
||||||
|
func ContainerBatchSize(c *config.Config) uint32 {
|
||||||
|
if c.Sub(subsection).Sub(listStreamSubsection).Value("batch_size") == nil {
|
||||||
|
return ContainerBatchSizeDefault
|
||||||
|
}
|
||||||
|
size := config.Uint32Safe(c.Sub(subsection).Sub(listStreamSubsection), "batch_size")
|
||||||
|
if size == 0 {
|
||||||
|
return ContainerBatchSizeDefault
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
27
cmd/frostfs-node/config/container/container_test.go
Normal file
27
cmd/frostfs-node/config/container/container_test.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package containerconfig_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
containerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/container"
|
||||||
|
configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestContainerSection(t *testing.T) {
|
||||||
|
t.Run("defaults", func(t *testing.T) {
|
||||||
|
empty := configtest.EmptyConfig()
|
||||||
|
require.Equal(t, uint32(containerconfig.ContainerBatchSizeDefault), containerconfig.ContainerBatchSize(empty))
|
||||||
|
})
|
||||||
|
|
||||||
|
const path = "../../../../config/example/node"
|
||||||
|
fileConfigTest := func(c *config.Config) {
|
||||||
|
require.Equal(t, uint32(500), containerconfig.ContainerBatchSize(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
configtest.ForEachFileType(path, fileConfigTest)
|
||||||
|
t.Run("ENV", func(t *testing.T) {
|
||||||
|
configtest.ForEnvFileType(t, path, fileConfigTest)
|
||||||
|
})
|
||||||
|
}
|
|
@ -41,6 +41,10 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config)
|
||||||
c.Sub(si),
|
c.Sub(si),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if sc.Mode() == mode.Disabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Path for the blobstor can't be present in the default section, because different shards
|
// Path for the blobstor can't be present in the default section, because different shards
|
||||||
// must have different paths, so if it is missing, the shard is not here.
|
// must have different paths, so if it is missing, the shard is not here.
|
||||||
// At the same time checking for "blobstor" section doesn't work proper
|
// At the same time checking for "blobstor" section doesn't work proper
|
||||||
|
@ -50,10 +54,6 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config)
|
||||||
}
|
}
|
||||||
(*config.Config)(sc).SetDefault(def)
|
(*config.Config)(sc).SetDefault(def)
|
||||||
|
|
||||||
if sc.Mode() == mode.Disabled {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f(sc); err != nil {
|
if err := f(sc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,22 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestIterateShards(t *testing.T) {
|
||||||
|
fileConfigTest := func(c *config.Config) {
|
||||||
|
var res []string
|
||||||
|
require.NoError(t,
|
||||||
|
engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error {
|
||||||
|
res = append(res, sc.Metabase().Path())
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
require.Equal(t, []string{"abc", "xyz"}, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cfgDir = "./testdata/shards"
|
||||||
|
configtest.ForEachFileType(cfgDir, fileConfigTest)
|
||||||
|
configtest.ForEnvFileType(t, cfgDir, fileConfigTest)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEngineSection(t *testing.T) {
|
func TestEngineSection(t *testing.T) {
|
||||||
t.Run("defaults", func(t *testing.T) {
|
t.Run("defaults", func(t *testing.T) {
|
||||||
empty := configtest.EmptyConfig()
|
empty := configtest.EmptyConfig()
|
||||||
|
|
3
cmd/frostfs-node/config/engine/testdata/shards.env
vendored
Normal file
3
cmd/frostfs-node/config/engine/testdata/shards.env
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
FROSTFS_STORAGE_SHARD_0_METABASE_PATH=abc
|
||||||
|
FROSTFS_STORAGE_SHARD_1_MODE=disabled
|
||||||
|
FROSTFS_STORAGE_SHARD_2_METABASE_PATH=xyz
|
13
cmd/frostfs-node/config/engine/testdata/shards.json
vendored
Normal file
13
cmd/frostfs-node/config/engine/testdata/shards.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"storage.shard": {
|
||||||
|
"0": {
|
||||||
|
"metabase.path": "abc"
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"mode": "disabled"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"metabase.path": "xyz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
cmd/frostfs-node/config/engine/testdata/shards.yaml
vendored
Normal file
7
cmd/frostfs-node/config/engine/testdata/shards.yaml
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
storage.shard:
|
||||||
|
0:
|
||||||
|
metabase.path: abc
|
||||||
|
1:
|
||||||
|
mode: disabled
|
||||||
|
2:
|
||||||
|
metabase.path: xyz
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
||||||
|
@ -24,6 +25,7 @@ func ToTracingConfig(c *config.Config) (*tracing.Config, error) {
|
||||||
Service: "frostfs-node",
|
Service: "frostfs-node",
|
||||||
InstanceID: getInstanceIDOrDefault(c),
|
InstanceID: getInstanceIDOrDefault(c),
|
||||||
Version: misc.Version,
|
Version: misc.Version,
|
||||||
|
Attributes: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
if trustedCa := config.StringSafe(c.Sub(subsection), "trusted_ca"); trustedCa != "" {
|
if trustedCa := config.StringSafe(c.Sub(subsection), "trusted_ca"); trustedCa != "" {
|
||||||
|
@ -38,11 +40,30 @@ func ToTracingConfig(c *config.Config) (*tracing.Config, error) {
|
||||||
}
|
}
|
||||||
conf.ServerCaCertPool = certPool
|
conf.ServerCaCertPool = certPool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i := uint64(0)
|
||||||
|
for ; ; i++ {
|
||||||
|
si := strconv.FormatUint(i, 10)
|
||||||
|
ac := c.Sub(subsection).Sub("attributes").Sub(si)
|
||||||
|
k := config.StringSafe(ac, "key")
|
||||||
|
if k == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v := config.StringSafe(ac, "value")
|
||||||
|
if v == "" {
|
||||||
|
return nil, fmt.Errorf("empty tracing attribute value for key %s", k)
|
||||||
|
}
|
||||||
|
if _, ok := conf.Attributes[k]; ok {
|
||||||
|
return nil, fmt.Errorf("tracing attribute key %s defined more than once", k)
|
||||||
|
}
|
||||||
|
conf.Attributes[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInstanceIDOrDefault(c *config.Config) string {
|
func getInstanceIDOrDefault(c *config.Config) string {
|
||||||
s := config.StringSlice(c.Sub("node"), "addresses")
|
s := config.StringSliceSafe(c.Sub("node"), "addresses")
|
||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
return s[0]
|
return s[0]
|
||||||
}
|
}
|
||||||
|
|
46
cmd/frostfs-node/config/tracing/config_test.go
Normal file
46
cmd/frostfs-node/config/tracing/config_test.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package tracing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTracingSection(t *testing.T) {
|
||||||
|
t.Run("defaults", func(t *testing.T) {
|
||||||
|
tc, err := ToTracingConfig(configtest.EmptyConfig())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, false, tc.Enabled)
|
||||||
|
require.Equal(t, tracing.Exporter(""), tc.Exporter)
|
||||||
|
require.Equal(t, "", tc.Endpoint)
|
||||||
|
require.Equal(t, "frostfs-node", tc.Service)
|
||||||
|
require.Equal(t, "", tc.InstanceID)
|
||||||
|
require.Nil(t, tc.ServerCaCertPool)
|
||||||
|
require.Empty(t, tc.Attributes)
|
||||||
|
})
|
||||||
|
|
||||||
|
const path = "../../../../config/example/node"
|
||||||
|
|
||||||
|
fileConfigTest := func(c *config.Config) {
|
||||||
|
tc, err := ToTracingConfig(c)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, true, tc.Enabled)
|
||||||
|
require.Equal(t, tracing.OTLPgRPCExporter, tc.Exporter)
|
||||||
|
require.Equal(t, "localhost", tc.Endpoint)
|
||||||
|
require.Equal(t, "frostfs-node", tc.Service)
|
||||||
|
require.Nil(t, tc.ServerCaCertPool)
|
||||||
|
require.EqualValues(t, map[string]string{
|
||||||
|
"key0": "value",
|
||||||
|
"key1": "value",
|
||||||
|
}, tc.Attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
configtest.ForEachFileType(path, fileConfigTest)
|
||||||
|
|
||||||
|
t.Run("ENV", func(t *testing.T) {
|
||||||
|
configtest.ForEnvFileType(t, path, fileConfigTest)
|
||||||
|
})
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
subsection = "tree"
|
subsection = "tree"
|
||||||
|
|
||||||
|
SyncBatchSizeDefault = 1000
|
||||||
)
|
)
|
||||||
|
|
||||||
// TreeConfig is a wrapper over "tree" config section
|
// TreeConfig is a wrapper over "tree" config section
|
||||||
|
@ -74,6 +76,17 @@ func (c TreeConfig) SyncInterval() time.Duration {
|
||||||
return config.DurationSafe(c.cfg, "sync_interval")
|
return config.DurationSafe(c.cfg, "sync_interval")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncBatchSize returns the value of "sync_batch_size"
|
||||||
|
// config parameter from the "tree" section.
|
||||||
|
//
|
||||||
|
// Returns `SyncBatchSizeDefault` if config value is not specified.
|
||||||
|
func (c TreeConfig) SyncBatchSize() int {
|
||||||
|
if v := config.IntSafe(c.cfg, "sync_batch_size"); v > 0 {
|
||||||
|
return int(v)
|
||||||
|
}
|
||||||
|
return SyncBatchSizeDefault
|
||||||
|
}
|
||||||
|
|
||||||
// AuthorizedKeys parses and returns an array of "authorized_keys" config
|
// AuthorizedKeys parses and returns an array of "authorized_keys" config
|
||||||
// parameter from "tree" section.
|
// parameter from "tree" section.
|
||||||
//
|
//
|
||||||
|
|
|
@ -44,6 +44,7 @@ func TestTreeSection(t *testing.T) {
|
||||||
require.Equal(t, 32, treeSec.ReplicationWorkerCount())
|
require.Equal(t, 32, treeSec.ReplicationWorkerCount())
|
||||||
require.Equal(t, 5*time.Second, treeSec.ReplicationTimeout())
|
require.Equal(t, 5*time.Second, treeSec.ReplicationTimeout())
|
||||||
require.Equal(t, time.Hour, treeSec.SyncInterval())
|
require.Equal(t, time.Hour, treeSec.SyncInterval())
|
||||||
|
require.Equal(t, 2000, treeSec.SyncBatchSize())
|
||||||
require.Equal(t, expectedKeys, treeSec.AuthorizedKeys())
|
require.Equal(t, expectedKeys, treeSec.AuthorizedKeys())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
containerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/container"
|
||||||
morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph"
|
morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics"
|
||||||
|
@ -28,7 +29,7 @@ import (
|
||||||
func initContainerService(_ context.Context, c *cfg) {
|
func initContainerService(_ context.Context, c *cfg) {
|
||||||
// container wrapper that tries to invoke notary
|
// container wrapper that tries to invoke notary
|
||||||
// requests if chain is configured so
|
// requests if chain is configured so
|
||||||
wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, cntClient.TryNotary())
|
wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0)
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
|
|
||||||
c.shared.cnrClient = wrap
|
c.shared.cnrClient = wrap
|
||||||
|
@ -47,6 +48,7 @@ func initContainerService(_ context.Context, c *cfg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.shared.frostfsidClient = frostfsIDSubjectProvider
|
c.shared.frostfsidClient = frostfsIDSubjectProvider
|
||||||
|
c.cfgContainer.containerBatchSize = containerconfig.ContainerBatchSize(c.appCfg)
|
||||||
|
|
||||||
defaultChainRouter := engine.NewDefaultChainRouterWithLocalOverrides(
|
defaultChainRouter := engine.NewDefaultChainRouterWithLocalOverrides(
|
||||||
c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(),
|
c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(),
|
||||||
|
@ -56,7 +58,9 @@ func initContainerService(_ context.Context, c *cfg) {
|
||||||
&c.key.PrivateKey,
|
&c.key.PrivateKey,
|
||||||
containerService.NewAPEServer(defaultChainRouter, cnrRdr,
|
containerService.NewAPEServer(defaultChainRouter, cnrRdr,
|
||||||
newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient,
|
newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient,
|
||||||
containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc),
|
containerService.NewSplitterService(
|
||||||
|
c.cfgContainer.containerBatchSize, c.respSvc,
|
||||||
|
containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
service = containerService.NewAuditService(service, c.log, c.audit)
|
service = containerService.NewAuditService(service, c.log, c.audit)
|
||||||
|
@ -73,10 +77,6 @@ func initContainerService(_ context.Context, c *cfg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) {
|
func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) {
|
||||||
eACLFetcher := &morphEACLFetcher{
|
|
||||||
w: client,
|
|
||||||
}
|
|
||||||
|
|
||||||
cnrRdr := new(morphContainerReader)
|
cnrRdr := new(morphContainerReader)
|
||||||
|
|
||||||
cnrWrt := &morphContainerWriter{
|
cnrWrt := &morphContainerWriter{
|
||||||
|
@ -84,8 +84,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cfgMorph.cacheTTL <= 0 {
|
if c.cfgMorph.cacheTTL <= 0 {
|
||||||
c.cfgObject.eaclSource = eACLFetcher
|
|
||||||
cnrRdr.eacl = eACLFetcher
|
|
||||||
c.cfgObject.cnrSource = cnrSrc
|
c.cfgObject.cnrSource = cnrSrc
|
||||||
cnrRdr.src = cnrSrc
|
cnrRdr.src = cnrSrc
|
||||||
cnrRdr.lister = client
|
cnrRdr.lister = client
|
||||||
|
@ -95,7 +93,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
if c.cfgMorph.containerCacheSize > 0 {
|
if c.cfgMorph.containerCacheSize > 0 {
|
||||||
containerCache := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL, c.cfgMorph.containerCacheSize)
|
containerCache := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL, c.cfgMorph.containerCacheSize)
|
||||||
|
|
||||||
subscribeToContainerCreation(c, func(e event.Event) {
|
subscribeToContainerCreation(c, func(ctx context.Context, e event.Event) {
|
||||||
ev := e.(containerEvent.PutSuccess)
|
ev := e.(containerEvent.PutSuccess)
|
||||||
|
|
||||||
// read owner of the created container in order to update the reading cache.
|
// read owner of the created container in order to update the reading cache.
|
||||||
|
@ -108,32 +106,28 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c
|
||||||
} else {
|
} else {
|
||||||
// unlike removal, we expect successful receive of the container
|
// unlike removal, we expect successful receive of the container
|
||||||
// after successful creation, so logging can be useful
|
// after successful creation, so logging can be useful
|
||||||
c.log.Error(logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification,
|
c.log.Error(ctx, logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification,
|
||||||
zap.Stringer("id", ev.ID),
|
zap.Stringer("id", ev.ID),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debug(logs.FrostFSNodeContainerCreationEventsReceipt,
|
c.log.Debug(ctx, logs.FrostFSNodeContainerCreationEventsReceipt,
|
||||||
zap.Stringer("id", ev.ID),
|
zap.Stringer("id", ev.ID),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
subscribeToContainerRemoval(c, func(e event.Event) {
|
subscribeToContainerRemoval(c, func(ctx context.Context, e event.Event) {
|
||||||
ev := e.(containerEvent.DeleteSuccess)
|
ev := e.(containerEvent.DeleteSuccess)
|
||||||
containerCache.handleRemoval(ev.ID)
|
containerCache.handleRemoval(ev.ID)
|
||||||
c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt,
|
c.log.Debug(ctx, logs.FrostFSNodeContainerRemovalEventsReceipt,
|
||||||
zap.Stringer("id", ev.ID),
|
zap.Stringer("id", ev.ID),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
c.cfgObject.cnrSource = containerCache
|
c.cfgObject.cnrSource = containerCache
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL)
|
|
||||||
c.cfgObject.eaclSource = cachedEACLStorage
|
|
||||||
|
|
||||||
cnrRdr.lister = client
|
cnrRdr.lister = client
|
||||||
cnrRdr.eacl = c.cfgObject.eaclSource
|
|
||||||
cnrRdr.src = c.cfgObject.cnrSource
|
cnrRdr.src = c.cfgObject.cnrSource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,12 +218,11 @@ func (c *cfg) ExternalAddresses() []string {
|
||||||
|
|
||||||
// implements interface required by container service provided by morph executor.
|
// implements interface required by container service provided by morph executor.
|
||||||
type morphContainerReader struct {
|
type morphContainerReader struct {
|
||||||
eacl containerCore.EACLSource
|
|
||||||
|
|
||||||
src containerCore.Source
|
src containerCore.Source
|
||||||
|
|
||||||
lister interface {
|
lister interface {
|
||||||
ContainersOf(*user.ID) ([]cid.ID, error)
|
ContainersOf(*user.ID) ([]cid.ID, error)
|
||||||
|
IterateContainersOf(*user.ID, func(cid.ID) error) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,22 +234,22 @@ func (x *morphContainerReader) DeletionInfo(id cid.ID) (*containerCore.DelInfo,
|
||||||
return x.src.DeletionInfo(id)
|
return x.src.DeletionInfo(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *morphContainerReader) GetEACL(id cid.ID) (*containerCore.EACL, error) {
|
|
||||||
return x.eacl.GetEACL(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) {
|
func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) {
|
||||||
return x.lister.ContainersOf(id)
|
return x.lister.ContainersOf(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *morphContainerReader) IterateContainersOf(id *user.ID, processCID func(cid.ID) error) error {
|
||||||
|
return x.lister.IterateContainersOf(id, processCID)
|
||||||
|
}
|
||||||
|
|
||||||
type morphContainerWriter struct {
|
type morphContainerWriter struct {
|
||||||
neoClient *cntClient.Client
|
neoClient *cntClient.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) {
|
func (m morphContainerWriter) Put(ctx context.Context, cnr containerCore.Container) (*cid.ID, error) {
|
||||||
return cntClient.Put(m.neoClient, cnr)
|
return cntClient.Put(ctx, m.neoClient, cnr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
|
func (m morphContainerWriter) Delete(ctx context.Context, witness containerCore.RemovalWitness) error {
|
||||||
return cntClient.Delete(m.neoClient, witness)
|
return cntClient.Delete(ctx, m.neoClient, witness)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
const serviceNameControl = "control"
|
const serviceNameControl = "control"
|
||||||
|
|
||||||
func initControlService(c *cfg) {
|
func initControlService(ctx context.Context, c *cfg) {
|
||||||
endpoint := controlconfig.GRPC(c.appCfg).Endpoint()
|
endpoint := controlconfig.GRPC(c.appCfg).Endpoint()
|
||||||
if endpoint == controlconfig.GRPCEndpointDefault {
|
if endpoint == controlconfig.GRPCEndpointDefault {
|
||||||
return
|
return
|
||||||
|
@ -46,21 +46,21 @@ func initControlService(c *cfg) {
|
||||||
|
|
||||||
lis, err := net.Listen("tcp", endpoint)
|
lis, err := net.Listen("tcp", endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cfgControlService.server = grpc.NewServer()
|
c.cfgControlService.server = grpc.NewServer()
|
||||||
|
|
||||||
c.onShutdown(func() {
|
c.onShutdown(func() {
|
||||||
stopGRPC("FrostFS Control API", c.cfgControlService.server, c.log)
|
stopGRPC(ctx, "FrostFS Control API", c.cfgControlService.server, c.log)
|
||||||
})
|
})
|
||||||
|
|
||||||
control.RegisterControlServiceServer(c.cfgControlService.server, ctlSvc)
|
control.RegisterControlServiceServer(c.cfgControlService.server, ctlSvc)
|
||||||
|
|
||||||
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
|
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
|
||||||
runAndLog(ctx, c, serviceNameControl, false, func(context.Context, *cfg) {
|
runAndLog(ctx, c, serviceNameControl, false, func(context.Context, *cfg) {
|
||||||
c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
|
c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint,
|
||||||
zap.String("service", serviceNameControl),
|
zap.String("service", serviceNameControl),
|
||||||
zap.String("endpoint", endpoint))
|
zap.String("endpoint", endpoint))
|
||||||
fatalOnErr(c.cfgControlService.server.Serve(lis))
|
fatalOnErr(c.cfgControlService.server.Serve(lis))
|
||||||
|
@ -72,23 +72,23 @@ func (c *cfg) NetmapStatus() control.NetmapStatus {
|
||||||
return c.cfgNetmap.state.controlNetmapStatus()
|
return c.cfgNetmap.state.controlNetmapStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) setHealthStatus(st control.HealthStatus) {
|
func (c *cfg) setHealthStatus(ctx context.Context, st control.HealthStatus) {
|
||||||
c.notifySystemd(st)
|
c.notifySystemd(ctx, st)
|
||||||
c.healthStatus.Store(int32(st))
|
c.healthStatus.Store(int32(st))
|
||||||
c.metricsCollector.State().SetHealth(int32(st))
|
c.metricsCollector.State().SetHealth(int32(st))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) compareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) {
|
func (c *cfg) compareAndSwapHealthStatus(ctx context.Context, oldSt, newSt control.HealthStatus) (swapped bool) {
|
||||||
if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped {
|
if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped {
|
||||||
c.notifySystemd(newSt)
|
c.notifySystemd(ctx, newSt)
|
||||||
c.metricsCollector.State().SetHealth(int32(newSt))
|
c.metricsCollector.State().SetHealth(int32(newSt))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatus) {
|
func (c *cfg) swapHealthStatus(ctx context.Context, st control.HealthStatus) (old control.HealthStatus) {
|
||||||
old = control.HealthStatus(c.healthStatus.Swap(int32(st)))
|
old = control.HealthStatus(c.healthStatus.Swap(int32(st)))
|
||||||
c.notifySystemd(st)
|
c.notifySystemd(ctx, st)
|
||||||
c.metricsCollector.State().SetHealth(int32(st))
|
c.metricsCollector.State().SetHealth(int32(st))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ func (c *cfg) HealthStatus() control.HealthStatus {
|
||||||
return control.HealthStatus(c.healthStatus.Load())
|
return control.HealthStatus(c.healthStatus.Load())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) notifySystemd(st control.HealthStatus) {
|
func (c *cfg) notifySystemd(ctx context.Context, st control.HealthStatus) {
|
||||||
if !c.sdNotify {
|
if !c.sdNotify {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,6 @@ func (c *cfg) notifySystemd(st control.HealthStatus) {
|
||||||
err = sdnotify.Status(fmt.Sprintf("%v", st))
|
err = sdnotify.Status(fmt.Sprintf("%v", st))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err))
|
c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
@ -18,11 +19,11 @@ import (
|
||||||
|
|
||||||
const maxRecvMsgSize = 256 << 20
|
const maxRecvMsgSize = 256 << 20
|
||||||
|
|
||||||
func initGRPC(c *cfg) {
|
func initGRPC(ctx context.Context, c *cfg) {
|
||||||
var endpointsToReconnect []string
|
var endpointsToReconnect []string
|
||||||
var successCount int
|
var successCount int
|
||||||
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
|
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
|
||||||
serverOpts, ok := getGrpcServerOpts(c, sc)
|
serverOpts, ok := getGrpcServerOpts(ctx, c, sc)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -30,7 +31,7 @@ func initGRPC(c *cfg) {
|
||||||
lis, err := net.Listen("tcp", sc.Endpoint())
|
lis, err := net.Listen("tcp", sc.Endpoint())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint())
|
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint())
|
||||||
c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err))
|
||||||
endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint())
|
endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -39,7 +40,7 @@ func initGRPC(c *cfg) {
|
||||||
srv := grpc.NewServer(serverOpts...)
|
srv := grpc.NewServer(serverOpts...)
|
||||||
|
|
||||||
c.onShutdown(func() {
|
c.onShutdown(func() {
|
||||||
stopGRPC("FrostFS Public API", srv, c.log)
|
stopGRPC(ctx, "FrostFS Public API", srv, c.log)
|
||||||
})
|
})
|
||||||
|
|
||||||
c.cfgGRPC.append(sc.Endpoint(), lis, srv)
|
c.cfgGRPC.append(sc.Endpoint(), lis, srv)
|
||||||
|
@ -52,11 +53,11 @@ func initGRPC(c *cfg) {
|
||||||
c.cfgGRPC.reconnectTimeout = grpcconfig.ReconnectTimeout(c.appCfg)
|
c.cfgGRPC.reconnectTimeout = grpcconfig.ReconnectTimeout(c.appCfg)
|
||||||
|
|
||||||
for _, endpoint := range endpointsToReconnect {
|
for _, endpoint := range endpointsToReconnect {
|
||||||
scheduleReconnect(endpoint, c)
|
scheduleReconnect(ctx, endpoint, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func scheduleReconnect(endpoint string, c *cfg) {
|
func scheduleReconnect(ctx context.Context, endpoint string, c *cfg) {
|
||||||
c.wg.Add(1)
|
c.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
|
@ -65,7 +66,7 @@ func scheduleReconnect(endpoint string, c *cfg) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
if tryReconnect(endpoint, c) {
|
if tryReconnect(ctx, endpoint, c) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case <-c.done:
|
case <-c.done:
|
||||||
|
@ -75,20 +76,20 @@ func scheduleReconnect(endpoint string, c *cfg) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryReconnect(endpoint string, c *cfg) bool {
|
func tryReconnect(ctx context.Context, endpoint string, c *cfg) bool {
|
||||||
c.log.Info(logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint))
|
c.log.Info(ctx, logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint))
|
||||||
|
|
||||||
serverOpts, found := getGRPCEndpointOpts(endpoint, c)
|
serverOpts, found := getGRPCEndpointOpts(ctx, endpoint, c)
|
||||||
if !found {
|
if !found {
|
||||||
c.log.Warn(logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint))
|
c.log.Warn(ctx, logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
lis, err := net.Listen("tcp", endpoint)
|
lis, err := net.Listen("tcp", endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint)
|
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint)
|
||||||
c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err))
|
||||||
c.log.Warn(logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout))
|
c.log.Warn(ctx, logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint)
|
c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint)
|
||||||
|
@ -96,16 +97,16 @@ func tryReconnect(endpoint string, c *cfg) bool {
|
||||||
srv := grpc.NewServer(serverOpts...)
|
srv := grpc.NewServer(serverOpts...)
|
||||||
|
|
||||||
c.onShutdown(func() {
|
c.onShutdown(func() {
|
||||||
stopGRPC("FrostFS Public API", srv, c.log)
|
stopGRPC(ctx, "FrostFS Public API", srv, c.log)
|
||||||
})
|
})
|
||||||
|
|
||||||
c.cfgGRPC.appendAndHandle(endpoint, lis, srv)
|
c.cfgGRPC.appendAndHandle(endpoint, lis, srv)
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint))
|
c.log.Info(ctx, logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, found bool) {
|
func getGRPCEndpointOpts(ctx context.Context, endpoint string, c *cfg) (result []grpc.ServerOption, found bool) {
|
||||||
unlock := c.LockAppConfigShared()
|
unlock := c.LockAppConfigShared()
|
||||||
defer unlock()
|
defer unlock()
|
||||||
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
|
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
|
||||||
|
@ -116,7 +117,7 @@ func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, f
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var ok bool
|
var ok bool
|
||||||
result, ok = getGrpcServerOpts(c, sc)
|
result, ok = getGrpcServerOpts(ctx, c, sc)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -125,7 +126,7 @@ func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, f
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) {
|
func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) {
|
||||||
serverOpts := []grpc.ServerOption{
|
serverOpts := []grpc.ServerOption{
|
||||||
grpc.MaxRecvMsgSize(maxRecvMsgSize),
|
grpc.MaxRecvMsgSize(maxRecvMsgSize),
|
||||||
grpc.ChainUnaryInterceptor(
|
grpc.ChainUnaryInterceptor(
|
||||||
|
@ -143,7 +144,7 @@ func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool
|
||||||
if tlsCfg != nil {
|
if tlsCfg != nil {
|
||||||
cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile())
|
cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err))
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,38 +175,38 @@ func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool
|
||||||
return serverOpts, true
|
return serverOpts, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveGRPC(c *cfg) {
|
func serveGRPC(ctx context.Context, c *cfg) {
|
||||||
c.cfgGRPC.performAndSave(func(e string, l net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(e string, l net.Listener, s *grpc.Server) {
|
||||||
c.wg.Add(1)
|
c.wg.Add(1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
c.log.Info(logs.FrostFSNodeStopListeningGRPCEndpoint,
|
c.log.Info(ctx, logs.FrostFSNodeStopListeningGRPCEndpoint,
|
||||||
zap.Stringer("endpoint", l.Addr()),
|
zap.Stringer("endpoint", l.Addr()),
|
||||||
)
|
)
|
||||||
|
|
||||||
c.wg.Done()
|
c.wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
|
c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint,
|
||||||
zap.String("service", "gRPC"),
|
zap.String("service", "gRPC"),
|
||||||
zap.Stringer("endpoint", l.Addr()),
|
zap.Stringer("endpoint", l.Addr()),
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := s.Serve(l); err != nil {
|
if err := s.Serve(l); err != nil {
|
||||||
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e)
|
c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e)
|
||||||
c.log.Error(logs.FrostFSNodeGRPCServerError, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeGRPCServerError, zap.Error(err))
|
||||||
c.cfgGRPC.dropConnection(e)
|
c.cfgGRPC.dropConnection(e)
|
||||||
scheduleReconnect(e, c)
|
scheduleReconnect(ctx, e, c)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopGRPC(name string, s *grpc.Server, l *logger.Logger) {
|
func stopGRPC(ctx context.Context, name string, s *grpc.Server, l *logger.Logger) {
|
||||||
l = &logger.Logger{Logger: l.With(zap.String("name", name))}
|
l = l.With(zap.String("name", name))
|
||||||
|
|
||||||
l.Info(logs.FrostFSNodeStoppingGRPCServer)
|
l.Info(ctx, logs.FrostFSNodeStoppingGRPCServer)
|
||||||
|
|
||||||
// GracefulStop() may freeze forever, see #1270
|
// GracefulStop() may freeze forever, see #1270
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
@ -217,9 +218,9 @@ func stopGRPC(name string, s *grpc.Server, l *logger.Logger) {
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
case <-time.After(1 * time.Minute):
|
case <-time.After(1 * time.Minute):
|
||||||
l.Info(logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop)
|
l.Info(ctx, logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop)
|
||||||
s.Stop()
|
s.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Info(logs.FrostFSNodeGRPCServerStoppedSuccessfully)
|
l.Info(ctx, logs.FrostFSNodeGRPCServerStoppedSuccessfully)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ type httpComponent struct {
|
||||||
preReload func(c *cfg)
|
preReload func(c *cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmp *httpComponent) init(c *cfg) {
|
func (cmp *httpComponent) init(ctx context.Context, c *cfg) {
|
||||||
if !cmp.enabled {
|
if !cmp.enabled {
|
||||||
c.log.Info(cmp.name + " is disabled")
|
c.log.Info(ctx, cmp.name+" is disabled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Init server with parameters
|
// Init server with parameters
|
||||||
|
@ -39,14 +39,14 @@ func (cmp *httpComponent) init(c *cfg) {
|
||||||
go func() {
|
go func() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
|
c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint,
|
||||||
zap.String("service", cmp.name),
|
zap.String("service", cmp.name),
|
||||||
zap.String("endpoint", cmp.address))
|
zap.String("endpoint", cmp.address))
|
||||||
fatalOnErr(srv.Serve())
|
fatalOnErr(srv.Serve())
|
||||||
}()
|
}()
|
||||||
c.closers = append(c.closers, closer{
|
c.closers = append(c.closers, closer{
|
||||||
cmp.name,
|
cmp.name,
|
||||||
func() { stopAndLog(c, cmp.name, srv.Shutdown) },
|
func() { stopAndLog(ctx, c, cmp.name, srv.Shutdown) },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ func (cmp *httpComponent) reload(ctx context.Context) error {
|
||||||
// Cleanup
|
// Cleanup
|
||||||
delCloser(cmp.cfg, cmp.name)
|
delCloser(cmp.cfg, cmp.name)
|
||||||
// Init server with new parameters
|
// Init server with new parameters
|
||||||
cmp.init(cmp.cfg)
|
cmp.init(ctx, cmp.cfg)
|
||||||
// Start worker
|
// Start worker
|
||||||
if cmp.enabled {
|
if cmp.enabled {
|
||||||
startWorker(ctx, cmp.cfg, *getWorker(cmp.cfg, cmp.name))
|
startWorker(ctx, cmp.cfg, *getWorker(cmp.cfg, cmp.name))
|
||||||
|
|
|
@ -61,21 +61,21 @@ func main() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
ctx, c.ctxCancel = context.WithCancel(context.Background())
|
ctx, c.ctxCancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
c.setHealthStatus(control.HealthStatus_STARTING)
|
c.setHealthStatus(ctx, control.HealthStatus_STARTING)
|
||||||
|
|
||||||
initApp(ctx, c)
|
initApp(ctx, c)
|
||||||
|
|
||||||
bootUp(ctx, c)
|
bootUp(ctx, c)
|
||||||
|
|
||||||
c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY)
|
c.compareAndSwapHealthStatus(ctx, control.HealthStatus_STARTING, control.HealthStatus_READY)
|
||||||
|
|
||||||
wait(c)
|
wait(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initAndLog(c *cfg, name string, initializer func(*cfg)) {
|
func initAndLog(ctx context.Context, c *cfg, name string, initializer func(*cfg)) {
|
||||||
c.log.Info(fmt.Sprintf("initializing %s service...", name))
|
c.log.Info(ctx, fmt.Sprintf("initializing %s service...", name))
|
||||||
initializer(c)
|
initializer(c)
|
||||||
c.log.Info(name + " service has been successfully initialized")
|
c.log.Info(ctx, name+" service has been successfully initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initApp(ctx context.Context, c *cfg) {
|
func initApp(ctx context.Context, c *cfg) {
|
||||||
|
@ -85,72 +85,72 @@ func initApp(ctx context.Context, c *cfg) {
|
||||||
c.wg.Done()
|
c.wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
setRuntimeParameters(c)
|
setRuntimeParameters(ctx, c)
|
||||||
metrics, _ := metricsComponent(c)
|
metrics, _ := metricsComponent(c)
|
||||||
initAndLog(c, "profiler", initProfilerService)
|
initAndLog(ctx, c, "profiler", func(c *cfg) { initProfilerService(ctx, c) })
|
||||||
initAndLog(c, metrics.name, metrics.init)
|
initAndLog(ctx, c, metrics.name, func(c *cfg) { metrics.init(ctx, c) })
|
||||||
|
|
||||||
initAndLog(c, "tracing", func(c *cfg) { initTracing(ctx, c) })
|
initAndLog(ctx, c, "tracing", func(c *cfg) { initTracing(ctx, c) })
|
||||||
|
|
||||||
initLocalStorage(ctx, c)
|
initLocalStorage(ctx, c)
|
||||||
|
|
||||||
initAndLog(c, "storage engine", func(c *cfg) {
|
initAndLog(ctx, c, "storage engine", func(c *cfg) {
|
||||||
fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open(ctx))
|
fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open(ctx))
|
||||||
fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx))
|
fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx))
|
||||||
})
|
})
|
||||||
|
|
||||||
initAndLog(c, "gRPC", initGRPC)
|
initAndLog(ctx, c, "gRPC", func(c *cfg) { initGRPC(ctx, c) })
|
||||||
initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) })
|
initAndLog(ctx, c, "netmap", func(c *cfg) { initNetmapService(ctx, c) })
|
||||||
|
|
||||||
initAccessPolicyEngine(ctx, c)
|
initAccessPolicyEngine(ctx, c)
|
||||||
initAndLog(c, "access policy engine", func(c *cfg) {
|
initAndLog(ctx, c, "access policy engine", func(c *cfg) {
|
||||||
fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx))
|
fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx))
|
||||||
fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init())
|
fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init())
|
||||||
})
|
})
|
||||||
|
|
||||||
initAndLog(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) })
|
initAndLog(ctx, c, "accounting", func(c *cfg) { initAccountingService(ctx, c) })
|
||||||
initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) })
|
initAndLog(ctx, c, "container", func(c *cfg) { initContainerService(ctx, c) })
|
||||||
initAndLog(c, "session", initSessionService)
|
initAndLog(ctx, c, "session", initSessionService)
|
||||||
initAndLog(c, "object", initObjectService)
|
initAndLog(ctx, c, "object", initObjectService)
|
||||||
initAndLog(c, "tree", initTreeService)
|
initAndLog(ctx, c, "tree", initTreeService)
|
||||||
initAndLog(c, "apemanager", initAPEManagerService)
|
initAndLog(ctx, c, "apemanager", initAPEManagerService)
|
||||||
initAndLog(c, "control", initControlService)
|
initAndLog(ctx, c, "control", func(c *cfg) { initControlService(ctx, c) })
|
||||||
|
|
||||||
initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) })
|
initAndLog(ctx, c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starter func(context.Context, *cfg)) {
|
func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starter func(context.Context, *cfg)) {
|
||||||
c.log.Info(fmt.Sprintf("starting %s service...", name))
|
c.log.Info(ctx, fmt.Sprintf("starting %s service...", name))
|
||||||
starter(ctx, c)
|
starter(ctx, c)
|
||||||
|
|
||||||
if logSuccess {
|
if logSuccess {
|
||||||
c.log.Info(name + " service started successfully")
|
c.log.Info(ctx, name+" service started successfully")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopAndLog(c *cfg, name string, stopper func() error) {
|
func stopAndLog(ctx context.Context, c *cfg, name string, stopper func(context.Context) error) {
|
||||||
c.log.Debug(fmt.Sprintf("shutting down %s service", name))
|
c.log.Debug(ctx, fmt.Sprintf("shutting down %s service", name))
|
||||||
|
|
||||||
err := stopper()
|
err := stopper(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Debug(fmt.Sprintf("could not shutdown %s server", name),
|
c.log.Debug(ctx, fmt.Sprintf("could not shutdown %s server", name),
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debug(name + " service has been stopped")
|
c.log.Debug(ctx, name+" service has been stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootUp(ctx context.Context, c *cfg) {
|
func bootUp(ctx context.Context, c *cfg) {
|
||||||
runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(c) })
|
runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(ctx, c) })
|
||||||
runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit)
|
runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit)
|
||||||
|
|
||||||
bootstrapNode(c)
|
bootstrapNode(ctx, c)
|
||||||
startWorkers(ctx, c)
|
startWorkers(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func wait(c *cfg) {
|
func wait(c *cfg) {
|
||||||
c.log.Info(logs.CommonApplicationStarted,
|
c.log.Info(context.Background(), logs.CommonApplicationStarted,
|
||||||
zap.String("version", misc.Version))
|
zap.String("version", misc.Version))
|
||||||
|
|
||||||
<-c.done // graceful shutdown
|
<-c.done // graceful shutdown
|
||||||
|
@ -160,12 +160,12 @@ func wait(c *cfg) {
|
||||||
go func() {
|
go func() {
|
||||||
defer drain.Done()
|
defer drain.Done()
|
||||||
for err := range c.internalErr {
|
for err := range c.internalErr {
|
||||||
c.log.Warn(logs.FrostFSNodeInternalApplicationError,
|
c.log.Warn(context.Background(), logs.FrostFSNodeInternalApplicationError,
|
||||||
zap.String("message", err.Error()))
|
zap.String("message", err.Error()))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c.log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop)
|
c.log.Debug(context.Background(), logs.FrostFSNodeWaitingForAllProcessesToStop)
|
||||||
|
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,20 +35,16 @@ func (c *cfg) initMorphComponents(ctx context.Context) {
|
||||||
|
|
||||||
lookupScriptHashesInNNS(c) // smart contract auto negotiation
|
lookupScriptHashesInNNS(c) // smart contract auto negotiation
|
||||||
|
|
||||||
if c.cfgMorph.notaryEnabled {
|
err := c.cfgMorph.client.EnableNotarySupport(
|
||||||
err := c.cfgMorph.client.EnableNotarySupport(
|
client.WithProxyContract(
|
||||||
client.WithProxyContract(
|
c.cfgMorph.proxyScriptHash,
|
||||||
c.cfgMorph.proxyScriptHash,
|
),
|
||||||
),
|
|
||||||
)
|
|
||||||
fatalOnErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeNotarySupport,
|
|
||||||
zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled),
|
|
||||||
)
|
)
|
||||||
|
fatalOnErr(err)
|
||||||
|
|
||||||
wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, nmClient.TryNotary())
|
c.log.Info(ctx, logs.FrostFSNodeNotarySupport)
|
||||||
|
|
||||||
|
wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0)
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
|
|
||||||
var netmapSource netmap.Source
|
var netmapSource netmap.Source
|
||||||
|
@ -64,7 +56,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) {
|
||||||
msPerBlock, err := c.cfgMorph.client.MsPerBlock()
|
msPerBlock, err := c.cfgMorph.client.MsPerBlock()
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond
|
c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond
|
||||||
c.log.Debug(logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL))
|
c.log.Debug(ctx, logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL))
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cfgMorph.cacheTTL < 0 {
|
if c.cfgMorph.cacheTTL < 0 {
|
||||||
|
@ -102,41 +94,35 @@ func initMorphClient(ctx context.Context, c *cfg) {
|
||||||
client.WithDialerSource(c.dialerSource),
|
client.WithDialerSource(c.dialerSource),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient,
|
c.log.Info(ctx, logs.FrostFSNodeFailedToCreateNeoRPCClient,
|
||||||
zap.Any("endpoints", addresses),
|
zap.Any("endpoints", addresses),
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.onShutdown(func() {
|
c.onShutdown(func() {
|
||||||
c.log.Info(logs.FrostFSNodeClosingMorphComponents)
|
c.log.Info(ctx, logs.FrostFSNodeClosingMorphComponents)
|
||||||
cli.Close()
|
cli.Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := cli.SetGroupSignerScope(); err != nil {
|
if err := cli.SetGroupSignerScope(); err != nil {
|
||||||
c.log.Info(logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err))
|
c.log.Info(ctx, logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cfgMorph.client = cli
|
c.cfgMorph.client = cli
|
||||||
c.cfgMorph.notaryEnabled = cli.ProbeNotary()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
|
func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
|
||||||
// skip notary deposit in non-notary environments
|
tx, vub, err := makeNotaryDeposit(ctx, c)
|
||||||
if !c.cfgMorph.notaryEnabled {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tx, vub, err := makeNotaryDeposit(c)
|
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
|
|
||||||
if tx.Equals(util.Uint256{}) {
|
if tx.Equals(util.Uint256{}) {
|
||||||
// non-error deposit with an empty TX hash means
|
// non-error deposit with an empty TX hash means
|
||||||
// that the deposit has already been made; no
|
// that the deposit has already been made; no
|
||||||
// need to wait it.
|
// need to wait it.
|
||||||
c.log.Info(logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade)
|
c.log.Info(ctx, logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +130,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) {
|
func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error) {
|
||||||
const (
|
const (
|
||||||
// gasMultiplier defines how many times more the notary
|
// gasMultiplier defines how many times more the notary
|
||||||
// balance must be compared to the GAS balance of the node:
|
// balance must be compared to the GAS balance of the node:
|
||||||
|
@ -161,51 +147,16 @@ func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) {
|
||||||
return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err)
|
return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.cfgMorph.client.DepositEndlessNotary(depositAmount)
|
return c.cfgMorph.client.DepositEndlessNotary(ctx, depositAmount)
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errNotaryDepositFail = errors.New("notary deposit tx has faulted")
|
|
||||||
errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network")
|
|
||||||
)
|
|
||||||
|
|
||||||
type waiterClient struct {
|
|
||||||
c *client.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *waiterClient) Context() context.Context {
|
|
||||||
return context.Background()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *waiterClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) {
|
|
||||||
return w.c.GetApplicationLog(hash, trig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *waiterClient) GetBlockCount() (uint32, error) {
|
|
||||||
return w.c.BlockCount()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *waiterClient) GetVersion() (*result.Version, error) {
|
|
||||||
return w.c.GetVersion()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error {
|
func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error {
|
||||||
w, err := waiter.NewPollingBased(&waiterClient{c: c.cfgMorph.client})
|
if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return fmt.Errorf("could not create notary deposit waiter: %w", err)
|
|
||||||
}
|
}
|
||||||
res, err := w.WaitAny(ctx, vub, tx)
|
|
||||||
if err != nil {
|
c.log.Info(ctx, logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted)
|
||||||
if errors.Is(err, waiter.ErrTxNotAccepted) {
|
return nil
|
||||||
return errNotaryDepositTimeout
|
|
||||||
}
|
|
||||||
return fmt.Errorf("could not wait for notary deposit persists in chain: %w", err)
|
|
||||||
}
|
|
||||||
if res.Execution.VMState.HasFlag(vmstate.Halt) {
|
|
||||||
c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errNotaryDepositFail
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func listenMorphNotifications(ctx context.Context, c *cfg) {
|
func listenMorphNotifications(ctx context.Context, c *cfg) {
|
||||||
|
@ -217,7 +168,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
|
||||||
fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey)
|
fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fromSideChainBlock = 0
|
fromSideChainBlock = 0
|
||||||
c.log.Warn(logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
|
c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
subs, err = subscriber.New(ctx, &subscriber.Params{
|
subs, err = subscriber.New(ctx, &subscriber.Params{
|
||||||
|
@ -246,7 +197,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
|
||||||
setNetmapNotificationParser(c, newEpochNotification, func(src *state.ContainedNotificationEvent) (event.Event, error) {
|
setNetmapNotificationParser(c, newEpochNotification, func(src *state.ContainedNotificationEvent) (event.Event, error) {
|
||||||
res, err := netmapEvent.ParseNewEpoch(src)
|
res, err := netmapEvent.ParseNewEpoch(src)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.log.Info(logs.FrostFSNodeNewEpochEventFromSidechain,
|
c.log.Info(ctx, logs.FrostFSNodeNewEpochEventFromSidechain,
|
||||||
zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()),
|
zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -256,12 +207,12 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
|
||||||
registerNotificationHandlers(c.cfgNetmap.scriptHash, lis, c.cfgNetmap.parsers, c.cfgNetmap.subscribers)
|
registerNotificationHandlers(c.cfgNetmap.scriptHash, lis, c.cfgNetmap.parsers, c.cfgNetmap.subscribers)
|
||||||
registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers)
|
registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers)
|
||||||
|
|
||||||
registerBlockHandler(lis, func(block *block.Block) {
|
registerBlockHandler(lis, func(ctx context.Context, block *block.Block) {
|
||||||
c.log.Debug(logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index))
|
c.log.Debug(ctx, logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index))
|
||||||
|
|
||||||
err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index)
|
err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Warn(logs.FrostFSNodeCantUpdatePersistentState,
|
c.log.Warn(ctx, logs.FrostFSNodeCantUpdatePersistentState,
|
||||||
zap.String("chain", "side"),
|
zap.String("chain", "side"),
|
||||||
zap.Uint32("block_index", block.Index))
|
zap.Uint32("block_index", block.Index))
|
||||||
}
|
}
|
||||||
|
@ -272,27 +223,17 @@ func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parse
|
||||||
subs map[event.Type][]event.Handler,
|
subs map[event.Type][]event.Handler,
|
||||||
) {
|
) {
|
||||||
for typ, handlers := range subs {
|
for typ, handlers := range subs {
|
||||||
pi := event.NotificationParserInfo{}
|
|
||||||
pi.SetType(typ)
|
|
||||||
pi.SetScriptHash(scHash)
|
|
||||||
|
|
||||||
p, ok := parsers[typ]
|
p, ok := parsers[typ]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("missing parser for event %s", typ))
|
panic(fmt.Sprintf("missing parser for event %s", typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
pi.SetParser(p)
|
lis.RegisterNotificationHandler(event.NotificationHandlerInfo{
|
||||||
|
Contract: scHash,
|
||||||
lis.SetNotificationParser(pi)
|
Type: typ,
|
||||||
|
Parser: p,
|
||||||
for _, h := range handlers {
|
Handlers: handlers,
|
||||||
hi := event.NotificationHandlerInfo{}
|
})
|
||||||
hi.SetType(typ)
|
|
||||||
hi.SetScriptHash(scHash)
|
|
||||||
hi.SetHandler(h)
|
|
||||||
|
|
||||||
lis.RegisterNotificationHandler(hi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,10 +262,6 @@ func lookupScriptHashesInNNS(c *cfg) {
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, t := range targets {
|
for _, t := range targets {
|
||||||
if t.nnsName == client.NNSProxyContractName && !c.cfgMorph.notaryEnabled {
|
|
||||||
continue // ignore proxy contract if notary disabled
|
|
||||||
}
|
|
||||||
|
|
||||||
if emptyHash.Equals(*t.h) {
|
if emptyHash.Equals(*t.h) {
|
||||||
*t.h, err = c.cfgMorph.client.NNSContractAddress(t.nnsName)
|
*t.h, err = c.cfgMorph.client.NNSContractAddress(t.nnsName)
|
||||||
fatalOnErrDetails(fmt.Sprintf("can't resolve %s in NNS", t.nnsName), err)
|
fatalOnErrDetails(fmt.Sprintf("can't resolve %s in NNS", t.nnsName), err)
|
||||||
|
|
|
@ -145,7 +145,7 @@ func initNetmapService(ctx context.Context, c *cfg) {
|
||||||
|
|
||||||
c.initMorphComponents(ctx)
|
c.initMorphComponents(ctx)
|
||||||
|
|
||||||
initNetmapState(c)
|
initNetmapState(ctx, c)
|
||||||
|
|
||||||
server := netmapTransportGRPC.New(
|
server := netmapTransportGRPC.New(
|
||||||
netmapService.NewSignService(
|
netmapService.NewSignService(
|
||||||
|
@ -175,45 +175,43 @@ func initNetmapService(ctx context.Context, c *cfg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func addNewEpochNotificationHandlers(c *cfg) {
|
func addNewEpochNotificationHandlers(c *cfg) {
|
||||||
addNewEpochNotificationHandler(c, func(ev event.Event) {
|
addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) {
|
||||||
c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber())
|
c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber())
|
||||||
})
|
})
|
||||||
|
|
||||||
addNewEpochAsyncNotificationHandler(c, func(ev event.Event) {
|
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) {
|
||||||
e := ev.(netmapEvent.NewEpoch).EpochNumber()
|
e := ev.(netmapEvent.NewEpoch).EpochNumber()
|
||||||
|
|
||||||
c.updateContractNodeInfo(e)
|
c.updateContractNodeInfo(ctx, e)
|
||||||
|
|
||||||
if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470
|
if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.bootstrap(); err != nil {
|
if err := c.bootstrap(ctx); err != nil {
|
||||||
c.log.Warn(logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err))
|
c.log.Warn(ctx, logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if c.cfgMorph.notaryEnabled {
|
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) {
|
||||||
addNewEpochAsyncNotificationHandler(c, func(_ event.Event) {
|
_, _, err := makeNotaryDeposit(ctx, c)
|
||||||
_, _, err := makeNotaryDeposit(c)
|
if err != nil {
|
||||||
if err != nil {
|
c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit,
|
||||||
c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit,
|
zap.Error(err),
|
||||||
zap.String("error", err.Error()),
|
)
|
||||||
)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bootstrapNode adds current node to the Network map.
|
// bootstrapNode adds current node to the Network map.
|
||||||
// Must be called after initNetmapService.
|
// Must be called after initNetmapService.
|
||||||
func bootstrapNode(c *cfg) {
|
func bootstrapNode(ctx context.Context, c *cfg) {
|
||||||
if c.needBootstrap() {
|
if c.needBootstrap() {
|
||||||
if c.IsMaintenance() {
|
if c.IsMaintenance() {
|
||||||
c.log.Info(logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap)
|
c.log.Info(ctx, logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := c.bootstrap()
|
err := c.bootstrap(ctx)
|
||||||
fatalOnErrDetails("bootstrap error", err)
|
fatalOnErrDetails("bootstrap error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,17 +238,17 @@ func setNetmapNotificationParser(c *cfg, sTyp string, p event.NotificationParser
|
||||||
|
|
||||||
// initNetmapState inits current Network map state.
|
// initNetmapState inits current Network map state.
|
||||||
// Must be called after Morph components initialization.
|
// Must be called after Morph components initialization.
|
||||||
func initNetmapState(c *cfg) {
|
func initNetmapState(ctx context.Context, c *cfg) {
|
||||||
epoch, err := c.cfgNetmap.wrapper.Epoch()
|
epoch, err := c.cfgNetmap.wrapper.Epoch()
|
||||||
fatalOnErrDetails("could not initialize current epoch number", err)
|
fatalOnErrDetails("could not initialize current epoch number", err)
|
||||||
|
|
||||||
var ni *netmapSDK.NodeInfo
|
var ni *netmapSDK.NodeInfo
|
||||||
ni, err = c.netmapInitLocalNodeState(epoch)
|
ni, err = c.netmapInitLocalNodeState(ctx, epoch)
|
||||||
fatalOnErrDetails("could not init network state", err)
|
fatalOnErrDetails("could not init network state", err)
|
||||||
|
|
||||||
stateWord := nodeState(ni)
|
stateWord := nodeState(ni)
|
||||||
|
|
||||||
c.log.Info(logs.FrostFSNodeInitialNetworkState,
|
c.log.Info(ctx, logs.FrostFSNodeInitialNetworkState,
|
||||||
zap.Uint64("epoch", epoch),
|
zap.Uint64("epoch", epoch),
|
||||||
zap.String("state", stateWord),
|
zap.String("state", stateWord),
|
||||||
)
|
)
|
||||||
|
@ -279,7 +277,7 @@ func nodeState(ni *netmapSDK.NodeInfo) string {
|
||||||
return "undefined"
|
return "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) {
|
func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netmapSDK.NodeInfo, error) {
|
||||||
nmNodes, err := c.cfgNetmap.wrapper.GetCandidates()
|
nmNodes, err := c.cfgNetmap.wrapper.GetCandidates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -307,7 +305,7 @@ func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error
|
||||||
if nmState != candidateState {
|
if nmState != candidateState {
|
||||||
// This happens when the node was switched to maintenance without epoch tick.
|
// This happens when the node was switched to maintenance without epoch tick.
|
||||||
// We expect it to continue staying in maintenance.
|
// We expect it to continue staying in maintenance.
|
||||||
c.log.Info(logs.CandidateStatusPriority,
|
c.log.Info(ctx, logs.CandidateStatusPriority,
|
||||||
zap.String("netmap", nmState),
|
zap.String("netmap", nmState),
|
||||||
zap.String("candidate", candidateState))
|
zap.String("candidate", candidateState))
|
||||||
}
|
}
|
||||||
|
@ -353,16 +351,16 @@ func addNewEpochAsyncNotificationHandler(c *cfg, h event.Handler) {
|
||||||
|
|
||||||
var errRelayBootstrap = errors.New("setting netmap status is forbidden in relay mode")
|
var errRelayBootstrap = errors.New("setting netmap status is forbidden in relay mode")
|
||||||
|
|
||||||
func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error {
|
func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) error {
|
||||||
switch st {
|
switch st {
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported status %v", st)
|
return fmt.Errorf("unsupported status %v", st)
|
||||||
case control.NetmapStatus_MAINTENANCE:
|
case control.NetmapStatus_MAINTENANCE:
|
||||||
return c.setMaintenanceStatus(false)
|
return c.setMaintenanceStatus(ctx, false)
|
||||||
case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE:
|
case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE:
|
||||||
}
|
}
|
||||||
|
|
||||||
c.stopMaintenance()
|
c.stopMaintenance(ctx)
|
||||||
|
|
||||||
if !c.needBootstrap() {
|
if !c.needBootstrap() {
|
||||||
return errRelayBootstrap
|
return errRelayBootstrap
|
||||||
|
@ -370,12 +368,12 @@ func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error {
|
||||||
|
|
||||||
if st == control.NetmapStatus_ONLINE {
|
if st == control.NetmapStatus_ONLINE {
|
||||||
c.cfgNetmap.reBoostrapTurnedOff.Store(false)
|
c.cfgNetmap.reBoostrapTurnedOff.Store(false)
|
||||||
return bootstrapOnline(c)
|
return bootstrapOnline(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cfgNetmap.reBoostrapTurnedOff.Store(true)
|
c.cfgNetmap.reBoostrapTurnedOff.Store(true)
|
||||||
|
|
||||||
return c.updateNetMapState(func(*nmClient.UpdatePeerPrm) {})
|
return c.updateNetMapState(ctx, func(*nmClient.UpdatePeerPrm) {})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
|
func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
|
||||||
|
@ -387,11 +385,11 @@ func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) {
|
||||||
return st, epoch, nil
|
return st, epoch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) ForceMaintenance() error {
|
func (c *cfg) ForceMaintenance(ctx context.Context) error {
|
||||||
return c.setMaintenanceStatus(true)
|
return c.setMaintenanceStatus(ctx, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfg) setMaintenanceStatus(force bool) error {
|
func (c *cfg) setMaintenanceStatus(ctx context.Context, force bool) error {
|
||||||
netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration()
|
netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("read network settings to check maintenance allowance: %w", err)
|
err = fmt.Errorf("read network settings to check maintenance allowance: %w", err)
|
||||||
|
@ -400,10 +398,10 @@ func (c *cfg) setMaintenanceStatus(force bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil || force {
|
if err == nil || force {
|
||||||
c.startMaintenance()
|
c.startMaintenance(ctx)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = c.updateNetMapState((*nmClient.UpdatePeerPrm).SetMaintenance)
|
err = c.updateNetMapState(ctx, (*nmClient.UpdatePeerPrm).SetMaintenance)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -416,13 +414,16 @@ func (c *cfg) setMaintenanceStatus(force bool) error {
|
||||||
|
|
||||||
// calls UpdatePeerState operation of Netmap contract's client for the local node.
|
// calls UpdatePeerState operation of Netmap contract's client for the local node.
|
||||||
// State setter is used to specify node state to switch to.
|
// State setter is used to specify node state to switch to.
|
||||||
func (c *cfg) updateNetMapState(stateSetter func(*nmClient.UpdatePeerPrm)) error {
|
func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient.UpdatePeerPrm)) error {
|
||||||
var prm nmClient.UpdatePeerPrm
|
var prm nmClient.UpdatePeerPrm
|
||||||
prm.SetKey(c.key.PublicKey().Bytes())
|
prm.SetKey(c.key.PublicKey().Bytes())
|
||||||
stateSetter(&prm)
|
stateSetter(&prm)
|
||||||
|
|
||||||
_, err := c.cfgNetmap.wrapper.UpdatePeerState(prm)
|
res, err := c.cfgNetmap.wrapper.UpdatePeerState(ctx, prm)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
type netInfo struct {
|
type netInfo struct {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
@ -14,8 +13,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
||||||
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
||||||
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache"
|
||||||
objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc"
|
objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc"
|
||||||
objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object"
|
objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object"
|
||||||
|
@ -37,7 +34,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
||||||
objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc"
|
objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
@ -61,19 +57,19 @@ type objectSvc struct {
|
||||||
func (c *cfg) MaxObjectSize() uint64 {
|
func (c *cfg) MaxObjectSize() uint64 {
|
||||||
sz, err := c.cfgNetmap.wrapper.MaxObjectSize()
|
sz, err := c.cfgNetmap.wrapper.MaxObjectSize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeCouldNotGetMaxObjectSizeValue,
|
c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue,
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sz
|
return sz
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectSvc) Put() (objectService.PutObjectStream, error) {
|
func (s *objectSvc) Put(_ context.Context) (objectService.PutObjectStream, error) {
|
||||||
return s.put.Put()
|
return s.put.Put()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *objectSvc) Patch() (objectService.PatchObjectStream, error) {
|
func (s *objectSvc) Patch(_ context.Context) (objectService.PatchObjectStream, error) {
|
||||||
return s.patch.Patch()
|
return s.patch.Patch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,24 +136,6 @@ func (fn *innerRingFetcherWithNotary) InnerRingKeys() ([][]byte, error) {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type innerRingFetcherWithoutNotary struct {
|
|
||||||
nm *nmClient.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *innerRingFetcherWithoutNotary) InnerRingKeys() ([][]byte, error) {
|
|
||||||
keys, err := f.nm.GetInnerRingList()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("can't get inner ring keys from netmap contract: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make([][]byte, 0, len(keys))
|
|
||||||
for i := range keys {
|
|
||||||
result = append(result, keys[i].Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func initObjectService(c *cfg) {
|
func initObjectService(c *cfg) {
|
||||||
keyStorage := util.NewKeyStorage(&c.key.PrivateKey, c.privateTokenStore, c.cfgNetmap.state)
|
keyStorage := util.NewKeyStorage(&c.key.PrivateKey, c.privateTokenStore, c.cfgNetmap.state)
|
||||||
|
|
||||||
|
@ -226,7 +204,7 @@ func initObjectService(c *cfg) {
|
||||||
|
|
||||||
func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.ClientCache) {
|
func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.ClientCache) {
|
||||||
if policerconfig.UnsafeDisable(c.appCfg) {
|
if policerconfig.UnsafeDisable(c.appCfg) {
|
||||||
c.log.Warn(logs.FrostFSNodePolicerIsDisabled)
|
c.log.Warn(context.Background(), logs.FrostFSNodePolicerIsDisabled)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +268,8 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl
|
||||||
|
|
||||||
_, err := ls.Inhume(ctx, inhumePrm)
|
_, err := ls.Inhume(ctx, inhumePrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Warn(logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage,
|
c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage,
|
||||||
zap.String("error", err.Error()),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -308,13 +286,8 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInnerRingFetcher(c *cfg) v2.InnerRingFetcher {
|
func createInnerRingFetcher(c *cfg) v2.InnerRingFetcher {
|
||||||
if c.cfgMorph.client.ProbeNotary() {
|
return &innerRingFetcherWithNotary{
|
||||||
return &innerRingFetcherWithNotary{
|
sidechain: c.cfgMorph.client,
|
||||||
sidechain: c.cfgMorph.client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &innerRingFetcherWithoutNotary{
|
|
||||||
nm: c.cfgNetmap.wrapper,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,29 +457,6 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type morphEACLFetcher struct {
|
|
||||||
w *cntClient.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *morphEACLFetcher) GetEACL(cnr cid.ID) (*containercore.EACL, error) {
|
|
||||||
eaclInfo, err := s.w.GetEACL(cnr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
binTable, err := eaclInfo.Value.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("marshal eACL table: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !eaclInfo.Signature.Verify(binTable) {
|
|
||||||
// TODO(@cthulhu-rider): #468 use "const" error
|
|
||||||
return nil, errors.New("invalid signature of the eACL table")
|
|
||||||
}
|
|
||||||
|
|
||||||
return eaclInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type engineWithoutNotifications struct {
|
type engineWithoutNotifications struct {
|
||||||
engine *engine.StorageEngine
|
engine *engine.StorageEngine
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
profilerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler"
|
profilerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler"
|
||||||
httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http"
|
httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initProfilerService(c *cfg) {
|
func initProfilerService(ctx context.Context, c *cfg) {
|
||||||
tuneProfilers(c)
|
tuneProfilers(c)
|
||||||
|
|
||||||
pprof, _ := pprofComponent(c)
|
pprof, _ := pprofComponent(c)
|
||||||
pprof.init(c)
|
pprof.init(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func pprofComponent(c *cfg) (*httpComponent, bool) {
|
func pprofComponent(c *cfg) (*httpComponent, bool) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
|
||||||
|
@ -9,17 +10,17 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setRuntimeParameters(c *cfg) {
|
func setRuntimeParameters(ctx context.Context, c *cfg) {
|
||||||
if len(os.Getenv("GOMEMLIMIT")) != 0 {
|
if len(os.Getenv("GOMEMLIMIT")) != 0 {
|
||||||
// default limit < yaml limit < app env limit < GOMEMLIMIT
|
// default limit < yaml limit < app env limit < GOMEMLIMIT
|
||||||
c.log.Warn(logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT)
|
c.log.Warn(ctx, logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
memLimitBytes := runtime.GCMemoryLimitBytes(c.appCfg)
|
memLimitBytes := runtime.GCMemoryLimitBytes(c.appCfg)
|
||||||
previous := debug.SetMemoryLimit(memLimitBytes)
|
previous := debug.SetMemoryLimit(memLimitBytes)
|
||||||
if memLimitBytes != previous {
|
if memLimitBytes != previous {
|
||||||
c.log.Info(logs.RuntimeSoftMemoryLimitUpdated,
|
c.log.Info(ctx, logs.RuntimeSoftMemoryLimitUpdated,
|
||||||
zap.Int64("new_value", memLimitBytes),
|
zap.Int64("new_value", memLimitBytes),
|
||||||
zap.Int64("old_value", previous))
|
zap.Int64("old_value", previous))
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func initSessionService(c *cfg) {
|
||||||
_ = c.privateTokenStore.Close()
|
_ = c.privateTokenStore.Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
addNewEpochNotificationHandler(c, func(ev event.Event) {
|
addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) {
|
||||||
c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber())
|
c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,12 @@ import (
|
||||||
func initTracing(ctx context.Context, c *cfg) {
|
func initTracing(ctx context.Context, c *cfg) {
|
||||||
conf, err := tracingconfig.ToTracingConfig(c.appCfg)
|
conf, err := tracingconfig.ToTracingConfig(c.appCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeFailedInitTracing, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = tracing.Setup(ctx, *conf)
|
_, err = tracing.Setup(ctx, *conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeFailedInitTracing, zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ func initTracing(ctx context.Context, c *cfg) {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
err := tracing.Shutdown(ctx) // cfg context cancels before close
|
err := tracing.Shutdown(ctx) // cfg context cancels before close
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error(logs.FrostFSNodeFailedShutdownTracing, zap.Error(err))
|
c.log.Error(ctx, logs.FrostFSNodeFailedShutdownTracing, zap.Error(err))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue