WIP: Billing service #1198
24 changed files with 2632 additions and 13 deletions
61
cmd/frostfs-node/billing.go
Normal file
61
cmd/frostfs-node/billing.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
billingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/billing"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/billing"
|
||||||
|
billingSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/billing/server"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceNameBilling = "billing"
|
||||||
|
|
||||||
|
func initBillingService(c *cfg) {
|
||||||
|
endpoint := billingconfig.GRPC(c.appCfg).Endpoint()
|
||||||
|
if endpoint == billingconfig.GRPCEndpointDefault {
|
||||||
|
c.log.Info(logs.FrostFSNodeBillingServiceDisabled)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pubs := billingconfig.AuthorizedKeys(c.appCfg)
|
||||||
|
rawPubs := make([][]byte, 0, len(pubs)+1)
|
||||||
|
rawPubs = append(rawPubs, c.key.PublicKey().Bytes())
|
||||||
|
|
||||||
|
for i := range pubs {
|
||||||
|
rawPubs = append(rawPubs, pubs[i].Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
billingSvc := billingSvc.New(
|
||||||
|
&c.key.PrivateKey,
|
||||||
|
rawPubs,
|
||||||
|
c.cfgObject.cnrSource,
|
||||||
|
c.cfgObject.cfgLocalStorage.localStorage,
|
||||||
|
)
|
||||||
|
|
||||||
|
lis, err := net.Listen("tcp", endpoint)
|
||||||
|
if err != nil {
|
||||||
|
c.log.Error(logs.FrostFSNodeCantListenGRPCEndpointBilling, zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.cfgBillingService.server = grpc.NewServer()
|
||||||
|
|
||||||
|
c.onShutdown(func() {
|
||||||
|
stopGRPC("FrostFS Billing API", c.cfgBillingService.server, c.log)
|
||||||
|
})
|
||||||
|
|
||||||
|
billing.RegisterBillingServiceServer(c.cfgBillingService.server, billingSvc)
|
||||||
|
|
||||||
|
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
|
||||||
|
runAndLog(ctx, c, serviceNameBilling, false, func(context.Context, *cfg) {
|
||||||
|
c.log.Info(logs.FrostFSNodeStartListeningEndpoint,
|
||||||
|
zap.String("service", serviceNameBilling),
|
||||||
|
zap.String("endpoint", endpoint))
|
||||||
|
fatalOnErr(c.cfgBillingService.server.Serve(lis))
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
|
@ -476,6 +476,7 @@ type cfg struct {
|
||||||
cfgNetmap cfgNetmap
|
cfgNetmap cfgNetmap
|
||||||
cfgControlService cfgControlService
|
cfgControlService cfgControlService
|
||||||
cfgObject cfgObject
|
cfgObject cfgObject
|
||||||
|
cfgBillingService cfgBillingService
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadCurrentNetMap reads network map which has been cached at the
|
// ReadCurrentNetMap reads network map which has been cached at the
|
||||||
|
@ -656,6 +657,10 @@ type cfgControlService struct {
|
||||||
server *grpc.Server
|
server *grpc.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cfgBillingService struct {
|
||||||
|
server *grpc.Server
|
||||||
|
}
|
||||||
|
|
||||||
var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
|
var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block")
|
||||||
|
|
||||||
func initCfg(appCfg *config.Config) *cfg {
|
func initCfg(appCfg *config.Config) *cfg {
|
||||||
|
|
58
cmd/frostfs-node/config/billing/config.go
Normal file
58
cmd/frostfs-node/config/billing/config.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package billing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GRPCConfig struct {
|
||||||
|
cfg *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
subsection = "billing"
|
||||||
|
grpcSubsection = "grpc"
|
||||||
|
|
||||||
|
// GRPCEndpointDefault is a default endpoint of gRPC Billing service.
|
||||||
|
GRPCEndpointDefault = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthorizedKeys parses and returns an array of "authorized_keys" config
|
||||||
|
// parameter from "control" section.
|
||||||
|
//
|
||||||
|
// Returns an empty list if not set.
|
||||||
|
func AuthorizedKeys(c *config.Config) keys.PublicKeys {
|
||||||
|
strKeys := config.StringSliceSafe(c.Sub(subsection), "authorized_keys")
|
||||||
|
pubs := make(keys.PublicKeys, 0, len(strKeys))
|
||||||
|
|
||||||
|
for i := range strKeys {
|
||||||
|
pub, err := keys.NewPublicKeyFromString(strKeys[i])
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("invalid permitted key for Billing service %s: %w", strKeys[i], err))
|
||||||
|
}
|
||||||
|
|
||||||
|
pubs = append(pubs, pub)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pubs
|
||||||
|
}
|
||||||
|
|
||||||
|
func GRPC(c *config.Config) GRPCConfig {
|
||||||
|
return GRPCConfig{
|
||||||
|
c.Sub(subsection).Sub(grpcSubsection),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoint returns the value of "endpoint" config parameter.
|
||||||
|
//
|
||||||
|
// Returns GRPCEndpointDefault if the value is not a non-empty string.
|
||||||
|
func (g GRPCConfig) Endpoint() string {
|
||||||
|
v := config.String(g.cfg, "endpoint")
|
||||||
|
if v != "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRPCEndpointDefault
|
||||||
|
}
|
37
cmd/frostfs-node/config/billing/config_test.go
Normal file
37
cmd/frostfs-node/config/billing/config_test.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package billing_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
billingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/billing"
|
||||||
|
configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBillingSection(t *testing.T) {
|
||||||
|
t.Run("defaults", func(t *testing.T) {
|
||||||
|
empty := configtest.EmptyConfig()
|
||||||
|
|
||||||
|
require.Empty(t, billingconfig.AuthorizedKeys(empty))
|
||||||
|
require.Equal(t, billingconfig.GRPCEndpointDefault, billingconfig.GRPC(empty).Endpoint())
|
||||||
|
})
|
||||||
|
|
||||||
|
const path = "../../../../config/example/node"
|
||||||
|
|
||||||
|
pubs := make(keys.PublicKeys, 2)
|
||||||
|
pubs[0], _ = keys.NewPublicKeyFromString("035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11")
|
||||||
|
pubs[1], _ = keys.NewPublicKeyFromString("028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6")
|
||||||
|
|
||||||
|
fileConfigTest := func(c *config.Config) {
|
||||||
|
require.Equal(t, pubs, billingconfig.AuthorizedKeys(c))
|
||||||
|
require.Equal(t, "localhost:8092", billingconfig.GRPC(c).Endpoint())
|
||||||
|
}
|
||||||
|
|
||||||
|
configtest.ForEachFileType(path, fileConfigTest)
|
||||||
|
|
||||||
|
t.Run("ENV", func(t *testing.T) {
|
||||||
|
configtest.ForEnvFileType(t, path, fileConfigTest)
|
||||||
|
})
|
||||||
|
}
|
|
@ -115,6 +115,7 @@ func initApp(ctx context.Context, c *cfg) {
|
||||||
initAndLog(c, "tree", initTreeService)
|
initAndLog(c, "tree", initTreeService)
|
||||||
initAndLog(c, "apemanager", initAPEManagerService)
|
initAndLog(c, "apemanager", initAPEManagerService)
|
||||||
initAndLog(c, "control", initControlService)
|
initAndLog(c, "control", initControlService)
|
||||||
|
initAndLog(c, "billing", initBillingService)
|
||||||
|
|
||||||
initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) })
|
initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) })
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,10 @@ FROSTFS_GRPC_1_TLS_ENABLED=false
|
||||||
FROSTFS_CONTROL_AUTHORIZED_KEYS="035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6"
|
FROSTFS_CONTROL_AUTHORIZED_KEYS="035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6"
|
||||||
FROSTFS_CONTROL_GRPC_ENDPOINT=localhost:8090
|
FROSTFS_CONTROL_GRPC_ENDPOINT=localhost:8090
|
||||||
|
|
||||||
|
# Billing service section
|
||||||
|
FROSTFS_BILLING_AUTHORIZED_KEYS="035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6"
|
||||||
|
FROSTFS_BILLING_GRPC_ENDPOINT=localhost:8092
|
||||||
|
|
||||||
# Contracts section
|
# Contracts section
|
||||||
FROSTFS_CONTRACTS_BALANCE=5263abba1abedbf79bb57f3e40b50b4425d2d6cd
|
FROSTFS_CONTRACTS_BALANCE=5263abba1abedbf79bb57f3e40b50b4425d2d6cd
|
||||||
FROSTFS_CONTRACTS_CONTAINER=5d084790d7aa36cea7b53fe897380dab11d2cd3c
|
FROSTFS_CONTRACTS_CONTAINER=5d084790d7aa36cea7b53fe897380dab11d2cd3c
|
||||||
|
|
|
@ -82,6 +82,15 @@
|
||||||
"endpoint": "localhost:8090"
|
"endpoint": "localhost:8090"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"billing": {
|
||||||
|
"authorized_keys": [
|
||||||
|
"035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11",
|
||||||
|
"028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6"
|
||||||
|
],
|
||||||
|
"grpc": {
|
||||||
|
"endpoint": "localhost:8092"
|
||||||
|
}
|
||||||
|
},
|
||||||
"contracts": {
|
"contracts": {
|
||||||
"balance": "5263abba1abedbf79bb57f3e40b50b4425d2d6cd",
|
"balance": "5263abba1abedbf79bb57f3e40b50b4425d2d6cd",
|
||||||
"container": "5d084790d7aa36cea7b53fe897380dab11d2cd3c",
|
"container": "5d084790d7aa36cea7b53fe897380dab11d2cd3c",
|
||||||
|
|
|
@ -69,6 +69,13 @@ control:
|
||||||
grpc:
|
grpc:
|
||||||
endpoint: localhost:8090 # endpoint that is listened by the Control Service
|
endpoint: localhost:8090 # endpoint that is listened by the Control Service
|
||||||
|
|
||||||
|
billing:
|
||||||
|
authorized_keys: # list of hex-encoded public keys that have rights to use the Billing Service
|
||||||
|
- 035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11
|
||||||
|
- 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6
|
||||||
|
grpc:
|
||||||
|
endpoint: localhost:8092 # endpoint that is listened by the Billing Service
|
||||||
|
|
||||||
contracts: # side chain NEOFS contract script hashes; optional, override values retrieved from NNS contract
|
contracts: # side chain NEOFS contract script hashes; optional, override values retrieved from NNS contract
|
||||||
balance: 5263abba1abedbf79bb57f3e40b50b4425d2d6cd
|
balance: 5263abba1abedbf79bb57f3e40b50b4425d2d6cd
|
||||||
container: 5d084790d7aa36cea7b53fe897380dab11d2cd3c
|
container: 5d084790d7aa36cea7b53fe897380dab11d2cd3c
|
||||||
|
|
|
@ -49,6 +49,8 @@
|
||||||
"FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8080",
|
"FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8080",
|
||||||
"FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8081",
|
"FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8081",
|
||||||
"FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a",
|
"FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a",
|
||||||
|
"FROSTFS_BILLING_GRPC_ENDPOINT":"127.0.0.1:8082",
|
||||||
|
"FROSTFS_BILLING_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a",
|
||||||
"FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev",
|
"FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev",
|
||||||
"FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW",
|
"FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW",
|
||||||
"FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-node-s1-state",
|
"FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-node-s1-state",
|
||||||
|
|
|
@ -18,6 +18,7 @@ There are some custom types used for brevity:
|
||||||
| `pprof` | [PProf configuration](#pprof-section) |
|
| `pprof` | [PProf configuration](#pprof-section) |
|
||||||
| `prometheus` | [Prometheus metrics configuration](#prometheus-section) |
|
| `prometheus` | [Prometheus metrics configuration](#prometheus-section) |
|
||||||
| `control` | [Control service configuration](#control-section) |
|
| `control` | [Control service configuration](#control-section) |
|
||||||
|
| `billing` | [Billing service configuration](#billing-section) |
|
||||||
| `contracts` | [Override FrostFS contracts hashes](#contracts-section) |
|
| `contracts` | [Override FrostFS contracts hashes](#contracts-section) |
|
||||||
| `morph` | [N3 blockchain client configuration](#morph-section) |
|
| `morph` | [N3 blockchain client configuration](#morph-section) |
|
||||||
| `apiclient` | [FrostFS API client configuration](#apiclient-section) |
|
| `apiclient` | [FrostFS API client configuration](#apiclient-section) |
|
||||||
|
@ -42,6 +43,20 @@ control:
|
||||||
| `authorized_keys` | `[]public key` | empty | List of public keys which are used to authorize requests to the control service. |
|
| `authorized_keys` | `[]public key` | empty | List of public keys which are used to authorize requests to the control service. |
|
||||||
| `grpc.endpoint` | `string` | empty | Address that control service listener binds to. |
|
| `grpc.endpoint` | `string` | empty | Address that control service listener binds to. |
|
||||||
|
|
||||||
|
# `billing` section
|
||||||
|
```yaml
|
||||||
|
billing:
|
||||||
|
authorized_keys:
|
||||||
|
- 035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11
|
||||||
|
- 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6
|
||||||
|
grpc:
|
||||||
|
endpoint: 127.0.0.1:8092
|
||||||
|
```
|
||||||
|
| Parameter | Type | Default value | Description |
|
||||||
|
|-------------------|----------------|---------------|----------------------------------------------------------------------------------|
|
||||||
|
| `authorized_keys` | `[]public key` | empty | List of public keys which are used to authorize requests to the billing service. |
|
||||||
|
| `grpc.endpoint` | `string` | empty | Address that billing service listener binds to. |
|
||||||
|
|
||||||
# `grpc` section
|
# `grpc` section
|
||||||
```yaml
|
```yaml
|
||||||
grpc:
|
grpc:
|
||||||
|
|
|
@ -443,6 +443,8 @@ const (
|
||||||
FrostFSNodeRemovingAllTreesForContainer = "removing all trees for container"
|
FrostFSNodeRemovingAllTreesForContainer = "removing all trees for container"
|
||||||
FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved = "container removal event received, but trees weren't removed"
|
FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved = "container removal event received, but trees weren't removed"
|
||||||
FrostFSNodeCantListenGRPCEndpointControl = "can't listen gRPC endpoint (control)"
|
FrostFSNodeCantListenGRPCEndpointControl = "can't listen gRPC endpoint (control)"
|
||||||
|
FrostFSNodeCantListenGRPCEndpointBilling = "can't listen gRPC endpoint (billing)"
|
||||||
|
FrostFSNodeBillingServiceDisabled = "billing service is disabled"
|
||||||
FrostFSNodePolicerIsDisabled = "policer is disabled"
|
FrostFSNodePolicerIsDisabled = "policer is disabled"
|
||||||
CommonApplicationStarted = "application started"
|
CommonApplicationStarted = "application started"
|
||||||
ShardGCCollectingExpiredObjectsStarted = "collecting expired objects started"
|
ShardGCCollectingExpiredObjectsStarted = "collecting expired objects started"
|
||||||
|
|
167
pkg/local_object_storage/engine/container_stat.go
Normal file
167
pkg/local_object_storage/engine/container_stat.go
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
package engine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContainerStatPrm struct {
|
||||||
|
ContainerID []cid.ID
|
||||||
|
|
||||||
|
Limit uint32
|
||||||
|
StartFromContainerID *cid.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerStatRes struct {
|
||||||
|
ContainerStats []ContainerStat
|
||||||
|
Partial bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerStat struct {
|
||||||
|
ContainerID cid.ID
|
||||||
|
SizeLogic uint64
|
||||||
|
CountPhy, CountLogic, CountUser uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
var errInvalidLimit = errors.New("limit must be greater than zero")
|
||||||
|
|
||||||
|
func (e *StorageEngine) ContainerStat(ctx context.Context, prm ContainerStatPrm) (*ContainerStatRes, error) {
|
||||||
|
if e.metrics != nil {
|
||||||
|
defer elapsed("ContainerStat", e.metrics.AddMethodDuration)()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.ContainerStat",
|
||||||
|
trace.WithAttributes(
|
||||||
|
attribute.Int("container_ids", len(prm.ContainerID)),
|
||||||
|
attribute.Int64("limit", int64(prm.Limit)),
|
||||||
|
attribute.Bool("start_from_container_id", prm.StartFromContainerID != nil),
|
||||||
|
))
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
if len(prm.ContainerID) == 0 && prm.Limit == 0 {
|
||||||
|
return nil, errInvalidLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
var result *ContainerStatRes
|
||||||
|
err := e.execIfNotBlocked(func() error {
|
||||||
|
var sErr error
|
||||||
|
result, sErr = e.containerStat(ctx, prm)
|
||||||
|
return sErr
|
||||||
|
})
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *StorageEngine) containerStat(ctx context.Context, prm ContainerStatPrm) (*ContainerStatRes, error) {
|
||||||
|
e.mtx.RLock()
|
||||||
|
defer e.mtx.RUnlock()
|
||||||
|
|
||||||
|
if len(prm.ContainerID) > 0 {
|
||||||
|
sort.Slice(prm.ContainerID, func(i, j int) bool {
|
||||||
|
return bytes.Compare(prm.ContainerID[i][:], prm.ContainerID[j][:]) < 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
shardResults, partial, err := e.collectShardContainerStats(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ContainerStatRes{
|
||||||
|
ContainerStats: e.mergeShardContainerStats(shardResults, int(prm.Limit)),
|
||||||
|
Partial: partial,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *StorageEngine) collectShardContainerStats(ctx context.Context, prm ContainerStatPrm) ([][]shard.ContainerStat, bool, error) {
|
||||||
|
if len(prm.ContainerID) > 0 {
|
||||||
|
sort.Slice(prm.ContainerID, func(i, j int) bool {
|
||||||
|
return bytes.Compare(prm.ContainerID[i][:], prm.ContainerID[j][:]) < 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var shardResults [][]shard.ContainerStat
|
||||||
|
var shardErrors []error
|
||||||
|
var resultsGuard sync.Mutex
|
||||||
|
|
||||||
|
shPrm := shard.ContainerStatPrm{
|
||||||
|
ContainerID: prm.ContainerID,
|
||||||
|
Limit: prm.Limit,
|
||||||
|
StartFromContainerID: prm.StartFromContainerID,
|
||||||
|
}
|
||||||
|
|
||||||
|
eg, egCtx := errgroup.WithContext(ctx)
|
||||||
|
var shardsCount int
|
||||||
|
e.iterateOverUnsortedShards(func(hs hashedShard) (stop bool) {
|
||||||
|
shardsCount++
|
||||||
|
eg.Go(func() error {
|
||||||
|
s, err := hs.ContainerStat(egCtx, shPrm)
|
||||||
|
resultsGuard.Lock()
|
||||||
|
defer resultsGuard.Unlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
shardErrors = append(shardErrors, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s) > 0 {
|
||||||
|
shardResults = append(shardResults, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if err := eg.Wait(); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
if shardsCount == len(shardErrors) {
|
||||||
|
return nil, false, errors.Join(shardErrors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return shardResults, len(shardErrors) > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *StorageEngine) mergeShardContainerStats(shardResults [][]shard.ContainerStat, limit int) []ContainerStat {
|
||||||
|
var stats []ContainerStat
|
||||||
|
for len(stats) <= limit && len(shardResults) > 0 {
|
||||||
|
// shard results are sorted by container ID
|
||||||
|
sort.Slice(shardResults, func(i, j int) bool {
|
||||||
|
return bytes.Compare(shardResults[i][0].ContainerID[:], shardResults[j][0].ContainerID[:]) < 0
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(stats) > 0 && stats[len(stats)-1].ContainerID == shardResults[0][0].ContainerID {
|
||||||
|
stats[len(stats)-1].SizeLogic += shardResults[0][0].SizeLogic
|
||||||
|
stats[len(stats)-1].CountPhy += shardResults[0][0].CountPhy
|
||||||
|
stats[len(stats)-1].CountLogic += shardResults[0][0].CountLogic
|
||||||
|
stats[len(stats)-1].CountUser += shardResults[0][0].CountUser
|
||||||
|
} else {
|
||||||
|
stats = append(stats, ContainerStat{
|
||||||
|
ContainerID: shardResults[0][0].ContainerID,
|
||||||
|
SizeLogic: shardResults[0][0].SizeLogic,
|
||||||
|
CountPhy: shardResults[0][0].CountPhy,
|
||||||
|
CountLogic: shardResults[0][0].CountLogic,
|
||||||
|
CountUser: shardResults[0][0].CountUser,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(shardResults[0]) == 1 { // last item for shard
|
||||||
|
shardResults = shardResults[1:]
|
||||||
|
} else {
|
||||||
|
shardResults[0] = shardResults[0][1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(stats) > limit {
|
||||||
|
stats = stats[:limit]
|
||||||
|
}
|
||||||
|
return stats
|
||||||
|
}
|
221
pkg/local_object_storage/engine/container_stat_test.go
Normal file
221
pkg/local_object_storage/engine/container_stat_test.go
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
package engine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||||
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestContainerList(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
s1 := testNewShard(t)
|
||||||
|
s2 := testNewShard(t)
|
||||||
|
s3 := testNewShard(t)
|
||||||
|
|
||||||
|
e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine
|
||||||
|
e.log = test.NewLogger(t)
|
||||||
|
defer e.Close(context.Background())
|
||||||
|
|
||||||
|
const containerCount = 10
|
||||||
|
expStat := testPutComplexObject(t, []*shard.Shard{s1, s2, s3}, containerCount, nil)
|
||||||
|
expStat = testPutSimpleObject(t, []*shard.Shard{s1, s2, s3}, containerCount, expStat)
|
||||||
|
expStat = testPutSimpleObject(t, []*shard.Shard{s1, s2}, containerCount, expStat)
|
||||||
|
expStat = testPutSimpleObject(t, []*shard.Shard{s2, s3}, containerCount, expStat)
|
||||||
|
expStat = testPutSimpleObject(t, []*shard.Shard{s1}, containerCount, expStat)
|
||||||
|
expStat = testPutSimpleObject(t, []*shard.Shard{s2}, containerCount, expStat)
|
||||||
|
expStat = testPutSimpleObject(t, []*shard.Shard{s3}, containerCount, expStat)
|
||||||
|
|
||||||
|
t.Run("with default limit", func(t *testing.T) {
|
||||||
|
var prm ContainerStatPrm
|
||||||
|
prm.Limit = 10_000
|
||||||
|
res, err := e.ContainerStat(context.Background(), prm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, res)
|
||||||
|
require.ElementsMatch(t, expStat, res.ContainerStats)
|
||||||
|
require.False(t, res.Partial)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with limit, batched", func(t *testing.T) {
|
||||||
|
var prm ContainerStatPrm
|
||||||
|
prm.Limit = 1
|
||||||
|
var stats []ContainerStat
|
||||||
|
|
||||||
|
for {
|
||||||
|
res, err := e.ContainerStat(context.Background(), prm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, res)
|
||||||
|
require.False(t, res.Partial)
|
||||||
|
if len(res.ContainerStats) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
stats = append(stats, res.ContainerStats...)
|
||||||
|
last := res.ContainerStats[len(res.ContainerStats)-1].ContainerID
|
||||||
|
prm.StartFromContainerID = &last
|
||||||
|
prm.Limit += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
require.ElementsMatch(t, expStat, stats)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("by container id", func(t *testing.T) {
|
||||||
|
for _, cc := range []int{1, 2, 3, 4, 5} {
|
||||||
|
var prm ContainerStatPrm
|
||||||
|
for idx := 0; idx+cc < len(expStat); idx += cc {
|
||||||
|
prm.ContainerID = nil
|
||||||
|
for i := 0; i < cc; i++ {
|
||||||
|
prm.ContainerID = append(prm.ContainerID, expStat[idx+i].ContainerID)
|
||||||
|
}
|
||||||
|
prm.Limit = uint32(len(prm.ContainerID))
|
||||||
|
res, err := e.ContainerStat(context.Background(), prm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, res)
|
||||||
|
require.False(t, res.Partial)
|
||||||
|
require.ElementsMatch(t, expStat[idx:idx+cc], res.ContainerStats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unknown container id", func(t *testing.T) {
|
||||||
|
var prm ContainerStatPrm
|
||||||
|
prm.ContainerID = append(prm.ContainerID, cidtest.ID())
|
||||||
|
prm.Limit = uint32(len(prm.ContainerID))
|
||||||
|
res, err := e.ContainerStat(context.Background(), prm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, res)
|
||||||
|
require.False(t, res.Partial)
|
||||||
|
require.ElementsMatch(t, []ContainerStat{{ContainerID: prm.ContainerID[0]}}, res.ContainerStats)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("degraded shard", func(t *testing.T) {
|
||||||
|
s1.SetMode(mode.Degraded)
|
||||||
|
var prm ContainerStatPrm
|
||||||
|
prm.Limit = 10_000
|
||||||
|
res, err := e.ContainerStat(context.Background(), prm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, res)
|
||||||
|
require.True(t, res.Partial)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPutComplexObject(t *testing.T, shards []*shard.Shard, count int, stats []ContainerStat) []ContainerStat {
|
||||||
|
const payloadSize = 10 * 1024
|
||||||
|
for count > 0 {
|
||||||
|
var cnr cid.ID
|
||||||
|
var stat *ContainerStat
|
||||||
|
var newStat bool
|
||||||
|
if len(stats) == 0 || count%2 == 0 {
|
||||||
|
cnr = cidtest.ID()
|
||||||
|
stat = &ContainerStat{ContainerID: cnr}
|
||||||
|
newStat = true
|
||||||
|
} else {
|
||||||
|
cnr = stats[count%len(stats)].ContainerID
|
||||||
|
stat = &stats[count%len(stats)]
|
||||||
|
}
|
||||||
|
|
||||||
|
parentID := oidtest.ID()
|
||||||
|
splitID := objectSDK.NewSplitID()
|
||||||
|
|
||||||
|
parent := testutil.GenerateObjectWithCID(cnr)
|
||||||
|
parent.SetID(parentID)
|
||||||
|
parent.SetPayload(nil)
|
||||||
|
|
||||||
|
const childCount = 10
|
||||||
|
children := make([]*objectSDK.Object, childCount)
|
||||||
|
childIDs := make([]oid.ID, childCount)
|
||||||
|
for i := range children {
|
||||||
|
children[i] = testutil.GenerateObjectWithCID(cnr)
|
||||||
|
if i != 0 {
|
||||||
|
children[i].SetPreviousID(childIDs[i-1])
|
||||||
|
}
|
||||||
|
if i == len(children)-1 {
|
||||||
|
children[i].SetParent(parent)
|
||||||
|
}
|
||||||
|
children[i].SetSplitID(splitID)
|
||||||
|
children[i].SetPayload(make([]byte, payloadSize))
|
||||||
|
children[i].SetPayloadSize(payloadSize)
|
||||||
|
childIDs[i], _ = children[i].ID()
|
||||||
|
|
||||||
|
stat.SizeLogic += payloadSize
|
||||||
|
stat.CountLogic += 1
|
||||||
|
stat.CountPhy += 1
|
||||||
|
}
|
||||||
|
stat.CountUser += 1
|
||||||
|
|
||||||
|
link := testutil.GenerateObjectWithCID(cnr)
|
||||||
|
link.SetParent(parent)
|
||||||
|
link.SetParentID(parentID)
|
||||||
|
link.SetSplitID(splitID)
|
||||||
|
link.SetChildren(childIDs...)
|
||||||
|
|
||||||
|
stat.CountLogic += 1
|
||||||
|
stat.CountPhy += 1
|
||||||
|
stat.SizeLogic += link.PayloadSize()
|
||||||
|
|
||||||
|
for i := range children {
|
||||||
|
sh := shards[i%len(shards)]
|
||||||
|
var putPrm shard.PutPrm
|
||||||
|
putPrm.SetObject(children[i])
|
||||||
|
_, err := sh.Put(context.Background(), putPrm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
sh := shards[count%len(shards)]
|
||||||
|
var putPrm shard.PutPrm
|
||||||
|
putPrm.SetObject(link)
|
||||||
|
_, err := sh.Put(context.Background(), putPrm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if newStat {
|
||||||
|
stats = append(stats, *stat)
|
||||||
|
}
|
||||||
|
count--
|
||||||
|
}
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPutSimpleObject(t *testing.T, shards []*shard.Shard, count int, stats []ContainerStat) []ContainerStat {
|
||||||
|
const payloadSize = 7 * 1024
|
||||||
|
for count > 0 {
|
||||||
|
var cnr cid.ID
|
||||||
|
var stat *ContainerStat
|
||||||
|
var newStat bool
|
||||||
|
if len(stats) == 0 || count%2 == 0 {
|
||||||
|
cnr = cidtest.ID()
|
||||||
|
stat = &ContainerStat{ContainerID: cnr}
|
||||||
|
newStat = true
|
||||||
|
} else {
|
||||||
|
cnr = stats[count%len(stats)].ContainerID
|
||||||
|
stat = &stats[count%len(stats)]
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := testutil.GenerateObjectWithCID(cnr)
|
||||||
|
obj.SetPayload(make([]byte, payloadSize))
|
||||||
|
obj.SetPayloadSize(payloadSize)
|
||||||
|
stat.SizeLogic += payloadSize
|
||||||
|
stat.CountLogic += 1
|
||||||
|
stat.CountPhy += 1
|
||||||
|
stat.CountUser += 1
|
||||||
|
|
||||||
|
sh := shards[count%len(shards)]
|
||||||
|
var putPrm shard.PutPrm
|
||||||
|
putPrm.SetObject(obj)
|
||||||
|
_, err := sh.Put(context.Background(), putPrm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if newStat {
|
||||||
|
stats = append(stats, *stat)
|
||||||
|
}
|
||||||
|
count--
|
||||||
|
}
|
||||||
|
return stats
|
||||||
|
}
|
237
pkg/local_object_storage/metabase/container_stat.go
Normal file
237
pkg/local_object_storage/metabase/container_stat.go
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
package meta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"go.etcd.io/bbolt"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContainerStatPrm struct {
|
||||||
|
ContainerID []cid.ID
|
||||||
|
|
||||||
|
Limit uint32
|
||||||
|
StartFromContainerID *cid.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerStat struct {
|
||||||
|
ContainerID cid.ID
|
||||||
|
SizeLogic uint64
|
||||||
|
CountPhy, CountLogic, CountUser uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerStat returns object count and size for containers.
|
||||||
|
// If len(prm.ContainerID) > 0, then result slice contains records in the same order as prm.ContainerID.
|
||||||
|
// Otherwise result slice sorted by ContainerID.
|
||||||
|
func (db *DB) ContainerStat(ctx context.Context, prm ContainerStatPrm) ([]ContainerStat, error) {
|
||||||
|
var (
|
||||||
|
startedAt = time.Now()
|
||||||
|
success = false
|
||||||
|
)
|
||||||
|
defer func() {
|
||||||
|
db.metrics.AddMethodDuration("ContainerStat", time.Since(startedAt), success)
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, span := tracing.StartSpanFromContext(ctx, "metabase.ContainerStat",
|
||||||
|
trace.WithAttributes(
|
||||||
|
attribute.Int("container_ids", len(prm.ContainerID)),
|
||||||
|
attribute.Int64("limit", int64(prm.Limit)),
|
||||||
|
attribute.Bool("start_from_container_id", prm.StartFromContainerID != nil),
|
||||||
|
))
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
db.modeMtx.RLock()
|
||||||
|
defer db.modeMtx.RUnlock()
|
||||||
|
|
||||||
|
if db.mode.NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(prm.ContainerID) > 0 {
|
||||||
|
return db.containerStatByContainerID(prm.ContainerID)
|
||||||
|
}
|
||||||
|
return db.containerStatByLimit(prm.StartFromContainerID, prm.Limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) containerStatByContainerID(containerID []cid.ID) ([]ContainerStat, error) {
|
||||||
|
var result []ContainerStat
|
||||||
|
err := db.boltDB.View(func(tx *bbolt.Tx) error {
|
||||||
|
for _, contID := range containerID {
|
||||||
|
var stat ContainerStat
|
||||||
|
stat.ContainerID = contID
|
||||||
|
stat.SizeLogic = db.containerSize(tx, contID)
|
||||||
|
|
||||||
|
counters, err := db.containerCounters(tx, contID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stat.CountPhy = counters.Phy
|
||||||
|
stat.CountLogic = counters.Logic
|
||||||
|
stat.CountUser = counters.User
|
||||||
|
result = append(result, stat)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, metaerr.Wrap(err)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) containerStatByLimit(startFrom *cid.ID, limit uint32) ([]ContainerStat, error) {
|
||||||
|
var result []ContainerStat
|
||||||
|
|
||||||
|
var lastKey []byte
|
||||||
|
if startFrom != nil {
|
||||||
|
lastKey = make([]byte, sha256.Size)
|
||||||
|
startFrom.Encode(lastKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
var counts []containerIDObjectCounters
|
||||||
|
var sizes []containerIDSize
|
||||||
|
|
||||||
|
err := db.boltDB.View(func(tx *bbolt.Tx) error {
|
||||||
|
var e error
|
||||||
|
counts, e = getContainerCountersBatch(tx, lastKey, limit)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes, e = getContainerSizesBatch(tx, lastKey, limit)
|
||||||
|
return e
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, metaerr.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mergeSizeAndCounts(counts, sizes)
|
||||||
|
if len(result) > int(limit) {
|
||||||
|
result = result[:limit]
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type containerIDObjectCounters struct {
|
||||||
|
ContainerID cid.ID
|
||||||
|
ObjectCounters
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContainerCountersBatch(tx *bbolt.Tx, lastKey []byte, limit uint32) ([]containerIDObjectCounters, error) {
|
||||||
|
var result []containerIDObjectCounters
|
||||||
|
b := tx.Bucket(containerCounterBucketName)
|
||||||
|
if b == nil {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
var key, value []byte
|
||||||
|
for key, value = c.Seek(lastKey); key != nil && uint32(len(result)) < limit; key, value = c.Next() {
|
||||||
|
if bytes.Equal(lastKey, key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cnrID, err := parseContainerCounterKey(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ent, err := parseContainerCounterValue(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, containerIDObjectCounters{
|
||||||
|
ContainerID: cnrID,
|
||||||
|
ObjectCounters: ent,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type containerIDSize struct {
|
||||||
|
ContainerID cid.ID
|
||||||
|
Size uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContainerSizesBatch(tx *bbolt.Tx, lastKey []byte, limit uint32) ([]containerIDSize, error) {
|
||||||
|
var result []containerIDSize
|
||||||
|
b := tx.Bucket(containerVolumeBucketName)
|
||||||
|
c := b.Cursor()
|
||||||
|
var key, value []byte
|
||||||
|
for key, value = c.Seek(lastKey); key != nil && uint32(len(result)) < limit; key, value = c.Next() {
|
||||||
|
if bytes.Equal(lastKey, key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var r containerIDSize
|
||||||
|
r.Size = parseContainerSize(value)
|
||||||
|
if err := r.ContainerID.Decode(key); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, r)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeSizeAndCounts merges sizes and counts.
|
||||||
|
// As records are deleted in background, it can happen that metabase contains size record for container,
|
||||||
|
// but doesn't contain record for count.
|
||||||
|
func mergeSizeAndCounts(counts []containerIDObjectCounters, sizes []containerIDSize) []ContainerStat {
|
||||||
|
var result []ContainerStat
|
||||||
|
|
||||||
|
for len(counts) > 0 || len(sizes) > 0 {
|
||||||
|
if len(counts) == 0 {
|
||||||
|
result = append(result, ContainerStat{
|
||||||
|
ContainerID: sizes[0].ContainerID,
|
||||||
|
SizeLogic: sizes[0].Size,
|
||||||
|
})
|
||||||
|
sizes = sizes[1:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sizes) == 0 {
|
||||||
|
result = append(result, ContainerStat{
|
||||||
|
ContainerID: counts[0].ContainerID,
|
||||||
|
CountPhy: counts[0].Phy,
|
||||||
|
CountLogic: counts[0].Logic,
|
||||||
|
CountUser: counts[0].User,
|
||||||
|
})
|
||||||
|
counts = counts[1:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
v := bytes.Compare(sizes[0].ContainerID[:], counts[0].ContainerID[:])
|
||||||
|
|
||||||
|
if v == 0 { // equal
|
||||||
|
result = append(result, ContainerStat{
|
||||||
|
ContainerID: counts[0].ContainerID,
|
||||||
|
CountPhy: counts[0].Phy,
|
||||||
|
CountLogic: counts[0].Logic,
|
||||||
|
CountUser: counts[0].User,
|
||||||
|
SizeLogic: sizes[0].Size,
|
||||||
|
})
|
||||||
|
counts = counts[1:]
|
||||||
|
sizes = sizes[1:]
|
||||||
|
} else if v < 0 { // from sizes
|
||||||
|
result = append(result, ContainerStat{
|
||||||
|
ContainerID: sizes[0].ContainerID,
|
||||||
|
SizeLogic: sizes[0].Size,
|
||||||
|
})
|
||||||
|
sizes = sizes[1:]
|
||||||
|
} else { // from counts
|
||||||
|
result = append(result, ContainerStat{
|
||||||
|
ContainerID: counts[0].ContainerID,
|
||||||
|
CountPhy: counts[0].Phy,
|
||||||
|
CountLogic: counts[0].Logic,
|
||||||
|
CountUser: counts[0].User,
|
||||||
|
})
|
||||||
|
counts = counts[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -65,20 +65,19 @@ func (db *DB) ContainerSize(id cid.ID) (size uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.boltDB.View(func(tx *bbolt.Tx) error {
|
err = db.boltDB.View(func(tx *bbolt.Tx) error {
|
||||||
size, err = db.containerSize(tx, id)
|
size = db.containerSize(tx, id)
|
||||||
|
return nil
|
||||||
return err
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return size, metaerr.Wrap(err)
|
return size, metaerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) containerSize(tx *bbolt.Tx, id cid.ID) (uint64, error) {
|
func (db *DB) containerSize(tx *bbolt.Tx, id cid.ID) uint64 {
|
||||||
containerVolume := tx.Bucket(containerVolumeBucketName)
|
containerVolume := tx.Bucket(containerVolumeBucketName)
|
||||||
key := make([]byte, cidSize)
|
key := make([]byte, cidSize)
|
||||||
id.Encode(key)
|
id.Encode(key)
|
||||||
|
|
||||||
return parseContainerSize(containerVolume.Get(key)), nil
|
return parseContainerSize(containerVolume.Get(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseContainerID(dst *cid.ID, name []byte, ignore map[string]struct{}) bool {
|
func parseContainerID(dst *cid.ID, name []byte, ignore map[string]struct{}) bool {
|
||||||
|
|
|
@ -216,21 +216,28 @@ func (db *DB) ContainerCount(ctx context.Context, id cid.ID) (ObjectCounters, er
|
||||||
var result ObjectCounters
|
var result ObjectCounters
|
||||||
|
|
||||||
err := db.boltDB.View(func(tx *bbolt.Tx) error {
|
err := db.boltDB.View(func(tx *bbolt.Tx) error {
|
||||||
b := tx.Bucket(containerCounterBucketName)
|
|
||||||
key := make([]byte, cidSize)
|
|
||||||
id.Encode(key)
|
|
||||||
v := b.Get(key)
|
|
||||||
if v == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var err error
|
var err error
|
||||||
result, err = parseContainerCounterValue(v)
|
result, err = db.containerCounters(tx, id)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
return result, metaerr.Wrap(err)
|
return result, metaerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*DB) containerCounters(tx *bbolt.Tx, id cid.ID) (ObjectCounters, error) {
|
||||||
|
b := tx.Bucket(containerCounterBucketName)
|
||||||
|
if b == nil {
|
||||||
|
return ObjectCounters{}, nil
|
||||||
|
}
|
||||||
|
key := make([]byte, cidSize)
|
||||||
|
id.Encode(key)
|
||||||
|
v := b.Get(key)
|
||||||
|
if v == nil {
|
||||||
|
return ObjectCounters{}, nil
|
||||||
|
}
|
||||||
|
return parseContainerCounterValue(v)
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error {
|
func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error {
|
||||||
b := tx.Bucket(shardInfoBucket)
|
b := tx.Bucket(shardInfoBucket)
|
||||||
if b == nil {
|
if b == nil {
|
||||||
|
|
63
pkg/local_object_storage/shard/container_stat.go
Normal file
63
pkg/local_object_storage/shard/container_stat.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package shard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContainerStatPrm struct {
|
||||||
|
ContainerID []cid.ID
|
||||||
|
|
||||||
|
Limit uint32
|
||||||
|
StartFromContainerID *cid.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainerStat struct {
|
||||||
|
ContainerID cid.ID
|
||||||
|
SizeLogic uint64
|
||||||
|
CountPhy, CountLogic, CountUser uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerStat returns object count and size for containers from metabase.
|
||||||
|
func (s *Shard) ContainerStat(ctx context.Context, prm ContainerStatPrm) ([]ContainerStat, error) {
|
||||||
|
_, span := tracing.StartSpanFromContext(ctx, "Shard.ContainerStat",
|
||||||
|
trace.WithAttributes(
|
||||||
|
attribute.String("shard_id", s.ID().String()),
|
||||||
|
attribute.Int("container_ids", len(prm.ContainerID)),
|
||||||
|
attribute.Int64("limit", int64(prm.Limit)),
|
||||||
|
attribute.Bool("start_from_container_id", prm.StartFromContainerID != nil),
|
||||||
|
))
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
s.m.RLock()
|
||||||
|
defer s.m.RUnlock()
|
||||||
|
|
||||||
|
if s.GetMode().NoMetabase() {
|
||||||
|
return nil, ErrDegradedMode
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := s.metaBase.ContainerStat(ctx, meta.ContainerStatPrm{
|
||||||
|
ContainerID: prm.ContainerID,
|
||||||
|
Limit: prm.Limit,
|
||||||
|
StartFromContainerID: prm.StartFromContainerID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := make([]ContainerStat, 0, len(res))
|
||||||
|
for _, r := range res {
|
||||||
|
result = append(result, ContainerStat{
|
||||||
|
ContainerID: r.ContainerID,
|
||||||
|
SizeLogic: r.SizeLogic,
|
||||||
|
CountPhy: r.CountPhy,
|
||||||
|
CountLogic: r.CountLogic,
|
||||||
|
CountUser: r.CountUser,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
137
pkg/services/billing/server/list_containers.go
Normal file
137
pkg/services/billing/server/list_containers.go
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
containerApi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||||
|
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/billing"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultLimit = 1000
|
||||||
|
maxLimit = 10000
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidContainerIDLenght = errors.New("count of container ID array must be lower or equal 10 000 items")
|
||||||
|
errInvalidLimit = errors.New("limit value must be lower or equal 10 000")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) ListContainers(ctx context.Context, req *billing.ListContainersRequest) (*billing.ListContainersResponse, error) {
|
||||||
|
err := s.isValidRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.PermissionDenied, err.Error())
|
||||||
|
}
|
||||||
|
enginePrm, err := convertToEngineContainerStatPrm(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := s.se.ContainerStat(ctx, enginePrm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &billing.ListContainersResponse{
|
||||||
|
Body: &billing.ListContainersResponse_Body{
|
||||||
|
Result: s.addContainerInfo(res.ContainerStats),
|
||||||
|
NextPageToken: containerListNextPageToken(res.ContainerStats, enginePrm.Limit),
|
||||||
|
Partial: res.Partial,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = SignMessage(s.key, resp); err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) addContainerInfo(engineStats []engine.ContainerStat) []*billing.ListContainersResponse_Body_ContainerInfo {
|
||||||
|
var result []*billing.ListContainersResponse_Body_ContainerInfo
|
||||||
|
|
||||||
|
for _, engineStat := range engineStats {
|
||||||
|
containerInfo := &billing.ListContainersResponse_Body_ContainerInfo{
|
||||||
|
ContainerId: engineStat.ContainerID[:],
|
||||||
|
Count: &billing.ListContainersResponse_Body_ContainerInfo_Count{
|
||||||
|
Phy: engineStat.CountPhy,
|
||||||
|
Logic: engineStat.CountLogic,
|
||||||
|
User: engineStat.CountUser,
|
||||||
|
},
|
||||||
|
Size: &billing.ListContainersResponse_Body_ContainerInfo_Size{
|
||||||
|
Logic: engineStat.SizeLogic,
|
||||||
|
},
|
||||||
|
ContainerStatus: billing.ListContainersResponse_Body_ContainerInfo_UNDEFINED,
|
||||||
|
}
|
||||||
|
|
||||||
|
cnr, err := s.cnrSrc.Get(engineStat.ContainerID)
|
||||||
|
if err != nil {
|
||||||
|
if client.IsErrContainerNotFound(err) {
|
||||||
|
existed, errWasRemoved := containercore.WasRemoved(s.cnrSrc, engineStat.ContainerID)
|
||||||
|
if errWasRemoved == nil && existed {
|
||||||
|
containerInfo.ContainerStatus = billing.ListContainersResponse_Body_ContainerInfo_DELETED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
containerInfo.ContainerStatus = billing.ListContainersResponse_Body_ContainerInfo_AVAILABLE
|
||||||
|
containerInfo.Attributes = &billing.ListContainersResponse_Body_ContainerInfo_Attributes{
|
||||||
|
OwnerWallet: cnr.Value.Owner().WalletBytes(),
|
||||||
|
Zone: cnr.Value.Attribute(containerApi.SysAttributeZone),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = append(result, containerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func containerListNextPageToken(engineStats []engine.ContainerStat, limit uint32) []byte {
|
||||||
|
if uint32(len(engineStats)) <= limit {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return engineStats[len(engineStats)-1].ContainerID[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToEngineContainerStatPrm(req *billing.ListContainersRequest) (engine.ContainerStatPrm, error) {
|
||||||
|
var result engine.ContainerStatPrm
|
||||||
|
|
||||||
|
if len(req.GetBody().GetContainerId()) > 10000 {
|
||||||
|
return result, errInvalidContainerIDLenght
|
||||||
|
}
|
||||||
|
if len(req.GetBody().GetContainerId()) > 0 {
|
||||||
|
for idx, contIDBytes := range req.GetBody().GetContainerId() {
|
||||||
|
var contID cid.ID
|
||||||
|
if err := contID.Decode(contIDBytes); err != nil {
|
||||||
|
return result, fmt.Errorf("failed to decode container ID at index %d: %w", idx, err)
|
||||||
|
}
|
||||||
|
result.ContainerID = append(result.ContainerID, contID)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Limit = defaultLimit
|
||||||
|
if req.GetBody().GetLimit() > maxLimit {
|
||||||
|
return result, errInvalidLimit
|
||||||
|
}
|
||||||
|
if req.GetBody().GetLimit() > 0 {
|
||||||
|
result.Limit = req.GetBody().GetLimit()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.GetBody().GetNextPageToken()) > 0 {
|
||||||
|
var contID cid.ID
|
||||||
|
if err := contID.Decode(req.GetBody().GetNextPageToken()); err != nil {
|
||||||
|
return result, fmt.Errorf("invalid next page token: %w", err)
|
||||||
|
}
|
||||||
|
result.StartFromContainerID = &contID
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
34
pkg/services/billing/server/server.go
Normal file
34
pkg/services/billing/server/server.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cfg struct {
|
||||||
|
key *ecdsa.PrivateKey
|
||||||
|
allowedKeys [][]byte
|
||||||
|
cnrSrc container.Source
|
||||||
|
se *engine.StorageEngine
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
*cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(key *ecdsa.PrivateKey,
|
||||||
|
allowedKeys [][]byte,
|
||||||
|
cnrSrc container.Source,
|
||||||
|
se *engine.StorageEngine,
|
||||||
|
) *Server {
|
||||||
|
return &Server{
|
||||||
|
cfg: &cfg{
|
||||||
|
key: key,
|
||||||
|
allowedKeys: allowedKeys,
|
||||||
|
cnrSrc: cnrSrc,
|
||||||
|
se: se,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
92
pkg/services/billing/server/sign.go
Normal file
92
pkg/services/billing/server/sign.go
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/billing"
|
||||||
|
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||||
|
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SignedMessage is an interface of Control service message.
|
||||||
|
type SignedMessage interface {
|
||||||
|
ReadSignedData([]byte) ([]byte, error)
|
||||||
|
GetSignature() *billing.Signature
|
||||||
|
SetSignature(*billing.Signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errDisallowedKey = errors.New("key is not in the allowed list")
|
||||||
|
errMissingSignature = errors.New("missing signature")
|
||||||
|
errInvalidSignature = errors.New("invalid signature")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) isValidRequest(req SignedMessage) error {
|
||||||
|
sign := req.GetSignature()
|
||||||
|
if sign == nil {
|
||||||
|
return errMissingSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
key = sign.GetKey()
|
||||||
|
allowed = false
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := range s.allowedKeys {
|
||||||
|
if allowed = bytes.Equal(s.allowedKeys[i], key); allowed {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
return errDisallowedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
binBody, err := req.ReadSignedData(nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("marshal request body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sigV2 refs.Signature
|
||||||
|
sigV2.SetKey(sign.GetKey())
|
||||||
|
sigV2.SetSign(sign.GetSignature())
|
||||||
|
sigV2.SetScheme(refs.ECDSA_SHA512)
|
||||||
|
|
||||||
|
var sig frostfscrypto.Signature
|
||||||
|
if err := sig.ReadFromV2(sigV2); err != nil {
|
||||||
|
return fmt.Errorf("can't read signature: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sig.Verify(binBody) {
|
||||||
|
return errInvalidSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignMessage(key *ecdsa.PrivateKey, msg SignedMessage) error {
|
||||||
|
binBody, err := msg.ReadSignedData(nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("marshal request body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sig frostfscrypto.Signature
|
||||||
|
|
||||||
|
err = sig.Calculate(frostfsecdsa.Signer(*key), binBody)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("calculate signature: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sigV2 refs.Signature
|
||||||
|
sig.WriteToV2(&sigV2)
|
||||||
|
|
||||||
|
var sigBilling billing.Signature
|
||||||
|
sigBilling.Key = sigV2.GetKey()
|
||||||
|
sigBilling.Signature = sigV2.GetSign()
|
||||||
|
msg.SetSignature(&sigBilling)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
905
pkg/services/billing/service.pb.go
generated
Normal file
905
pkg/services/billing/service.pb.go
generated
Normal file
|
@ -0,0 +1,905 @@
|
||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.33.0
|
||||||
|
// protoc v4.25.0
|
||||||
|
// source: pkg/services/billing/service.proto
|
||||||
|
|
||||||
|
package billing
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListContainersResponse_Body_ContainerInfo_Status int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Undefined status, default value.
|
||||||
|
ListContainersResponse_Body_ContainerInfo_UNDEFINED ListContainersResponse_Body_ContainerInfo_Status = 0
|
||||||
|
// Container is available.
|
||||||
|
ListContainersResponse_Body_ContainerInfo_AVAILABLE ListContainersResponse_Body_ContainerInfo_Status = 1
|
||||||
|
// Container is deleted.
|
||||||
|
ListContainersResponse_Body_ContainerInfo_DELETED ListContainersResponse_Body_ContainerInfo_Status = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for ListContainersResponse_Body_ContainerInfo_Status.
|
||||||
|
var (
|
||||||
|
ListContainersResponse_Body_ContainerInfo_Status_name = map[int32]string{
|
||||||
|
0: "UNDEFINED",
|
||||||
|
1: "AVAILABLE",
|
||||||
|
2: "DELETED",
|
||||||
|
}
|
||||||
|
ListContainersResponse_Body_ContainerInfo_Status_value = map[string]int32{
|
||||||
|
"UNDEFINED": 0,
|
||||||
|
"AVAILABLE": 1,
|
||||||
|
"DELETED": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x ListContainersResponse_Body_ContainerInfo_Status) Enum() *ListContainersResponse_Body_ContainerInfo_Status {
|
||||||
|
p := new(ListContainersResponse_Body_ContainerInfo_Status)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x ListContainersResponse_Body_ContainerInfo_Status) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ListContainersResponse_Body_ContainerInfo_Status) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_pkg_services_billing_service_proto_enumTypes[0].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ListContainersResponse_Body_ContainerInfo_Status) Type() protoreflect.EnumType {
|
||||||
|
return &file_pkg_services_billing_service_proto_enumTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x ListContainersResponse_Body_ContainerInfo_Status) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse_Body_ContainerInfo_Status.Descriptor instead.
|
||||||
|
func (ListContainersResponse_Body_ContainerInfo_Status) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2, 0, 0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature of some message.
|
||||||
|
type Signature struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Public key used for signing.
|
||||||
|
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
|
// Binary signature.
|
||||||
|
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Signature) Reset() {
|
||||||
|
*x = Signature{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Signature) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Signature) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Signature) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Signature.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Signature) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Signature) GetKey() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Key
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Signature) GetSignature() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Signature
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Body *ListContainersRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
|
||||||
|
Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest) Reset() {
|
||||||
|
*x = ListContainersRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest) GetBody() *ListContainersRequest_Body {
|
||||||
|
if x != nil {
|
||||||
|
return x.Body
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest) GetSignature() *Signature {
|
||||||
|
if x != nil {
|
||||||
|
return x.Signature
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Body *ListContainersResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
|
||||||
|
Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse) Reset() {
|
||||||
|
*x = ListContainersResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse) GetBody() *ListContainersResponse_Body {
|
||||||
|
if x != nil {
|
||||||
|
return x.Body
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse) GetSignature() *Signature {
|
||||||
|
if x != nil {
|
||||||
|
return x.Signature
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersRequest_Body struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Container IDs to get container metrics. Not required. Maximum count is
|
||||||
|
// 10000 items.
|
||||||
|
ContainerId [][]byte `protobuf:"bytes,1,rep,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
|
||||||
|
// Max items count in the response. Not required. Default value is 1000. Not
|
||||||
|
// applicable if container_id is specified. Maximum value is 10000.
|
||||||
|
Limit uint32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
|
||||||
|
// Next page token used to continue listing. Not required. If null or empty,
|
||||||
|
// listing starts from the beginning.
|
||||||
|
NextPageToken []byte `protobuf:"bytes,3,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest_Body) Reset() {
|
||||||
|
*x = ListContainersRequest_Body{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest_Body) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersRequest_Body) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest_Body) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersRequest_Body.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersRequest_Body) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{1, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest_Body) GetContainerId() [][]byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.ContainerId
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest_Body) GetLimit() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Limit
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest_Body) GetNextPageToken() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.NextPageToken
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersResponse_Body struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Result []*ListContainersResponse_Body_ContainerInfo `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"`
|
||||||
|
// Next page token used to get next batch. If returned value is null or
|
||||||
|
// empty, then listing completed.
|
||||||
|
NextPageToken []byte `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
|
||||||
|
// Returned result is partial. This could happend if some shards are in
|
||||||
|
// degraded mode or returned an error.
|
||||||
|
Partial bool `protobuf:"varint,3,opt,name=partial,proto3" json:"partial,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body) Reset() {
|
||||||
|
*x = ListContainersResponse_Body{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersResponse_Body) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse_Body.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersResponse_Body) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body) GetResult() []*ListContainersResponse_Body_ContainerInfo {
|
||||||
|
if x != nil {
|
||||||
|
return x.Result
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body) GetNextPageToken() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.NextPageToken
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body) GetPartial() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Partial
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersResponse_Body_ContainerInfo struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Container ID.
|
||||||
|
ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
|
||||||
|
// Container status.
|
||||||
|
ContainerStatus ListContainersResponse_Body_ContainerInfo_Status `protobuf:"varint,2,opt,name=container_status,json=containerStatus,proto3,enum=billing.ListContainersResponse_Body_ContainerInfo_Status" json:"container_status,omitempty"`
|
||||||
|
// Container attributes. May be null if container attributes are
|
||||||
|
// unavailable for current moment or container already deleted.
|
||||||
|
Attributes *ListContainersResponse_Body_ContainerInfo_Attributes `protobuf:"bytes,3,opt,name=attributes,proto3" json:"attributes,omitempty"`
|
||||||
|
// Count of the objects in container.
|
||||||
|
Count *ListContainersResponse_Body_ContainerInfo_Count `protobuf:"bytes,4,opt,name=count,proto3" json:"count,omitempty"`
|
||||||
|
// Size of the objects in container.
|
||||||
|
Size *ListContainersResponse_Body_ContainerInfo_Size `protobuf:"bytes,5,opt,name=size,proto3" json:"size,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) Reset() {
|
||||||
|
*x = ListContainersResponse_Body_ContainerInfo{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[5]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse_Body_ContainerInfo.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2, 0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) GetContainerId() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.ContainerId
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) GetContainerStatus() ListContainersResponse_Body_ContainerInfo_Status {
|
||||||
|
if x != nil {
|
||||||
|
return x.ContainerStatus
|
||||||
|
}
|
||||||
|
return ListContainersResponse_Body_ContainerInfo_UNDEFINED
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) GetAttributes() *ListContainersResponse_Body_ContainerInfo_Attributes {
|
||||||
|
if x != nil {
|
||||||
|
return x.Attributes
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) GetCount() *ListContainersResponse_Body_ContainerInfo_Count {
|
||||||
|
if x != nil {
|
||||||
|
return x.Count
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) GetSize() *ListContainersResponse_Body_ContainerInfo_Size {
|
||||||
|
if x != nil {
|
||||||
|
return x.Size
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersResponse_Body_ContainerInfo_Count struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Phy uint64 `protobuf:"varint,1,opt,name=phy,proto3" json:"phy,omitempty"`
|
||||||
|
Logic uint64 `protobuf:"varint,2,opt,name=logic,proto3" json:"logic,omitempty"`
|
||||||
|
User uint64 `protobuf:"varint,3,opt,name=user,proto3" json:"user,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) Reset() {
|
||||||
|
*x = ListContainersResponse_Body_ContainerInfo_Count{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[6]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo_Count) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[6]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse_Body_ContainerInfo_Count.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo_Count) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2, 0, 0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) GetPhy() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Phy
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) GetLogic() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Logic
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) GetUser() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.User
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersResponse_Body_ContainerInfo_Size struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Logic uint64 `protobuf:"varint,1,opt,name=logic,proto3" json:"logic,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Size) Reset() {
|
||||||
|
*x = ListContainersResponse_Body_ContainerInfo_Size{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[7]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Size) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo_Size) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Size) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[7]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse_Body_ContainerInfo_Size.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo_Size) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2, 0, 0, 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Size) GetLogic() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Logic
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListContainersResponse_Body_ContainerInfo_Attributes struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Container owner's wallet bytes.
|
||||||
|
OwnerWallet []byte `protobuf:"bytes,1,opt,name=owner_wallet,json=ownerWallet,proto3" json:"owner_wallet,omitempty"`
|
||||||
|
// Container zone.
|
||||||
|
Zone string `protobuf:"bytes,2,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) Reset() {
|
||||||
|
*x = ListContainersResponse_Body_ContainerInfo_Attributes{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[8]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo_Attributes) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pkg_services_billing_service_proto_msgTypes[8]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ListContainersResponse_Body_ContainerInfo_Attributes.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ListContainersResponse_Body_ContainerInfo_Attributes) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescGZIP(), []int{2, 0, 0, 2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) GetOwnerWallet() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.OwnerWallet
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) GetZone() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Zone
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_pkg_services_billing_service_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_pkg_services_billing_service_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x22, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x62,
|
||||||
|
0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0x3b, 0x0a,
|
||||||
|
0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||||
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09,
|
||||||
|
0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||||
|
0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xeb, 0x01, 0x0a, 0x15, 0x4c,
|
||||||
|
0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73,
|
||||||
|
0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
|
0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a,
|
||||||
|
0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||||
|
0x32, 0x12, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61,
|
||||||
|
0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a,
|
||||||
|
0x67, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61,
|
||||||
|
0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0b, 0x63,
|
||||||
|
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69,
|
||||||
|
0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
||||||
|
0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f,
|
||||||
|
0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50,
|
||||||
|
0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8f, 0x07, 0x0a, 0x16, 0x4c, 0x69, 0x73,
|
||||||
|
0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
|
0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x24, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||||
|
0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a,
|
||||||
|
0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||||
|
0x32, 0x12, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61,
|
||||||
|
0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a,
|
||||||
|
0x88, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x4a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75,
|
||||||
|
0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69,
|
||||||
|
0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
|
||||||
|
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x43,
|
||||||
|
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x72, 0x65,
|
||||||
|
0x73, 0x75, 0x6c, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67,
|
||||||
|
0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6e,
|
||||||
|
0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07,
|
||||||
|
0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70,
|
||||||
|
0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x1a, 0xf1, 0x04, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61,
|
||||||
|
0x69, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74,
|
||||||
|
0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b,
|
||||||
|
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x64, 0x0a, 0x10, 0x63,
|
||||||
|
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
|
||||||
|
0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e,
|
||||||
|
0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65,
|
||||||
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x74,
|
||||||
|
0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||||
|
0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||||
|
0x73, 0x12, 0x5d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18,
|
||||||
|
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e,
|
||||||
|
0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65,
|
||||||
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x74,
|
||||||
|
0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62,
|
||||||
|
0x75, 0x74, 0x65, 0x73, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||||
|
0x12, 0x4e, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
|
0x38, 0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f,
|
||||||
|
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
|
0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49,
|
||||||
|
0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||||
|
0x12, 0x4b, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37,
|
||||||
|
0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e,
|
||||||
|
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
|
||||||
|
0x42, 0x6f, 0x64, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6e,
|
||||||
|
0x66, 0x6f, 0x2e, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, 0x43, 0x0a,
|
||||||
|
0x05, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x68, 0x79, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x04, 0x52, 0x03, 0x70, 0x68, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f, 0x67, 0x69,
|
||||||
|
0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x12, 0x12,
|
||||||
|
0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x75, 0x73,
|
||||||
|
0x65, 0x72, 0x1a, 0x1c, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f,
|
||||||
|
0x67, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x6f, 0x67, 0x69, 0x63,
|
||||||
|
0x1a, 0x43, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x21,
|
||||||
|
0x0a, 0x0c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x18, 0x01,
|
||||||
|
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x57, 0x61, 0x6c, 0x6c, 0x65,
|
||||||
|
0x74, 0x12, 0x12, 0x0a, 0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
|
0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x22, 0x33, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
|
||||||
|
0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d,
|
||||||
|
0x0a, 0x09, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a,
|
||||||
|
0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x32, 0x63, 0x0a, 0x0e, 0x42, 0x69,
|
||||||
|
0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x0e,
|
||||||
|
0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1e,
|
||||||
|
0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e,
|
||||||
|
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f,
|
||||||
|
0x2e, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e,
|
||||||
|
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
|
||||||
|
0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69,
|
||||||
|
0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62,
|
||||||
|
0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b,
|
||||||
|
0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x62, 0x69, 0x6c, 0x6c, 0x69,
|
||||||
|
0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_pkg_services_billing_service_proto_rawDescOnce sync.Once
|
||||||
|
file_pkg_services_billing_service_proto_rawDescData = file_pkg_services_billing_service_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_pkg_services_billing_service_proto_rawDescGZIP() []byte {
|
||||||
|
file_pkg_services_billing_service_proto_rawDescOnce.Do(func() {
|
||||||
|
file_pkg_services_billing_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_billing_service_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_pkg_services_billing_service_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_pkg_services_billing_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
|
var file_pkg_services_billing_service_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||||
|
var file_pkg_services_billing_service_proto_goTypes = []interface{}{
|
||||||
|
(ListContainersResponse_Body_ContainerInfo_Status)(0), // 0: billing.ListContainersResponse.Body.ContainerInfo.Status
|
||||||
|
(*Signature)(nil), // 1: billing.Signature
|
||||||
|
(*ListContainersRequest)(nil), // 2: billing.ListContainersRequest
|
||||||
|
(*ListContainersResponse)(nil), // 3: billing.ListContainersResponse
|
||||||
|
(*ListContainersRequest_Body)(nil), // 4: billing.ListContainersRequest.Body
|
||||||
|
(*ListContainersResponse_Body)(nil), // 5: billing.ListContainersResponse.Body
|
||||||
|
(*ListContainersResponse_Body_ContainerInfo)(nil), // 6: billing.ListContainersResponse.Body.ContainerInfo
|
||||||
|
(*ListContainersResponse_Body_ContainerInfo_Count)(nil), // 7: billing.ListContainersResponse.Body.ContainerInfo.Count
|
||||||
|
(*ListContainersResponse_Body_ContainerInfo_Size)(nil), // 8: billing.ListContainersResponse.Body.ContainerInfo.Size
|
||||||
|
(*ListContainersResponse_Body_ContainerInfo_Attributes)(nil), // 9: billing.ListContainersResponse.Body.ContainerInfo.Attributes
|
||||||
|
}
|
||||||
|
var file_pkg_services_billing_service_proto_depIdxs = []int32{
|
||||||
|
4, // 0: billing.ListContainersRequest.body:type_name -> billing.ListContainersRequest.Body
|
||||||
|
1, // 1: billing.ListContainersRequest.signature:type_name -> billing.Signature
|
||||||
|
5, // 2: billing.ListContainersResponse.body:type_name -> billing.ListContainersResponse.Body
|
||||||
|
1, // 3: billing.ListContainersResponse.signature:type_name -> billing.Signature
|
||||||
|
6, // 4: billing.ListContainersResponse.Body.result:type_name -> billing.ListContainersResponse.Body.ContainerInfo
|
||||||
|
0, // 5: billing.ListContainersResponse.Body.ContainerInfo.container_status:type_name -> billing.ListContainersResponse.Body.ContainerInfo.Status
|
||||||
|
9, // 6: billing.ListContainersResponse.Body.ContainerInfo.attributes:type_name -> billing.ListContainersResponse.Body.ContainerInfo.Attributes
|
||||||
|
7, // 7: billing.ListContainersResponse.Body.ContainerInfo.count:type_name -> billing.ListContainersResponse.Body.ContainerInfo.Count
|
||||||
|
8, // 8: billing.ListContainersResponse.Body.ContainerInfo.size:type_name -> billing.ListContainersResponse.Body.ContainerInfo.Size
|
||||||
|
2, // 9: billing.BillingService.ListContainers:input_type -> billing.ListContainersRequest
|
||||||
|
3, // 10: billing.BillingService.ListContainers:output_type -> billing.ListContainersResponse
|
||||||
|
10, // [10:11] is the sub-list for method output_type
|
||||||
|
9, // [9:10] is the sub-list for method input_type
|
||||||
|
9, // [9:9] is the sub-list for extension type_name
|
||||||
|
9, // [9:9] is the sub-list for extension extendee
|
||||||
|
0, // [0:9] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_pkg_services_billing_service_proto_init() }
|
||||||
|
func file_pkg_services_billing_service_proto_init() {
|
||||||
|
if File_pkg_services_billing_service_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Signature); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersRequest_Body); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersResponse_Body); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersResponse_Body_ContainerInfo); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersResponse_Body_ContainerInfo_Count); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersResponse_Body_ContainerInfo_Size); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_pkg_services_billing_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ListContainersResponse_Body_ContainerInfo_Attributes); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_pkg_services_billing_service_proto_rawDesc,
|
||||||
|
NumEnums: 1,
|
||||||
|
NumMessages: 9,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_pkg_services_billing_service_proto_goTypes,
|
||||||
|
DependencyIndexes: file_pkg_services_billing_service_proto_depIdxs,
|
||||||
|
EnumInfos: file_pkg_services_billing_service_proto_enumTypes,
|
||||||
|
MessageInfos: file_pkg_services_billing_service_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_pkg_services_billing_service_proto = out.File
|
||||||
|
file_pkg_services_billing_service_proto_rawDesc = nil
|
||||||
|
file_pkg_services_billing_service_proto_goTypes = nil
|
||||||
|
file_pkg_services_billing_service_proto_depIdxs = nil
|
||||||
|
}
|
87
pkg/services/billing/service.proto
Normal file
87
pkg/services/billing/service.proto
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package billing;
|
||||||
|
|
||||||
|
option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/billing";
|
||||||
|
|
||||||
|
// `BillingService` provides an interface to get usage statistics.
|
||||||
|
service BillingService {
|
||||||
|
// Returns list that contains container usage statistic.
|
||||||
|
rpc ListContainers(ListContainersRequest) returns (ListContainersResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature of some message.
|
||||||
|
message Signature {
|
||||||
|
// Public key used for signing.
|
||||||
|
bytes key = 1;
|
||||||
|
|
||||||
|
// Binary signature.
|
||||||
|
bytes signature = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListContainersRequest {
|
||||||
|
message Body {
|
||||||
|
// Container IDs to get container metrics. Not required. Maximum count is
|
||||||
|
// 10000 items.
|
||||||
|
repeated bytes container_id = 1;
|
||||||
|
// Max items count in the response. Not required. Default value is 1000. Not
|
||||||
|
// applicable if container_id is specified. Maximum value is 10000.
|
||||||
|
uint32 limit = 2;
|
||||||
|
// Next page token used to continue listing. Not required. If null or empty,
|
||||||
|
// listing starts from the beginning.
|
||||||
|
bytes next_page_token = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Body body = 1;
|
||||||
|
Signature signature = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListContainersResponse {
|
||||||
|
message Body {
|
||||||
|
message ContainerInfo {
|
||||||
|
message Count {
|
||||||
|
uint64 phy = 1;
|
||||||
|
uint64 logic = 2;
|
||||||
|
uint64 user = 3;
|
||||||
|
}
|
||||||
|
message Size { uint64 logic = 1; }
|
||||||
|
message Attributes {
|
||||||
|
// Container owner's wallet bytes.
|
||||||
|
bytes owner_wallet = 1;
|
||||||
|
// Container zone.
|
||||||
|
string zone = 2;
|
||||||
|
}
|
||||||
|
enum Status {
|
||||||
|
// Undefined status, default value.
|
||||||
|
UNDEFINED = 0;
|
||||||
|
// Container is available.
|
||||||
|
AVAILABLE = 1;
|
||||||
|
// Container is deleted.
|
||||||
|
DELETED = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container ID.
|
||||||
|
bytes container_id = 1;
|
||||||
|
// Container status.
|
||||||
|
Status container_status = 2;
|
||||||
|
// Container attributes. May be null if container attributes are
|
||||||
|
// unavailable for current moment or container already deleted.
|
||||||
|
Attributes attributes = 3;
|
||||||
|
// Count of the objects in container.
|
||||||
|
Count count = 4;
|
||||||
|
// Size of the objects in container.
|
||||||
|
Size size = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated ContainerInfo result = 1;
|
||||||
|
// Next page token used to get next batch. If returned value is null or
|
||||||
|
// empty, then listing completed.
|
||||||
|
bytes next_page_token = 2;
|
||||||
|
// Returned result is partial. This could happend if some shards are in
|
||||||
|
// degraded mode or returned an error.
|
||||||
|
bool partial = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Body body = 1;
|
||||||
|
Signature signature = 2;
|
||||||
|
}
|
360
pkg/services/billing/service_frostfs.pb.go
generated
Normal file
360
pkg/services/billing/service_frostfs.pb.go
generated
Normal file
|
@ -0,0 +1,360 @@
|
||||||
|
// Code generated by protoc-gen-go-frostfs. DO NOT EDIT.
|
||||||
|
|
||||||
|
package billing
|
||||||
|
|
||||||
|
import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *Signature) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.BytesSize(1, x.Key)
|
||||||
|
size += proto.BytesSize(2, x.Signature)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *Signature) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.BytesMarshal(1, buf[offset:], x.Key)
|
||||||
|
offset += proto.BytesMarshal(2, buf[offset:], x.Signature)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersRequest_Body) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.RepeatedBytesSize(1, x.ContainerId)
|
||||||
|
size += proto.UInt32Size(2, x.Limit)
|
||||||
|
size += proto.BytesSize(3, x.NextPageToken)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersRequest_Body) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.ContainerId)
|
||||||
|
offset += proto.UInt32Marshal(2, buf[offset:], x.Limit)
|
||||||
|
offset += proto.BytesMarshal(3, buf[offset:], x.NextPageToken)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersRequest) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.NestedStructureSize(1, x.Body)
|
||||||
|
size += proto.NestedStructureSize(2, x.Signature)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersRequest) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body)
|
||||||
|
offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSignedData fills buf with signed data of x.
|
||||||
|
// If buffer length is less than x.SignedDataSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same signed data.
|
||||||
|
func (x *ListContainersRequest) SignedDataSize() int {
|
||||||
|
return x.GetBody().StableSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignedDataSize returns size of the request signed data in bytes.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same signed data size.
|
||||||
|
func (x *ListContainersRequest) ReadSignedData(buf []byte) ([]byte, error) {
|
||||||
|
return x.GetBody().StableMarshal(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersRequest) SetSignature(sig *Signature) {
|
||||||
|
x.Signature = sig
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.UInt64Size(1, x.Phy)
|
||||||
|
size += proto.UInt64Size(2, x.Logic)
|
||||||
|
size += proto.UInt64Size(3, x.User)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Count) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.UInt64Marshal(1, buf[offset:], x.Phy)
|
||||||
|
offset += proto.UInt64Marshal(2, buf[offset:], x.Logic)
|
||||||
|
offset += proto.UInt64Marshal(3, buf[offset:], x.User)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Size) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.UInt64Size(1, x.Logic)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Size) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.UInt64Marshal(1, buf[offset:], x.Logic)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.BytesSize(1, x.OwnerWallet)
|
||||||
|
size += proto.StringSize(2, x.Zone)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo_Attributes) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.BytesMarshal(1, buf[offset:], x.OwnerWallet)
|
||||||
|
offset += proto.StringMarshal(2, buf[offset:], x.Zone)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.BytesSize(1, x.ContainerId)
|
||||||
|
size += proto.EnumSize(2, int32(x.ContainerStatus))
|
||||||
|
size += proto.NestedStructureSize(3, x.Attributes)
|
||||||
|
size += proto.NestedStructureSize(4, x.Count)
|
||||||
|
size += proto.NestedStructureSize(5, x.Size)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersResponse_Body_ContainerInfo) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId)
|
||||||
|
offset += proto.EnumMarshal(2, buf[offset:], int32(x.ContainerStatus))
|
||||||
|
offset += proto.NestedStructureMarshal(3, buf[offset:], x.Attributes)
|
||||||
|
offset += proto.NestedStructureMarshal(4, buf[offset:], x.Count)
|
||||||
|
offset += proto.NestedStructureMarshal(5, buf[offset:], x.Size)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersResponse_Body) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for i := range x.Result {
|
||||||
|
size += proto.NestedStructureSize(1, x.Result[i])
|
||||||
|
}
|
||||||
|
size += proto.BytesSize(2, x.NextPageToken)
|
||||||
|
size += proto.BoolSize(3, x.Partial)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersResponse_Body) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
for i := range x.Result {
|
||||||
|
offset += proto.NestedStructureMarshal(1, buf[offset:], x.Result[i])
|
||||||
|
}
|
||||||
|
offset += proto.BytesMarshal(2, buf[offset:], x.NextPageToken)
|
||||||
|
offset += proto.BoolMarshal(3, buf[offset:], x.Partial)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableSize returns the size of x in protobuf format.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary size.
|
||||||
|
func (x *ListContainersResponse) StableSize() (size int) {
|
||||||
|
if x == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size += proto.NestedStructureSize(1, x.Body)
|
||||||
|
size += proto.NestedStructureSize(2, x.Signature)
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
// StableMarshal marshals x in protobuf binary format with stable field order.
|
||||||
|
//
|
||||||
|
// If buffer length is less than x.StableSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same binary format.
|
||||||
|
func (x *ListContainersResponse) StableMarshal(buf []byte) []byte {
|
||||||
|
if x == nil {
|
||||||
|
return []byte{}
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
buf = make([]byte, x.StableSize())
|
||||||
|
}
|
||||||
|
var offset int
|
||||||
|
offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body)
|
||||||
|
offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadSignedData fills buf with signed data of x.
|
||||||
|
// If buffer length is less than x.SignedDataSize(), new buffer is allocated.
|
||||||
|
//
|
||||||
|
// Returns any error encountered which did not allow writing the data completely.
|
||||||
|
// Otherwise, returns the buffer in which the data is written.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same signed data.
|
||||||
|
func (x *ListContainersResponse) SignedDataSize() int {
|
||||||
|
return x.GetBody().StableSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignedDataSize returns size of the request signed data in bytes.
|
||||||
|
//
|
||||||
|
// Structures with the same field values have the same signed data size.
|
||||||
|
func (x *ListContainersResponse) ReadSignedData(buf []byte) ([]byte, error) {
|
||||||
|
return x.GetBody().StableMarshal(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ListContainersResponse) SetSignature(sig *Signature) {
|
||||||
|
x.Signature = sig
|
||||||
|
}
|
109
pkg/services/billing/service_grpc.pb.go
generated
Normal file
109
pkg/services/billing/service_grpc.pb.go
generated
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v4.25.0
|
||||||
|
// source: pkg/services/billing/service.proto
|
||||||
|
|
||||||
|
package billing
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
const (
|
||||||
|
BillingService_ListContainers_FullMethodName = "/billing.BillingService/ListContainers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BillingServiceClient is the client API for BillingService service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type BillingServiceClient interface {
|
||||||
|
// Returns list that contains container usage statistic.
|
||||||
|
ListContainers(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type billingServiceClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBillingServiceClient(cc grpc.ClientConnInterface) BillingServiceClient {
|
||||||
|
return &billingServiceClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *billingServiceClient) ListContainers(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, error) {
|
||||||
|
out := new(ListContainersResponse)
|
||||||
|
err := c.cc.Invoke(ctx, BillingService_ListContainers_FullMethodName, in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BillingServiceServer is the server API for BillingService service.
|
||||||
|
// All implementations should embed UnimplementedBillingServiceServer
|
||||||
|
// for forward compatibility
|
||||||
|
type BillingServiceServer interface {
|
||||||
|
// Returns list that contains container usage statistic.
|
||||||
|
ListContainers(context.Context, *ListContainersRequest) (*ListContainersResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedBillingServiceServer should be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedBillingServiceServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedBillingServiceServer) ListContainers(context.Context, *ListContainersRequest) (*ListContainersResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListContainers not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsafeBillingServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to BillingServiceServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeBillingServiceServer interface {
|
||||||
|
mustEmbedUnimplementedBillingServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterBillingServiceServer(s grpc.ServiceRegistrar, srv BillingServiceServer) {
|
||||||
|
s.RegisterService(&BillingService_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _BillingService_ListContainers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListContainersRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(BillingServiceServer).ListContainers(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: BillingService_ListContainers_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(BillingServiceServer).ListContainers(ctx, req.(*ListContainersRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BillingService_ServiceDesc is the grpc.ServiceDesc for BillingService service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var BillingService_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "billing.BillingService",
|
||||||
|
HandlerType: (*BillingServiceServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "ListContainers",
|
||||||
|
Handler: _BillingService_ListContainers_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "pkg/services/billing/service.proto",
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue