Compare commits
No commits in common. "master" and "fix/out-of-range-panics" have entirely different histories.
master
...
fix/out-of
695 changed files with 8428 additions and 10691 deletions
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23 AS builder
|
||||
FROM golang:1.22 AS builder
|
||||
ARG BUILD=now
|
||||
ARG VERSION=dev
|
||||
ARG REPO=repository
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23
|
||||
FROM golang:1.22
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23 AS builder
|
||||
FROM golang:1.22 AS builder
|
||||
ARG BUILD=now
|
||||
ARG VERSION=dev
|
||||
ARG REPO=repository
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23 AS builder
|
||||
FROM golang:1.22 AS builder
|
||||
ARG BUILD=now
|
||||
ARG VERSION=dev
|
||||
ARG REPO=repository
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23 AS builder
|
||||
FROM golang:1.22 AS builder
|
||||
ARG BUILD=now
|
||||
ARG VERSION=dev
|
||||
ARG REPO=repository
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
name: Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
name: Pre-commit hooks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
precommit:
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
name: Tests and linters
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
@ -111,6 +106,4 @@ jobs:
|
|||
run: make fumpt-install
|
||||
|
||||
- name: Run gofumpt
|
||||
run: |
|
||||
make fumpt
|
||||
git diff --exit-code --quiet
|
||||
run: make fumpt
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
name: Vulncheck
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
vulncheck:
|
||||
|
|
0
.forgejo/logo.svg → .github/logo.svg
vendored
0
.forgejo/logo.svg → .github/logo.svg
vendored
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
@ -38,10 +38,6 @@ linters-settings:
|
|||
alias:
|
||||
pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object
|
||||
alias: objectSDK
|
||||
unused:
|
||||
field-writes-are-uses: false
|
||||
exported-fields-are-used: false
|
||||
local-variables-are-used: false
|
||||
custom:
|
||||
truecloudlab-linters:
|
||||
path: bin/linters/external_linters.so
|
||||
|
@ -87,7 +83,5 @@ linters:
|
|||
- perfsprint
|
||||
- testifylint
|
||||
- protogetter
|
||||
- intrange
|
||||
- tenv
|
||||
disable-all: true
|
||||
fast: false
|
||||
|
|
11
.woodpecker/pre-commit.yml
Normal file
11
.woodpecker/pre-commit.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
pipeline:
|
||||
# Kludge for non-root containers under WoodPecker
|
||||
fix-ownership:
|
||||
image: alpine:latest
|
||||
commands: chown -R 1234:1234 .
|
||||
|
||||
pre-commit:
|
||||
image: git.frostfs.info/truecloudlab/frostfs-ci:v0.36
|
||||
commands:
|
||||
- export HOME="$(getent passwd $(id -u) | cut '-d:' -f6)"
|
||||
- pre-commit run --hook-stage manual
|
34
Makefile
34
Makefile
|
@ -4,14 +4,14 @@ SHELL = bash
|
|||
REPO ?= $(shell go list -m)
|
||||
VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 2>/dev/null || cat VERSION 2>/dev/null || echo "develop")
|
||||
|
||||
HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs
|
||||
HUB_IMAGE ?= truecloudlab/frostfs
|
||||
HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')"
|
||||
|
||||
GO_VERSION ?= 1.22
|
||||
LINT_VERSION ?= 1.62.0
|
||||
TRUECLOUDLAB_LINT_VERSION ?= 0.0.8
|
||||
LINT_VERSION ?= 1.60.3
|
||||
TRUECLOUDLAB_LINT_VERSION ?= 0.0.7
|
||||
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-api-go/v2)
|
||||
PROTOC_OS_VERSION=osx-x86_64
|
||||
ifeq ($(shell uname), Linux)
|
||||
PROTOC_OS_VERSION=linux-x86_64
|
||||
|
@ -27,6 +27,12 @@ DIRS = $(BIN) $(RELEASE)
|
|||
CMDS = $(notdir $(basename $(wildcard cmd/frostfs-*)))
|
||||
BINS = $(addprefix $(BIN)/, $(CMDS))
|
||||
|
||||
# .deb package versioning
|
||||
OS_RELEASE = $(shell lsb_release -cs)
|
||||
PKG_VERSION ?= $(shell echo $(VERSION) | sed "s/^v//" | \
|
||||
sed -E "s/(.*)-(g[a-fA-F0-9]{6,8})(.*)/\1\3~\2/" | \
|
||||
sed "s/-/~/")-${OS_RELEASE}
|
||||
|
||||
OUTPUT_LINT_DIR ?= $(abspath $(BIN))/linters
|
||||
LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION)
|
||||
TMP_DIR := .cache
|
||||
|
@ -52,7 +58,7 @@ LOCODE_DB_PATH=$(abspath ./.cache/locode_db)
|
|||
LOCODE_DB_VERSION=v0.4.0
|
||||
|
||||
.PHONY: help all images dep clean fmts fumpt imports test lint docker/lint
|
||||
prepare-release pre-commit unpre-commit
|
||||
prepare-release debpackage pre-commit unpre-commit
|
||||
|
||||
# To build a specific binary, use it's name prefix with bin/ as a target
|
||||
# For example `make bin/frostfs-node` will build only storage node binary
|
||||
|
@ -121,7 +127,7 @@ protoc-install:
|
|||
@unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR)
|
||||
@rm $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip
|
||||
@echo "⇒ Instaling protogen FrostFS plugin..."
|
||||
@GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/protogen@$(PROTOGEN_FROSTFS_VERSION)
|
||||
@GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen@$(PROTOGEN_FROSTFS_VERSION)
|
||||
|
||||
# Build FrostFS component's docker image
|
||||
image-%:
|
||||
|
@ -257,6 +263,19 @@ clean:
|
|||
rm -rf $(BIN)
|
||||
rm -rf $(RELEASE)
|
||||
|
||||
# Package for Debian
|
||||
debpackage:
|
||||
dch -b --package frostfs-node \
|
||||
--controlmaint \
|
||||
--newversion $(PKG_VERSION) \
|
||||
--distribution $(OS_RELEASE) \
|
||||
"Please see CHANGELOG.md for code changes for $(VERSION)"
|
||||
dpkg-buildpackage --no-sign -b
|
||||
|
||||
# Cleanup deb package build directories
|
||||
debclean:
|
||||
dh clean
|
||||
|
||||
# Download locode database
|
||||
locode-download:
|
||||
mkdir -p $(TMP_DIR)
|
||||
|
@ -282,6 +301,7 @@ env-up: all
|
|||
|
||||
# Shutdown dev environment
|
||||
env-down:
|
||||
docker compose -f dev/docker-compose.yml down -v
|
||||
docker compose -f dev/docker-compose.yml down
|
||||
docker volume rm -f frostfs-node_neo-go
|
||||
rm -rf ./$(TMP_DIR)/state
|
||||
rm -rf ./$(TMP_DIR)/storage
|
||||
|
|
19
README.md
19
README.md
|
@ -1,5 +1,5 @@
|
|||
<p align="center">
|
||||
<img src="./.forgejo/logo.svg" width="500px" alt="FrostFS">
|
||||
<img src="./.github/logo.svg" width="500px" alt="FrostFS">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
@ -7,8 +7,9 @@
|
|||
</p>
|
||||
|
||||
---
|
||||
[![Report](https://goreportcard.com/badge/git.frostfs.info/TrueCloudLab/frostfs-node)](https://goreportcard.com/report/git.frostfs.info/TrueCloudLab/frostfs-node)
|
||||
![Release (latest)](https://git.frostfs.info/TrueCloudLab/frostfs-node/badges/release.svg)
|
||||
[![Report](https://goreportcard.com/badge/github.com/TrueCloudLab/frostfs-node)](https://goreportcard.com/report/github.com/TrueCloudLab/frostfs-node)
|
||||
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/TrueCloudLab/frostfs-node?sort=semver)
|
||||
![License](https://img.shields.io/github/license/TrueCloudLab/frostfs-node.svg?style=popout)
|
||||
|
||||
# Overview
|
||||
|
||||
|
@ -32,8 +33,8 @@ manipulate large amounts of data without paying a prohibitive price.
|
|||
|
||||
FrostFS has a native [gRPC API](https://git.frostfs.info/TrueCloudLab/frostfs-api) and has
|
||||
protocol gateways for popular protocols such as [AWS
|
||||
S3](https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw),
|
||||
[HTTP](https://git.frostfs.info/TrueCloudLab/frostfs-http-gw),
|
||||
S3](https://github.com/TrueCloudLab/frostfs-s3-gw),
|
||||
[HTTP](https://github.com/TrueCloudLab/frostfs-http-gw),
|
||||
[FUSE](https://wikipedia.org/wiki/Filesystem_in_Userspace) and
|
||||
[sFTP](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) allowing
|
||||
developers to integrate applications without rewriting their code.
|
||||
|
@ -44,7 +45,7 @@ Now, we only support GNU/Linux on amd64 CPUs with AVX/AVX2 instructions. More
|
|||
platforms will be officially supported after release `1.0`.
|
||||
|
||||
The latest version of frostfs-node works with frostfs-contract
|
||||
[v0.19.2](https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/tag/v0.19.2).
|
||||
[v0.16.0](https://github.com/TrueCloudLab/frostfs-contract/releases/tag/v0.16.0).
|
||||
|
||||
# Building
|
||||
|
||||
|
@ -70,7 +71,7 @@ make docker/bin/frostfs-<name> # build a specific binary
|
|||
|
||||
## Docker images
|
||||
|
||||
To make docker images suitable for use in [frostfs-dev-env](https://git.frostfs.info/TrueCloudLab/frostfs-dev-env/) use:
|
||||
To make docker images suitable for use in [frostfs-dev-env](https://github.com/TrueCloudLab/frostfs-dev-env/) use:
|
||||
```
|
||||
make images
|
||||
```
|
||||
|
@ -98,7 +99,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):
|
||||
|
||||
```
|
||||
./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
|
||||
./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
|
||||
Enter password > <- press ENTER, the is no password for wallet
|
||||
CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju
|
||||
|
||||
|
@ -124,7 +125,7 @@ the feature/topic you are going to implement.
|
|||
|
||||
# Credits
|
||||
|
||||
FrostFS is maintained by [True Cloud Lab](https://git.frostfs.info/TrueCloudLab/) with the help and
|
||||
FrostFS is maintained by [True Cloud Lab](https://github.com/TrueCloudLab/) with the help and
|
||||
contributions from community members.
|
||||
|
||||
Please see [CREDITS](CREDITS.md) for details.
|
||||
|
|
|
@ -9,8 +9,8 @@ related configuration details.
|
|||
|
||||
To follow this guide you need:
|
||||
- latest released version of [neo-go](https://github.com/nspcc-dev/neo-go/releases) (v0.97.2 at the moment),
|
||||
- latest released version of [frostfs-adm](https://git.frostfs.info/TrueCloudLab/frostfs-node/releases) utility (v0.42.9 at the moment),
|
||||
- latest released version of compiled [frostfs-contract](https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases) (v0.19.2 at the moment).
|
||||
- latest released version of [frostfs-adm](https://github.com/TrueCloudLab/frostfs-node/releases) utility (v0.25.1 at the moment),
|
||||
- latest released version of compiled [frostfs-contract](https://github.com/TrueCloudLab/frostfs-contract/releases) (v0.11.0 at the moment).
|
||||
|
||||
## Step 1: Prepare network configuration
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ const (
|
|||
AlphabetWalletsFlagDesc = "Path to alphabet wallets dir"
|
||||
|
||||
LocalDumpFlag = "local-dump"
|
||||
ProtoConfigPath = "protocol"
|
||||
ContractsInitFlag = "contracts"
|
||||
ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)"
|
||||
ContractsURLFlag = "contracts-url"
|
||||
|
|
|
@ -128,7 +128,7 @@ func generateConfigExample(appDir string, credSize int) (string, error) {
|
|||
tmpl.AlphabetDir = filepath.Join(appDir, "alphabet-wallets")
|
||||
|
||||
var i innerring.GlagoliticLetter
|
||||
for i = range innerring.GlagoliticLetter(credSize) {
|
||||
for i = 0; i < innerring.GlagoliticLetter(credSize); i++ {
|
||||
tmpl.Glagolitics = append(tmpl.Glagolitics, i.String())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
package metabase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||
engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine"
|
||||
shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard"
|
||||
morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph"
|
||||
nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
morphcontainer "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
const (
|
||||
pathFlag = "path"
|
||||
noCompactFlag = "no-compact"
|
||||
)
|
||||
|
||||
var (
|
||||
errNoPathsFound = errors.New("no metabase paths found")
|
||||
errNoMorphEndpointsFound = errors.New("no morph endpoints found")
|
||||
)
|
||||
var errNoPathsFound = errors.New("no metabase paths found")
|
||||
|
||||
var path string
|
||||
|
||||
var UpgradeCmd = &cobra.Command{
|
||||
Use: "upgrade",
|
||||
|
@ -45,10 +37,17 @@ func upgrade(cmd *cobra.Command, _ []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
noCompact, _ := cmd.Flags().GetBool(noCompactFlag)
|
||||
var paths []string
|
||||
if path != "" {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
appCfg := config.New(configFile, configDir, config.EnvPrefix)
|
||||
paths, err := getMetabasePaths(appCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
if err := engineconfig.IterateShards(appCfg, false, func(sc *shardconfig.Config) error {
|
||||
paths = append(paths, sc.Metabase().Path())
|
||||
return nil
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to get metabase paths: %w", err)
|
||||
}
|
||||
if len(paths) == 0 {
|
||||
return errNoPathsFound
|
||||
|
@ -57,39 +56,18 @@ func upgrade(cmd *cobra.Command, _ []string) error {
|
|||
for i, path := range paths {
|
||||
cmd.Println(i+1, ":", path)
|
||||
}
|
||||
mc, err := createMorphClient(cmd.Context(), appCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer mc.Close()
|
||||
civ, err := createContainerInfoProvider(mc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
noCompact, _ := cmd.Flags().GetBool(noCompactFlag)
|
||||
result := make(map[string]bool)
|
||||
var resultGuard sync.Mutex
|
||||
eg, ctx := errgroup.WithContext(cmd.Context())
|
||||
for _, path := range paths {
|
||||
eg.Go(func() error {
|
||||
var success bool
|
||||
cmd.Println("upgrading metabase", path, "...")
|
||||
if err := meta.Upgrade(ctx, path, !noCompact, civ, func(a ...any) {
|
||||
cmd.Println(append([]any{time.Now().Format(time.RFC3339), ":", path, ":"}, a...)...)
|
||||
}); err != nil {
|
||||
cmd.Println("error: failed to upgrade metabase", path, ":", err)
|
||||
} else {
|
||||
success = true
|
||||
cmd.Println("metabase", path, "upgraded successfully")
|
||||
}
|
||||
resultGuard.Lock()
|
||||
result[path] = success
|
||||
resultGuard.Unlock()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := eg.Wait(); err != nil {
|
||||
return err
|
||||
cmd.Println("upgrading metabase", path, "...")
|
||||
if err := meta.Upgrade(cmd.Context(), path, !noCompact, func(a ...any) {
|
||||
cmd.Println(append([]any{time.Now().Format(time.RFC3339), ":", path, ":"}, a...)...)
|
||||
}); err != nil {
|
||||
result[path] = false
|
||||
cmd.Println("error: failed to upgrade metabase", path, ":", err)
|
||||
} else {
|
||||
result[path] = true
|
||||
cmd.Println("metabase", path, "upgraded successfully")
|
||||
}
|
||||
}
|
||||
for mb, ok := range result {
|
||||
if ok {
|
||||
|
@ -101,50 +79,8 @@ func upgrade(cmd *cobra.Command, _ []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getMetabasePaths(appCfg *config.Config) ([]string, error) {
|
||||
var paths []string
|
||||
if err := engineconfig.IterateShards(appCfg, false, func(sc *shardconfig.Config) error {
|
||||
paths = append(paths, sc.Metabase().Path())
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("get metabase paths: %w", err)
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
func createMorphClient(ctx context.Context, appCfg *config.Config) (*client.Client, error) {
|
||||
addresses := morphconfig.RPCEndpoint(appCfg)
|
||||
if len(addresses) == 0 {
|
||||
return nil, errNoMorphEndpointsFound
|
||||
}
|
||||
key := nodeconfig.Key(appCfg)
|
||||
cli, err := client.New(ctx,
|
||||
key,
|
||||
client.WithDialTimeout(morphconfig.DialTimeout(appCfg)),
|
||||
client.WithEndpoints(addresses...),
|
||||
client.WithSwitchInterval(morphconfig.SwitchInterval(appCfg)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create morph client:%w", err)
|
||||
}
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func createContainerInfoProvider(cli *client.Client) (container.InfoProvider, error) {
|
||||
sh, err := cli.NNSContractAddress(client.NNSContainerContractName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve container contract hash: %w", err)
|
||||
}
|
||||
cc, err := morphcontainer.NewFromMorph(cli, sh, 0, morphcontainer.TryNotary())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create morph container client: %w", err)
|
||||
}
|
||||
return container.NewInfoProvider(func() (container.Source, error) {
|
||||
return morphcontainer.AsContainerSource(cc), nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func initUpgradeCommand() {
|
||||
flags := UpgradeCmd.Flags()
|
||||
flags.StringVar(&path, pathFlag, "", "Path to metabase file")
|
||||
flags.Bool(noCompactFlag, false, "Do not compact upgraded metabase file")
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"encoding/json"
|
||||
|
||||
"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"
|
||||
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -14,10 +14,26 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
jsonFlag = "json"
|
||||
jsonFlagDesc = "Output rule chains in JSON format"
|
||||
addrAdminFlag = "addr"
|
||||
addrAdminDesc = "The address of the admins wallet"
|
||||
namespaceTarget = "namespace"
|
||||
containerTarget = "container"
|
||||
userTarget = "user"
|
||||
groupTarget = "group"
|
||||
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 (
|
||||
|
@ -85,17 +101,17 @@ func initAddRuleChainCmd() {
|
|||
addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
|
||||
addRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
addRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag)
|
||||
addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag)
|
||||
addRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc)
|
||||
_ = addRuleChainCmd.MarkFlagRequired(targetNameFlag)
|
||||
|
||||
addRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||
_ = addRuleChainCmd.MarkFlagRequired(apeCmd.ChainIDFlag)
|
||||
addRuleChainCmd.Flags().StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc)
|
||||
addRuleChainCmd.Flags().String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc)
|
||||
addRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
|
||||
addRuleChainCmd.MarkFlagsMutuallyExclusive(apeCmd.RuleFlag, apeCmd.PathFlag)
|
||||
addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc)
|
||||
_ = addRuleChainCmd.MarkFlagRequired(chainIDFlag)
|
||||
addRuleChainCmd.Flags().StringArray(ruleFlag, []string{}, ruleFlagDesc)
|
||||
addRuleChainCmd.Flags().String(pathFlag, "", pathFlagDesc)
|
||||
addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
|
||||
addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, pathFlag)
|
||||
}
|
||||
|
||||
func initRemoveRuleChainCmd() {
|
||||
|
@ -104,25 +120,26 @@ func initRemoveRuleChainCmd() {
|
|||
removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
|
||||
removeRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
removeRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
_ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag)
|
||||
removeRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||
removeRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
|
||||
removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag)
|
||||
removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc)
|
||||
_ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag)
|
||||
removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc)
|
||||
removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
|
||||
removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target")
|
||||
removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, apeCmd.ChainIDFlag)
|
||||
removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, chainIDFlag)
|
||||
}
|
||||
|
||||
func initListRuleChainsCmd() {
|
||||
Cmd.AddCommand(listRuleChainsCmd)
|
||||
|
||||
listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
listRuleChainsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = listRuleChainsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
listRuleChainsCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc)
|
||||
_ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag)
|
||||
listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc)
|
||||
_ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag)
|
||||
listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc)
|
||||
listRuleChainsCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc)
|
||||
listRuleChainsCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc)
|
||||
}
|
||||
|
||||
func initSetAdminCmd() {
|
||||
|
@ -144,15 +161,15 @@ func initListTargetsCmd() {
|
|||
Cmd.AddCommand(listTargetsCmd)
|
||||
|
||||
listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
listTargetsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = listTargetsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
listTargetsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc)
|
||||
_ = listTargetsCmd.MarkFlagRequired(targetTypeFlag)
|
||||
}
|
||||
|
||||
func addRuleChain(cmd *cobra.Command, _ []string) {
|
||||
chain := apeCmd.ParseChain(cmd)
|
||||
chain := parseChain(cmd)
|
||||
target := parseTarget(cmd)
|
||||
pci, ac := newPolicyContractInterface(cmd)
|
||||
h, vub, err := pci.AddMorphRuleChain(apeCmd.ParseChainName(cmd), target, chain)
|
||||
h, vub, err := pci.AddMorphRuleChain(parseChainName(cmd), target, chain)
|
||||
cmd.Println("Waiting for transaction to persist...")
|
||||
_, err = ac.Wait(h, vub, err)
|
||||
commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err)
|
||||
|
@ -164,14 +181,14 @@ func removeRuleChain(cmd *cobra.Command, _ []string) {
|
|||
pci, ac := newPolicyContractInterface(cmd)
|
||||
removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag)
|
||||
if removeAll {
|
||||
h, vub, err := pci.RemoveMorphRuleChainsByTarget(apeCmd.ParseChainName(cmd), target)
|
||||
h, vub, err := pci.RemoveMorphRuleChainsByTarget(parseChainName(cmd), target)
|
||||
cmd.Println("Waiting for transaction to persist...")
|
||||
_, err = ac.Wait(h, vub, err)
|
||||
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
|
||||
cmd.Println("All chains for target removed successfully")
|
||||
} else {
|
||||
chainID := apeCmd.ParseChainID(cmd)
|
||||
h, vub, err := pci.RemoveMorphRuleChain(apeCmd.ParseChainName(cmd), target, chainID)
|
||||
chainID := parseChainID(cmd)
|
||||
h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID)
|
||||
cmd.Println("Waiting for transaction to persist...")
|
||||
_, err = ac.Wait(h, vub, err)
|
||||
commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err)
|
||||
|
@ -182,7 +199,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) {
|
|||
func listRuleChains(cmd *cobra.Command, _ []string) {
|
||||
target := parseTarget(cmd)
|
||||
pci, _ := newPolicyContractReaderInterface(cmd)
|
||||
chains, err := pci.ListMorphRuleChains(apeCmd.ParseChainName(cmd), target)
|
||||
chains, err := pci.ListMorphRuleChains(parseChainName(cmd), target)
|
||||
commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err)
|
||||
if len(chains) == 0 {
|
||||
return
|
||||
|
@ -193,7 +210,7 @@ func listRuleChains(cmd *cobra.Command, _ []string) {
|
|||
prettyJSONFormat(cmd, chains)
|
||||
} else {
|
||||
for _, c := range chains {
|
||||
apeCmd.PrintHumanReadableAPEChain(cmd, c)
|
||||
parseutil.PrintHumanReadableAPEChain(cmd, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +235,8 @@ func getAdmin(cmd *cobra.Command, _ []string) {
|
|||
}
|
||||
|
||||
func listTargets(cmd *cobra.Command, _ []string) {
|
||||
typ := apeCmd.ParseTargetType(cmd)
|
||||
typ, err := parseTargetType(cmd)
|
||||
commonCmd.ExitOnErr(cmd, "parse target type error: %w", err)
|
||||
pci, inv := newPolicyContractReaderInterface(cmd)
|
||||
|
||||
sid, it, err := pci.ListTargetsIterator(typ)
|
||||
|
|
|
@ -2,12 +2,13 @@ package ape
|
|||
|
||||
import (
|
||||
"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/helper"
|
||||
parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||
morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||
|
@ -17,29 +18,90 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var errUnknownTargetType = errors.New("unknown target type")
|
||||
const (
|
||||
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 {
|
||||
typ := apeCmd.ParseTargetType(cmd)
|
||||
name, _ := cmd.Flags().GetString(apeCmd.TargetNameFlag)
|
||||
switch typ {
|
||||
case policyengine.Namespace:
|
||||
if name == "root" {
|
||||
name = ""
|
||||
}
|
||||
return policyengine.NamespaceTarget(name)
|
||||
case policyengine.Container:
|
||||
var cnr cid.ID
|
||||
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)
|
||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
||||
typ, err := parseTargetType(cmd)
|
||||
|
||||
// interpret "root" namespace as empty
|
||||
if typ == policyengine.Namespace && name == "root" {
|
||||
name = ""
|
||||
}
|
||||
panic("unreachable")
|
||||
|
||||
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 {
|
||||
case namespaceTarget:
|
||||
return policyengine.Namespace, nil
|
||||
case containerTarget:
|
||||
return policyengine.Container, nil
|
||||
case userTarget:
|
||||
return policyengine.User, nil
|
||||
case groupTarget:
|
||||
return policyengine.Group, nil
|
||||
}
|
||||
return -1, errUnknownTargetType
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -77,7 +139,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *he
|
|||
c, err := helper.GetN3Client(viper.GetViper())
|
||||
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)
|
||||
commonCmd.ExitOnErr(cmd, "can't create actor: %w", err)
|
||||
|
||||
var ch util.Uint160
|
||||
|
|
|
@ -4,6 +4,7 @@ import "time"
|
|||
|
||||
const (
|
||||
ConsensusAccountName = "consensus"
|
||||
ProtoConfigPath = "protocol"
|
||||
|
||||
// MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size
|
||||
// of the invocation script.
|
||||
|
|
|
@ -139,12 +139,13 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
|
|||
func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invoker, id []byte) (*Container, error) {
|
||||
bw.Reset()
|
||||
emit.AppCall(bw.BinWriter, ch, "get", callflag.All, id)
|
||||
emit.AppCall(bw.BinWriter, ch, "eACL", callflag.All, id)
|
||||
res, err := inv.Run(bw.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't get container info: %w", err)
|
||||
}
|
||||
if len(res.Stack) != 1 {
|
||||
return nil, fmt.Errorf("%w: expected 1 items on stack", errInvalidContainerResponse)
|
||||
if len(res.Stack) != 2 {
|
||||
return nil, fmt.Errorf("%w: expected 2 items on stack", errInvalidContainerResponse)
|
||||
}
|
||||
|
||||
cnt := new(Container)
|
||||
|
@ -153,6 +154,14 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo
|
|||
return nil, fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
||||
}
|
||||
|
||||
ea := new(EACL)
|
||||
err = ea.FromStackItem(res.Stack[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
||||
}
|
||||
if len(ea.Value) != 0 {
|
||||
cnt.EACL = ea
|
||||
}
|
||||
return cnt, nil
|
||||
}
|
||||
|
||||
|
@ -249,6 +258,10 @@ func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd
|
|||
func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) {
|
||||
emit.AppCall(bw.BinWriter, ch, "put", callflag.All,
|
||||
cnt.Value, cnt.Signature, cnt.PublicKey, cnt.Token)
|
||||
if ea := cnt.EACL; ea != nil {
|
||||
emit.AppCall(bw.BinWriter, ch, "setEACL", callflag.All,
|
||||
ea.Value, ea.Signature, ea.PublicKey, ea.Token)
|
||||
}
|
||||
}
|
||||
|
||||
func isContainerRestored(cmd *cobra.Command, wCtx *helper.InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) {
|
||||
|
@ -309,6 +322,15 @@ type Container struct {
|
|||
Signature []byte `json:"signature"`
|
||||
PublicKey []byte `json:"public_key"`
|
||||
Token []byte `json:"token"`
|
||||
EACL *EACL `json:"eacl"`
|
||||
}
|
||||
|
||||
// EACL represents extended ACL struct in contract storage.
|
||||
type EACL struct {
|
||||
Value []byte `json:"value"`
|
||||
Signature []byte `json:"signature"`
|
||||
PublicKey []byte `json:"public_key"`
|
||||
Token []byte `json:"token"`
|
||||
}
|
||||
|
||||
// ToStackItem implements stackitem.Convertible.
|
||||
|
@ -355,6 +377,50 @@ func (c *Container) FromStackItem(item stackitem.Item) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem implements stackitem.Convertible.
|
||||
func (c *EACL) ToStackItem() (stackitem.Item, error) {
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray(c.Value),
|
||||
stackitem.NewByteArray(c.Signature),
|
||||
stackitem.NewByteArray(c.PublicKey),
|
||||
stackitem.NewByteArray(c.Token),
|
||||
}), nil
|
||||
}
|
||||
|
||||
// FromStackItem implements stackitem.Convertible.
|
||||
func (c *EACL) FromStackItem(item stackitem.Item) error {
|
||||
arr, ok := item.Value().([]stackitem.Item)
|
||||
if !ok || len(arr) != 4 {
|
||||
return errors.New("invalid stack item type")
|
||||
}
|
||||
|
||||
value, err := arr[0].TryBytes()
|
||||
if err != nil {
|
||||
return errors.New("invalid eACL value")
|
||||
}
|
||||
|
||||
sig, err := arr[1].TryBytes()
|
||||
if err != nil {
|
||||
return errors.New("invalid eACL signature")
|
||||
}
|
||||
|
||||
pub, err := arr[2].TryBytes()
|
||||
if err != nil {
|
||||
return errors.New("invalid eACL public key")
|
||||
}
|
||||
|
||||
tok, err := arr[3].TryBytes()
|
||||
if err != nil {
|
||||
return errors.New("invalid eACL token")
|
||||
}
|
||||
|
||||
c.Value = value
|
||||
c.Signature = sig
|
||||
c.PublicKey = pub
|
||||
c.Token = tok
|
||||
return nil
|
||||
}
|
||||
|
||||
// getCIDFilterFunc returns filtering function for container IDs.
|
||||
// Raw byte slices are used because it works with structures returned
|
||||
// from contract.
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
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)
|
||||
}
|
|
@ -61,6 +61,7 @@ var (
|
|||
Use: "list-namespaces",
|
||||
Short: "List all namespaces in frostfsid",
|
||||
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: frostfsidListNamespaces,
|
||||
|
@ -90,6 +91,7 @@ var (
|
|||
Use: "list-subjects",
|
||||
Short: "List subjects in namespace",
|
||||
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: frostfsidListSubjects,
|
||||
|
@ -119,6 +121,7 @@ var (
|
|||
Use: "list-groups",
|
||||
Short: "List groups in namespace",
|
||||
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: frostfsidListGroups,
|
||||
|
@ -148,6 +151,7 @@ var (
|
|||
Use: "list-group-subjects",
|
||||
Short: "List subjects in group",
|
||||
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: frostfsidListGroupSubjects,
|
||||
|
@ -165,6 +169,7 @@ func initFrostfsIDCreateNamespaceCmd() {
|
|||
func initFrostfsIDListNamespacesCmd() {
|
||||
Cmd.AddCommand(frostfsidListNamespacesCmd)
|
||||
frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
frostfsidListNamespacesCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
}
|
||||
|
||||
func initFrostfsIDCreateSubjectCmd() {
|
||||
|
@ -188,6 +193,7 @@ func initFrostfsIDListSubjectsCmd() {
|
|||
frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects")
|
||||
frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)")
|
||||
frostfsidListSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
}
|
||||
|
||||
func initFrostfsIDCreateGroupCmd() {
|
||||
|
@ -211,6 +217,7 @@ func initFrostfsIDListGroupsCmd() {
|
|||
Cmd.AddCommand(frostfsidListGroupsCmd)
|
||||
frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups")
|
||||
frostfsidListGroupsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
}
|
||||
|
||||
func initFrostfsIDAddSubjectToGroupCmd() {
|
||||
|
@ -235,6 +242,7 @@ func initFrostfsIDListGroupSubjectsCmd() {
|
|||
frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name")
|
||||
frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id")
|
||||
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) {
|
||||
|
|
|
@ -12,6 +12,4 @@ func init() {
|
|||
initFrostfsIDAddSubjectToGroupCmd()
|
||||
initFrostfsIDRemoveSubjectFromGroupCmd()
|
||||
initFrostfsIDListGroupSubjectsCmd()
|
||||
initFrostfsIDAddSubjectKeyCmd()
|
||||
initFrostfsIDRemoveSubjectKeyCmd()
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func TestGenerateAlphabet(t *testing.T) {
|
|||
buf.Reset()
|
||||
v.Set(commonflags.AlphabetWalletsFlag, walletDir)
|
||||
require.NoError(t, GenerateAlphabetCmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10)))
|
||||
for i := range uint64(size) {
|
||||
for i := uint64(0); i < size; i++ {
|
||||
buf.WriteString(strconv.FormatUint(i, 10) + "\r")
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
|
@ -30,32 +31,42 @@ type LocalActor struct {
|
|||
|
||||
// NewLocalActor create LocalActor with accounts form provided wallets.
|
||||
// In case of empty wallets provided created actor with dummy account only for read operation.
|
||||
//
|
||||
// If wallets are provided, the contract client will use accounts with accName name from these wallets.
|
||||
// To determine which account name should be used in a contract client, refer to how the contract
|
||||
// verifies the transaction signature.
|
||||
func NewLocalActor(cmd *cobra.Command, c actor.RPCActor, accName string) (*LocalActor, error) {
|
||||
func NewLocalActor(cmd *cobra.Command, c actor.RPCActor) (*LocalActor, error) {
|
||||
walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag))
|
||||
var act *actor.Actor
|
||||
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)
|
||||
|
||||
wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir)
|
||||
commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err)
|
||||
|
||||
for _, w := range wallets {
|
||||
acc, err := GetWalletAccount(w, accName)
|
||||
commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err)
|
||||
accounts = append(accounts, acc)
|
||||
}
|
||||
act, err = actor.New(c, []actor.SignerAccount{{
|
||||
Signer: transaction.Signer{
|
||||
Account: accounts[0].Contract.ScriptHash(),
|
||||
Scopes: transaction.Global,
|
||||
},
|
||||
Account: accounts[0],
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, w := range wallets {
|
||||
acc, err := GetWalletAccount(w, constants.CommitteeAccountName)
|
||||
commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err)
|
||||
accounts = append(accounts, acc)
|
||||
}
|
||||
act, err = actor.New(c, []actor.SignerAccount{{
|
||||
Signer: transaction.Signer{
|
||||
Account: accounts[0].Contract.ScriptHash(),
|
||||
Scopes: transaction.Global,
|
||||
},
|
||||
Account: accounts[0],
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &LocalActor{
|
||||
neoActor: act,
|
||||
|
|
|
@ -166,6 +166,5 @@ func DeployNNS(c *InitializeContext, method string) error {
|
|||
return fmt.Errorf("can't send deploy transaction: %w", err)
|
||||
}
|
||||
|
||||
c.Command.Println("NNS hash:", invokeHash.StringLE())
|
||||
return c.AwaitTx()
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"sort"
|
||||
"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"
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
|
@ -48,7 +47,7 @@ type LocalClient struct {
|
|||
}
|
||||
|
||||
func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) {
|
||||
cfg, err := config.LoadFile(v.GetString(commonflags.ProtoConfigPath))
|
||||
cfg, err := config.LoadFile(v.GetString(constants.ProtoConfigPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -72,17 +72,13 @@ func InvalidConfigValueErr(key string) error {
|
|||
return fmt.Errorf("invalid %s config value from netmap contract", key)
|
||||
}
|
||||
|
||||
func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160, countEpoch int64) error {
|
||||
if countEpoch <= 0 {
|
||||
return errors.New("number of epochs cannot be less than 1")
|
||||
}
|
||||
|
||||
func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error {
|
||||
curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch"))
|
||||
if err != nil {
|
||||
return errors.New("can't fetch current epoch from the netmap contract")
|
||||
}
|
||||
|
||||
newEpoch := curr + countEpoch
|
||||
newEpoch := curr + 1
|
||||
wCtx.Command.Printf("Current epoch: %d, increase to %d.\n", curr, newEpoch)
|
||||
|
||||
// In NeoFS this is done via Notary contract. Here, however, we can form the
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package initialize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
|
@ -31,14 +29,10 @@ func setNotaryAndAlphabetNodes(c *helper.InitializeContext) error {
|
|||
callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs)
|
||||
|
||||
if err := c.SendCommitteeTx(w.Bytes(), false); err != nil {
|
||||
return fmt.Errorf("send committee transaction: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err := c.AwaitTx()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("await committee transaction: %w", err)
|
||||
}
|
||||
return err
|
||||
return c.AwaitTx()
|
||||
}
|
||||
|
||||
func setRolesFinished(c *helper.InitializeContext) (bool, error) {
|
||||
|
|
|
@ -62,7 +62,7 @@ func testInitialize(t *testing.T, committeeSize int) {
|
|||
v := viper.GetViper()
|
||||
|
||||
require.NoError(t, generateTestData(testdataDir, committeeSize))
|
||||
v.Set(commonflags.ProtoConfigPath, filepath.Join(testdataDir, protoFileName))
|
||||
v.Set(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName))
|
||||
|
||||
// Set to the path or remove the next statement to download from the network.
|
||||
require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath))
|
||||
|
|
|
@ -3,7 +3,6 @@ package initialize
|
|||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"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/helper"
|
||||
|
@ -27,12 +26,12 @@ const (
|
|||
initialAlphabetGASAmount = 10_000 * native.GASFactor
|
||||
// initialProxyGASAmount represents the amount of GAS given to a proxy contract.
|
||||
initialProxyGASAmount = 50_000 * native.GASFactor
|
||||
// alphabetGasRatio is a coefficient that defines the threshold below which
|
||||
// the balance of the alphabet node is considered not replenished. The value
|
||||
// of this coefficient is determined empirically.
|
||||
alphabetGasRatio = 5
|
||||
)
|
||||
|
||||
func initialCommitteeGASAmount(c *helper.InitializeContext) int64 {
|
||||
return (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2
|
||||
}
|
||||
|
||||
func transferFunds(c *helper.InitializeContext) error {
|
||||
ok, err := transferFundsFinished(c)
|
||||
if ok || err != nil {
|
||||
|
@ -59,7 +58,7 @@ func transferFunds(c *helper.InitializeContext) error {
|
|||
transferTarget{
|
||||
Token: gas.Hash,
|
||||
Address: c.CommitteeAcc.Contract.ScriptHash(),
|
||||
Amount: initialCommitteeGASAmount(c),
|
||||
Amount: (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2,
|
||||
},
|
||||
transferTarget{
|
||||
Token: neo.Hash,
|
||||
|
@ -80,19 +79,12 @@ func transferFunds(c *helper.InitializeContext) error {
|
|||
return c.AwaitTx()
|
||||
}
|
||||
|
||||
// transferFundsFinished checks balances of accounts we transfer GAS to.
|
||||
// The stage is considered finished if the balance is greater than the half of what we need to transfer.
|
||||
func transferFundsFinished(c *helper.InitializeContext) (bool, error) {
|
||||
acc := c.Accounts[0]
|
||||
|
||||
r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash)
|
||||
res, err := r.BalanceOf(acc.Contract.ScriptHash())
|
||||
if err != nil || res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) != 1 {
|
||||
return false, err
|
||||
}
|
||||
|
||||
res, err = r.BalanceOf(c.CommitteeAcc.ScriptHash())
|
||||
return res != nil && res.Cmp(big.NewInt(initialCommitteeGASAmount(c)/2)) == 1, err
|
||||
return res.Cmp(big.NewInt(alphabetGasRatio*native.GASFactor)) == 1, err
|
||||
}
|
||||
|
||||
func transferGASToProxy(c *helper.InitializeContext) error {
|
||||
|
@ -152,17 +144,5 @@ func createNEP17MultiTransferTx(c helper.Client, acc *wallet.Account, recipients
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("can't create actor: %w", err)
|
||||
}
|
||||
tx, err := act.MakeRun(w.Bytes())
|
||||
if err != nil {
|
||||
sum := make(map[util.Uint160]int64)
|
||||
for _, recipient := range recipients {
|
||||
sum[recipient.Token] += recipient.Amount
|
||||
}
|
||||
detail := make([]string, 0, len(sum))
|
||||
for _, value := range sum {
|
||||
detail = append(detail, fmt.Sprintf("amount=%v", value))
|
||||
}
|
||||
err = fmt.Errorf("transfer failed: from=%s(%s) %s: %w", acc.Label, acc.Address, strings.Join(detail, " "), err)
|
||||
}
|
||||
return tx, err
|
||||
return act.MakeRun(w.Bytes())
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package initialize
|
|||
|
||||
import (
|
||||
"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/viper"
|
||||
)
|
||||
|
@ -31,7 +32,7 @@ var Cmd = &cobra.Command{
|
|||
_ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag))
|
||||
_ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag))
|
||||
_ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag))
|
||||
_ = viper.BindPFlag(commonflags.ProtoConfigPath, cmd.Flags().Lookup(commonflags.ProtoConfigPath))
|
||||
_ = viper.BindPFlag(constants.ProtoConfigPath, cmd.Flags().Lookup(constants.ProtoConfigPath))
|
||||
},
|
||||
RunE: initializeSideChainCmd,
|
||||
}
|
||||
|
@ -47,7 +48,7 @@ func initInitCmd() {
|
|||
// Defaults are taken from neo-preodolenie.
|
||||
Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee")
|
||||
Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee")
|
||||
Cmd.Flags().String(commonflags.ProtoConfigPath, "", "Path to the consensus node configuration")
|
||||
Cmd.Flags().String(constants.ProtoConfigPath, "", "Path to the consensus node configuration")
|
||||
Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file")
|
||||
Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag)
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const deltaFlag = "delta"
|
||||
|
||||
func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error {
|
||||
wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper())
|
||||
if err != nil {
|
||||
|
@ -32,8 +30,7 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error {
|
|||
}
|
||||
|
||||
bw := io.NewBufBinWriter()
|
||||
delta, _ := cmd.Flags().GetInt64(deltaFlag)
|
||||
if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, delta); err != nil {
|
||||
if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ var (
|
|||
Short: "List netmap candidates nodes",
|
||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
||||
},
|
||||
Run: listNetmapCandidatesNodes,
|
||||
}
|
||||
|
@ -34,7 +35,6 @@ func initForceNewEpochCmd() {
|
|||
ForceNewEpoch.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
ForceNewEpoch.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
ForceNewEpoch.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file")
|
||||
ForceNewEpoch.Flags().Int64(deltaFlag, 1, "Number of epochs to increase the current epoch")
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -2,37 +2,24 @@ package nns
|
|||
|
||||
import (
|
||||
client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns"
|
||||
"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"
|
||||
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/util"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) {
|
||||
func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, util.Uint160) {
|
||||
v := viper.GetViper()
|
||||
c, err := helper.GetN3Client(v)
|
||||
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)
|
||||
commonCmd.ExitOnErr(cmd, "can't create actor: %w", err)
|
||||
|
||||
r := management.NewReader(ac.Invoker)
|
||||
nnsCs, err := helper.GetContractByID(r, 1)
|
||||
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
|
||||
return client.New(ac, nnsCs.Hash), ac
|
||||
}
|
||||
|
||||
func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) {
|
||||
c, err := helper.GetN3Client(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
|
||||
return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
||||
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/spf13/cobra"
|
||||
)
|
||||
|
@ -28,6 +29,7 @@ func initAddRecordCmd() {
|
|||
func initGetRecordsCmd() {
|
||||
Cmd.AddCommand(getRecordsCmd)
|
||||
getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
getRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc)
|
||||
getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc)
|
||||
|
||||
|
@ -45,21 +47,8 @@ func initDelRecordsCmd() {
|
|||
_ = cobra.MarkFlagRequired(delRecordsCmd.Flags(), nnsRecordTypeFlag)
|
||||
}
|
||||
|
||||
func initDelRecordCmd() {
|
||||
Cmd.AddCommand(delRecordCmd)
|
||||
delRecordCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
delRecordCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
delRecordCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc)
|
||||
delRecordCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc)
|
||||
delRecordCmd.Flags().String(nnsRecordDataFlag, "", nnsRecordDataFlagDesc)
|
||||
|
||||
_ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsNameFlag)
|
||||
_ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsRecordTypeFlag)
|
||||
_ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsRecordDataFlag)
|
||||
}
|
||||
|
||||
func addRecord(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
c, actor, _ := getRPCClient(cmd)
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
|
||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||
|
@ -75,16 +64,16 @@ func addRecord(cmd *cobra.Command, _ []string) {
|
|||
}
|
||||
|
||||
func getRecords(cmd *cobra.Command, _ []string) {
|
||||
c, inv := nnsReader(cmd)
|
||||
c, act, hash := getRPCClient(cmd)
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||
if recordType == "" {
|
||||
sid, r, err := c.GetAllRecords(name)
|
||||
sid, r, err := unwrap.SessionIterator(act.Invoker.Call(hash, "getAllRecords", name))
|
||||
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
||||
defer func() {
|
||||
_ = inv.TerminateSession(sid)
|
||||
_ = act.Invoker.TerminateSession(sid)
|
||||
}()
|
||||
items, err := inv.TraverseIterator(sid, &r, 0)
|
||||
items, err := act.Invoker.TraverseIterator(sid, &r, 0)
|
||||
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
||||
for len(items) != 0 {
|
||||
for j := range items {
|
||||
|
@ -95,7 +84,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
|
|||
recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())),
|
||||
string(bs))
|
||||
}
|
||||
items, err = inv.TraverseIterator(sid, &r, 0)
|
||||
items, err = act.Invoker.TraverseIterator(sid, &r, 0)
|
||||
commonCmd.ExitOnErr(cmd, "unable to get records: %w", err)
|
||||
}
|
||||
} else {
|
||||
|
@ -112,7 +101,7 @@ func getRecords(cmd *cobra.Command, _ []string) {
|
|||
}
|
||||
|
||||
func delRecords(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
c, actor, _ := getRPCClient(cmd)
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||
typ, err := getRecordType(recordType)
|
||||
|
@ -126,22 +115,6 @@ func delRecords(cmd *cobra.Command, _ []string) {
|
|||
cmd.Println("Records removed successfully")
|
||||
}
|
||||
|
||||
func delRecord(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
data, _ := cmd.Flags().GetString(nnsRecordDataFlag)
|
||||
recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag)
|
||||
typ, err := getRecordType(recordType)
|
||||
commonCmd.ExitOnErr(cmd, "unable to parse record type: %w", err)
|
||||
h, vub, err := c.DeleteRecord(name, typ, data)
|
||||
commonCmd.ExitOnErr(cmd, "unable to delete record: %w", err)
|
||||
|
||||
cmd.Println("Waiting for transaction to persist...")
|
||||
_, err = actor.Wait(h, vub, err)
|
||||
commonCmd.ExitOnErr(cmd, "delete records error: %w", err)
|
||||
cmd.Println("Record removed successfully")
|
||||
}
|
||||
|
||||
func getRecordType(recordType string) (*big.Int, error) {
|
||||
switch strings.ToUpper(recordType) {
|
||||
case "A":
|
||||
|
|
|
@ -24,7 +24,7 @@ func initRegisterCmd() {
|
|||
}
|
||||
|
||||
func registerDomain(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
c, actor, _ := getRPCClient(cmd)
|
||||
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
email, _ := cmd.Flags().GetString(nnsEmailFlag)
|
||||
|
@ -42,23 +42,3 @@ func registerDomain(cmd *cobra.Command, _ []string) {
|
|||
commonCmd.ExitOnErr(cmd, "register domain error: %w", err)
|
||||
cmd.Println("Domain registered successfully")
|
||||
}
|
||||
|
||||
func initDeleteCmd() {
|
||||
Cmd.AddCommand(deleteCmd)
|
||||
deleteCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
deleteCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
deleteCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc)
|
||||
|
||||
_ = cobra.MarkFlagRequired(deleteCmd.Flags(), nnsNameFlag)
|
||||
}
|
||||
|
||||
func deleteDomain(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
h, vub, err := c.DeleteDomain(name)
|
||||
|
||||
_, err = actor.Wait(h, vub, err)
|
||||
commonCmd.ExitOnErr(cmd, "delete domain error: %w", err)
|
||||
cmd.Println("Domain deleted successfully")
|
||||
}
|
|
@ -14,7 +14,7 @@ func initRenewCmd() {
|
|||
}
|
||||
|
||||
func renewDomain(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
c, actor, _ := getRPCClient(cmd)
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
h, vub, err := c.Renew(name)
|
||||
commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err)
|
||||
|
|
|
@ -42,15 +42,6 @@ var (
|
|||
},
|
||||
Run: registerDomain,
|
||||
}
|
||||
deleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "Delete a domain by name",
|
||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
||||
},
|
||||
Run: deleteDomain,
|
||||
}
|
||||
renewCmd = &cobra.Command{
|
||||
Use: "renew",
|
||||
Short: "Increases domain expiration date",
|
||||
|
@ -95,25 +86,14 @@ var (
|
|||
},
|
||||
Run: delRecords,
|
||||
}
|
||||
delRecordCmd = &cobra.Command{
|
||||
Use: "delete-record",
|
||||
Short: "Removes domain record with the specified type and data",
|
||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||
_ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag))
|
||||
_ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag))
|
||||
},
|
||||
Run: delRecord,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
initTokensCmd()
|
||||
initRegisterCmd()
|
||||
initDeleteCmd()
|
||||
initRenewCmd()
|
||||
initUpdateCmd()
|
||||
initAddRecordCmd()
|
||||
initGetRecordsCmd()
|
||||
initDelRecordsCmd()
|
||||
initDelRecordCmd()
|
||||
}
|
||||
|
|
|
@ -1,65 +1,24 @@
|
|||
package nns
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
||||
client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns"
|
||||
"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"
|
||||
)
|
||||
|
||||
const (
|
||||
verboseDesc = "Include additional information about CNAME record."
|
||||
)
|
||||
|
||||
func initTokensCmd() {
|
||||
Cmd.AddCommand(tokensCmd)
|
||||
tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc)
|
||||
tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
}
|
||||
|
||||
func listTokens(cmd *cobra.Command, _ []string) {
|
||||
c, _ := nnsReader(cmd)
|
||||
c, _, _ := getRPCClient(cmd)
|
||||
it, err := c.Tokens()
|
||||
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 _, token := range toks {
|
||||
output := string(token)
|
||||
if verbose, _ := cmd.Flags().GetBool(commonflags.Verbose); verbose {
|
||||
cname, err := getCnameRecord(c, token)
|
||||
commonCmd.ExitOnErr(cmd, "", err)
|
||||
if cname != "" {
|
||||
output += " (CNAME: " + cname + ")"
|
||||
}
|
||||
}
|
||||
cmd.Println(output)
|
||||
cmd.Println(string(token))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCnameRecord(c *client.ContractReader, token []byte) (string, error) {
|
||||
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.
|
||||
if err != nil && strings.Contains(err.Error(), "not an array") {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
record, err := items[0].TryBytes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(record), nil
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ func initUpdateCmd() {
|
|||
}
|
||||
|
||||
func updateSOA(cmd *cobra.Command, _ []string) {
|
||||
c, actor := nnsWriter(cmd)
|
||||
c, actor, _ := getRPCClient(cmd)
|
||||
|
||||
name, _ := cmd.Flags().GetString(nnsNameFlag)
|
||||
email, _ := cmd.Flags().GetString(nnsEmailFlag)
|
||||
|
|
|
@ -53,7 +53,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error {
|
|||
int64(netmapcontract.NodeStateOffline), nodeKeys[i].Bytes())
|
||||
}
|
||||
|
||||
if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, 1); err != nil {
|
||||
if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -30,13 +30,11 @@ var (
|
|||
func initProxyAddAccount() {
|
||||
AddAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string")
|
||||
AddAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
}
|
||||
|
||||
func initProxyRemoveAccount() {
|
||||
RemoveAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
|
||||
RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string")
|
||||
RemoveAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -72,3 +72,4 @@ All other `object` sub-commands support only static sessions (2).
|
|||
List of commands supporting sessions (static only):
|
||||
- `create`
|
||||
- `delete`
|
||||
- `set-eacl`
|
||||
|
|
|
@ -565,6 +565,13 @@ type HeadObjectPrm struct {
|
|||
commonObjectPrm
|
||||
objectAddressPrm
|
||||
rawPrm
|
||||
|
||||
mainOnly bool
|
||||
}
|
||||
|
||||
// SetMainOnlyFlag sets flag to get only main fields of an object header in terms of FrostFS API.
|
||||
func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) {
|
||||
x.mainOnly = v
|
||||
}
|
||||
|
||||
// HeadObjectRes groups the resulting values of HeadObject operation.
|
||||
|
@ -659,7 +666,9 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes
|
|||
|
||||
for {
|
||||
n, ok = rdr.Read(buf)
|
||||
list = append(list, buf[:n]...)
|
||||
for i := range n {
|
||||
list = append(list, buf[i])
|
||||
}
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
@ -670,8 +679,9 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes
|
|||
return nil, fmt.Errorf("read object list: %w", err)
|
||||
}
|
||||
|
||||
slices.SortFunc(list, func(a, b oid.ID) int {
|
||||
return strings.Compare(a.EncodeToString(), b.EncodeToString())
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString()
|
||||
return strings.Compare(lhs, rhs) < 0
|
||||
})
|
||||
|
||||
return &SearchObjectsRes{
|
||||
|
|
|
@ -58,7 +58,6 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey
|
|||
GRPCDialOptions: []grpc.DialOption{
|
||||
grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()),
|
||||
grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor()),
|
||||
grpc.WithDefaultCallOptions(grpc.WaitForReady(true)),
|
||||
},
|
||||
}
|
||||
if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 {
|
||||
|
|
|
@ -2,7 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
|
@ -45,11 +45,15 @@ func StartClientCommandSpan(cmd *cobra.Command) {
|
|||
})
|
||||
commonCmd.ExitOnErr(cmd, "init tracing: %w", err)
|
||||
|
||||
var components []string
|
||||
var components sort.StringSlice
|
||||
for c := cmd; c != nil; c = c.Parent() {
|
||||
components = append(components, c.Name())
|
||||
}
|
||||
slices.Reverse(components)
|
||||
for i, j := 0, len(components)-1; i < j; {
|
||||
components.Swap(i, j)
|
||||
i++
|
||||
j--
|
||||
}
|
||||
|
||||
operation := strings.Join(components, ".")
|
||||
ctx, span := tracing.StartSpanFromContext(cmd.Context(), operation)
|
||||
|
|
|
@ -1,19 +1,45 @@
|
|||
package apemanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
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/key"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
||||
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"
|
||||
client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"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 (
|
||||
defaultNamespace = ""
|
||||
namespaceTarget = "namespace"
|
||||
containerTarget = "container"
|
||||
userTarget = "user"
|
||||
groupTarget = "group"
|
||||
)
|
||||
|
||||
var errUnknownTargetType = errors.New("unknown target type")
|
||||
|
||||
var addCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add rule chain for a target",
|
||||
|
@ -24,28 +50,55 @@ var addCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) {
|
||||
t := apeCmd.ParseTarget(cmd)
|
||||
typ, _ := cmd.Flags().GetString(targetTypeFlag)
|
||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
||||
|
||||
ct.Name = t.Name
|
||||
ct.Name = name
|
||||
|
||||
switch t.Type {
|
||||
case engine.Namespace:
|
||||
switch typ {
|
||||
case namespaceTarget:
|
||||
ct.TargetType = apeSDK.TargetTypeNamespace
|
||||
case engine.Container:
|
||||
case containerTarget:
|
||||
var cnr cid.ID
|
||||
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
|
||||
ct.TargetType = apeSDK.TargetTypeContainer
|
||||
case engine.User:
|
||||
case userTarget:
|
||||
ct.TargetType = apeSDK.TargetTypeUser
|
||||
case engine.Group:
|
||||
case groupTarget:
|
||||
ct.TargetType = apeSDK.TargetTypeGroup
|
||||
default:
|
||||
commonCmd.ExitOnErr(cmd, "conversion error: %w", fmt.Errorf("unknown type '%c'", t.Type))
|
||||
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
|
||||
}
|
||||
return ct
|
||||
}
|
||||
|
||||
func parseChain(cmd *cobra.Command) apeSDK.Chain {
|
||||
c := apeCmd.ParseChain(cmd)
|
||||
serialized := c.Bytes()
|
||||
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: %w", errors.New("rule is not passed"))
|
||||
}
|
||||
|
||||
cmd.Println("Parsed chain:")
|
||||
util.PrintHumanReadableAPEChain(cmd, chain)
|
||||
|
||||
serialized := chain.Bytes()
|
||||
return apeSDK.Chain{
|
||||
Raw: serialized,
|
||||
}
|
||||
|
@ -74,13 +127,13 @@ func initAddCmd() {
|
|||
commonflags.Init(addCmd)
|
||||
|
||||
ff := addCmd.Flags()
|
||||
ff.StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc)
|
||||
ff.String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc)
|
||||
ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = addCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
|
||||
ff.StringArray(ruleFlag, []string{}, "Rule statement")
|
||||
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||
ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = addCmd.MarkFlagRequired(targetTypeFlag)
|
||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
|
||||
addCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag)
|
||||
addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
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/key"
|
||||
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
||||
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"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -35,7 +35,7 @@ func list(cmd *cobra.Command, _ []string) {
|
|||
for _, respChain := range resp.Chains {
|
||||
var chain apechain.Chain
|
||||
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw))
|
||||
apeCmd.PrintHumanReadableAPEChain(cmd, &chain)
|
||||
apeutil.PrintHumanReadableAPEChain(cmd, &chain)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ func initListCmd() {
|
|||
commonflags.Init(listCmd)
|
||||
|
||||
ff := listCmd.Flags()
|
||||
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = listCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = listCmd.MarkFlagRequired(targetTypeFlag)
|
||||
}
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
package apemanager
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
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/key"
|
||||
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"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var removeCmd = &cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "Remove rule chain for a target",
|
||||
Run: remove,
|
||||
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
|
||||
commonflags.Bind(cmd)
|
||||
},
|
||||
}
|
||||
var (
|
||||
errEmptyChainID = errors.New("chain id cannot be empty")
|
||||
|
||||
removeCmd = &cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "Remove rule chain for a target",
|
||||
Run: remove,
|
||||
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
|
||||
commonflags.Bind(cmd)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func remove(cmd *cobra.Command, _ []string) {
|
||||
target := parseTarget(cmd)
|
||||
|
@ -25,9 +31,19 @@ func remove(cmd *cobra.Command, _ []string) {
|
|||
key := key.Get(cmd)
|
||||
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)
|
||||
|
||||
chainID := apeCmd.ParseChainID(cmd)
|
||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
||||
if chainID == "" {
|
||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
|
||||
}
|
||||
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{
|
||||
ChainTarget: target,
|
||||
ChainID: chainIDRaw,
|
||||
|
@ -42,10 +58,9 @@ func initRemoveCmd() {
|
|||
commonflags.Init(removeCmd)
|
||||
|
||||
ff := removeCmd.Flags()
|
||||
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = removeCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc)
|
||||
_ = removeCmd.MarkFlagRequired(apeCmd.ChainIDFlag)
|
||||
ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc)
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = removeCmd.MarkFlagRequired(targetTypeFlag)
|
||||
ff.String(chainIDFlag, "", "Chain id")
|
||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
}
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
package bearer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"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"
|
||||
apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape"
|
||||
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
errChainIDCannotBeEmpty = errors.New("chain id cannot be empty")
|
||||
errRuleIsNotParsed = errors.New("rule is not passed")
|
||||
)
|
||||
|
||||
const (
|
||||
outputFlag = "output"
|
||||
chainIDFlag = "chain-id"
|
||||
chainIDHexFlag = "chain-id-hex"
|
||||
ruleFlag = "rule"
|
||||
pathFlag = "path"
|
||||
outputFlag = "output"
|
||||
)
|
||||
|
||||
var generateAPEOverrideCmd = &cobra.Command{
|
||||
|
@ -29,7 +40,7 @@ Generated APE override can be dumped to a file in JSON format that is passed to
|
|||
}
|
||||
|
||||
func genereateAPEOverride(cmd *cobra.Command, _ []string) {
|
||||
c := apeCmd.ParseChain(cmd)
|
||||
c := parseChain(cmd)
|
||||
|
||||
targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag)
|
||||
var cid cidSDK.ID
|
||||
|
@ -66,11 +77,39 @@ func init() {
|
|||
ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.")
|
||||
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag)
|
||||
|
||||
ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement")
|
||||
ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||
ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain")
|
||||
ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
ff.StringArray(ruleFlag, []string{}, "Rule statement")
|
||||
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||
ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
|
||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
|
||||
ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override")
|
||||
_ = 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
|
||||
}
|
||||
|
|
|
@ -7,20 +7,22 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
containerApi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||
"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/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
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/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/user"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
containerACL string
|
||||
containerPolicy string
|
||||
containerAttributes []string
|
||||
containerAwait bool
|
||||
|
@ -87,6 +89,9 @@ It will be stored in sidechain when inner ring will accepts it.`,
|
|||
err = parseAttributes(&cnr, containerAttributes)
|
||||
commonCmd.ExitOnErr(cmd, "", err)
|
||||
|
||||
var basicACL acl.Basic
|
||||
commonCmd.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL))
|
||||
|
||||
tok := getSession(cmd)
|
||||
|
||||
if tok != nil {
|
||||
|
@ -100,6 +105,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
|
|||
}
|
||||
|
||||
cnr.SetPlacementPolicy(*placementPolicy)
|
||||
cnr.SetBasicACL(basicACL)
|
||||
|
||||
var syncContainerPrm internalclient.SyncContainerPrm
|
||||
syncContainerPrm.SetClient(cli)
|
||||
|
@ -157,6 +163,10 @@ func initContainerCreateCmd() {
|
|||
flags.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage)
|
||||
flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
|
||||
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.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")
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
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/key"
|
||||
|
@ -81,8 +84,12 @@ var listContainersCmd = &cobra.Command{
|
|||
cmd.Println(cnrID.String())
|
||||
|
||||
if flagVarListPrintAttr {
|
||||
cnr.IterateUserAttributes(func(key, val string) {
|
||||
cmd.Printf(" %s: %s\n", key, val)
|
||||
cnr.IterateAttributes(func(key, val string) {
|
||||
if !strings.HasPrefix(key, container.SysAttributePrefix) && !strings.HasPrefix(key, container.SysAttributePrefixNeoFS) {
|
||||
// FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/issues/97
|
||||
// Use dedicated method to skip system attributes.
|
||||
cmd.Printf(" %s: %s\n", key, val)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
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/key"
|
||||
|
@ -64,8 +67,14 @@ var listContainerObjectsCmd = &cobra.Command{
|
|||
|
||||
resHead, err := internalclient.HeadObject(cmd.Context(), prmHead)
|
||||
if err == nil {
|
||||
for _, attr := range resHead.Header().UserAttributes() {
|
||||
cmd.Printf(" %s: %s\n", attr.Key(), attr.Value())
|
||||
attrs := resHead.Header().Attributes()
|
||||
for i := range attrs {
|
||||
attrKey := attrs[i].Key()
|
||||
if !strings.HasPrefix(attrKey, v2object.SysAttributePrefix) && !strings.HasPrefix(attrKey, v2object.SysAttributePrefixNeoFS) {
|
||||
// FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/issues/97
|
||||
// Use dedicated method to skip system attributes.
|
||||
cmd.Printf(" %s: %s\n", attrKey, attrs[i].Value())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cmd.Printf(" failed to read attributes: %v\n", err)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
|
@ -13,7 +14,6 @@ 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-sdk-go/netmap"
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
@ -163,16 +163,6 @@ func (repl *policyPlaygroundREPL) netMap() netmap.NetMap {
|
|||
return nm
|
||||
}
|
||||
|
||||
var policyPlaygroundCompleter = readline.NewPrefixCompleter(
|
||||
readline.PcItem("list"),
|
||||
readline.PcItem("ls"),
|
||||
readline.PcItem("add"),
|
||||
readline.PcItem("load"),
|
||||
readline.PcItem("remove"),
|
||||
readline.PcItem("rm"),
|
||||
readline.PcItem("eval"),
|
||||
)
|
||||
|
||||
func (repl *policyPlaygroundREPL) run() error {
|
||||
if len(viper.GetString(commonflags.RPC)) > 0 {
|
||||
key := key.GetOrGenerate(repl.cmd)
|
||||
|
@ -199,38 +189,22 @@ func (repl *policyPlaygroundREPL) run() error {
|
|||
"rm": repl.handleRemove,
|
||||
"eval": repl.handleEval,
|
||||
}
|
||||
|
||||
rl, err := readline.NewEx(&readline.Config{
|
||||
Prompt: "> ",
|
||||
InterruptPrompt: "^C",
|
||||
AutoComplete: policyPlaygroundCompleter,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error initializing readline: %w", err)
|
||||
}
|
||||
defer rl.Close()
|
||||
|
||||
var exit bool
|
||||
for {
|
||||
line, err := rl.Readline()
|
||||
for reader := bufio.NewReader(os.Stdin); ; {
|
||||
fmt.Print("> ")
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
if errors.Is(err, readline.ErrInterrupt) {
|
||||
if exit {
|
||||
return nil
|
||||
}
|
||||
exit = true
|
||||
continue
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("reading line: %w", err)
|
||||
return fmt.Errorf("reading line: %v", err)
|
||||
}
|
||||
exit = false
|
||||
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
cmd := parts[0]
|
||||
if handler, exists := cmdHandlers[cmd]; exists {
|
||||
handler, exists := cmdHandlers[cmd]
|
||||
if exists {
|
||||
if err := handler(parts[1:]); err != nil {
|
||||
fmt.Printf("error: %v\n", err)
|
||||
}
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
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-sdk-go/api/rpc/client"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
ruleFlag = "rule"
|
||||
pathFlag = "path"
|
||||
)
|
||||
|
||||
var addRuleCmd = &cobra.Command{
|
||||
Use: "add-rule",
|
||||
Short: "Add local override",
|
||||
|
@ -22,12 +31,41 @@ control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ..
|
|||
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) {
|
||||
pk := key.Get(cmd)
|
||||
|
||||
target := parseTarget(cmd)
|
||||
|
||||
parsed := apeCmd.ParseChain(cmd)
|
||||
parsed := parseChain(cmd)
|
||||
|
||||
req := &control.AddChainLocalOverrideRequest{
|
||||
Body: &control.AddChainLocalOverrideRequest_Body{
|
||||
|
@ -56,13 +94,13 @@ func initControlAddRuleCmd() {
|
|||
initControlFlags(addRuleCmd)
|
||||
|
||||
ff := addRuleCmd.Flags()
|
||||
ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement")
|
||||
ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||
ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain")
|
||||
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = addRuleCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
ff.StringArray(ruleFlag, []string{}, "Rule statement")
|
||||
ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format")
|
||||
ff.String(chainIDFlag, "", "Assign ID to the parsed chain")
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = addRuleCmd.MarkFlagRequired(targetTypeFlag)
|
||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
|
||||
addRuleCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag)
|
||||
addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
)
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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/local_object_storage/shard"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -20,10 +20,6 @@ const (
|
|||
awaitFlag = "await"
|
||||
noProgressFlag = "no-progress"
|
||||
scopeFlag = "scope"
|
||||
repOneOnlyFlag = "rep-one-only"
|
||||
|
||||
containerWorkerCountFlag = "container-worker-count"
|
||||
objectWorkerCountFlag = "object-worker-count"
|
||||
|
||||
scopeAll = "all"
|
||||
scopeObjects = "objects"
|
||||
|
@ -68,18 +64,12 @@ func startEvacuateShard(cmd *cobra.Command, _ []string) {
|
|||
pk := key.Get(cmd)
|
||||
|
||||
ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag)
|
||||
containerWorkerCount, _ := cmd.Flags().GetUint32(containerWorkerCountFlag)
|
||||
objectWorkerCount, _ := cmd.Flags().GetUint32(objectWorkerCountFlag)
|
||||
repOneOnly, _ := cmd.Flags().GetBool(repOneOnlyFlag)
|
||||
|
||||
req := &control.StartShardEvacuationRequest{
|
||||
Body: &control.StartShardEvacuationRequest_Body{
|
||||
Shard_ID: getShardIDList(cmd),
|
||||
IgnoreErrors: ignoreErrors,
|
||||
Scope: getEvacuationScope(cmd),
|
||||
ContainerWorkerCount: containerWorkerCount,
|
||||
ObjectWorkerCount: objectWorkerCount,
|
||||
RepOneOnly: repOneOnly,
|
||||
Shard_ID: getShardIDList(cmd),
|
||||
IgnoreErrors: ignoreErrors,
|
||||
Scope: getEvacuationScope(cmd),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -381,9 +371,6 @@ func initControlStartEvacuationShardCmd() {
|
|||
flags.String(scopeFlag, scopeAll, fmt.Sprintf("Evacuation scope; possible values: %s, %s, %s", scopeTrees, scopeObjects, scopeAll))
|
||||
flags.Bool(awaitFlag, false, "Block execution until evacuation is completed")
|
||||
flags.Bool(noProgressFlag, false, fmt.Sprintf("Print progress if %s provided", awaitFlag))
|
||||
flags.Uint32(containerWorkerCountFlag, 0, "Count of concurrent container evacuation workers")
|
||||
flags.Uint32(objectWorkerCountFlag, 0, "Count of concurrent object evacuation workers")
|
||||
flags.Bool(repOneOnlyFlag, false, "Evacuate objects only from containers with policy 'REP 1 ...'")
|
||||
|
||||
startEvacuationShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ package control
|
|||
import (
|
||||
"encoding/hex"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
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-sdk-go/api/rpc/client"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -24,8 +24,8 @@ func getRule(cmd *cobra.Command, _ []string) {
|
|||
|
||||
target := parseTarget(cmd)
|
||||
|
||||
chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag)
|
||||
hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag)
|
||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
||||
|
||||
if hexEncoded {
|
||||
chainIDBytes, err := hex.DecodeString(chainID)
|
||||
|
@ -56,16 +56,16 @@ func getRule(cmd *cobra.Command, _ []string) {
|
|||
|
||||
var chain apechain.Chain
|
||||
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain()))
|
||||
apecmd.PrintHumanReadableAPEChain(cmd, &chain)
|
||||
util.PrintHumanReadableAPEChain(cmd, &chain)
|
||||
}
|
||||
|
||||
func initControGetRuleCmd() {
|
||||
initControlFlags(getRuleCmd)
|
||||
|
||||
ff := getRuleCmd.Flags()
|
||||
ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc)
|
||||
ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc)
|
||||
_ = getRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag)
|
||||
ff.String(apecmd.ChainIDFlag, "", "Chain id")
|
||||
ff.Bool(apecmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = getRuleCmd.MarkFlagRequired(targetTypeFlag)
|
||||
ff.String(chainIDFlag, "", "Chain id")
|
||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@ package control
|
|||
import (
|
||||
"os"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
"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"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ package control
|
|||
import (
|
||||
"os"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||
ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||
ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||
ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||
ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
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-sdk-go/api/rpc/client"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -21,25 +23,65 @@ var listRulesCmd = &cobra.Command{
|
|||
Run: listRules,
|
||||
}
|
||||
|
||||
var engineToControlSvcType = map[policyengine.TargetType]control.ChainTarget_TargetType{
|
||||
policyengine.Namespace: control.ChainTarget_NAMESPACE,
|
||||
policyengine.Container: control.ChainTarget_CONTAINER,
|
||||
policyengine.User: control.ChainTarget_USER,
|
||||
policyengine.Group: control.ChainTarget_GROUP,
|
||||
}
|
||||
const (
|
||||
defaultNamespace = "root"
|
||||
namespaceTarget = "namespace"
|
||||
containerTarget = "container"
|
||||
userTarget = "user"
|
||||
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 {
|
||||
target := apeCmd.ParseTarget(cmd)
|
||||
|
||||
typ, ok := engineToControlSvcType[target.Type]
|
||||
if !ok {
|
||||
commonCmd.ExitOnErr(cmd, "%w", fmt.Errorf("unknown type '%c", target.Type))
|
||||
}
|
||||
|
||||
return &control.ChainTarget{
|
||||
Name: target.Name,
|
||||
Type: typ,
|
||||
typ, _ := cmd.Flags().GetString(targetTypeFlag)
|
||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
||||
switch typ {
|
||||
case namespaceTarget:
|
||||
if name == "" {
|
||||
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)
|
||||
if len(ln) > 0 && (ln[0] == 'n') {
|
||||
commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined)
|
||||
}
|
||||
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) {
|
||||
|
@ -75,7 +117,7 @@ func listRules(cmd *cobra.Command, _ []string) {
|
|||
for _, c := range chains {
|
||||
var chain apechain.Chain
|
||||
commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c))
|
||||
apeCmd.PrintHumanReadableAPEChain(cmd, &chain)
|
||||
util.PrintHumanReadableAPEChain(cmd, &chain)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +125,7 @@ func initControlListRulesCmd() {
|
|||
initControlFlags(listRulesCmd)
|
||||
|
||||
ff := listRulesCmd.Flags()
|
||||
ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc)
|
||||
ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc)
|
||||
_ = listRulesCmd.MarkFlagRequired(apeCmd.TargetTypeFlag)
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = listRulesCmd.MarkFlagRequired(targetTypeFlag)
|
||||
}
|
||||
|
|
|
@ -2,20 +2,26 @@ package control
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"text/tabwriter"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||
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-sdk-go/api/rpc/client"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
chainNameFlag = "chain-name"
|
||||
chainNameFlagUsage = "Chain name(ingress|s3)"
|
||||
)
|
||||
|
||||
var listTargetsCmd = &cobra.Command{
|
||||
Use: "list-targets",
|
||||
Short: "List local targets",
|
||||
|
@ -26,11 +32,15 @@ var listTargetsCmd = &cobra.Command{
|
|||
func listTargets(cmd *cobra.Command, _ []string) {
|
||||
pk := key.Get(cmd)
|
||||
|
||||
chainName := apeCmd.ParseChainName(cmd)
|
||||
var cnr cid.ID
|
||||
chainName, _ := cmd.Flags().GetString(chainNameFlag)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
cnr.Encode(rawCID)
|
||||
|
||||
req := &control.ListTargetsLocalOverridesRequest{
|
||||
Body: &control.ListTargetsLocalOverridesRequest_Body{
|
||||
ChainName: string(chainName),
|
||||
ChainName: chainName,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -72,7 +82,7 @@ func initControlListTargetsCmd() {
|
|||
initControlFlags(listTargetsCmd)
|
||||
|
||||
ff := listTargetsCmd.Flags()
|
||||
ff.String(apeCmd.ChainNameFlag, "", apeCmd.ChainNameFlagDesc)
|
||||
ff.String(chainNameFlag, "", chainNameFlagUsage)
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, apeCmd.ChainNameFlag)
|
||||
_ = cobra.MarkFlagRequired(ff, chainNameFlag)
|
||||
}
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"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"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
fillPercentFlag = "fill_percent"
|
||||
)
|
||||
|
||||
var shardsRebuildCmd = &cobra.Command{
|
||||
Use: "rebuild",
|
||||
Short: "Rebuild shards",
|
||||
Long: "Rebuild reclaims storage occupied by dead objects and adjusts the storage structure according to the configuration (for blobovnicza only now)",
|
||||
Run: shardsRebuild,
|
||||
}
|
||||
|
||||
func shardsRebuild(cmd *cobra.Command, _ []string) {
|
||||
pk := key.Get(cmd)
|
||||
|
||||
req := &control.StartShardRebuildRequest{
|
||||
Body: &control.StartShardRebuildRequest_Body{
|
||||
Shard_ID: getShardIDList(cmd),
|
||||
TargetFillPercent: getFillPercentValue(cmd),
|
||||
ConcurrencyLimit: getConcurrencyValue(cmd),
|
||||
},
|
||||
}
|
||||
|
||||
signRequest(cmd, pk, req)
|
||||
|
||||
cli := getClient(cmd, pk)
|
||||
|
||||
var resp *control.StartShardRebuildResponse
|
||||
var err error
|
||||
err = cli.ExecRaw(func(client *rawclient.Client) error {
|
||||
resp, err = control.StartShardRebuild(client, req)
|
||||
return err
|
||||
})
|
||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
||||
|
||||
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
|
||||
|
||||
var success, failed uint
|
||||
for _, res := range resp.GetBody().GetResults() {
|
||||
if res.GetSuccess() {
|
||||
success++
|
||||
cmd.Printf("Shard %s: OK\n", base58.Encode(res.GetShard_ID()))
|
||||
} else {
|
||||
failed++
|
||||
cmd.Printf("Shard %s: failed with error %q\n", base58.Encode(res.GetShard_ID()), res.GetError())
|
||||
}
|
||||
}
|
||||
cmd.Printf("Total: %d success, %d failed\n", success, failed)
|
||||
}
|
||||
|
||||
func getFillPercentValue(cmd *cobra.Command) uint32 {
|
||||
v, _ := cmd.Flags().GetUint32(fillPercentFlag)
|
||||
if v <= 0 || v > 100 {
|
||||
commonCmd.ExitOnErr(cmd, "invalid fill_percent value", fmt.Errorf("fill_percent value must be (0, 100], current value: %d", v))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func getConcurrencyValue(cmd *cobra.Command) uint32 {
|
||||
v, _ := cmd.Flags().GetUint32(concurrencyFlag)
|
||||
if v <= 0 || v > 10000 {
|
||||
commonCmd.ExitOnErr(cmd, "invalid concurrency value", fmt.Errorf("concurrency value must be (0, 10 000], current value: %d", v))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func initControlShardRebuildCmd() {
|
||||
initControlFlags(shardsRebuildCmd)
|
||||
|
||||
flags := shardsRebuildCmd.Flags()
|
||||
flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding")
|
||||
flags.Bool(shardAllFlag, false, "Process all shards")
|
||||
flags.Uint32(fillPercentFlag, 80, "Target fill percent to reclaim space")
|
||||
flags.Uint32(concurrencyFlag, 20, "Maximum count of concurrently rebuilding files")
|
||||
setShardModeCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag)
|
||||
}
|
|
@ -4,14 +4,19 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
||||
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-sdk-go/api/rpc/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
chainIDFlag = "chain-id"
|
||||
chainIDHexFlag = "chain-id-hex"
|
||||
allFlag = "all"
|
||||
)
|
||||
|
||||
var (
|
||||
errEmptyChainID = errors.New("chain id cannot be empty")
|
||||
|
||||
|
@ -25,8 +30,8 @@ var (
|
|||
|
||||
func removeRule(cmd *cobra.Command, _ []string) {
|
||||
pk := key.Get(cmd)
|
||||
hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag)
|
||||
removeAll, _ := cmd.Flags().GetBool(apecmd.AllFlag)
|
||||
hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag)
|
||||
removeAll, _ := cmd.Flags().GetBool(allFlag)
|
||||
if removeAll {
|
||||
req := &control.RemoveChainLocalOverridesByTargetRequest{
|
||||
Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{
|
||||
|
@ -47,7 +52,7 @@ func removeRule(cmd *cobra.Command, _ []string) {
|
|||
return
|
||||
}
|
||||
|
||||
chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag)
|
||||
chainID, _ := cmd.Flags().GetString(chainIDFlag)
|
||||
if chainID == "" {
|
||||
commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID)
|
||||
}
|
||||
|
@ -87,11 +92,11 @@ func initControlRemoveRuleCmd() {
|
|||
initControlFlags(removeRuleCmd)
|
||||
|
||||
ff := removeRuleCmd.Flags()
|
||||
ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc)
|
||||
ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc)
|
||||
_ = removeRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag)
|
||||
ff.String(apecmd.ChainIDFlag, "", apecmd.ChainIDFlagDesc)
|
||||
ff.Bool(apecmd.ChainIDHexFlag, false, apecmd.ChainIDHexFlagDesc)
|
||||
ff.Bool(apecmd.AllFlag, false, "Remove all chains")
|
||||
removeRuleCmd.MarkFlagsMutuallyExclusive(apecmd.AllFlag, apecmd.ChainIDFlag)
|
||||
ff.String(targetNameFlag, "", targetNameDesc)
|
||||
ff.String(targetTypeFlag, "", targetTypeDesc)
|
||||
_ = removeRuleCmd.MarkFlagRequired(targetTypeFlag)
|
||||
ff.String(chainIDFlag, "", "Chain id")
|
||||
ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex")
|
||||
ff.Bool(allFlag, false, "Remove all chains")
|
||||
removeRuleCmd.MarkFlagsMutuallyExclusive(allFlag, chainIDFlag)
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
@ -19,7 +19,6 @@ func initControlShardsCmd() {
|
|||
shardsCmd.AddCommand(doctorCmd)
|
||||
shardsCmd.AddCommand(writecacheShardCmd)
|
||||
shardsCmd.AddCommand(shardsDetachCmd)
|
||||
shardsCmd.AddCommand(shardsRebuildCmd)
|
||||
|
||||
initControlShardsListCmd()
|
||||
initControlSetShardModeCmd()
|
||||
|
@ -29,5 +28,4 @@ func initControlShardsCmd() {
|
|||
initControlDoctorCmd()
|
||||
initControlShardsWritecacheCmd()
|
||||
initControlShardsDetachCmd()
|
||||
initControlShardRebuildCmd()
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
"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"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
@ -6,10 +6,10 @@ import (
|
|||
"slices"
|
||||
"strings"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
@ -4,12 +4,12 @@ import (
|
|||
"crypto/sha256"
|
||||
"errors"
|
||||
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
"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-node/pkg/services/control/server/ctrlmessage"
|
||||
rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"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/mr-tron/base58"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
@ -49,14 +49,14 @@ func prettyPrintNodeInfo(cmd *cobra.Command, i netmap.NodeInfo) {
|
|||
cmd.Println("key:", hex.EncodeToString(i.PublicKey()))
|
||||
|
||||
var stateWord string
|
||||
switch i.Status() {
|
||||
switch {
|
||||
default:
|
||||
stateWord = "<undefined>"
|
||||
case netmap.Online:
|
||||
case i.IsOnline():
|
||||
stateWord = "online"
|
||||
case netmap.Offline:
|
||||
case i.IsOffline():
|
||||
stateWord = "offline"
|
||||
case netmap.Maintenance:
|
||||
case i.IsMaintenance():
|
||||
stateWord = "maintenance"
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||
"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/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
|
@ -38,6 +38,7 @@ func initObjectHeadCmd() {
|
|||
_ = objectHeadCmd.MarkFlagRequired(commonflags.OIDFlag)
|
||||
|
||||
flags.String(fileFlag, "", "File to write header to. Default: stdout.")
|
||||
flags.Bool("main-only", false, "Return only main fields")
|
||||
flags.Bool(commonflags.JSON, false, "Marshal output in JSON")
|
||||
flags.Bool("proto", false, "Marshal output in Protobuf")
|
||||
flags.Bool(rawFlag, false, rawFlagDesc)
|
||||
|
@ -48,6 +49,7 @@ func getObjectHeader(cmd *cobra.Command, _ []string) {
|
|||
var obj oid.ID
|
||||
|
||||
objAddr := readObjectAddress(cmd, &cnr, &obj)
|
||||
mainOnly, _ := cmd.Flags().GetBool("main-only")
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
|
||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
||||
|
@ -60,6 +62,7 @@ func getObjectHeader(cmd *cobra.Command, _ []string) {
|
|||
raw, _ := cmd.Flags().GetBool(rawFlag)
|
||||
prm.SetRawFlag(raw)
|
||||
prm.SetAddress(objAddr)
|
||||
prm.SetMainOnlyFlag(mainOnly)
|
||||
|
||||
res, err := internalclient.HeadObject(cmd.Context(), prm)
|
||||
if err != nil {
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
||||
"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/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
|
|
|
@ -195,7 +195,7 @@ func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, member
|
|||
prmHead.SetRawFlag(true) // to get an error instead of whole object
|
||||
|
||||
eg, egCtx := errgroup.WithContext(cmd.Context())
|
||||
for idx := range members {
|
||||
for idx := range len(members) {
|
||||
partObjID := members[idx]
|
||||
|
||||
eg.Go(func() error {
|
||||
|
|
|
@ -10,11 +10,11 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
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/key"
|
||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/gendoc"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
@ -111,16 +112,14 @@ func initConfig() {
|
|||
// Use config file from the flag.
|
||||
viper.SetConfigFile(cfgFile)
|
||||
} else {
|
||||
// Find config directory.
|
||||
configDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
common.PrintVerbose(rootCmd, "Get config dir: %s", err)
|
||||
} else {
|
||||
// Search config in `$XDG_CONFIG_HOME/frostfs-cli/` with name "config.yaml"
|
||||
viper.AddConfigPath(filepath.Join(configDir, "frostfs-cli"))
|
||||
viper.SetConfigName("config")
|
||||
viper.SetConfigType("yaml")
|
||||
}
|
||||
// Find home directory.
|
||||
home, err := homedir.Dir()
|
||||
commonCmd.ExitOnErr(rootCmd, "", err)
|
||||
|
||||
// Search config in `$HOME/.config/frostfs-cli/` with name "config.yaml"
|
||||
viper.AddConfigPath(filepath.Join(home, ".config", "frostfs-cli"))
|
||||
viper.SetConfigName("config")
|
||||
viper.SetConfigType("yaml")
|
||||
}
|
||||
|
||||
viper.SetEnvPrefix(envPrefix)
|
||||
|
|
|
@ -30,6 +30,8 @@ func initAddCmd() {
|
|||
ff := addCmd.Flags()
|
||||
ff.StringSlice(metaFlagKey, nil, "Meta pairs in the form of Key1=[0x]Value1,Key2=[0x]Value2")
|
||||
ff.Uint64(parentIDFlagKey, 0, "Parent node ID")
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func add(cmd *cobra.Command, _ []string) {
|
||||
|
@ -45,10 +47,9 @@ func add(cmd *cobra.Command, _ []string) {
|
|||
meta, err := parseMeta(cmd)
|
||||
commonCmd.ExitOnErr(cmd, "meta data parsing: %w", err)
|
||||
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -36,6 +36,7 @@ func initAddByPathCmd() {
|
|||
ff.String(pathFlagKey, "", "Path to a node")
|
||||
ff.StringSlice(metaFlagKey, nil, "Meta pairs in the form of Key1=[0x]Value1,Key2=[0x]Value2")
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
_ = cobra.MarkFlagRequired(ff, pathFlagKey)
|
||||
}
|
||||
|
||||
|
@ -49,10 +50,9 @@ func addByPath(cmd *cobra.Command, _ []string) {
|
|||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
||||
|
||||
tid, _ := cmd.Flags().GetString(treeIDFlagKey)
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -2,16 +2,14 @@ package tree
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/pkg/network"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree"
|
||||
metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc"
|
||||
tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
@ -19,20 +17,15 @@ import (
|
|||
|
||||
// _client returns grpc Tree service client. Should be removed
|
||||
// after making Tree API public.
|
||||
func _client() (tree.TreeServiceClient, error) {
|
||||
func _client(ctx context.Context) (tree.TreeServiceClient, error) {
|
||||
var netAddr network.Address
|
||||
|
||||
rpcEndpoint := viper.GetString(commonflags.RPC)
|
||||
if rpcEndpoint == "" {
|
||||
return nil, fmt.Errorf("%s is not defined", commonflags.RPC)
|
||||
}
|
||||
|
||||
err := netAddr.FromString(rpcEndpoint)
|
||||
err := netAddr.FromString(viper.GetString(commonflags.RPC))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithChainUnaryInterceptor(
|
||||
metrics.NewUnaryClientInterceptor(),
|
||||
tracing.NewUnaryClientInteceptor(),
|
||||
|
@ -41,21 +34,18 @@ func _client() (tree.TreeServiceClient, error) {
|
|||
metrics.NewStreamClientInterceptor(),
|
||||
tracing.NewStreamClientInterceptor(),
|
||||
),
|
||||
grpc.WithDefaultCallOptions(grpc.WaitForReady(true)),
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(netAddr.URIAddr(), "grpcs:") {
|
||||
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
}
|
||||
|
||||
cc, err := grpc.NewClient(netAddr.URIAddr(), opts...)
|
||||
// a default connection establishing timeout
|
||||
const defaultClientConnectTimeout = time.Second * 2
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout)
|
||||
cc, err := grpc.DialContext(ctx, netAddr.URIAddr(), opts...)
|
||||
cancel()
|
||||
|
||||
return tree.NewTreeServiceClient(cc), err
|
||||
}
|
||||
|
||||
func contextWithTimeout(cmd *cobra.Command) (context.Context, context.CancelFunc) {
|
||||
if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 {
|
||||
common.PrintVerbose(cmd, "Set request timeout to %s.", timeout)
|
||||
return context.WithTimeout(cmd.Context(), timeout)
|
||||
}
|
||||
return context.WithTimeout(cmd.Context(), commonflags.TimeoutDefault)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ func initGetByPathCmd() {
|
|||
ff.String(pathFlagKey, "", "Path to a node")
|
||||
|
||||
ff.Bool(latestOnlyFlagKey, false, "Look only for the latest version of a node")
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func getByPath(cmd *cobra.Command, _ []string) {
|
||||
|
@ -48,10 +50,9 @@ func getByPath(cmd *cobra.Command, _ []string) {
|
|||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
||||
|
||||
tid, _ := cmd.Flags().GetString(treeIDFlagKey)
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -30,6 +30,8 @@ func initGetOpLogCmd() {
|
|||
ff := getOpLogCmd.Flags()
|
||||
ff.Uint64(heightFlagKey, 0, "Height to start with")
|
||||
ff.Uint64(countFlagKey, 10, "Logged operations count")
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func getOpLog(cmd *cobra.Command, _ []string) {
|
||||
|
@ -42,10 +44,9 @@ func getOpLog(cmd *cobra.Command, _ []string) {
|
|||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
||||
|
||||
tid, _ := cmd.Flags().GetString(treeIDFlagKey)
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -20,14 +20,15 @@ var healthcheckCmd = &cobra.Command{
|
|||
|
||||
func initHealthcheckCmd() {
|
||||
commonflags.Init(healthcheckCmd)
|
||||
ff := healthcheckCmd.Flags()
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func healthcheck(cmd *cobra.Command, _ []string) {
|
||||
pk := key.GetOrGenerate(cmd)
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
req := &tree.HealthcheckRequest{
|
||||
|
|
|
@ -26,6 +26,8 @@ func initListCmd() {
|
|||
ff := listCmd.Flags()
|
||||
ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
|
||||
_ = listCmd.MarkFlagRequired(commonflags.CIDFlag)
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func list(cmd *cobra.Command, _ []string) {
|
||||
|
@ -36,10 +38,9 @@ func list(cmd *cobra.Command, _ []string) {
|
|||
err := cnr.DecodeString(cidString)
|
||||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
||||
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -33,6 +33,8 @@ func initMoveCmd() {
|
|||
|
||||
_ = getSubtreeCmd.MarkFlagRequired(nodeIDFlagKey)
|
||||
_ = getSubtreeCmd.MarkFlagRequired(parentIDFlagKey)
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func move(cmd *cobra.Command, _ []string) {
|
||||
|
@ -43,10 +45,9 @@ func move(cmd *cobra.Command, _ []string) {
|
|||
err := cnr.DecodeString(cidString)
|
||||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
||||
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -29,6 +29,8 @@ func initRemoveCmd() {
|
|||
ff.Uint64(nodeIDFlagKey, 0, "Node ID.")
|
||||
|
||||
_ = getSubtreeCmd.MarkFlagRequired(nodeIDFlagKey)
|
||||
|
||||
_ = cobra.MarkFlagRequired(ff, commonflags.RPC)
|
||||
}
|
||||
|
||||
func remove(cmd *cobra.Command, _ []string) {
|
||||
|
@ -39,10 +41,9 @@ func remove(cmd *cobra.Command, _ []string) {
|
|||
err := cnr.DecodeString(cidString)
|
||||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
||||
|
||||
ctx, cancel := contextWithTimeout(cmd)
|
||||
defer cancel()
|
||||
ctx := cmd.Context()
|
||||
|
||||
cli, err := _client()
|
||||
cli, err := _client(ctx)
|
||||
commonCmd.ExitOnErr(cmd, "failed to create client: %w", err)
|
||||
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
|
|
|
@ -49,7 +49,6 @@ const (
|
|||
heightFlagKey = "height"
|
||||
countFlagKey = "count"
|
||||
depthFlagKey = "depth"
|
||||
orderFlagKey = "ordered"
|
||||
)
|
||||
|
||||
func initCTID(cmd *cobra.Command) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue