From 861e9ab59ab060bafc90fb5c91faf6b6aa8cf48c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 2 Mar 2023 13:56:11 +0300 Subject: [PATCH] [#83] pre-commit: Add initial configuration Signed-off-by: Evgenii Stratonikov --- .dockerignore | 2 +- .golangci.yml | 1 - .pre-commit-config.yaml | 19 +++ CHANGELOG.md | 120 +++++++++--------- CREDITS.md | 2 +- Makefile | 0 cmd/frostfs-adm/README.md | 27 ++-- cmd/frostfs-adm/docs/deploy.md | 44 +++---- cmd/frostfs-adm/docs/subnetwork-creation.md | 4 +- cmd/frostfs-adm/docs/subnetwork-usage.md | 10 +- .../modules/acl/extended/create.go | 10 +- cmd/frostfs-cli/modules/container/create.go | 2 +- cmd/frostfs-cli/modules/container/delete.go | 2 +- config/example/README.md | 6 +- config/mainnet/README.md | 4 +- config/testnet/README.md | 24 ++-- debian/clean | 2 +- debian/copyright | 4 +- debian/frostfs-ir.postinst | 0 debian/frostfs-ir.postrm | 0 debian/frostfs-ir.preinst | 0 debian/frostfs-ir.prerm | 0 debian/frostfs-storage.postinst | 0 debian/frostfs-storage.postrm | 0 debian/frostfs-storage.preinst | 0 debian/frostfs-storage.prerm | 0 docs/shard-modes.md | 4 +- docs/storage-node-configuration.md | 8 +- docs/update-go-instruction.md | 2 +- pkg/local_object_storage/metabase/VERSION.md | 6 +- pkg/util/autocomplete/autocomplete.go | 6 +- 31 files changed, 163 insertions(+), 146 deletions(-) create mode 100644 .pre-commit-config.yaml mode change 100644 => 100755 Makefile mode change 100644 => 100755 debian/frostfs-ir.postinst mode change 100644 => 100755 debian/frostfs-ir.postrm mode change 100644 => 100755 debian/frostfs-ir.preinst mode change 100644 => 100755 debian/frostfs-ir.prerm mode change 100644 => 100755 debian/frostfs-storage.postinst mode change 100644 => 100755 debian/frostfs-storage.postrm mode change 100644 => 100755 debian/frostfs-storage.preinst mode change 100644 => 100755 debian/frostfs-storage.prerm diff --git a/.dockerignore b/.dockerignore index ea5f329353..4a4248d960 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,4 +5,4 @@ docker-compose.yml Dockerfile temp .dockerignore -docker \ No newline at end of file +docker diff --git a/.golangci.yml b/.golangci.yml index 54a2261cbc..3adfd0f1ee 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,4 +53,3 @@ linters: - whitespace disable-all: true fast: false - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..9c6f60481f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +ci: + autofix_prs: false + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable + - id: check-merge-conflict + - id: check-json + - id: check-xml + - id: check-yaml + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + - id: end-of-file-fixer + exclude: ".key$" diff --git a/CHANGELOG.md b/CHANGELOG.md index ae018a3351..74a7a33b3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -199,7 +199,7 @@ Tree service network replication can now be fine-tuned with `tree.replication_ti - `neo-go` to `v0.99.4` - `protoc` to `v3.21.7` - `neofs-sdk` to `v1.0.0-rc.7` - + ### Updating from v0.33.0 Now storage node serves Control API `SetNemapStatus` request with `MAINTENANCE` status only if the mode is allowed in the network settings. To force starting the local @@ -237,7 +237,7 @@ command. - Policer marks nodes under maintenance as OK without requests (#1680) - Unify help messages in CLI (#1854) - `evacuate`, `set-mode` and `flush-cache` control subcommands now accept a list of shard ids (#1867) -- Reading `object` commands of NeoFS CLI don't open remote sessions (#1865) +- Reading `object` commands of NeoFS CLI don't open remote sessions (#1865) - Use hex format to print storage node ID (#1765) ### Fixed @@ -265,7 +265,7 @@ command. - `neofs-contract` to `v0.16.0` - `neofs-api-go` to `v2.14.0` -### Updating from v0.32.0 +### Updating from v0.32.0 Replace using the `control netmap-snapshot` command with `netmap snapshot` one in NeoFS CLI. Node can now specify additional addresses in `ExternalAddr` attribute. To allow a node to dial other nodes external address, use `apiclient.allow_external` config setting. @@ -275,7 +275,7 @@ Pass `maintenance` state to `neofs-cli control set-status` to enter maintenance If network allows maintenance state (*), it will be reflected in the network map. Storage nodes under maintenance are not excluded from the network map, but don't serve object operations. (*) can be fetched from network configuration via -`neofs-cli netmap netinfo` command. +`neofs-cli netmap netinfo` command. To allow maintenance mode during neofs-adm deployments, set `network.maintenance_mode_allowed` parameter in config. @@ -570,15 +570,15 @@ Clean up all metabases and re-sync them using `resync_metabase` config flag. - Reduced amount of slices with pointers (#1239) ### Updating from v0.28.0-rc.2 -Remove `NEOFS_IR_MAINNET_ENDPOINT_NOTIFICATION`, +Remove `NEOFS_IR_MAINNET_ENDPOINT_NOTIFICATION`, `NEOFS_IR_MORPH_ENDPOINT_NOTIFICATION`, and `NEOFS_MORPH_NOTIFICATION_ENDPOINT` -from Inner Ring and Storage configurations. +from Inner Ring and Storage configurations. Specify _WebSocket_ endpoints in `NEOFS_IR_MAINNET_ENDPOINT_CLIENT`, `NEOFS_IR_MORPH_ENDPOINT_CLIENT`, and `NEOFS_MORPH_RPC_ENDPOINT` at Inner Ring and Storage configurations. -Specify path to persistent session token db in Storage configuration with +Specify path to persistent session token db in Storage configuration with `NEOFS_NODE_PERSISTENT_SESSIONS_PATH`. ## [0.28.0-rc.2] - 2022-03-24 @@ -594,7 +594,7 @@ Specify path to persistent session token db in Storage configuration with ## [0.28.0-rc.1] - 2022-03-18 -Native RFC-6979 signatures of messages and tokens, LOCK object types, +Native RFC-6979 signatures of messages and tokens, LOCK object types, experimental notifications over NATS with NeoFS API v2.12 support ### Fixed @@ -630,8 +630,8 @@ experimental notifications over NATS with NeoFS API v2.12 support - Deprecated structures from SDK v1.0.0 rc (#1181) ### Updating from neofs-node v0.27.5 -Set shard error threshold for read-only mode switch with -`NEOFS_STORAGE_SHARD_RO_ERROR_THRESHOLD` (default: 0, deactivated). +Set shard error threshold for read-only mode switch with +`NEOFS_STORAGE_SHARD_RO_ERROR_THRESHOLD` (default: 0, deactivated). Set NATS configuration for notifications in `NEOFS_NODE_NOTIFICATION` section. See example config for more details. @@ -697,7 +697,7 @@ See example config for more details. Use `--wallet` key in CLI to provide WIF or binary key file instead of `--wif` and `--binary-key`. -Replace `NEOFS_STORAGE_SHARD_N_USE_WRITE_CACHE` with +Replace `NEOFS_STORAGE_SHARD_N_USE_WRITE_CACHE` with `NEOFS_STORAGE_SHARD_N_WRITECACHE_ENABLED` in Storage node config. Specify `password: xxx` in config file for NeoFS CLI to avoid password input. @@ -774,7 +774,7 @@ NeoFS API v2.11.0 support with response status codes and storage subnetworks. - CLI now opens LOCODE database in read-only mode for listing command (#958) - Tombstone owner now is always set (#842) - Node in relay mode does not require shard config anymore (#969) -- Alphabet nodes now ignore notary notifications with non-HALT main tx (#976) +- Alphabet nodes now ignore notary notifications with non-HALT main tx (#976) - neofs-adm now prints version of NNS contract (#1014) - Possible NPE in blobovnicza (#1007) - More precise calculation of blobovnicza size (#915) @@ -791,13 +791,13 @@ NeoFS API v2.11.0 support with response status codes and storage subnetworks. - Alphabet nodes resign `AddPeer` request if it updates Storage node info (#938) - All applications now use client from neofs-sdk-go library (#966) - Some shard configuration records were renamed, see upgrading section (#859) -- `Nonce` and `VUB` values of notary transactions generated from notification +- `Nonce` and `VUB` values of notary transactions generated from notification hash (#844) - Non alphabet notary invocations now have 4 witnesses (#975) - Object replication is now async and continuous (#965) - NeoFS ADM updated for the neofs-contract v0.13.0 deploy (#984) - Minimal TLS version is set to v1.2 (#878) -- Alphabet nodes now invoke `netmap.Register` to add node to the network map +- Alphabet nodes now invoke `netmap.Register` to add node to the network map candidates in notary enabled environment (#1008) ### Upgrading from v0.26.1 @@ -827,7 +827,7 @@ with `NEOFS_IR_FEE_NAMED_CONTAINER_REGISTER`. ### Fixed - Storage Node handles requests before its initialization is finished (#934) - Release worker pools gracefully (#901) -- Metabase ignored containers of storage group and tombstone objects +- Metabase ignored containers of storage group and tombstone objects in listing (#945) - CLI missed endpoint flag in `control netmap-snapshot` command (#942) - Write cache object persisting (#866) @@ -841,16 +841,16 @@ with `NEOFS_IR_FEE_NAMED_CONTAINER_REGISTER`. ### Changed - Use FSTree counter in write cache (#821) -- Calculate notary deposit `till` parameter depending on available +- Calculate notary deposit `till` parameter depending on available deposit (#910) -- Storage node returns session token error if attached token's private key +- Storage node returns session token error if attached token's private key is not available (#943) - Refactor of NeoFS API client in inner ring (#946) -- LOCODE generator tries to find the closest continent if there are +- LOCODE generator tries to find the closest continent if there are no exact match (#955) ### Upgrading from v0.26.0 -You can specify default section in storage engine configuration. +You can specify default section in storage engine configuration. See [example](./config/example/node.yaml) for more details. ## [0.26.0] - 2021-10-19 - Udo (우도, 牛島) @@ -860,7 +860,7 @@ NeoFS API v2.10 support ### Fixed - Check remote node public key in every response message (#645) - Do not lose local container size estimations (#872) -- Compressed and uncompressed objects are always available for reading +- Compressed and uncompressed objects are always available for reading regardless of compression configuration (#868) - Use request session token in ACL check of object.Put (#881) - Parse URI in neofs-cli properly (#883) @@ -914,7 +914,7 @@ instead. ### Added - Support of multiple Neo RPC endpoints in Inner Ring node (#792) -`mainchain` section of storage node config is left unused by the application. +`mainchain` section of storage node config is left unused by the application. ## [0.25.0] - 2021-09-27 - Mungapdo (문갑도, 文甲島) @@ -922,7 +922,7 @@ instead. - Work of a storage node with one Neo RPC endpoint instead of a list (#746) - Lack of support for HEAD operation on the object write cache (#762) - Storage node attribute parsing is stable now (#787) -- Inner Ring node now logs transaction hashes of Deposit and Withdraw events +- Inner Ring node now logs transaction hashes of Deposit and Withdraw events in LittleEndian encoding (#794) - Storage node uses public keys of the remote nodes in placement traverser checks (#645) @@ -930,7 +930,7 @@ instead. (#816) - neofs-adm supports update and deploy of neofs-contract v0.11.0 (#834, #836) - Possible NPE in public key conversion (#848) -- Object assembly routine do not forward existing request instead of creating +- Object assembly routine do not forward existing request instead of creating new one (#839) - Shard now returns only physical stored objects for replication (#840) @@ -939,7 +939,7 @@ instead. - Smart contract address auto negotiation with NNS contract (#736) - Detailed logs for all data writing operations in storage engine (#790) - Docker build and release targets in Makefile (#785) -- Metabase restore option in the shard config (#789) +- Metabase restore option in the shard config (#789) - Write cache used size limit in bytes (#776) ### Changed @@ -974,7 +974,7 @@ Added `NEOFS_STORAGE_SHARD__WRITECACHE_SIZE_LIMIT` where `` is shard ID. This is the size limit for the all write cache storages combined in bytes. Default size limit is 1 GiB. -Added `NEOFS_STORAGE_SHARD__REFILL_METABASE` bool flag where `` is shard +Added `NEOFS_STORAGE_SHARD__REFILL_METABASE` bool flag where `` is shard ID. This flag purges metabase instance at the application start and reinitialize it with available objects from the blobstor. @@ -983,12 +983,12 @@ Object service pool size now split into `NEOFS_OBJECT_PUT_POOL_SIZE_REMOTE` and ## [0.24.1] - 2021-09-07 -### Fixed +### Fixed - Storage and Inner Ring will not start until Neo RPC node will have the height of the latest processed block by the nodes (#795) ### Upgrading from v0.24.0 -Specify path to the local state DB in Inner Ring node config with +Specify path to the local state DB in Inner Ring node config with `NEOFS_IR_NODE_PERSISTENT_STATE_PATH`. Specify path to the local state DB in Storage node config with `NEOFS_NODE_PERSISTENT_STATE_PATH`. @@ -1007,7 +1007,7 @@ Storage node config with `NEOFS_NODE_PERSISTENT_STATE_PATH`. - Contract update support in `neofs-adm` utility (#748) - Container transferring support in `neofs-adm` utility (#755) - Storage Node's balance refilling support in `neofs-adm` utility (#758) -- Support `COMMON_PREFIX` filter for object attributes in storage engine and `neofs-cli` (#760) +- Support `COMMON_PREFIX` filter for object attributes in storage engine and `neofs-cli` (#760) - Node's and IR's notary status debug message on startup (#758) - Go `1.17` unit tests in CI (#766) - Supporting all eACL filter fields from the specification (#768) @@ -1069,7 +1069,7 @@ Improved stability for notary disabled environment. - Storage Node configuration example contains usable parameters (#699) ### Fixed -- Do not use side chain RoleManagement contract as source of Inner Ring list +- Do not use side chain RoleManagement contract as source of Inner Ring list when notary disabled in side chain (#672) - Alphabet list transition is even more effective (#697) - Inner Ring node does not require proxy and processing contracts if notary @@ -1136,9 +1136,9 @@ Storage nodes with a group of network endpoints. - Control service with healthcheck RPC in IR and CLI support ([#414](https://github.com/nspcc-dev/neofs-node/issues/414)). ### Fixed -- Approval of objects with with duplicate attribute keys or empty values ([#633](https://github.com/nspcc-dev/neofs-node/issues/633)). +- Approval of objects with with duplicate attribute keys or empty values ([#633](https://github.com/nspcc-dev/neofs-node/issues/633)). - Approval of containers with with duplicate attribute keys or empty values ([#634](https://github.com/nspcc-dev/neofs-node/issues/634)). -- Default path for CLI config ([#626](https://github.com/nspcc-dev/neofs-node/issues/626)). +- Default path for CLI config ([#626](https://github.com/nspcc-dev/neofs-node/issues/626)). ### Changed - `version` command replaced with `--version` flag in CLI ([#571](https://github.com/nspcc-dev/neofs-node/issues/571)). @@ -1166,7 +1166,7 @@ Storage nodes with a group of network endpoints. - grpc: [v1.38.0](https://github.com/grpc/grpc-go/releases/tag/v1.38.0). - cast: [v1.3.1](https://github.com/spf13/cast/releases/tag/v1.3.1). - cobra: [1.1.3](https://github.com/spf13/cobra/releases/tag/v1.1.3). -- viper: [v1.8.1](https://github.com/spf13/viper/releases/tag/v1.8.1). +- viper: [v1.8.1](https://github.com/spf13/viper/releases/tag/v1.8.1). ## [0.21.1] - 2021-06-10 @@ -1186,7 +1186,7 @@ Session token support in container service, refactored config in storage node, TLS support on gRPC servers. ### Fixed -- ACL service traverses over all RequestMetaHeader chain to find +- ACL service traverses over all RequestMetaHeader chain to find bearer and session tokens (#548). - Object service correctly resends complete objects without attached session token (#501). @@ -1194,7 +1194,7 @@ TLS support on gRPC servers. - Client cache now gracefully closes all available connections (#567). ### Added -- Session token support in container service for `container.Put`, +- Session token support in container service for `container.Put`, `container.Delete` and `container.SetEACL` operations. - Session token support in container and sign command of NeoFS CLI. - TLS encryption support of gRPC service in storage node. @@ -1204,8 +1204,8 @@ TLS support on gRPC servers. update earlier. - Inner ring processes extended ACL changes. - Inner ring makes signature checks of containers and extended ACLs. -- Refactored config of storage node. -- Static clients from `morph/client` do not process notary invocations +- Refactored config of storage node. +- Static clients from `morph/client` do not process notary invocations explicitly anymore. Now notary support specified at static client creation. - Updated neo-go to v0.95.1 release. - Updated neofs-api-go to v1.27.0 release. @@ -1216,7 +1216,7 @@ TLS support on gRPC servers. ## [0.20.0] - 2021-05-21 - Dolsando (돌산도, 突山島) -NeoFS is N3 RC2 compatible. +NeoFS is N3 RC2 compatible. ### Fixed - Calculations in EigenTrust algorithm (#527). @@ -1229,7 +1229,7 @@ NeoFS is N3 RC2 compatible. - Client for NeoFSID contract. ### Changed -- Reorganized and removed plenty of application configuration records +- Reorganized and removed plenty of application configuration records (#510, #511, #512, #514). - Nodes do not resolve remote addresses manually. - Presets for basic ACL in CLI are `private` ,`public-read` and @@ -1247,11 +1247,11 @@ NeoFS is N3 RC2 compatible. Storage nodes exchange, calculate, aggregate and store reputation information in reputation contract. Inner ring nodes support workflows with and without -notary subsystem in chains. +notary subsystem in chains. ### Fixed - Build with go1.16. -- Notary deposits last more blocks. +- Notary deposits last more blocks. - TX hashes now prints in little endian in logs. - Metabase deletes graves regardless of the presence of objects. - SplitInfo error created from all shards instead of first matched shard. @@ -1259,7 +1259,7 @@ notary subsystem in chains. - Storage node does not send rebootstrap messages after it went offline. ### Added -- Reputation subsystem that includes reputation collection, exchange, +- Reputation subsystem that includes reputation collection, exchange, calculation and storage components. - Notary and non notary workflows in inner ring. - Audit fee transfer for inner ring nodes that performed audit. @@ -1269,7 +1269,7 @@ calculation and storage components. ### Changed - Metabase puts data in batches. -- Network related new epoch handlers in storage node executed asynchronously. +- Network related new epoch handlers in storage node executed asynchronously. - Storage node gets epoch duration from global config. - Storage node resign and resend Search, Range, Head, Get requests of object service without modification. @@ -1286,7 +1286,7 @@ alphabet keys are synchronized with main chain. ### Fixed - Metabase does not store object payloads anymore. - TTLNetCache now always evict data after a timeout. -- NeoFS CLI keyer could misinterpret hex value as base58. +- NeoFS CLI keyer could misinterpret hex value as base58. ### Added - Local trust controller in storage node. @@ -1298,7 +1298,7 @@ alphabet keys are synchronized with main chain. ## [0.17.0] - 2021-03-22 - Jebudo (제부도, 濟扶島) -Notary contract support, updated neofs-api-go with raw client, some performance +Notary contract support, updated neofs-api-go with raw client, some performance tweaks with extra caches and enhanced metrics. ### Added @@ -1317,7 +1317,7 @@ tweaks with extra caches and enhanced metrics. Garbage collector is now running inside storage engine. It is accessed via Control API, from `policer` component and through object expiration -scrubbers. +scrubbers. Inner ring configuration now supports single chain mode with any number of alphabet contracts. @@ -1348,39 +1348,39 @@ Storage node now supports NetworkInfo method in netmap service. ## [0.15.0] - 2021-02-12 - Seonyudo (선유도, 仙遊島) -NeoFS nodes are now preview5-compatible. +NeoFS nodes are now preview5-compatible. IR nodes are now engaged in the distribution of funds to the storage nodes: -for the passed audit and for the amount of stored information. All timers -of the IR nodes related to the generation and processing of global system -events are decoupled from astronomical time, and are measured in the number +for the passed audit and for the amount of stored information. All timers +of the IR nodes related to the generation and processing of global system +events are decoupled from astronomical time, and are measured in the number of blockchain blocks. For the geographic positioning of storage nodes, a global NeoFS location -database is now used, the key in which is a UN/LOCODE, and the base itself +database is now used, the key in which is a UN/LOCODE, and the base itself is generated on the basis of the UN/LOCODE and OpenFlights databases. ### Added - Timers with time in blocks of the chain. - Subscriptions to new blocks in blockchain event `Listener`. -- Tracking the volume of stored information by containers in the +- Tracking the volume of stored information by containers in the storage engine and an external interface for obtaining this data. - `TransferX` operation in sidechain client. - Calculators of audit and basic settlements. -- Distribution of funds to storage nodes for audit and for the amount +- Distribution of funds to storage nodes for audit and for the amount of stored information (settlement processors of IR). - NeoFS API `Container.AnnounceUsedSpace` RPC service. -- Exchange of information about container volumes between storage nodes +- Exchange of information about container volumes between storage nodes controlled by IR through sidechain notifications. - Support of new search matchers (`STRING_NOT_EQUAL`, `NOT_PRESENT`). - Functional for the formation of NeoFS location database. - CLI commands for generating and reading the location database. -- Checking the locode attribute and generating geographic attributes +- Checking the locode attribute and generating geographic attributes for candidates for a network map on IR side. - Verification of the eACL signature when checking Object ACL rules. ### Fixed -- Overwriting the local configuration of node attributes when updating +- Overwriting the local configuration of node attributes when updating the network map. - Ignoring the X-headers CLI `storagegroup` commands. - Inability to attach bearer token in CLI `storagegroup` commands. @@ -1398,7 +1398,7 @@ is generated on the basis of the UN/LOCODE and OpenFlights databases. ### Fixed - Upload of objects bigger than single gRPC message. - Inconsistent placement issues (#347, #349). -- Bug when ACL request classifier failed to classify `RoleOthers` in +- Bug when ACL request classifier failed to classify `RoleOthers` in first epoch. ### Added @@ -1412,13 +1412,13 @@ is generated on the basis of the UN/LOCODE and OpenFlights databases. Testnet4 related bugfixes. -### Fixed -- Default values for blobovnicza object size limit and blobstor small object +### Fixed +- Default values for blobovnicza object size limit and blobstor small object size are not zero. - Various storage engine log messages. - Bug when inner ring node ignored bootstrap messages from restarted storage - nodes. - + nodes. + ### Added - Timeout for reading boltDB files at storage node initialization. diff --git a/CREDITS.md b/CREDITS.md index 14b9648bf6..ce4050b717 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -10,7 +10,7 @@ In alphabetical order: - Alexey Vanin - Anastasia Prasolova - Anatoly Bogatyrev -- Evgeny Kulikov +- Evgeny Kulikov - Evgeny Stratonikov - Leonard Liubich - Sergei Liubich diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 diff --git a/cmd/frostfs-adm/README.md b/cmd/frostfs-adm/README.md index d9df256ea8..dac264239d 100644 --- a/cmd/frostfs-adm/README.md +++ b/cmd/frostfs-adm/README.md @@ -3,31 +3,30 @@ ## Overview Admin tool provides an easier way to deploy and maintain private installation -of FrostFS. Private installation provides a set of N3 consensus nodes, FrostFS -Alphabet, and Storage nodes. Admin tool generates consensus keys, initializes +of FrostFS. Private installation provides a set of N3 consensus nodes, FrostFS +Alphabet, and Storage nodes. Admin tool generates consensus keys, initializes the sidechain, and provides functions to update the network and register new Storage nodes. ## Build -To build binary locally, use `make bin/frostfs-adm` command. +To build binary locally, use `make bin/frostfs-adm` command. -For clean build inside a docker container, use `make docker/bin/frostfs-adm`. +For clean build inside a docker container, use `make docker/bin/frostfs-adm`. Build docker image with `make image-adm`. -At FrostFS private install deployment, frostfs-adm requires compiled FrostFS -contracts. Find them in the latest release of +At FrostFS private install deployment, frostfs-adm requires compiled FrostFS +contracts. Find them in the latest release of [frostfs-contract repository](https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases). - ## Commands ### Config Config section provides `init` command that creates a configuration file for private installation deployment and updates. Config file is optional, all -parameters can be passed by arguments or read from standard input (wallet +parameters can be passed by arguments or read from standard input (wallet passwords). Config example: @@ -58,14 +57,14 @@ credentials: # passwords for consensus node / alphabet wallets #### Network deployment -- `generate-alphabet` generates a set of wallets for consensus and - Alphabet nodes. +- `generate-alphabet` generates a set of wallets for consensus and + Alphabet nodes. - `init` initializes the sidechain by deploying smart contracts and setting provided FrostFS network configuration. -- `generate-storage-wallet` generates a wallet for the Storage node that - is ready for deployment. It also transfers a bit of sidechain GAS, so this +- `generate-storage-wallet` generates a wallet for the Storage node that + is ready for deployment. It also transfers a bit of sidechain GAS, so this wallet can be used for FrostFS bootstrap. #### Network maintenance @@ -75,7 +74,7 @@ credentials: # passwords for consensus node / alphabet wallets - `force-new-epoch` increments FrostFS epoch number and executes new epoch handlers in FrostFS nodes. -- `refill-gas` transfers sidechain GAS to the specified wallet. +- `refill-gas` transfers sidechain GAS to the specified wallet. - `update-contracts` updates contracts to a new version. @@ -87,7 +86,7 @@ info. These commands **do not migrate actual objects**. - `dump-containers` saves all containers and metadata registered in the container contract to a file. -- `restore-containers` restores previously saved containers by their repeated registration in +- `restore-containers` restores previously saved containers by their repeated registration in the container contract. - `list-containers` output all containers ids. diff --git a/cmd/frostfs-adm/docs/deploy.md b/cmd/frostfs-adm/docs/deploy.md index da3aa7078c..a1923bb2cc 100644 --- a/cmd/frostfs-adm/docs/deploy.md +++ b/cmd/frostfs-adm/docs/deploy.md @@ -2,7 +2,7 @@ This is a short guide on how to deploy a private FrostFS storage network on bare metal without docker images. This guide does not cover details on how to start -consensus, Alphabet, or Storage nodes. This guide covers only `frostfs-adm` +consensus, Alphabet, or Storage nodes. This guide covers only `frostfs-adm` related configuration details. ## Prerequisites @@ -12,11 +12,11 @@ To follow this guide you need: - 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 +## Step 1: Prepare network configuration -To start a network, you need a set of consensus nodes, the same number of -Alphabet nodes and any number of Storage nodes. While the number of Storage -nodes can be scaled almost infinitely, the number of consensus and Alphabet +To start a network, you need a set of consensus nodes, the same number of +Alphabet nodes and any number of Storage nodes. While the number of Storage +nodes can be scaled almost infinitely, the number of consensus and Alphabet nodes can't be changed so easily right now. Consider this before going any further. It is easier to use`frostfs-adm` with a predefined configuration. First, create @@ -27,7 +27,7 @@ consensus / Alphabet node in the network. $ frostfs-adm config init --path foo.network.yml Initial config file saved to foo.network.yml -$ cat foo.network.yml +$ cat foo.network.yml rpc-endpoint: https://neo.rpc.node:30333 alphabet-wallets: /home/user/deploy/alphabet-wallets network: @@ -43,17 +43,17 @@ credentials: az: hunter2 ``` -For private installation, it is recommended to set all **fees** and **basic -income rate** to 0. +For private installation, it is recommended to set all **fees** and **basic +income rate** to 0. -As for **epoch duration**, consider consensus node block generation frequency. -With default 15 seconds per block, 240 blocks are going to be a 1-hour epoch. +As for **epoch duration**, consider consensus node block generation frequency. +With default 15 seconds per block, 240 blocks are going to be a 1-hour epoch. -For **max object size**, 67108864 (64 MiB) or 134217728 (128 MiB) should provide +For **max object size**, 67108864 (64 MiB) or 134217728 (128 MiB) should provide good chunk distribution in most cases. With this config, generate wallets (private keys) of consensus nodes. The same -wallets will be used for Alphabet nodes. Make sure, that dir for alphabet +wallets will be used for Alphabet nodes. Make sure, that dir for alphabet wallets already exists. ``` @@ -69,14 +69,14 @@ storage. ## Step 2: Launch consensus nodes Configure blockchain nodes with the generated wallets from the previous step. -Config examples can be found in +Config examples can be found in [neo-go repository](https://github.com/nspcc-dev/neo-go/tree/master/config). Gather public keys from **all** generated wallets. We are interested in the first `simple signature contract` public key. ``` -$ neo-go wallet dump-keys -w alphabet-wallets/az.json +$ neo-go wallet dump-keys -w alphabet-wallets/az.json NitdS4k4f1Hh5mbLJhAswBK3WC2gQgPN1o (simple signature contract): 02c1cc85f9c856dbe2d02017349bcb7b4e5defa78b8056a09b3240ba2a8c078869 @@ -87,10 +87,10 @@ NiMKabp3ddi3xShmLAXhTfbnuWb4cSJT6E (1 out of 1 multisig contract): 02c1cc85f9c856dbe2d02017349bcb7b4e5defa78b8056a09b3240ba2a8c078869 ``` -Put the list of public keys into `ProtocolConfiguration.StandbyCommittee` +Put the list of public keys into `ProtocolConfiguration.StandbyCommittee` section. Specify the wallet path and the password in `ApplicationConfiguration.P2PNotary` and `ApplicationConfiguration.UnlockWallet` sections. If config includes -`ProtocolConfiguration.NativeActivations` section, add notary +`ProtocolConfiguration.NativeActivations` section, add notary contract `Notary: [0]`. ```yaml @@ -121,7 +121,7 @@ and possible overload issues. Use archive with compiled FrostFS contracts to initialize the sidechain. ``` -$ tar -xzvf frostfs-contract-v0.11.0.tar.gz +$ tar -xzvf frostfs-contract-v0.11.0.tar.gz $ ./frostfs-adm -c foo.network.yml morph init --contracts ./frostfs-contract-v0.11.0 Stage 1: transfer GAS to alphabet nodes. @@ -153,8 +153,8 @@ Waiting for transactions to persist... ## Step 4: Launch Alphabet nodes -Configure Alphabet nodes with the wallets generated in step 1. For -`morph.validators` use a list of public keys from +Configure Alphabet nodes with the wallets generated in step 1. For +`morph.validators` use a list of public keys from `ProtocolConfiguration.StandbyCommittee`. ```yaml @@ -178,10 +178,10 @@ Generate a new wallet for a Storage node. ``` $ frostfs-adm -c foo.network.yml morph generate-storage-wallet --storage-wallet ./sn01.json --initial-gas 10.0 -New password > +New password > Waiting for transactions to persist... -$ neo-go wallet dump-keys -w sn01.json +$ neo-go wallet dump-keys -w sn01.json Ngr7p8Z9S22XDH6VkUG9oXobv8zZRAWwwv (simple signature contract): 0355eccb72cd46f09a3e5237eaa0f4949cceb5ecfa5a225bd3bb9fd021c4d75b85 ``` @@ -205,7 +205,7 @@ Current epoch: 8, increase to 9. Waiting for transactions to persist... ``` ---- +--- After that, FrostFS Storage is ready to work. You can access it directly or with protocol gates. diff --git a/cmd/frostfs-adm/docs/subnetwork-creation.md b/cmd/frostfs-adm/docs/subnetwork-creation.md index 0c969028fe..5ada943870 100644 --- a/cmd/frostfs-adm/docs/subnetwork-creation.md +++ b/cmd/frostfs-adm/docs/subnetwork-creation.md @@ -1,7 +1,7 @@ # FrostFS subnetwork creation -This is a short guide on how to create FrostFS subnetworks. This guide -considers that the sidechain and the inner ring (alphabet nodes) have already been +This is a short guide on how to create FrostFS subnetworks. This guide +considers that the sidechain and the inner ring (alphabet nodes) have already been deployed and the sidechain contains a deployed `subnet` contract. ## Prerequisites diff --git a/cmd/frostfs-adm/docs/subnetwork-usage.md b/cmd/frostfs-adm/docs/subnetwork-usage.md index 6bfa4d1879..0d505b3a49 100644 --- a/cmd/frostfs-adm/docs/subnetwork-usage.md +++ b/cmd/frostfs-adm/docs/subnetwork-usage.md @@ -88,11 +88,11 @@ has been added by the subnet owner). # Bootstrapping Storage Node -After a subnetwork [is created](subnetwork-creation.md) and a node is included into it, the +After a subnetwork [is created](subnetwork-creation.md) and a node is included into it, the node could be bootstrapped and service subnetwork containers. -For bootstrapping, you need to specify the ID of the subnetwork in the node's -configuration: +For bootstrapping, you need to specify the ID of the subnetwork in the node's +configuration: ```yaml ... @@ -106,7 +106,7 @@ node: ``` **NOTE:** specifying subnetwork that is denied for the node is not an error: -that configuration value would be ignored. You do not need to specify zero +that configuration value would be ignored. You do not need to specify zero (with 0 ID) subnetwork: its inclusion is implicit. On the contrary, to exclude a node from the default zero subnetwork, you need to specify it explicitly: @@ -122,7 +122,7 @@ node: # Creating container in non-zero subnetwork -Creating containers without using `--subnet` flag is equivalent to +Creating containers without using `--subnet` flag is equivalent to creating container in the zero subnetwork. To create a container in a private network, your wallet must be added to diff --git a/cmd/frostfs-cli/modules/acl/extended/create.go b/cmd/frostfs-cli/modules/acl/extended/create.go index f089345e1c..7da26f8ebc 100644 --- a/cmd/frostfs-cli/modules/acl/extended/create.go +++ b/cmd/frostfs-cli/modules/acl/extended/create.go @@ -26,18 +26,18 @@ Action is 'allow' or 'deny'. Operation is an object service verb: 'get', 'head', 'put', 'search', 'delete', 'getrange', or 'getrangehash'. Filter consists of : - Typ is 'obj' for object applied filter or 'req' for request applied filter. - Key is a valid unicode string corresponding to object or request header key. + Typ is 'obj' for object applied filter or 'req' for request applied filter. + Key is a valid unicode string corresponding to object or request header key. Well-known system object headers start with '$Object:' prefix. User defined headers start without prefix. Read more about filter keys at git.frostfs.info.com/TrueCloudLab/frostfs-api/src/branch/master/proto-docs/acl.md#message-eaclrecordfilter Match is '=' for matching and '!=' for non-matching filter. Value is a valid unicode string corresponding to object or request header value. -Target is - 'user' for container owner, +Target is + 'user' for container owner, 'system' for Storage nodes in container and Inner Ring nodes, - 'others' for all other request senders, + 'others' for all other request senders, 'pubkey:,,...' for exact request sender, where is a hex-encoded 33-byte public key. When both '--rule' and '--file' arguments are used, '--rule' records will be placed higher in resulting extended ACL table. diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 78de408233..410663e84e 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -37,7 +37,7 @@ var ( var createContainerCmd = &cobra.Command{ Use: "create", Short: "Create new container", - Long: `Create new container and register it in the FrostFS. + Long: `Create new container and register it in the FrostFS. It will be stored in sidechain when inner ring will accepts it.`, Run: func(cmd *cobra.Command, args []string) { placementPolicy, err := parseContainerPolicy(cmd, containerPolicy) diff --git a/cmd/frostfs-cli/modules/container/delete.go b/cmd/frostfs-cli/modules/container/delete.go index 09e76d5936..52ee5d4fba 100644 --- a/cmd/frostfs-cli/modules/container/delete.go +++ b/cmd/frostfs-cli/modules/container/delete.go @@ -17,7 +17,7 @@ import ( var deleteContainerCmd = &cobra.Command{ Use: "delete", Short: "Delete existing container", - Long: `Delete existing container. + Long: `Delete existing container. Only owner of the container has a permission to remove container.`, Run: func(cmd *cobra.Command, args []string) { id := parseContainerID(cmd) diff --git a/config/example/README.md b/config/example/README.md index afb594b145..8dd0fe44a0 100644 --- a/config/example/README.md +++ b/config/example/README.md @@ -1,9 +1,9 @@ -# Examples of correct configuration file structures +# Examples of correct configuration file structures Here are files in all supported formats and with all possible configuration values of FrostFS applications. See [node.yaml](node.yaml) for configuration notes. -All parameters are correct, however, they are for informational purposes only. +All parameters are correct, however, they are for informational purposes only. It is not recommended transferring these configs for real application launches. ## Config files @@ -15,7 +15,7 @@ It is not recommended transferring these configs for real application launches. - YAML: `ir.yaml` - CLI - YAML: `cli.yaml` - + ### Multiple configs You can split your configuration to several files. diff --git a/config/mainnet/README.md b/config/mainnet/README.md index 5b2ac7ac9f..717a9b0ff5 100644 --- a/config/mainnet/README.md +++ b/config/mainnet/README.md @@ -1,12 +1,12 @@ # N3 Mainnet Storage node configuration Here is a template for simple storage node configuration in N3 Mainnet. -Make sure to specify correct values instead of `<...>` placeholders. +Make sure to specify correct values instead of `<...>` placeholders. Do not change `contracts` section. Run the latest frostfs-node release with the fixed config `frostfs-node -c config.yml` To use NeoFS in the Mainnet, you need to deposit assets to NeoFS contract. -The contract sript hash is `2cafa46838e8b564468ebd868dcafdd99dce6221` +The contract sript hash is `2cafa46838e8b564468ebd868dcafdd99dce6221` (N3 address `NNxVrKjLsRkWsmGgmuNXLcMswtxTGaNQLk`) ## Tips diff --git a/config/testnet/README.md b/config/testnet/README.md index 82cbe3d221..b5faf2b277 100644 --- a/config/testnet/README.md +++ b/config/testnet/README.md @@ -6,8 +6,8 @@ docker image and run it with docker-compose. ## Build image -Prepared **frostfs-storage-testnet** image is available at Docker Hub. -However, if you need to rebuild it for some reason, run +Prepared **frostfs-storage-testnet** image is available at Docker Hub. +However, if you need to rebuild it for some reason, run `make image-storage-testnet` command. ``` @@ -19,13 +19,13 @@ Successfully tagged nspccdev/neofs-storage-testnet:0.25.1 ## Deploy node -To run a storage node in N3 Testnet environment, you should deposit GAS assets, +To run a storage node in N3 Testnet environment, you should deposit GAS assets, update docker-compose file and start the node. ### Deposit -The Storage Node owner should deposit GAS to NeoFS smart contract. It generates a -bit of sidechain GAS in the node's wallet. Sidechain GAS is used to send bootstrap tx. +The Storage Node owner should deposit GAS to NeoFS smart contract. It generates a +bit of sidechain GAS in the node's wallet. Sidechain GAS is used to send bootstrap tx. First, obtain GAS in N3 Testnet chain. You can do that with [faucet](https://neowish.ngd.network) service. @@ -34,7 +34,7 @@ Then, make a deposit by transferring GAS to NeoFS contract in N3 Testnet. You can provide scripthash in the `data` argument of transfer tx to make a deposit to a specified account. Otherwise, deposit is made to the tx sender. -NeoFS contract scripthash in N3 Testnet is `b65d8243ac63983206d17e5221af0653a7266fa1`, +NeoFS contract scripthash in N3 Testnet is `b65d8243ac63983206d17e5221af0653a7266fa1`, so the address is `NadZ8YfvkddivcFFkztZgfwxZyKf1acpRF`. See a deposit example with `neo-go`. @@ -57,7 +57,7 @@ NEOFS_GRPC_0_ENDPOINT=65.52.183.157:36512 NEOFS_NODE_ADDRESSES=65.52.183.157:36512 ``` -Set up your [UN/LOCODE](https://unece.org/trade/cefact/unlocode-code-list-country-and-territory) +Set up your [UN/LOCODE](https://unece.org/trade/cefact/unlocode-code-list-country-and-territory) attribute. ``` @@ -66,7 +66,7 @@ NEOFS_NODE_ADDRESSES=65.52.183.157:36512 NEOFS_NODE_ATTRIBUTE_2=UN-LOCODE:RU LED ``` -You can validate UN/LOCODE attribute in +You can validate UN/LOCODE attribute in [NeoFS LOCODE database](https://github.com/TrueCloudLab/frostfs-locode-db/releases/tag/v0.1.0) with frostfs-cli. @@ -79,7 +79,7 @@ Subdivision: [SPE] Sankt-Peterburg Coordinates: 59.53, 30.15 ``` -It is recommended to pass the node's key as a file. To do so, convert your wallet +It is recommended to pass the node's key as a file. To do so, convert your wallet WIF to 32-byte hex (via `frostfs-cli` for example) and save it to a file. ``` @@ -104,8 +104,8 @@ Then, specify the path to this file in `docker-compose.yml` ``` -NeoFS objects will be stored on your machine. By default, docker-compose -is configured to store objects in named docker volume `frostfs_storage`. You can +NeoFS objects will be stored on your machine. By default, docker-compose +is configured to store objects in named docker volume `frostfs_storage`. You can specify a directory on the filesystem to store objects there. ```yaml @@ -120,7 +120,7 @@ Run the node with `docker-compose up` command and stop it with `docker-compose d ### Debug -To print node logs, use `docker logs frostfs-testnet`. To print debug messages in +To print node logs, use `docker logs frostfs-testnet`. To print debug messages in log, set up log level to debug with this env: ```yaml diff --git a/debian/clean b/debian/clean index f38249144c..44dc05e0af 100644 --- a/debian/clean +++ b/debian/clean @@ -1,2 +1,2 @@ -man/ +man/ debian/*.bash-completion diff --git a/debian/copyright b/debian/copyright index 612863406a..61dab665d1 100644 --- a/debian/copyright +++ b/debian/copyright @@ -19,5 +19,5 @@ License: GPL-3 General Public License for more details. You should have received a copy of the GNU General Public License - along with this program or at /usr/share/common-licenses/GPL-3 - If not, see . + along with this program or at /usr/share/common-licenses/GPL-3 + If not, see . diff --git a/debian/frostfs-ir.postinst b/debian/frostfs-ir.postinst old mode 100644 new mode 100755 diff --git a/debian/frostfs-ir.postrm b/debian/frostfs-ir.postrm old mode 100644 new mode 100755 diff --git a/debian/frostfs-ir.preinst b/debian/frostfs-ir.preinst old mode 100644 new mode 100755 diff --git a/debian/frostfs-ir.prerm b/debian/frostfs-ir.prerm old mode 100644 new mode 100755 diff --git a/debian/frostfs-storage.postinst b/debian/frostfs-storage.postinst old mode 100644 new mode 100755 diff --git a/debian/frostfs-storage.postrm b/debian/frostfs-storage.postrm old mode 100644 new mode 100755 diff --git a/debian/frostfs-storage.preinst b/debian/frostfs-storage.preinst old mode 100644 new mode 100755 diff --git a/debian/frostfs-storage.prerm b/debian/frostfs-storage.prerm old mode 100644 new mode 100755 diff --git a/docs/shard-modes.md b/docs/shard-modes.md index 8f5a7d5f54..7fca33d093 100644 --- a/docs/shard-modes.md +++ b/docs/shard-modes.md @@ -4,7 +4,7 @@ Each mode is characterized by two important properties: 1. Whether modifying operations are allowed. -2. Whether metabase and write-cache is available. +2. Whether metabase and write-cache is available. The expected deployment scenario is to place both metabase and write-cache on an SSD drive thus these modes can be approximately described as no-SSD modes. @@ -45,4 +45,4 @@ However, all mode changing operations are idempotent. Shard can automatically switch to a `degraded-read-only` mode in 3 cases: 1. If the metabase was not available or couldn't be opened/initialized during shard startup. 2. If shard error counter exceeds threshold. -3. If the metabase couldn't be reopened during SIGHUP handling. \ No newline at end of file +3. If the metabase couldn't be reopened during SIGHUP handling. diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index b77253561e..16737ab9f1 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -45,8 +45,8 @@ control: grpc: - endpoint: localhost:8080 tls: - enabled: true - certificate: /path/to/cert.pem + enabled: true + certificate: /path/to/cert.pem key: /path/to/key.pem - endpoint: internal.ip:8080 - endpoint: external.ip:8080 @@ -237,7 +237,7 @@ gc: | Parameter | Type | Default value | Description | |--------------------------|------------|---------------|----------------------------------------------| | `remover_batch_size` | `int` | `100` | Amount of objects to grab in a single batch. | -| `remover_sleep_interval` | `duration` | `1m` | Time to sleep between iterations. | +| `remover_sleep_interval` | `duration` | `1m` | Time to sleep between iterations. | ### `metabase` subsection @@ -271,7 +271,7 @@ writecache: | Parameter | Type | Default value | Description | |----------------------|------------|---------------|----------------------------------------------------------------------------------------------------------------------| | `path` | `string` | | Path to the metabase file. | -| `capacity` | `size` | unrestricted | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | +| `capacity` | `size` | unrestricted | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | | `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | | `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | | `workers_number` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | diff --git a/docs/update-go-instruction.md b/docs/update-go-instruction.md index f69643d3d5..f992250463 100644 --- a/docs/update-go-instruction.md +++ b/docs/update-go-instruction.md @@ -30,5 +30,5 @@ Update `GO_VERSION` variable in `./Makefile`. ## Apply language changes -Open PR that fixes/updates repository's code according to +Open PR that fixes/updates repository's code according to language improvements. diff --git a/pkg/local_object_storage/metabase/VERSION.md b/pkg/local_object_storage/metabase/VERSION.md index c9707c0072..97e514db1f 100644 --- a/pkg/local_object_storage/metabase/VERSION.md +++ b/pkg/local_object_storage/metabase/VERSION.md @@ -7,7 +7,7 @@ This file describes changes between the metabase versions. ### Primary buckets - Graveyard bucket - Name: `_Graveyard` - - Key: object address + - Key: object address - Value: tombstone address - Garbage bucket - Name: `_Garbage` @@ -23,7 +23,7 @@ This file describes changes between the metabase versions. - Key: container ID - Value: container size in bytes as little-endian uint64 - Bucket for storing locked objects information - - Name: `_Locked` + - Name: `_Locked` - Key: container ID - Value: bucket mapping objects locked to the list of corresponding LOCK objects - Bucket containing auxilliary information. All keys are custom and are not connected to the container @@ -102,4 +102,4 @@ This file describes changes between the metabase versions. - Container ID is encoded as base58 string - Object ID is encoded as base58 string -- Address is encoded as container ID + "/" + object ID \ No newline at end of file +- Address is encoded as container ID + "/" + object ID diff --git a/pkg/util/autocomplete/autocomplete.go b/pkg/util/autocomplete/autocomplete.go index 1343c30a32..8962447118 100644 --- a/pkg/util/autocomplete/autocomplete.go +++ b/pkg/util/autocomplete/autocomplete.go @@ -21,15 +21,15 @@ Zsh: If shell completion is not already enabled in your environment you will need to enable it. You can execute the following once: $ echo "autoload -U compinit; compinit" >> ~/.zshrc - + To load completions for each session, execute once: $ %s completion zsh > "${fpath[1]}/_%s" - + You will need to start a new shell for this setup to take effect. Fish: $ %s completion fish | source - + To load completions for each session, execute once: $ %s completion fish > ~/.config/fish/completions/%s.fish `