forked from TrueCloudLab/xk6-frostfs
Compare commits
10 commits
f90a645594
...
3bf41e626e
Author | SHA1 | Date | |
---|---|---|---|
3bf41e626e | |||
6d3ecb6528 | |||
75f670b392 | |||
9b9db46a07 | |||
335c45c578 | |||
e7d4dd404a | |||
0a9aeab47c | |||
3bc1229062 | |||
e92ce668a8 | |||
6d1e7eb49e |
19 changed files with 398 additions and 163 deletions
|
@ -48,10 +48,11 @@ Create native client with `connect` method. Arguments:
|
||||||
- dial timeout in seconds (0 for the default value)
|
- dial timeout in seconds (0 for the default value)
|
||||||
- stream timeout in seconds (0 for the default value)
|
- stream timeout in seconds (0 for the default value)
|
||||||
- generate object header on the client side (for big object - split locally too)
|
- generate object header on the client side (for big object - split locally too)
|
||||||
|
- max size for generated object header on the client side (for big object - the size that the object is splitted into)
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import native from 'k6/x/frostfs/native';
|
import native from 'k6/x/frostfs/native';
|
||||||
const frostfs_cli = native.connect("s01.frostfs.devenv:8080", "", 0, 0, false)
|
const frostfs_cli = native.connect("s01.frostfs.devenv:8080", "", 0, 0, false, 0)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
55
cmd/xk6-registry/importer/import.go
Normal file
55
cmd/xk6-registry/importer/import.go
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package importer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/xk6-frostfs/internal/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PreGenObj struct {
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
Object string `json:"object"`
|
||||||
|
Container string `json:"container"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreGenerateInfo struct {
|
||||||
|
Buckets []string `json:"buckets"`
|
||||||
|
Containers []string `json:"containers"`
|
||||||
|
Objects []PreGenObj `json:"objects"`
|
||||||
|
ObjSize string `json:"obj_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportJSONPreGen writes objects from pregenerated JSON file
|
||||||
|
// to the registry.
|
||||||
|
// Note that ImportJSONPreGen does not check if object already
|
||||||
|
// exists in the registry so in case of re-entry the registry
|
||||||
|
// will have two entities representing the same object.
|
||||||
|
func ImportJSONPreGen(o *registry.ObjRegistry, filename string) error {
|
||||||
|
f, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pregenInfo PreGenerateInfo
|
||||||
|
err = json.Unmarshal(f, &pregenInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddObject uses DB.Batch to combine concurrent Batch calls
|
||||||
|
// into a single Bolt transaction. DB.Batch is limited by
|
||||||
|
// DB.MaxBatchDelay which may affect perfomance.
|
||||||
|
for _, obj := range pregenInfo.Objects {
|
||||||
|
if obj.Bucket != "" {
|
||||||
|
err = o.AddObject("", "", obj.Bucket, obj.Object, "")
|
||||||
|
} else {
|
||||||
|
err = o.AddObject(obj.Container, obj.Object, "", "", "")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
27
cmd/xk6-registry/importer/root.go
Normal file
27
cmd/xk6-registry/importer/root.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package importer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.frostfs.info/TrueCloudLab/xk6-frostfs/internal/registry"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cmd represents the import command.
|
||||||
|
var Cmd = &cobra.Command{
|
||||||
|
Use: "import",
|
||||||
|
Short: "Import objects into registry",
|
||||||
|
Long: "Import objects into registry from pregenerated files",
|
||||||
|
Example: `xk6-registry import registry.bolt preset.json
|
||||||
|
xk6-registry import --status created registry.bolt preset.json another_preset.json`,
|
||||||
|
RunE: runCmd,
|
||||||
|
Args: cobra.MinimumNArgs(2),
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCmd(cmd *cobra.Command, args []string) error {
|
||||||
|
objRegistry := registry.NewObjRegistry(cmd.Context(), args[0])
|
||||||
|
for i := 1; i < len(args); i++ {
|
||||||
|
if err := ImportJSONPreGen(objRegistry, args[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
18
cmd/xk6-registry/main.go
Normal file
18
cmd/xk6-registry/main.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
|
|
||||||
|
if cmd, err := rootCmd.ExecuteContextC(ctx); err != nil {
|
||||||
|
cmd.PrintErrln("Error:", err.Error())
|
||||||
|
cmd.PrintErrf("Run '%v --help' for usage.\n", cmd.CommandPath())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
33
cmd/xk6-registry/root.go
Normal file
33
cmd/xk6-registry/root.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/xk6-frostfs/cmd/xk6-registry/importer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/xk6-frostfs/internal/version"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "xk6-registry",
|
||||||
|
Version: version.Version,
|
||||||
|
Short: "Command Line Tool to work with Registry",
|
||||||
|
Long: `Registry provides tools to work with object registry for xk6.
|
||||||
|
It contains command for importing objects in registry from preset`,
|
||||||
|
SilenceErrors: true,
|
||||||
|
SilenceUsage: true,
|
||||||
|
Run: rootCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cobra.AddTemplateFunc("runtimeVersion", runtime.Version)
|
||||||
|
rootCmd.SetVersionTemplate(`FrostFS xk6-registry
|
||||||
|
{{printf "Version: %s" .Version }}
|
||||||
|
GoVersion: {{ runtimeVersion }}
|
||||||
|
`)
|
||||||
|
rootCmd.AddCommand(importer.Cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootCmdRun(cmd *cobra.Command, _ []string) {
|
||||||
|
_ = cmd.Usage()
|
||||||
|
}
|
|
@ -3,11 +3,11 @@ import { fail } from "k6";
|
||||||
import { uuidv4 } from '../scenarios/libs/k6-utils-1.4.0.js';
|
import { uuidv4 } from '../scenarios/libs/k6-utils-1.4.0.js';
|
||||||
|
|
||||||
const payload = open('../go.sum', 'b');
|
const payload = open('../go.sum', 'b');
|
||||||
const frostfs_cli = native.connect("s01.frostfs.devenv:8080", "1dd37fba80fec4e6a6f13fd708d8dcb3b29def768017052f6c930fa1c5d90bbb", 0, 0, false)
|
const frostfs_cli = native.connect("s01.frostfs.devenv:8080", "1dd37fba80fec4e6a6f13fd708d8dcb3b29def768017052f6c930fa1c5d90bbb", 0, 0, false, 0)
|
||||||
|
|
||||||
export const options = {
|
export const options = {
|
||||||
stages: [
|
stages: [
|
||||||
{duration: '30s', target: 10},
|
{ duration: '30s', target: 10 },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export function setup() {
|
||||||
fail(res.error)
|
fail(res.error)
|
||||||
}
|
}
|
||||||
console.info("created container", res.container_id)
|
console.info("created container", res.container_id)
|
||||||
return {container_id: res.container_id}
|
return { container_id: res.container_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (data) {
|
export default function (data) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { uuidv4 } from '../scenarios/libs/k6-utils-1.4.0.js';
|
||||||
|
|
||||||
const payload = open('../go.sum', 'b');
|
const payload = open('../go.sum', 'b');
|
||||||
const container = "AjSxSNNXbJUDPqqKYm1VbFVDGCakbpUNH8aGjPmGAH3B"
|
const container = "AjSxSNNXbJUDPqqKYm1VbFVDGCakbpUNH8aGjPmGAH3B"
|
||||||
const frostfs_cli = native.connect("s01.frostfs.devenv:8080", "", 0, 0, false)
|
const frostfs_cli = native.connect("s01.frostfs.devenv:8080", "", 0, 0, false, 0)
|
||||||
const frostfs_obj = frostfs_cli.onsite(container, payload)
|
const frostfs_obj = frostfs_cli.onsite(container, payload)
|
||||||
|
|
||||||
export const options = {
|
export const options = {
|
||||||
|
@ -14,11 +14,11 @@ export const options = {
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
let headers = {
|
let headers = {
|
||||||
'unique_header': uuidv4()
|
'unique_header': uuidv4()
|
||||||
}
|
}
|
||||||
let resp = frostfs_obj.put(headers)
|
let resp = frostfs_obj.put(headers)
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
frostfs_cli.get(container, resp.object_id)
|
frostfs_cli.get(container, resp.object_id)
|
||||||
} else {
|
} else {
|
||||||
console.log(resp.error)
|
console.log(resp.error)
|
||||||
}
|
}
|
||||||
|
|
58
internal/native/cache.go
Normal file
58
internal/native/cache.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package native
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
const networkCacheTTL = time.Minute
|
||||||
|
|
||||||
|
var networkInfoCache = &networkInfoCacheT{}
|
||||||
|
|
||||||
|
type networkInfoCacheT struct {
|
||||||
|
guard sync.RWMutex
|
||||||
|
current *netmap.NetworkInfo
|
||||||
|
fetchTS time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *networkInfoCacheT) getOrFetch(ctx context.Context, cli *client.Client) (*netmap.NetworkInfo, error) {
|
||||||
|
if v := c.get(); v != nil {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return c.fetch(ctx, cli)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *networkInfoCacheT) get() *netmap.NetworkInfo {
|
||||||
|
c.guard.RLock()
|
||||||
|
defer c.guard.RUnlock()
|
||||||
|
|
||||||
|
if c.current == nil || time.Since(c.fetchTS) > networkCacheTTL {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.current
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *networkInfoCacheT) fetch(ctx context.Context, cli *client.Client) (*netmap.NetworkInfo, error) {
|
||||||
|
c.guard.Lock()
|
||||||
|
defer c.guard.Unlock()
|
||||||
|
|
||||||
|
if time.Since(c.fetchTS) <= networkCacheTTL {
|
||||||
|
return c.current, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := cli.NetworkInfo(ctx, client.PrmNetworkInfo{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v := res.Info()
|
||||||
|
c.current = &v
|
||||||
|
c.fetchTS = time.Now()
|
||||||
|
|
||||||
|
return c.current, nil
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ type (
|
||||||
tok session.Object
|
tok session.Object
|
||||||
cli *client.Client
|
cli *client.Client
|
||||||
prepareLocally bool
|
prepareLocally bool
|
||||||
|
maxObjSize uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
PutResponse struct {
|
PutResponse struct {
|
||||||
|
@ -71,6 +72,7 @@ type (
|
||||||
hdr object.Object
|
hdr object.Object
|
||||||
payload []byte
|
payload []byte
|
||||||
prepareLocally bool
|
prepareLocally bool
|
||||||
|
maxObjSize uint64
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -103,7 +105,7 @@ func (c *Client) Put(containerID string, headers map[string]string, payload data
|
||||||
o.SetOwnerID(owner)
|
o.SetOwnerID(owner)
|
||||||
o.SetAttributes(attrs...)
|
o.SetAttributes(attrs...)
|
||||||
|
|
||||||
resp, err := put(c.vu, c.cli, c.prepareLocally, &tok, &o, payload, chunkSize)
|
resp, err := put(c.vu, c.cli, c.prepareLocally, &tok, &o, payload, chunkSize, c.maxObjSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PutResponse{Success: false, Error: err.Error()}
|
return PutResponse{Success: false, Error: err.Error()}
|
||||||
}
|
}
|
||||||
|
@ -373,6 +375,7 @@ func (c *Client) Onsite(containerID string, payload datagen.Payload) PreparedObj
|
||||||
hdr: *obj,
|
hdr: *obj,
|
||||||
payload: data,
|
payload: data,
|
||||||
prepareLocally: c.prepareLocally,
|
prepareLocally: c.prepareLocally,
|
||||||
|
maxObjSize: c.maxObjSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +401,7 @@ func (p PreparedObject) Put(headers map[string]string) PutResponse {
|
||||||
return PutResponse{Success: false, Error: err.Error()}
|
return PutResponse{Success: false, Error: err.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = put(p.vu, p.cli, p.prepareLocally, nil, &obj, datagen.NewFixedPayload(p.payload), 0)
|
_, err = put(p.vu, p.cli, p.prepareLocally, nil, &obj, datagen.NewFixedPayload(p.payload), 0, p.maxObjSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PutResponse{Success: false, Error: err.Error()}
|
return PutResponse{Success: false, Error: err.Error()}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +416,7 @@ func (s epochSource) CurrentEpoch() uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func put(vu modules.VU, cli *client.Client, prepareLocally bool, tok *session.Object,
|
func put(vu modules.VU, cli *client.Client, prepareLocally bool, tok *session.Object,
|
||||||
hdr *object.Object, payload datagen.Payload, chunkSize int,
|
hdr *object.Object, payload datagen.Payload, chunkSize int, maxObjSize uint64,
|
||||||
) (*client.ResObjectPut, error) {
|
) (*client.ResObjectPut, error) {
|
||||||
bufSize := defaultBufferSize
|
bufSize := defaultBufferSize
|
||||||
if chunkSize > 0 {
|
if chunkSize > 0 {
|
||||||
|
@ -434,13 +437,16 @@ func put(vu modules.VU, cli *client.Client, prepareLocally bool, tok *session.Ob
|
||||||
prm.MaxChunkLength = chunkSize
|
prm.MaxChunkLength = chunkSize
|
||||||
}
|
}
|
||||||
if prepareLocally {
|
if prepareLocally {
|
||||||
res, err := cli.NetworkInfo(vu.Context(), client.PrmNetworkInfo{})
|
ni, err := networkInfoCache.getOrFetch(vu.Context(), cli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
prm.MaxSize = res.Info().MaxObjectSize()
|
prm.MaxSize = ni.MaxObjectSize()
|
||||||
prm.EpochSource = epochSource(res.Info().CurrentEpoch())
|
prm.EpochSource = epochSource(ni.CurrentEpoch())
|
||||||
prm.WithoutHomomorphHash = true
|
prm.WithoutHomomorphHash = true
|
||||||
|
if maxObjSize > 0 {
|
||||||
|
prm.MaxSize = maxObjSize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objectWriter, err := cli.ObjectPutInit(vu.Context(), prm)
|
objectWriter, err := cli.ObjectPutInit(vu.Context(), prm)
|
||||||
|
|
|
@ -52,13 +52,17 @@ func (n *Native) Exports() modules.Exports {
|
||||||
return modules.Exports{Default: n}
|
return modules.Exports{Default: n}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Native) Connect(endpoint, hexPrivateKey string, dialTimeout, streamTimeout int, prepareLocally bool) (*Client, error) {
|
func (n *Native) Connect(endpoint, hexPrivateKey string, dialTimeout, streamTimeout int, prepareLocally bool, maxObjSize int) (*Client, error) {
|
||||||
var (
|
var (
|
||||||
cli client.Client
|
cli client.Client
|
||||||
pk *keys.PrivateKey
|
pk *keys.PrivateKey
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if maxObjSize < 0 {
|
||||||
|
return nil, fmt.Errorf("max object size value must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
pk, err = keys.NewPrivateKey()
|
pk, err = keys.NewPrivateKey()
|
||||||
if len(hexPrivateKey) != 0 {
|
if len(hexPrivateKey) != 0 {
|
||||||
pk, err = keys.NewPrivateKeyFromHex(hexPrivateKey)
|
pk, err = keys.NewPrivateKeyFromHex(hexPrivateKey)
|
||||||
|
@ -114,6 +118,16 @@ func (n *Native) Connect(endpoint, hexPrivateKey string, dialTimeout, streamTime
|
||||||
tok.SetAuthKey(&key)
|
tok.SetAuthKey(&key)
|
||||||
tok.SetExp(exp)
|
tok.SetExp(exp)
|
||||||
|
|
||||||
|
if prepareLocally && maxObjSize > 0 {
|
||||||
|
res, err := cli.NetworkInfo(n.vu.Context(), client.PrmNetworkInfo{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if uint64(maxObjSize) > res.Info().MaxObjectSize() {
|
||||||
|
return nil, fmt.Errorf("max object size must be not greater than %d bytes", res.Info().MaxObjectSize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// register metrics
|
// register metrics
|
||||||
|
|
||||||
objPutSuccess, _ = stats.Registry.NewMetric("frostfs_obj_put_success", metrics.Counter)
|
objPutSuccess, _ = stats.Registry.NewMetric("frostfs_obj_put_success", metrics.Counter)
|
||||||
|
@ -140,5 +154,6 @@ func (n *Native) Connect(endpoint, hexPrivateKey string, dialTimeout, streamTime
|
||||||
tok: tok,
|
tok: tok,
|
||||||
cli: &cli,
|
cli: &cli,
|
||||||
prepareLocally: prepareLocally,
|
prepareLocally: prepareLocally,
|
||||||
|
maxObjSize: uint64(maxObjSize),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const nextObjectTimeout = 10 * time.Second
|
||||||
|
|
||||||
type ObjFilter struct {
|
type ObjFilter struct {
|
||||||
Status string
|
Status string
|
||||||
Age int
|
Age int
|
||||||
|
@ -57,7 +59,16 @@ func NewObjSelector(registry *ObjRegistry, selectionSize int, kind SelectorKind,
|
||||||
// - underlying registry context is done, nil objects will be returned on the
|
// - underlying registry context is done, nil objects will be returned on the
|
||||||
// currently blocked and every further NextObject calls.
|
// currently blocked and every further NextObject calls.
|
||||||
func (o *ObjSelector) NextObject() *ObjectInfo {
|
func (o *ObjSelector) NextObject() *ObjectInfo {
|
||||||
return <-o.objChan
|
if o.kind == SelectorOneshot {
|
||||||
|
return <-o.objChan
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-time.After(nextObjectTimeout):
|
||||||
|
return nil
|
||||||
|
case obj := <-o.objChan:
|
||||||
|
return obj
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns total number of objects that match filter of the selector.
|
// Count returns total number of objects that match filter of the selector.
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import {sleep} from 'k6';
|
import { sleep } from 'k6';
|
||||||
import {SharedArray} from 'k6/data';
|
import { SharedArray } from 'k6/data';
|
||||||
import exec from 'k6/execution';
|
import exec from 'k6/execution';
|
||||||
import logging from 'k6/x/frostfs/logging';
|
import logging from 'k6/x/frostfs/logging';
|
||||||
import native from 'k6/x/frostfs/native';
|
import native from 'k6/x/frostfs/native';
|
||||||
import registry from 'k6/x/frostfs/registry';
|
import registry from 'k6/x/frostfs/registry';
|
||||||
import stats from 'k6/x/frostfs/stats';
|
import stats from 'k6/x/frostfs/stats';
|
||||||
|
|
||||||
import {newGenerator} from './libs/datagen.js';
|
import { newGenerator } from './libs/datagen.js';
|
||||||
import {parseEnv} from './libs/env-parser.js';
|
import { parseEnv } from './libs/env-parser.js';
|
||||||
import {textSummary} from './libs/k6-summary-0.0.2.js';
|
import { textSummary } from './libs/k6-summary-0.0.2.js';
|
||||||
import {uuidv4} from './libs/k6-utils-1.4.0.js';
|
import { uuidv4 } from './libs/k6-utils-1.4.0.js';
|
||||||
|
|
||||||
parseEnv();
|
parseEnv();
|
||||||
|
|
||||||
const obj_list = new SharedArray(
|
const obj_list = new SharedArray(
|
||||||
'obj_list',
|
'obj_list',
|
||||||
function() { return JSON.parse(open(__ENV.PREGEN_JSON)).objects; });
|
function () { return JSON.parse(open(__ENV.PREGEN_JSON)).objects; });
|
||||||
|
|
||||||
const container_list = new SharedArray(
|
const container_list = new SharedArray(
|
||||||
'container_list',
|
'container_list',
|
||||||
function() { return JSON.parse(open(__ENV.PREGEN_JSON)).containers; });
|
function () { return JSON.parse(open(__ENV.PREGEN_JSON)).containers; });
|
||||||
|
|
||||||
const read_size = JSON.parse(open(__ENV.PREGEN_JSON)).obj_size;
|
const read_size = JSON.parse(open(__ENV.PREGEN_JSON)).obj_size;
|
||||||
const summary_json = __ENV.SUMMARY_JSON || '/tmp/summary.json';
|
const summary_json = __ENV.SUMMARY_JSON || '/tmp/summary.json';
|
||||||
|
@ -27,17 +27,17 @@ const summary_json = __ENV.SUMMARY_JSON || '/tmp/summary.json';
|
||||||
// Select random gRPC endpoint for current VU
|
// Select random gRPC endpoint for current VU
|
||||||
const grpc_endpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
const grpc_endpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
||||||
const grpc_endpoint =
|
const grpc_endpoint =
|
||||||
grpc_endpoints[Math.floor(Math.random() * grpc_endpoints.length)];
|
grpc_endpoints[Math.floor(Math.random() * grpc_endpoints.length)];
|
||||||
const grpc_client = native.connect(
|
const grpc_client = native.connect(
|
||||||
grpc_endpoint, '', __ENV.DIAL_TIMEOUT ? parseInt(__ENV.DIAL_TIMEOUT) : 5,
|
grpc_endpoint, '', __ENV.DIAL_TIMEOUT ? parseInt(__ENV.DIAL_TIMEOUT) : 5,
|
||||||
__ENV.STREAM_TIMEOUT ? parseInt(__ENV.STREAM_TIMEOUT) : 60,
|
__ENV.STREAM_TIMEOUT ? parseInt(__ENV.STREAM_TIMEOUT) : 60,
|
||||||
__ENV.PREPARE_LOCALLY ? __ENV.PREPARE_LOCALLY.toLowerCase() === 'true'
|
__ENV.PREPARE_LOCALLY ? __ENV.PREPARE_LOCALLY.toLowerCase() === 'true' : false,
|
||||||
: false);
|
1024 * parseInt(__ENV.MAX_OBJECT_SIZE || '0'));
|
||||||
const log = logging.new().withField('endpoint', grpc_endpoint);
|
const log = logging.new().withField('endpoint', grpc_endpoint);
|
||||||
|
|
||||||
const registry_enabled = !!__ENV.REGISTRY_FILE;
|
const registry_enabled = !!__ENV.REGISTRY_FILE;
|
||||||
const obj_registry =
|
const obj_registry =
|
||||||
registry_enabled ? registry.open(__ENV.REGISTRY_FILE) : undefined;
|
registry_enabled ? registry.open(__ENV.REGISTRY_FILE) : undefined;
|
||||||
|
|
||||||
const duration = __ENV.DURATION;
|
const duration = __ENV.DURATION;
|
||||||
|
|
||||||
|
@ -49,11 +49,11 @@ const read_age = __ENV.READ_AGE ? parseInt(__ENV.READ_AGE) : 10;
|
||||||
let obj_to_read_selector = undefined;
|
let obj_to_read_selector = undefined;
|
||||||
if (registry_enabled) {
|
if (registry_enabled) {
|
||||||
obj_to_read_selector = registry.getLoopedSelector(
|
obj_to_read_selector = registry.getLoopedSelector(
|
||||||
__ENV.REGISTRY_FILE, 'obj_to_read',
|
__ENV.REGISTRY_FILE, 'obj_to_read',
|
||||||
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
||||||
status : 'created',
|
status: 'created',
|
||||||
age : read_age,
|
age: read_age,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const scenarios = {};
|
const scenarios = {};
|
||||||
|
@ -63,11 +63,11 @@ const write_grpc_chunk_size = 1024 * parseInt(__ENV.GRPC_CHUNK_SIZE || '0')
|
||||||
const generator = newGenerator(write_vu_count > 0);
|
const generator = newGenerator(write_vu_count > 0);
|
||||||
if (write_vu_count > 0) {
|
if (write_vu_count > 0) {
|
||||||
scenarios.write = {
|
scenarios.write = {
|
||||||
executor : 'constant-vus',
|
executor: 'constant-vus',
|
||||||
vus : write_vu_count,
|
vus: write_vu_count,
|
||||||
duration : `${duration}s`,
|
duration: `${duration}s`,
|
||||||
exec : 'obj_write',
|
exec: 'obj_write',
|
||||||
gracefulStop : '5s',
|
gracefulStop: '5s',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,24 +78,24 @@ if (registry_enabled && delete_age) {
|
||||||
obj_to_delete_exit_on_null = write_vu_count == 0;
|
obj_to_delete_exit_on_null = write_vu_count == 0;
|
||||||
|
|
||||||
let constructor = obj_to_delete_exit_on_null ? registry.getOneshotSelector
|
let constructor = obj_to_delete_exit_on_null ? registry.getOneshotSelector
|
||||||
: registry.getSelector;
|
: registry.getSelector;
|
||||||
|
|
||||||
obj_to_delete_selector =
|
obj_to_delete_selector =
|
||||||
constructor(__ENV.REGISTRY_FILE, 'obj_to_delete',
|
constructor(__ENV.REGISTRY_FILE, 'obj_to_delete',
|
||||||
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
||||||
status : 'created',
|
status: 'created',
|
||||||
age : delete_age,
|
age: delete_age,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const read_vu_count = parseInt(__ENV.READERS || '0');
|
const read_vu_count = parseInt(__ENV.READERS || '0');
|
||||||
if (read_vu_count > 0) {
|
if (read_vu_count > 0) {
|
||||||
scenarios.read = {
|
scenarios.read = {
|
||||||
executor : 'constant-vus',
|
executor: 'constant-vus',
|
||||||
vus : read_vu_count,
|
vus: read_vu_count,
|
||||||
duration : `${duration}s`,
|
duration: `${duration}s`,
|
||||||
exec : 'obj_read',
|
exec: 'obj_read',
|
||||||
gracefulStop : '5s',
|
gracefulStop: '5s',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,21 +103,21 @@ const delete_vu_count = parseInt(__ENV.DELETERS || '0');
|
||||||
if (delete_vu_count > 0) {
|
if (delete_vu_count > 0) {
|
||||||
if (!obj_to_delete_selector) {
|
if (!obj_to_delete_selector) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Positive DELETE worker number without a proper object selector');
|
'Positive DELETE worker number without a proper object selector');
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios.delete = {
|
scenarios.delete = {
|
||||||
executor : 'constant-vus',
|
executor: 'constant-vus',
|
||||||
vus : delete_vu_count,
|
vus: delete_vu_count,
|
||||||
duration : `${duration}s`,
|
duration: `${duration}s`,
|
||||||
exec : 'obj_delete',
|
exec: 'obj_delete',
|
||||||
gracefulStop : '5s',
|
gracefulStop: '5s',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const options = {
|
export const options = {
|
||||||
scenarios,
|
scenarios,
|
||||||
setupTimeout : '5s',
|
setupTimeout: '5s',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setup() {
|
export function setup() {
|
||||||
|
@ -133,7 +133,7 @@ export function setup() {
|
||||||
|
|
||||||
const start_timestamp = Date.now()
|
const start_timestamp = Date.now()
|
||||||
console.log(
|
console.log(
|
||||||
`Load started at: ${Date(start_timestamp).toString()}`)
|
`Load started at: ${Date(start_timestamp).toString()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function teardown(data) {
|
export function teardown(data) {
|
||||||
|
@ -142,13 +142,13 @@ export function teardown(data) {
|
||||||
}
|
}
|
||||||
const end_timestamp = Date.now()
|
const end_timestamp = Date.now()
|
||||||
console.log(
|
console.log(
|
||||||
`Load finished at: ${Date(end_timestamp).toString()}`)
|
`Load finished at: ${Date(end_timestamp).toString()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleSummary(data) {
|
export function handleSummary(data) {
|
||||||
return {
|
return {
|
||||||
'stdout' : textSummary(data, {indent : ' ', enableColors : false}),
|
'stdout': textSummary(data, { indent: ' ', enableColors: false }),
|
||||||
[summary_json] : JSON.stringify(data),
|
[summary_json]: JSON.stringify(data),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,13 +157,13 @@ export function obj_write() {
|
||||||
sleep(__ENV.SLEEP_WRITE);
|
sleep(__ENV.SLEEP_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {unique_header : uuidv4()};
|
const headers = { unique_header: uuidv4() };
|
||||||
const container =
|
const container =
|
||||||
container_list[Math.floor(Math.random() * container_list.length)];
|
container_list[Math.floor(Math.random() * container_list.length)];
|
||||||
|
|
||||||
const payload = generator.genPayload();
|
const payload = generator.genPayload();
|
||||||
const resp =
|
const resp =
|
||||||
grpc_client.put(container, headers, payload, write_grpc_chunk_size);
|
grpc_client.put(container, headers, payload, write_grpc_chunk_size);
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
log.withField('cid', container).error(resp.error);
|
log.withField('cid', container).error(resp.error);
|
||||||
return;
|
return;
|
||||||
|
@ -186,7 +186,7 @@ export function obj_read() {
|
||||||
}
|
}
|
||||||
const resp = grpc_client.get(obj.c_id, obj.o_id)
|
const resp = grpc_client.get(obj.c_id, obj.o_id)
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
log.withFields({cid : obj.c_id, oid : obj.o_id}).error(resp.error);
|
log.withFields({ cid: obj.c_id, oid: obj.o_id }).error(resp.error);
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ export function obj_read() {
|
||||||
const obj = obj_list[Math.floor(Math.random() * obj_list.length)];
|
const obj = obj_list[Math.floor(Math.random() * obj_list.length)];
|
||||||
const resp = grpc_client.get(obj.container, obj.object)
|
const resp = grpc_client.get(obj.container, obj.object)
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
log.withFields({cid : obj.container, oid : obj.object}).error(resp.error);
|
log.withFields({ cid: obj.container, oid: obj.object }).error(resp.error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ export function obj_delete() {
|
||||||
const resp = grpc_client.delete(obj.c_id, obj.o_id);
|
const resp = grpc_client.delete(obj.c_id, obj.o_id);
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
// Log errors except (2052 - object already deleted)
|
// Log errors except (2052 - object already deleted)
|
||||||
log.withFields({cid : obj.c_id, oid : obj.o_id}).error(resp.error);
|
log.withFields({ cid: obj.c_id, oid: obj.o_id }).error(resp.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import {sleep} from 'k6';
|
import { sleep } from 'k6';
|
||||||
import {SharedArray} from 'k6/data';
|
import { SharedArray } from 'k6/data';
|
||||||
import logging from 'k6/x/frostfs/logging';
|
import logging from 'k6/x/frostfs/logging';
|
||||||
import native from 'k6/x/frostfs/native';
|
import native from 'k6/x/frostfs/native';
|
||||||
import registry from 'k6/x/frostfs/registry';
|
import registry from 'k6/x/frostfs/registry';
|
||||||
import stats from 'k6/x/frostfs/stats';
|
import stats from 'k6/x/frostfs/stats';
|
||||||
|
|
||||||
import {newGenerator} from './libs/datagen.js';
|
import { newGenerator } from './libs/datagen.js';
|
||||||
import {parseEnv} from './libs/env-parser.js';
|
import { parseEnv } from './libs/env-parser.js';
|
||||||
import {textSummary} from './libs/k6-summary-0.0.2.js';
|
import { textSummary } from './libs/k6-summary-0.0.2.js';
|
||||||
import {uuidv4} from './libs/k6-utils-1.4.0.js';
|
import { uuidv4 } from './libs/k6-utils-1.4.0.js';
|
||||||
|
|
||||||
parseEnv();
|
parseEnv();
|
||||||
|
|
||||||
const obj_list = new SharedArray('obj_list', function() {
|
const obj_list = new SharedArray('obj_list', function () {
|
||||||
return JSON.parse(open(__ENV.PREGEN_JSON)).objects;
|
return JSON.parse(open(__ENV.PREGEN_JSON)).objects;
|
||||||
});
|
});
|
||||||
|
|
||||||
const container_list = new SharedArray('container_list', function() {
|
const container_list = new SharedArray('container_list', function () {
|
||||||
return JSON.parse(open(__ENV.PREGEN_JSON)).containers;
|
return JSON.parse(open(__ENV.PREGEN_JSON)).containers;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,17 +26,17 @@ const summary_json = __ENV.SUMMARY_JSON || '/tmp/summary.json';
|
||||||
// Select random gRPC endpoint for current VU
|
// Select random gRPC endpoint for current VU
|
||||||
const grpc_endpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
const grpc_endpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
||||||
const grpc_endpoint =
|
const grpc_endpoint =
|
||||||
grpc_endpoints[Math.floor(Math.random() * grpc_endpoints.length)];
|
grpc_endpoints[Math.floor(Math.random() * grpc_endpoints.length)];
|
||||||
const grpc_client = native.connect(
|
const grpc_client = native.connect(
|
||||||
grpc_endpoint, '', __ENV.DIAL_TIMEOUT ? parseInt(__ENV.DIAL_TIMEOUT) : 5,
|
grpc_endpoint, '', __ENV.DIAL_TIMEOUT ? parseInt(__ENV.DIAL_TIMEOUT) : 5,
|
||||||
__ENV.STREAM_TIMEOUT ? parseInt(__ENV.STREAM_TIMEOUT) : 60,
|
__ENV.STREAM_TIMEOUT ? parseInt(__ENV.STREAM_TIMEOUT) : 60,
|
||||||
__ENV.PREPARE_LOCALLY ? __ENV.PREPARE_LOCALLY.toLowerCase() === 'true' :
|
__ENV.PREPARE_LOCALLY ? __ENV.PREPARE_LOCALLY.toLowerCase() === 'true' : false,
|
||||||
false);
|
1024 * parseInt(__ENV.MAX_OBJECT_SIZE || '0'));
|
||||||
const log = logging.new().withField('endpoint', grpc_endpoint);
|
const log = logging.new().withField('endpoint', grpc_endpoint);
|
||||||
|
|
||||||
const registry_enabled = !!__ENV.REGISTRY_FILE;
|
const registry_enabled = !!__ENV.REGISTRY_FILE;
|
||||||
const obj_registry =
|
const obj_registry =
|
||||||
registry_enabled ? registry.open(__ENV.REGISTRY_FILE) : undefined;
|
registry_enabled ? registry.open(__ENV.REGISTRY_FILE) : undefined;
|
||||||
|
|
||||||
const duration = __ENV.DURATION;
|
const duration = __ENV.DURATION;
|
||||||
|
|
||||||
|
@ -48,22 +48,22 @@ const delete_age = __ENV.DELETE_AGE ? parseInt(__ENV.DELETE_AGE) : undefined;
|
||||||
let obj_to_delete_selector = undefined;
|
let obj_to_delete_selector = undefined;
|
||||||
if (registry_enabled && delete_age) {
|
if (registry_enabled && delete_age) {
|
||||||
obj_to_delete_selector = registry.getSelector(
|
obj_to_delete_selector = registry.getSelector(
|
||||||
__ENV.REGISTRY_FILE, 'obj_to_delete',
|
__ENV.REGISTRY_FILE, 'obj_to_delete',
|
||||||
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
||||||
status: 'created',
|
status: 'created',
|
||||||
age: delete_age,
|
age: delete_age,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const read_age = __ENV.READ_AGE ? parseInt(__ENV.READ_AGE) : 10;
|
const read_age = __ENV.READ_AGE ? parseInt(__ENV.READ_AGE) : 10;
|
||||||
let obj_to_read_selector = undefined;
|
let obj_to_read_selector = undefined;
|
||||||
if (registry_enabled) {
|
if (registry_enabled) {
|
||||||
obj_to_read_selector = registry.getLoopedSelector(
|
obj_to_read_selector = registry.getLoopedSelector(
|
||||||
__ENV.REGISTRY_FILE, 'obj_to_read',
|
__ENV.REGISTRY_FILE, 'obj_to_read',
|
||||||
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
||||||
status: 'created',
|
status: 'created',
|
||||||
age: read_age,
|
age: read_age,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const scenarios = {};
|
const scenarios = {};
|
||||||
|
@ -109,7 +109,7 @@ const delete_rate = parseInt(__ENV.DELETE_RATE || '0');
|
||||||
if (delete_rate > 0) {
|
if (delete_rate > 0) {
|
||||||
if (!obj_to_delete_selector) {
|
if (!obj_to_delete_selector) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Positive DELETE worker number without a proper object selector');
|
'Positive DELETE worker number without a proper object selector');
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios.delete = {
|
scenarios.delete = {
|
||||||
|
@ -131,7 +131,7 @@ export const options = {
|
||||||
|
|
||||||
export function setup() {
|
export function setup() {
|
||||||
const total_pre_allocated_vu_count =
|
const total_pre_allocated_vu_count =
|
||||||
pre_alloc_write_vus + pre_alloc_read_vus + pre_alloc_delete_vus;
|
pre_alloc_write_vus + pre_alloc_read_vus + pre_alloc_delete_vus;
|
||||||
const total_max_vu_count = max_read_vus + max_write_vus + max_delete_vus
|
const total_max_vu_count = max_read_vus + max_write_vus + max_delete_vus
|
||||||
|
|
||||||
console.log(`Pregenerated containers: ${container_list.length}`);
|
console.log(`Pregenerated containers: ${container_list.length}`);
|
||||||
|
@ -152,7 +152,7 @@ export function setup() {
|
||||||
|
|
||||||
const start_timestamp = Date.now()
|
const start_timestamp = Date.now()
|
||||||
console.log(
|
console.log(
|
||||||
`Load started at: ${Date(start_timestamp).toString()}`)
|
`Load started at: ${Date(start_timestamp).toString()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function teardown(data) {
|
export function teardown(data) {
|
||||||
|
@ -161,12 +161,12 @@ export function teardown(data) {
|
||||||
}
|
}
|
||||||
const end_timestamp = Date.now()
|
const end_timestamp = Date.now()
|
||||||
console.log(
|
console.log(
|
||||||
`Load finished at: ${Date(end_timestamp).toString()}`)
|
`Load finished at: ${Date(end_timestamp).toString()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleSummary(data) {
|
export function handleSummary(data) {
|
||||||
return {
|
return {
|
||||||
'stdout': textSummary(data, {indent: ' ', enableColors: false}),
|
'stdout': textSummary(data, { indent: ' ', enableColors: false }),
|
||||||
[summary_json]: JSON.stringify(data),
|
[summary_json]: JSON.stringify(data),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -176,13 +176,13 @@ export function obj_write() {
|
||||||
sleep(__ENV.SLEEP_WRITE);
|
sleep(__ENV.SLEEP_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {unique_header: uuidv4()};
|
const headers = { unique_header: uuidv4() };
|
||||||
const container =
|
const container =
|
||||||
container_list[Math.floor(Math.random() * container_list.length)];
|
container_list[Math.floor(Math.random() * container_list.length)];
|
||||||
|
|
||||||
const payload = generator.genPayload();
|
const payload = generator.genPayload();
|
||||||
const resp =
|
const resp =
|
||||||
grpc_client.put(container, headers, payload, write_grpc_chunk_size);
|
grpc_client.put(container, headers, payload, write_grpc_chunk_size);
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
log.withField('cid', container).error(resp.error);
|
log.withField('cid', container).error(resp.error);
|
||||||
return;
|
return;
|
||||||
|
@ -205,7 +205,7 @@ export function obj_read() {
|
||||||
}
|
}
|
||||||
const resp = grpc_client.get(obj.c_id, obj.o_id)
|
const resp = grpc_client.get(obj.c_id, obj.o_id)
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
log.withFields({cid: obj.c_id, oid: obj.o_id}).error(resp.error);
|
log.withFields({ cid: obj.c_id, oid: obj.o_id }).error(resp.error);
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ export function obj_read() {
|
||||||
const obj = obj_list[Math.floor(Math.random() * obj_list.length)];
|
const obj = obj_list[Math.floor(Math.random() * obj_list.length)];
|
||||||
const resp = grpc_client.get(obj.container, obj.object)
|
const resp = grpc_client.get(obj.container, obj.object)
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
log.withFields({cid: obj.container, oid: obj.object}).error(resp.error);
|
log.withFields({ cid: obj.container, oid: obj.object }).error(resp.error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ export function obj_delete() {
|
||||||
const resp = grpc_client.delete(obj.c_id, obj.o_id);
|
const resp = grpc_client.delete(obj.c_id, obj.o_id);
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
// Log errors except (2052 - object already deleted)
|
// Log errors except (2052 - object already deleted)
|
||||||
log.withFields({cid: obj.c_id, oid: obj.o_id}).error(resp.error);
|
log.withFields({ cid: obj.c_id, oid: obj.o_id }).error(resp.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,16 @@ from helpers.cmd import execute_cmd, log
|
||||||
|
|
||||||
|
|
||||||
def create_bucket(endpoint, versioning, location, acl, no_verify_ssl):
|
def create_bucket(endpoint, versioning, location, acl, no_verify_ssl):
|
||||||
|
configuration = ""
|
||||||
if location:
|
if location:
|
||||||
location = f"--create-bucket-configuration 'LocationConstraint={location}'"
|
configuration = f"--create-bucket-configuration 'LocationConstraint={location}'"
|
||||||
if acl:
|
if acl:
|
||||||
acl = f"--acl {acl}"
|
acl = f"--acl {acl}"
|
||||||
|
|
||||||
bucket_name = str(uuid.uuid4())
|
bucket_name = str(uuid.uuid4())
|
||||||
no_verify_ssl_str = "--no-verify-ssl" if no_verify_ssl else ""
|
no_verify_ssl_str = "--no-verify-ssl" if no_verify_ssl else ""
|
||||||
cmd_line = f"aws {no_verify_ssl_str} s3api create-bucket --bucket {bucket_name} " \
|
cmd_line = f"aws {no_verify_ssl_str} s3api create-bucket --bucket {bucket_name} " \
|
||||||
f"--endpoint {endpoint} {location} {acl} "
|
f"--endpoint {endpoint} {configuration} {acl} "
|
||||||
cmd_line_ver = f"aws {no_verify_ssl_str} s3api put-bucket-versioning --bucket {bucket_name} " \
|
cmd_line_ver = f"aws {no_verify_ssl_str} s3api put-bucket-versioning --bucket {bucket_name} " \
|
||||||
f"--versioning-configuration Status=Enabled --endpoint {endpoint} {acl} "
|
f"--versioning-configuration Status=Enabled --endpoint {endpoint} {acl} "
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ def create_bucket(endpoint, versioning, location, acl, no_verify_ssl):
|
||||||
else:
|
else:
|
||||||
log(f"Bucket versioning has been applied for bucket {bucket_name}", endpoint)
|
log(f"Bucket versioning has been applied for bucket {bucket_name}", endpoint)
|
||||||
|
|
||||||
log(f"Created bucket: {bucket_name}", endpoint)
|
log(f"Created bucket: {bucket_name} ({location})", endpoint)
|
||||||
return bucket_name
|
return bucket_name
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import re
|
import re
|
||||||
from helpers.cmd import execute_cmd, log
|
from helpers.cmd import execute_cmd, log
|
||||||
|
|
||||||
def create_container(endpoint, policy, wallet_path, config, acl, local=False, depth=0):
|
def create_container(endpoint, policy, container_creation_retry, wallet_path, config, acl, local=False, retry=0):
|
||||||
if depth > 20:
|
if retry > int(container_creation_retry):
|
||||||
raise ValueError(f"unable to create container: too many unsuccessful attempts")
|
raise ValueError(f"unable to create container: too many unsuccessful attempts")
|
||||||
|
|
||||||
if wallet_path:
|
if wallet_path:
|
||||||
|
@ -34,7 +34,7 @@ def create_container(endpoint, policy, wallet_path, config, acl, local=False, de
|
||||||
raise ValueError(f"no CID was parsed from command output:\t{fst_str}")
|
raise ValueError(f"no CID was parsed from command output:\t{fst_str}")
|
||||||
cid = splitted[1]
|
cid = splitted[1]
|
||||||
|
|
||||||
log(f"Created container {cid}", endpoint)
|
log(f"Created container: {cid} ({policy})", endpoint)
|
||||||
|
|
||||||
if not local:
|
if not local:
|
||||||
return cid
|
return cid
|
||||||
|
@ -88,7 +88,7 @@ def create_container(endpoint, policy, wallet_path, config, acl, local=False, de
|
||||||
return cid
|
return cid
|
||||||
|
|
||||||
log(f"Created container {cid} is not stored on {endpoint}, creating another one...", endpoint)
|
log(f"Created container {cid} is not stored on {endpoint}, creating another one...", endpoint)
|
||||||
return create_container(endpoint, policy, wallet_path, config, acl, local, depth + 1)
|
return create_container(endpoint, policy, container_creation_retry, wallet_path, config, acl, local, retry + 1)
|
||||||
|
|
||||||
|
|
||||||
def upload_object(container, payload_filepath, endpoint, wallet_file, wallet_config):
|
def upload_object(container, payload_filepath, endpoint, wallet_file, wallet_config):
|
||||||
|
|
|
@ -15,18 +15,20 @@ from helpers.frostfs_cli import create_container, upload_object
|
||||||
ERROR_WRONG_CONTAINERS_COUNT = 1
|
ERROR_WRONG_CONTAINERS_COUNT = 1
|
||||||
ERROR_WRONG_OBJECTS_COUNT = 2
|
ERROR_WRONG_OBJECTS_COUNT = 2
|
||||||
MAX_WORKERS = 50
|
MAX_WORKERS = 50
|
||||||
|
DEFAULT_POLICY = "REP 2 IN X CBF 2 SELECT 2 FROM * AS X"
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--size', help='Upload objects size in kb')
|
parser.add_argument('--size', help='Upload objects size in kb')
|
||||||
parser.add_argument('--containers', help='Number of containers to create')
|
parser.add_argument('--containers', help='Number of containers to create')
|
||||||
|
parser.add_argument('--retry', default=20, help='Maximum number of retries to create a container')
|
||||||
parser.add_argument('--out', help='JSON file with output')
|
parser.add_argument('--out', help='JSON file with output')
|
||||||
parser.add_argument('--preload_obj', help='Number of pre-loaded objects')
|
parser.add_argument('--preload_obj', help='Number of pre-loaded objects')
|
||||||
parser.add_argument('--wallet', help='Wallet file path')
|
parser.add_argument('--wallet', help='Wallet file path')
|
||||||
parser.add_argument('--config', help='Wallet config file path')
|
parser.add_argument('--config', help='Wallet config file path')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--policy",
|
"--policy",
|
||||||
help="Container placement policy",
|
help=f"Container placement policy. Default is {DEFAULT_POLICY}",
|
||||||
default="REP 2 IN X CBF 2 SELECT 2 FROM * AS X"
|
action="append"
|
||||||
)
|
)
|
||||||
parser.add_argument('--endpoint', help='Nodes addresses separated by comma.')
|
parser.add_argument('--endpoint', help='Nodes addresses separated by comma.')
|
||||||
parser.add_argument('--update', help='Save existed containers')
|
parser.add_argument('--update', help='Save existed containers')
|
||||||
|
@ -46,7 +48,10 @@ def main():
|
||||||
objects_list = []
|
objects_list = []
|
||||||
|
|
||||||
endpoints = args.endpoint.split(',')
|
endpoints = args.endpoint.split(',')
|
||||||
|
if not args.policy:
|
||||||
|
args.policy = [DEFAULT_POLICY]
|
||||||
|
|
||||||
|
container_creation_retry = args.retry
|
||||||
wallet = args.wallet
|
wallet = args.wallet
|
||||||
wallet_config = args.config
|
wallet_config = args.config
|
||||||
workers = int(args.workers)
|
workers = int(args.workers)
|
||||||
|
@ -63,9 +68,9 @@ def main():
|
||||||
containers_count = int(args.containers)
|
containers_count = int(args.containers)
|
||||||
print(f"Create containers: {containers_count}")
|
print(f"Create containers: {containers_count}")
|
||||||
with ProcessPoolExecutor(max_workers=min(MAX_WORKERS, workers)) as executor:
|
with ProcessPoolExecutor(max_workers=min(MAX_WORKERS, workers)) as executor:
|
||||||
containers_runs = [executor.submit(create_container, endpoint, args.policy, wallet, wallet_config, args.acl, args.local)
|
containers_runs = [executor.submit(create_container, endpoint, policy, container_creation_retry, wallet, wallet_config, args.acl, args.local)
|
||||||
for _, endpoint in
|
for _, endpoint, policy in
|
||||||
zip(range(containers_count), cycle(endpoints))]
|
zip(range(containers_count), cycle(endpoints), cycle(args.policy))]
|
||||||
|
|
||||||
for run in containers_runs:
|
for run in containers_runs:
|
||||||
container_id = run.result()
|
container_id = run.result()
|
||||||
|
|
|
@ -11,6 +11,11 @@ from concurrent.futures import ProcessPoolExecutor
|
||||||
from helpers.cmd import random_payload
|
from helpers.cmd import random_payload
|
||||||
from helpers.aws_cli import create_bucket, upload_object
|
from helpers.aws_cli import create_bucket, upload_object
|
||||||
|
|
||||||
|
ERROR_WRONG_CONTAINERS_COUNT = 1
|
||||||
|
ERROR_WRONG_OBJECTS_COUNT = 2
|
||||||
|
MAX_WORKERS = 50
|
||||||
|
DEFAULT_LOCATION = ""
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument('--size', help='Upload objects size in kb.')
|
parser.add_argument('--size', help='Upload objects size in kb.')
|
||||||
|
@ -20,7 +25,7 @@ parser.add_argument('--preload_obj', help='Number of pre-loaded objects.')
|
||||||
parser.add_argument('--endpoint', help='S3 Gateways addresses separated by comma.')
|
parser.add_argument('--endpoint', help='S3 Gateways addresses separated by comma.')
|
||||||
parser.add_argument('--update', help='True/False, False by default. Save existed buckets from target file (--out). '
|
parser.add_argument('--update', help='True/False, False by default. Save existed buckets from target file (--out). '
|
||||||
'New buckets will not be created.')
|
'New buckets will not be created.')
|
||||||
parser.add_argument('--location', help='AWS location. Will be empty, if has not be declared.', default="")
|
parser.add_argument('--location', help=f'AWS location constraint. Default is "{DEFAULT_LOCATION}"', action="append")
|
||||||
parser.add_argument('--versioning', help='True/False, False by default.')
|
parser.add_argument('--versioning', help='True/False, False by default.')
|
||||||
parser.add_argument('--ignore-errors', help='Ignore preset errors', action='store_true')
|
parser.add_argument('--ignore-errors', help='Ignore preset errors', action='store_true')
|
||||||
parser.add_argument('--no-verify-ssl', help='Ignore SSL verifications', action='store_true')
|
parser.add_argument('--no-verify-ssl', help='Ignore SSL verifications', action='store_true')
|
||||||
|
@ -32,10 +37,6 @@ parser.add_argument('--acl', help='Bucket ACL. Default is private. Expected valu
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
print(args)
|
print(args)
|
||||||
|
|
||||||
ERROR_WRONG_CONTAINERS_COUNT = 1
|
|
||||||
ERROR_WRONG_OBJECTS_COUNT = 2
|
|
||||||
MAX_WORKERS = 50
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
buckets = []
|
buckets = []
|
||||||
objects_list = []
|
objects_list = []
|
||||||
|
@ -43,6 +44,8 @@ def main():
|
||||||
no_verify_ssl = args.no_verify_ssl
|
no_verify_ssl = args.no_verify_ssl
|
||||||
|
|
||||||
endpoints = args.endpoint.split(',')
|
endpoints = args.endpoint.split(',')
|
||||||
|
if not args.location:
|
||||||
|
args.location = [DEFAULT_LOCATION]
|
||||||
|
|
||||||
workers = int(args.workers)
|
workers = int(args.workers)
|
||||||
objects_per_bucket = int(args.preload_obj)
|
objects_per_bucket = int(args.preload_obj)
|
||||||
|
@ -59,9 +62,9 @@ def main():
|
||||||
print(f"Create buckets: {buckets_count}")
|
print(f"Create buckets: {buckets_count}")
|
||||||
|
|
||||||
with ProcessPoolExecutor(max_workers=min(MAX_WORKERS, workers)) as executor:
|
with ProcessPoolExecutor(max_workers=min(MAX_WORKERS, workers)) as executor:
|
||||||
buckets_runs = [executor.submit(create_bucket, endpoint, args.versioning, args.location, args.acl, no_verify_ssl)
|
buckets_runs = [executor.submit(create_bucket, endpoint, args.versioning, location, args.acl, no_verify_ssl)
|
||||||
for _, endpoint in
|
for _, endpoint, location in
|
||||||
zip(range(buckets_count), cycle(endpoints))]
|
zip(range(buckets_count), cycle(endpoints), cycle(args.location))]
|
||||||
|
|
||||||
for run in buckets_runs:
|
for run in buckets_runs:
|
||||||
bucket_name = run.result()
|
bucket_name = run.result()
|
||||||
|
|
|
@ -71,11 +71,23 @@ if (write_vu_count > 0) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const read_vu_count = parseInt(__ENV.READERS || '0');
|
||||||
|
if (read_vu_count > 0) {
|
||||||
|
scenarios.read = {
|
||||||
|
executor : 'constant-vus',
|
||||||
|
vus : read_vu_count,
|
||||||
|
duration : `${duration}s`,
|
||||||
|
exec : 'obj_read',
|
||||||
|
gracefulStop : '5s',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const delete_age = __ENV.DELETE_AGE ? parseInt(__ENV.DELETE_AGE) : undefined;
|
const delete_age = __ENV.DELETE_AGE ? parseInt(__ENV.DELETE_AGE) : undefined;
|
||||||
let obj_to_delete_selector = undefined;
|
let obj_to_delete_selector = undefined;
|
||||||
let obj_to_delete_exit_on_null = undefined;
|
let obj_to_delete_exit_on_null = undefined;
|
||||||
if (registry_enabled && delete_age) {
|
|
||||||
obj_to_delete_exit_on_null = write_vu_count == 0;
|
if (registry_enabled ) {
|
||||||
|
obj_to_delete_exit_on_null = (write_vu_count == 0) && (read_vu_count == 0)
|
||||||
|
|
||||||
let constructor = obj_to_delete_exit_on_null ? registry.getOneshotSelector
|
let constructor = obj_to_delete_exit_on_null ? registry.getOneshotSelector
|
||||||
: registry.getSelector;
|
: registry.getSelector;
|
||||||
|
@ -88,16 +100,7 @@ if (registry_enabled && delete_age) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const read_vu_count = parseInt(__ENV.READERS || '0');
|
|
||||||
if (read_vu_count > 0) {
|
|
||||||
scenarios.read = {
|
|
||||||
executor : 'constant-vus',
|
|
||||||
vus : read_vu_count,
|
|
||||||
duration : `${duration}s`,
|
|
||||||
exec : 'obj_read',
|
|
||||||
gracefulStop : '5s',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const delete_vu_count = parseInt(__ENV.DELETERS || '0');
|
const delete_vu_count = parseInt(__ENV.DELETERS || '0');
|
||||||
if (delete_vu_count > 0) {
|
if (delete_vu_count > 0) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import {sleep} from 'k6';
|
import { sleep } from 'k6';
|
||||||
import {Counter} from 'k6/metrics';
|
import { Counter } from 'k6/metrics';
|
||||||
import logging from 'k6/x/frostfs/logging';
|
import logging from 'k6/x/frostfs/logging';
|
||||||
import native from 'k6/x/frostfs/native';
|
import native from 'k6/x/frostfs/native';
|
||||||
import registry from 'k6/x/frostfs/registry';
|
import registry from 'k6/x/frostfs/registry';
|
||||||
import s3 from 'k6/x/frostfs/s3';
|
import s3 from 'k6/x/frostfs/s3';
|
||||||
import stats from 'k6/x/frostfs/stats';
|
import stats from 'k6/x/frostfs/stats';
|
||||||
|
|
||||||
import {parseEnv} from './libs/env-parser.js';
|
import { parseEnv } from './libs/env-parser.js';
|
||||||
import {textSummary} from './libs/k6-summary-0.0.2.js';
|
import { textSummary } from './libs/k6-summary-0.0.2.js';
|
||||||
|
|
||||||
parseEnv();
|
parseEnv();
|
||||||
|
|
||||||
|
@ -39,24 +39,23 @@ let grpc_client = undefined;
|
||||||
if (__ENV.GRPC_ENDPOINTS) {
|
if (__ENV.GRPC_ENDPOINTS) {
|
||||||
const grpcEndpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
const grpcEndpoints = __ENV.GRPC_ENDPOINTS.split(',');
|
||||||
const grpcEndpoint =
|
const grpcEndpoint =
|
||||||
grpcEndpoints[Math.floor(Math.random() * grpcEndpoints.length)];
|
grpcEndpoints[Math.floor(Math.random() * grpcEndpoints.length)];
|
||||||
log = log.withField('endpoint', grpcEndpoint);
|
log = log.withField('endpoint', grpcEndpoint);
|
||||||
grpc_client = native.connect(
|
grpc_client = native.connect(
|
||||||
grpcEndpoint, '', __ENV.DIAL_TIMEOUT ? parseInt(__ENV.DIAL_TIMEOUT) : 0,
|
grpcEndpoint, '', __ENV.DIAL_TIMEOUT ? parseInt(__ENV.DIAL_TIMEOUT) : 0,
|
||||||
__ENV.STREAM_TIMEOUT ? parseInt(__ENV.STREAM_TIMEOUT) : 0,
|
__ENV.STREAM_TIMEOUT ? parseInt(__ENV.STREAM_TIMEOUT) : 0,
|
||||||
__ENV.PREPARE_LOCALLY ? __ENV.PREPARE_LOCALLY.toLowerCase() === 'true' :
|
__ENV.PREPARE_LOCALLY ? __ENV.PREPARE_LOCALLY.toLowerCase() === 'true' : false,
|
||||||
false,
|
1024 * parseInt(__ENV.MAX_OBJECT_SIZE || '0'));
|
||||||
'');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to random S3 endpoint
|
// Connect to random S3 endpoint
|
||||||
let s3_client = undefined;
|
let s3_client = undefined;
|
||||||
if (__ENV.S3_ENDPOINTS) {
|
if (__ENV.S3_ENDPOINTS) {
|
||||||
const no_verify_ssl = __ENV.NO_VERIFY_SSL || 'true';
|
const no_verify_ssl = __ENV.NO_VERIFY_SSL || 'true';
|
||||||
const connection_args = {no_verify_ssl: no_verify_ssl};
|
const connection_args = { no_verify_ssl: no_verify_ssl };
|
||||||
const s3_endpoints = __ENV.S3_ENDPOINTS.split(',');
|
const s3_endpoints = __ENV.S3_ENDPOINTS.split(',');
|
||||||
const s3_endpoint =
|
const s3_endpoint =
|
||||||
s3_endpoints[Math.floor(Math.random() * s3_endpoints.length)];
|
s3_endpoints[Math.floor(Math.random() * s3_endpoints.length)];
|
||||||
log = log.withField('endpoint', s3_endpoint);
|
log = log.withField('endpoint', s3_endpoint);
|
||||||
s3_client = s3.connect(s3_endpoint, connection_args);
|
s3_client = s3.connect(s3_endpoint, connection_args);
|
||||||
}
|
}
|
||||||
|
@ -65,10 +64,10 @@ if (__ENV.S3_ENDPOINTS) {
|
||||||
// execute as many iterations as there are objects. Each object will have 3
|
// execute as many iterations as there are objects. Each object will have 3
|
||||||
// retries to be verified
|
// retries to be verified
|
||||||
const obj_to_verify_selector = registry.getSelector(
|
const obj_to_verify_selector = registry.getSelector(
|
||||||
__ENV.REGISTRY_FILE, 'obj_to_verify',
|
__ENV.REGISTRY_FILE, 'obj_to_verify',
|
||||||
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {
|
||||||
status: 'created',
|
status: 'created',
|
||||||
});
|
});
|
||||||
const obj_to_verify_count = obj_to_verify_selector.count();
|
const obj_to_verify_count = obj_to_verify_selector.count();
|
||||||
// Execute at least one iteration (executor shared-iterations can't run 0
|
// Execute at least one iteration (executor shared-iterations can't run 0
|
||||||
// iterations)
|
// iterations)
|
||||||
|
@ -97,15 +96,15 @@ export function setup() {
|
||||||
// Populate counters with initial values
|
// Populate counters with initial values
|
||||||
for (const [status, counter] of Object.entries(obj_counters)) {
|
for (const [status, counter] of Object.entries(obj_counters)) {
|
||||||
const obj_selector = registry.getSelector(
|
const obj_selector = registry.getSelector(
|
||||||
__ENV.REGISTRY_FILE, status,
|
__ENV.REGISTRY_FILE, status,
|
||||||
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, {status});
|
__ENV.SELECTION_SIZE ? parseInt(__ENV.SELECTION_SIZE) : 0, { status });
|
||||||
counter.add(obj_selector.count());
|
counter.add(obj_selector.count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleSummary(data) {
|
export function handleSummary(data) {
|
||||||
return {
|
return {
|
||||||
'stdout': textSummary(data, {indent: ' ', enableColors: false}),
|
'stdout': textSummary(data, { indent: ' ', enableColors: false }),
|
||||||
[summary_json]: JSON.stringify(data),
|
[summary_json]: JSON.stringify(data),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -138,19 +137,19 @@ function verify_object_with_retries(obj, attempts) {
|
||||||
// ReferenceError: Cannot access a variable before initialization.
|
// ReferenceError: Cannot access a variable before initialization.
|
||||||
let lg = log;
|
let lg = log;
|
||||||
if (obj.c_id && obj.o_id) {
|
if (obj.c_id && obj.o_id) {
|
||||||
lg = lg.withFields({cid: obj.c_id, oid: obj.o_id});
|
lg = lg.withFields({ cid: obj.c_id, oid: obj.o_id });
|
||||||
result = grpc_client.verifyHash(obj.c_id, obj.o_id, obj.payload_hash);
|
result = grpc_client.verifyHash(obj.c_id, obj.o_id, obj.payload_hash);
|
||||||
} else if (obj.s3_bucket && obj.s3_key) {
|
} else if (obj.s3_bucket && obj.s3_key) {
|
||||||
lg = lg.withFields({bucket: obj.s3_bucket, key: obj.s3_key});
|
lg = lg.withFields({ bucket: obj.s3_bucket, key: obj.s3_key });
|
||||||
result =
|
result =
|
||||||
s3_client.verifyHash(obj.s3_bucket, obj.s3_key, obj.payload_hash);
|
s3_client.verifyHash(obj.s3_bucket, obj.s3_key, obj.payload_hash);
|
||||||
} else {
|
} else {
|
||||||
lg.withFields({
|
lg.withFields({
|
||||||
cid: obj.c_id,
|
cid: obj.c_id,
|
||||||
oid: obj.o_id,
|
oid: obj.o_id,
|
||||||
bucket: obj.s3_bucket,
|
bucket: obj.s3_bucket,
|
||||||
key: obj.s3_key
|
key: obj.s3_key
|
||||||
}).warn(`Object cannot be verified with supported protocols`);
|
}).warn(`Object cannot be verified with supported protocols`);
|
||||||
return 'skipped';
|
return 'skipped';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue