Compare commits
1 commit
master
...
feature/oc
Author | SHA1 | Date | |
---|---|---|---|
b53eade89e |
15 changed files with 59 additions and 236 deletions
|
@ -1,7 +1,10 @@
|
||||||
FROM golang:1.24-alpine AS basebuilder
|
FROM golang:1.24 AS builder
|
||||||
RUN apk add --update make bash ca-certificates
|
RUN apt-get update && \
|
||||||
|
apt-get install --no-install-recommends -y \
|
||||||
FROM basebuilder AS builder
|
bash \
|
||||||
|
ca-certificates \
|
||||||
|
&& \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
ENV GOGC=off
|
ENV GOGC=off
|
||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
ARG BUILD=now
|
ARG BUILD=now
|
||||||
|
@ -13,7 +16,7 @@ COPY . /src
|
||||||
RUN make
|
RUN make
|
||||||
|
|
||||||
# Executable image
|
# Executable image
|
||||||
FROM scratch
|
FROM debian:stable-slim
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
FROM alpine
|
FROM debian:stable-slim
|
||||||
RUN apk add --update --no-cache bash ca-certificates
|
RUN apt-get update && \
|
||||||
|
apt-get install --no-install-recommends -y \
|
||||||
|
bash \
|
||||||
|
ca-certificates \
|
||||||
|
&& \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler/middleware"
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
|
||||||
internalnet "git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/net"
|
internalnet "git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/net"
|
||||||
containerClient "git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/service/contracts/container"
|
|
||||||
contractsUtil "git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/service/contracts/util"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/service/frostfs"
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/service/frostfs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/templates"
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/templates"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/metrics"
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/metrics"
|
||||||
|
@ -41,7 +39,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/panjf2000/ants/v2"
|
"github.com/panjf2000/ants/v2"
|
||||||
|
@ -279,14 +276,6 @@ func (a *app) initContainers(ctx context.Context) {
|
||||||
a.corsCnrID = *corsCnrID
|
a.corsCnrID = *corsCnrID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *app) initRPCClient(ctx context.Context) *rpcclient.Client {
|
|
||||||
rpcCli, err := rpcclient.New(ctx, a.config().GetString(cfgRPCEndpoint), rpcclient.Options{})
|
|
||||||
if err != nil {
|
|
||||||
a.log.Fatal(logs.InitRPCClientFailed, zap.Error(err), logs.TagField(logs.TagApp))
|
|
||||||
}
|
|
||||||
return rpcCli
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *app) initAppSettings(lc *logLevelConfig) {
|
func (a *app) initAppSettings(lc *logLevelConfig) {
|
||||||
a.settings = &appSettings{
|
a.settings = &appSettings{
|
||||||
reconnectInterval: fetchReconnectInterval(a.config()),
|
reconnectInterval: fetchReconnectInterval(a.config()),
|
||||||
|
@ -761,22 +750,7 @@ func (a *app) stopServices() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *app) configureRouter(workerPool *ants.Pool) {
|
func (a *app) configureRouter(workerPool *ants.Pool) {
|
||||||
rpcCli := a.initRPCClient(a.ctx)
|
a.handle = handler.New(a.AppParams(), a.settings, tree.NewTree(frostfs.NewPoolWrapper(a.treePool), a.log), workerPool)
|
||||||
cnrContractName := a.config().GetString(cfgContractsContainerName)
|
|
||||||
rpcEndpoint := a.config().GetString(cfgRPCEndpoint)
|
|
||||||
cnrAddr, err := contractsUtil.ResolveContractHash(cnrContractName, rpcEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
a.log.Fatal(logs.FailedToResolveContractHash, zap.Error(err), logs.TagField(logs.TagApp))
|
|
||||||
}
|
|
||||||
cnrClient, err := containerClient.New(containerClient.Config{
|
|
||||||
ContractHash: cnrAddr,
|
|
||||||
Key: a.key,
|
|
||||||
RPCClient: rpcCli,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
a.log.Fatal(logs.InitContainerContractFailed, zap.Error(err), logs.TagField(logs.TagApp))
|
|
||||||
}
|
|
||||||
a.handle = handler.New(a.AppParams(), a.settings, tree.NewTree(frostfs.NewPoolWrapper(a.treePool), a.log), cnrClient, workerPool)
|
|
||||||
|
|
||||||
r := router.New()
|
r := router.New()
|
||||||
r.RedirectTrailingSlash = true
|
r.RedirectTrailingSlash = true
|
||||||
|
|
|
@ -62,8 +62,6 @@ const (
|
||||||
|
|
||||||
defaultMultinetFallbackDelay = 300 * time.Millisecond
|
defaultMultinetFallbackDelay = 300 * time.Millisecond
|
||||||
|
|
||||||
defaultContainerContractName = "container.frostfs"
|
|
||||||
|
|
||||||
cfgServer = "server"
|
cfgServer = "server"
|
||||||
cfgTLSEnabled = "tls.enabled"
|
cfgTLSEnabled = "tls.enabled"
|
||||||
cfgTLSCertFile = "tls.cert_file"
|
cfgTLSCertFile = "tls.cert_file"
|
||||||
|
@ -199,9 +197,6 @@ const (
|
||||||
cmdConfig = "config"
|
cmdConfig = "config"
|
||||||
cmdConfigDir = "config-dir"
|
cmdConfigDir = "config-dir"
|
||||||
cmdListenAddress = "listen_address"
|
cmdListenAddress = "listen_address"
|
||||||
|
|
||||||
// Contracts.
|
|
||||||
cfgContractsContainerName = "contracts.container.name"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ignore = map[string]struct{}{
|
var ignore = map[string]struct{}{
|
||||||
|
@ -406,9 +401,6 @@ func setDefaults(v *viper.Viper, flags *pflag.FlagSet) {
|
||||||
// multinet
|
// multinet
|
||||||
v.SetDefault(cfgMultinetFallbackDelay, defaultMultinetFallbackDelay)
|
v.SetDefault(cfgMultinetFallbackDelay, defaultMultinetFallbackDelay)
|
||||||
|
|
||||||
// contracts
|
|
||||||
v.SetDefault(cfgContractsContainerName, defaultContainerContractName)
|
|
||||||
|
|
||||||
if resolveMethods, err := flags.GetStringSlice(cfgResolveOrder); err == nil {
|
if resolveMethods, err := flags.GetStringSlice(cfgResolveOrder); err == nil {
|
||||||
v.SetDefault(cfgResolveOrder, resolveMethods)
|
v.SetDefault(cfgResolveOrder, resolveMethods)
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,3 @@ HTTP_GW_FEATURES_TREE_POOL_NETMAP_SUPPORT=true
|
||||||
|
|
||||||
# Containers properties
|
# Containers properties
|
||||||
HTTP_GW_CONTAINERS_CORS=AZjLTXfK4vs4ovxMic2xEJKSymMNLqdwq9JT64ASFCRj
|
HTTP_GW_CONTAINERS_CORS=AZjLTXfK4vs4ovxMic2xEJKSymMNLqdwq9JT64ASFCRj
|
||||||
|
|
||||||
# Container contract hash (LE) or name in NNS.
|
|
||||||
HTTP_GW_CONTRACTS_CONTAINER_NAME=container.frostfs
|
|
||||||
|
|
|
@ -199,8 +199,3 @@ features:
|
||||||
|
|
||||||
containers:
|
containers:
|
||||||
cors: AZjLTXfK4vs4ovxMic2xEJKSymMNLqdwq9JT64ASFCRj
|
cors: AZjLTXfK4vs4ovxMic2xEJKSymMNLqdwq9JT64ASFCRj
|
||||||
|
|
||||||
contracts:
|
|
||||||
container:
|
|
||||||
# Container contract hash (LE) or name in NNS.
|
|
||||||
name: container.frostfs
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ $ cat http.log
|
||||||
| `multinet` | [Multinet configuration](#multinet-section) |
|
| `multinet` | [Multinet configuration](#multinet-section) |
|
||||||
| `features` | [Features configuration](#features-section) |
|
| `features` | [Features configuration](#features-section) |
|
||||||
| `containers` | [Containers configuration](#containers-section) |
|
| `containers` | [Containers configuration](#containers-section) |
|
||||||
| `contracts` | [Contracts configuration](#contracts-section) |
|
|
||||||
|
|
||||||
# General section
|
# General section
|
||||||
|
|
||||||
|
@ -528,15 +527,3 @@ containers:
|
||||||
| Parameter | Type | SIGHUP reload | Default value | Description |
|
| Parameter | Type | SIGHUP reload | Default value | Description |
|
||||||
|-----------|----------|---------------|---------------|-----------------------------------------|
|
|-----------|----------|---------------|---------------|-----------------------------------------|
|
||||||
| `cors` | `string` | no | | Container name for CORS configurations. |
|
| `cors` | `string` | no | | Container name for CORS configurations. |
|
||||||
|
|
||||||
# `contracts` section
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
contracts:
|
|
||||||
container:
|
|
||||||
name: container.frostfs
|
|
||||||
```
|
|
||||||
|
|
||||||
| Parameter | Type | SIGHUP reload | Default value | Description |
|
|
||||||
|------------------|----------|---------------|---------------------|----------------------------------------------|
|
|
||||||
| `container.name` | `string` | no | `container.frostfs` | Container contract hash (LE) or name in NNS. |
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-http-gw
|
||||||
go 1.23
|
go 1.23
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
|
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241125133852-37bd75821121
|
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241125133852-37bd75821121
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe
|
git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250317082814-87bb55f992dc
|
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250317082814-87bb55f992dc
|
||||||
|
@ -34,6 +33,7 @@ require (
|
||||||
|
|
||||||
require (
|
require (
|
||||||
dario.cat/mergo v1.0.0 // indirect
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
|
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e // indirect
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect
|
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect
|
||||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1 // indirect
|
git.frostfs.info/TrueCloudLab/hrw v1.2.1 // indirect
|
||||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/data"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (h *Handler) containerInfo(ctx context.Context, cnrID cid.ID) (*data.BucketInfo, error) {
|
|
||||||
info := &data.BucketInfo{
|
|
||||||
CID: cnrID,
|
|
||||||
Name: cnrID.EncodeToString(),
|
|
||||||
}
|
|
||||||
res, err := h.cnrContract.GetContainerByID(cnrID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get frostfs container: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cnr := *res
|
|
||||||
|
|
||||||
if domain := container.ReadDomain(cnr); domain.Name() != "" {
|
|
||||||
info.Name = domain.Name()
|
|
||||||
info.Zone = domain.Zone()
|
|
||||||
}
|
|
||||||
info.HomomorphicHashDisabled = container.IsHomomorphicHashingDisabled(cnr)
|
|
||||||
info.PlacementPolicy = cnr.PlacementPolicy()
|
|
||||||
|
|
||||||
if err = h.cache.Put(info); err != nil {
|
|
||||||
h.reqLogger(ctx).Warn(logs.CouldntPutBucketIntoCache,
|
|
||||||
zap.String("bucket name", info.Name),
|
|
||||||
zap.Stringer("cid", info.CID),
|
|
||||||
zap.Error(err),
|
|
||||||
logs.TagField(logs.TagDatapath))
|
|
||||||
}
|
|
||||||
|
|
||||||
return info, nil
|
|
||||||
}
|
|
|
@ -233,16 +233,6 @@ func (t *TestFrostFS) SearchObjects(_ context.Context, prm PrmObjectSearch) (Res
|
||||||
return &resObjectSearchMock{res: res}, nil
|
return &resObjectSearchMock{res: res}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestFrostFS) GetContainerByID(cid cid.ID) (*container.Container, error) {
|
|
||||||
for k, v := range t.containers {
|
|
||||||
if k == cid.EncodeToString() {
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("container does not exist %s", cid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TestFrostFS) InitMultiObjectReader(context.Context, PrmInitMultiObjectReader) (io.Reader, error) {
|
func (t *TestFrostFS) InitMultiObjectReader(context.Context, PrmInitMultiObjectReader) (io.Reader, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,18 +167,12 @@ type ContainerResolver interface {
|
||||||
Resolve(ctx context.Context, zone, name string) (*cid.ID, error)
|
Resolve(ctx context.Context, zone, name string) (*cid.ID, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContainerContract interface {
|
|
||||||
// GetContainerByID reads a container from contract by ID.
|
|
||||||
GetContainerByID(cid.ID) (*container.Container, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
frostfs FrostFS
|
frostfs FrostFS
|
||||||
ownerID *user.ID
|
ownerID *user.ID
|
||||||
config Config
|
config Config
|
||||||
containerResolver ContainerResolver
|
containerResolver ContainerResolver
|
||||||
cnrContract ContainerContract
|
|
||||||
tree *tree.Tree
|
tree *tree.Tree
|
||||||
cache *cache.BucketCache
|
cache *cache.BucketCache
|
||||||
workerPool *ants.Pool
|
workerPool *ants.Pool
|
||||||
|
@ -196,7 +190,7 @@ type AppParams struct {
|
||||||
CORSCache *cache.CORSCache
|
CORSCache *cache.CORSCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(params *AppParams, config Config, tree *tree.Tree, rpcCli ContainerContract, workerPool *ants.Pool) *Handler {
|
func New(params *AppParams, config Config, tree *tree.Tree, workerPool *ants.Pool) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
log: params.Logger,
|
log: params.Logger,
|
||||||
frostfs: params.FrostFS,
|
frostfs: params.FrostFS,
|
||||||
|
@ -208,7 +202,6 @@ func New(params *AppParams, config Config, tree *tree.Tree, rpcCli ContainerCont
|
||||||
workerPool: workerPool,
|
workerPool: workerPool,
|
||||||
corsCnrID: params.CORSCnrID,
|
corsCnrID: params.CORSCnrID,
|
||||||
corsCache: params.CORSCache,
|
corsCache: params.CORSCache,
|
||||||
cnrContract: rpcCli,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +308,43 @@ func (h *Handler) getBucketInfo(ctx context.Context, containerName string) (*dat
|
||||||
return nil, fmt.Errorf("resolve container: %w", err)
|
return nil, fmt.Errorf("resolve container: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return h.containerInfo(ctx, *cnrID)
|
bktInfo, err := h.readContainer(ctx, *cnrID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read container: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = h.cache.Put(bktInfo); err != nil {
|
||||||
|
h.reqLogger(ctx).Warn(logs.CouldntPutBucketIntoCache,
|
||||||
|
zap.String("bucket name", bktInfo.Name),
|
||||||
|
zap.Stringer("bucket cid", bktInfo.CID),
|
||||||
|
zap.Error(err),
|
||||||
|
logs.TagField(logs.TagDatapath))
|
||||||
|
}
|
||||||
|
|
||||||
|
return bktInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) readContainer(ctx context.Context, cnrID cid.ID) (*data.BucketInfo, error) {
|
||||||
|
prm := PrmContainer{ContainerID: cnrID}
|
||||||
|
res, err := h.frostfs.Container(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get frostfs container '%s': %w", cnrID.String(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bktInfo := &data.BucketInfo{
|
||||||
|
CID: cnrID,
|
||||||
|
Name: cnrID.EncodeToString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if domain := container.ReadDomain(*res); domain.Name() != "" {
|
||||||
|
bktInfo.Name = domain.Name()
|
||||||
|
bktInfo.Zone = domain.Zone()
|
||||||
|
}
|
||||||
|
|
||||||
|
bktInfo.HomomorphicHashDisabled = container.IsHomomorphicHashingDisabled(*res)
|
||||||
|
bktInfo.PlacementPolicy = res.PlacementPolicy()
|
||||||
|
|
||||||
|
return bktInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListFunc func(ctx context.Context, bucketInfo *data.BucketInfo, prefix string) (*GetObjectsResponse, error)
|
type ListFunc func(ctx context.Context, bucketInfo *data.BucketInfo, prefix string) (*GetObjectsResponse, error)
|
||||||
|
|
|
@ -156,7 +156,7 @@ func prepareHandlerContextBase(logger *zap.Logger) (*handlerContext, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
handler := New(params, cfgMock, tree.NewTree(treeMock, logger), testFrostFS, workerPool)
|
handler := New(params, cfgMock, tree.NewTree(treeMock, logger), workerPool)
|
||||||
|
|
||||||
return &handlerContext{
|
return &handlerContext{
|
||||||
key: key,
|
key: key,
|
||||||
|
|
|
@ -73,9 +73,6 @@ const (
|
||||||
FailedToReadIndexPageTemplate = "failed to read index page template"
|
FailedToReadIndexPageTemplate = "failed to read index page template"
|
||||||
SetCustomIndexPageTemplate = "set custom index page template"
|
SetCustomIndexPageTemplate = "set custom index page template"
|
||||||
CouldNotFetchCORSContainerInfo = "couldn't fetch CORS container info"
|
CouldNotFetchCORSContainerInfo = "couldn't fetch CORS container info"
|
||||||
InitRPCClientFailed = "init rpc client faileds"
|
|
||||||
InitContainerContractFailed = "init container contract failed"
|
|
||||||
FailedToResolveContractHash = "failed to resolve contract hash"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log messages with the "datapath" tag.
|
// Log messages with the "datapath" tag.
|
||||||
|
@ -110,7 +107,9 @@ const (
|
||||||
IteratingOverSelectedObjectsFailed = "iterating over selected objects failed"
|
IteratingOverSelectedObjectsFailed = "iterating over selected objects failed"
|
||||||
FailedToGetBucketInfo = "could not get bucket info"
|
FailedToGetBucketInfo = "could not get bucket info"
|
||||||
FailedToSubmitTaskToPool = "failed to submit task to pool"
|
FailedToSubmitTaskToPool = "failed to submit task to pool"
|
||||||
|
ObjectWasDeleted = "object was deleted"
|
||||||
IndexWasDeleted = "index was deleted"
|
IndexWasDeleted = "index was deleted"
|
||||||
|
FailedToGetLatestVersionOfObject = "failed to get latest version of object"
|
||||||
FailedToGetLatestVersionOfIndexObject = "failed to get latest version of index object"
|
FailedToGetLatestVersionOfIndexObject = "failed to get latest version of index object"
|
||||||
FailedToCheckIfSettingsNodeExist = "failed to check if settings node exists"
|
FailedToCheckIfSettingsNodeExist = "failed to check if settings node exists"
|
||||||
FailedToListObjects = "failed to list objects"
|
FailedToListObjects = "failed to list objects"
|
||||||
|
@ -122,6 +121,7 @@ const (
|
||||||
FailedToGetObjectPayload = "failed to get object payload"
|
FailedToGetObjectPayload = "failed to get object payload"
|
||||||
FailedToFindObjectByAttribute = "failed to get find object by attribute"
|
FailedToFindObjectByAttribute = "failed to get find object by attribute"
|
||||||
FailedToUnescapePath = "failed to unescape path"
|
FailedToUnescapePath = "failed to unescape path"
|
||||||
|
InvalidOIDParam = "invalid oid param"
|
||||||
CouldNotGetCORSConfiguration = "could not get cors configuration"
|
CouldNotGetCORSConfiguration = "could not get cors configuration"
|
||||||
EmptyOriginRequestHeader = "empty Origin request header"
|
EmptyOriginRequestHeader = "empty Origin request header"
|
||||||
EmptyAccessControlRequestMethodHeader = "empty Access-Control-Request-Method request header"
|
EmptyAccessControlRequestMethodHeader = "empty Access-Control-Request-Method request header"
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
containercontract "git.frostfs.info/TrueCloudLab/frostfs-contract/container"
|
|
||||||
containerclient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
contract *containerclient.Contract
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
ContractHash util.Uint160
|
|
||||||
Key *keys.PrivateKey
|
|
||||||
RPCClient *rpcclient.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(cfg Config) (*Client, error) {
|
|
||||||
var err error
|
|
||||||
key := cfg.Key
|
|
||||||
if key == nil {
|
|
||||||
if key, err = keys.NewPrivateKey(); err != nil {
|
|
||||||
return nil, fmt.Errorf("generate anon private key for container contract: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acc := wallet.NewAccountFromPrivateKey(key)
|
|
||||||
|
|
||||||
act, err := actor.NewSimple(cfg.RPCClient, acc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("create new actor: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
contract: containerclient.New(act, cfg.ContractHash),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetContainerByID(cnrID cid.ID) (*container.Container, error) {
|
|
||||||
items, err := c.contract.Get(cnrID[:])
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), containercontract.NotFoundError) {
|
|
||||||
return nil, fmt.Errorf("%w: %s", handler.ErrContainerNotFound, err)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(items) != 4 {
|
|
||||||
return nil, fmt.Errorf("unexpected container stack item count: %d", len(items))
|
|
||||||
}
|
|
||||||
|
|
||||||
cnrBytes, err := items[0].TryBytes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get byte array of container: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var cnr container.Container
|
|
||||||
if err = cnr.Unmarshal(cnrBytes); err != nil {
|
|
||||||
return nil, fmt.Errorf("can't unmarshal container: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cnr, nil
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package util
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ns"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ResolveContractHash determine contract hash by resolving NNS name.
|
|
||||||
func ResolveContractHash(contractHash, rpcAddress string) (util.Uint160, error) {
|
|
||||||
if hash, err := util.Uint160DecodeStringLE(contractHash); err == nil {
|
|
||||||
return hash, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
splitName := strings.Split(contractHash, ".")
|
|
||||||
if len(splitName) != 2 {
|
|
||||||
return util.Uint160{}, fmt.Errorf("invalid contract name: '%s'", contractHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
var domain container.Domain
|
|
||||||
domain.SetName(splitName[0])
|
|
||||||
domain.SetZone(splitName[1])
|
|
||||||
|
|
||||||
var nns ns.NNS
|
|
||||||
if err := nns.Dial(rpcAddress); err != nil {
|
|
||||||
return util.Uint160{}, fmt.Errorf("dial nns %s: %w", rpcAddress, err)
|
|
||||||
}
|
|
||||||
defer nns.Close()
|
|
||||||
|
|
||||||
return nns.ResolveContractHash(domain)
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue