[#222] Add support for aio v1.7.0 in integration tests
Some checks failed
/ DCO (pull_request) Successful in 35s
/ Builds (pull_request) Successful in 1m5s
/ Vulncheck (pull_request) Successful in 59s
/ OCI image (pull_request) Successful in 1m23s
/ Lint (pull_request) Successful in 2m21s
/ Tests (pull_request) Successful in 1m9s
/ Integration tests (pull_request) Failing after 6m41s

Signed-off-by: Aleksey Kravchenko <al.kravchenko@yadro.com>
This commit is contained in:
Aleksey Kravchenko 2025-05-05 11:54:02 +03:00
parent 96a22d98f2
commit 101d6370b8
3 changed files with 147 additions and 5 deletions

View file

@ -14,10 +14,12 @@ import (
"net/http"
"os"
"sort"
"strconv"
"strings"
"testing"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
containerv2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
@ -31,6 +33,8 @@ import (
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
docker "github.com/docker/docker/api/types/container"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/wallet"
@ -51,6 +55,58 @@ const (
testCORSContainerName = "cors"
)
func versionToUint(t *testing.T, v string) uint64 {
parts := strings.Split(v, ".")
require.Len(t, parts, 3)
major, err := strconv.ParseUint(parts[0], 10, 16)
require.NoError(t, err)
minor, err := strconv.ParseUint(parts[1], 10, 16)
require.NoError(t, err)
patch, err := strconv.ParseUint(parts[2], 10, 32)
require.NoError(t, err)
versionNumber := major<<48 | minor<<32 | patch
return versionNumber
}
func publicReadWriteRules() []chain.Rule {
return []chain.Rule{
{
Status: chain.Allow,
Actions: chain.Actions{
Inverted: false,
Names: []string{
native.MethodPutObject,
native.MethodGetObject,
native.MethodHeadObject,
native.MethodDeleteObject,
native.MethodSearchObject,
native.MethodRangeObject,
native.MethodHashObject,
native.MethodPatchObject,
},
},
Resources: chain.Resources{
Inverted: false,
Names: []string{native.ResourceFormatRootObjects},
},
Any: false},
}
}
func privateRules() []chain.Rule {
rule := publicReadWriteRules()
// The same as public-read-write, except that only the owner is allowed to perform the listed actions
rule[0].Condition = []chain.Condition{
{
Op: chain.CondStringEquals,
Kind: chain.KindRequest,
Key: native.PropertyKeyActorRole,
Value: native.PropertyValueContainerRoleOwner,
},
}
return rule
}
func TestIntegration(t *testing.T) {
rootCtx := context.Background()
aioImage := "git.frostfs.info/truecloudlab/frostfs-aio:"
@ -59,6 +115,7 @@ func TestIntegration(t *testing.T) {
"1.3.0",
"1.5.0",
"1.6.5",
"1.7.0",
}
key, err := keys.NewPrivateKeyFromHex("1dd37fba80fec4e6a6f13fd708d8dcb3b29def768017052f6c930fa1c5d90bbb")
require.NoError(t, err)
@ -75,10 +132,16 @@ func TestIntegration(t *testing.T) {
ctx, cancel2 := context.WithCancel(rootCtx)
aioContainer := createDockerContainer(ctx, t, aioImage+version)
if strings.HasPrefix(version, "1.6") {
versionNumber := versionToUint(t, version)
if versionNumber >= versionToUint(t, "1.6.0") {
registerUser(t, ctx, aioContainer, file.Name())
}
createContainer := createContainerWithACL
if versionNumber >= versionToUint(t, "1.7.0") {
createContainer = createContainerWithAPE
}
// Creating CORS container
clientPool := getPool(ctx, t, key)
_, err = createContainer(ctx, t, clientPool, ownerID, testCORSContainerName)
@ -469,15 +532,18 @@ func checkStatusCodes(ctx context.Context, t *testing.T, clientPool *pool.Pool,
t.Run("access denied", func(t *testing.T) {
basicACL := acl.Private
var recs []*eacl.Record
var APERules []chain.Rule
if version == "1.2.7" {
basicACL = acl.PublicRWExtended
rec := eacl.NewRecord()
rec.SetAction(eacl.ActionDeny)
rec.SetOperation(eacl.OperationGet)
recs = append(recs, rec)
} else if versionToUint(t, version) >= versionToUint(t, "1.7.0") {
APERules = privateRules()
}
cnrID, err := createContainerBase(ctx, t, clientPool, ownerID, basicACL, "")
cnrID, err := createContainerBase(ctx, t, clientPool, ownerID, basicACL, APERules, "")
require.NoError(t, err)
key, err := keys.NewPrivateKey()
@ -560,11 +626,77 @@ func getPool(ctx context.Context, t *testing.T, key *keys.PrivateKey) *pool.Pool
return clientPool
}
func createContainer(ctx context.Context, t *testing.T, clientPool *pool.Pool, ownerID user.ID, name string) (cid.ID, error) {
return createContainerBase(ctx, t, clientPool, ownerID, acl.PublicRWExtended, name)
func createContainerWithACL(ctx context.Context, t *testing.T, clientPool *pool.Pool, ownerID user.ID, name string) (cid.ID, error) {
return createContainerBase(ctx, t, clientPool, ownerID, acl.PublicRWExtended, nil, name)
}
func createContainerBase(ctx context.Context, t *testing.T, clientPool *pool.Pool, ownerID user.ID, basicACL acl.Basic, name string) (cid.ID, error) {
func createContainerWithAPE(ctx context.Context, t *testing.T, clientPool *pool.Pool, ownerID user.ID, name string) (cid.ID, error) {
return createContainerBase(ctx, t, clientPool, ownerID, 0, publicReadWriteRules(), name)
}
func waitForAPEBeApplied(ctx context.Context, clientPool *pool.Pool, expectedCh chain.Chain, cnrID cid.ID) error {
prmListAPEChains := pool.PrmListAPEChains{
Target: ape.ChainTarget{
TargetType: ape.TargetTypeContainer,
Name: cnrID.EncodeToString(),
},
}
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
for {
chains, err := clientPool.ListAPEChains(ctx, prmListAPEChains)
if err != nil {
return fmt.Errorf("list APE chains: %w", err)
}
for _, rawChain := range chains {
var ch chain.Chain
err = ch.UnmarshalBinary(rawChain.Raw)
if err != nil {
return fmt.Errorf("unmarshal chain: %w", err)
}
if bytes.Equal(ch.ID, expectedCh.ID) {
// At the moment, according to the core team, there is no way through the API
// to check whether the APE chain stored in the contract has been applied to the container.
// So after we make sure that the APE chain is stored, we just wait for a certain period of time
// (8 seconds by default, the time until the next block and cache invalidation)
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(8 * time.Second):
return nil
}
}
}
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(500 * time.Millisecond):
}
}
}
func addAPEChainToContainer(ctx context.Context, t *testing.T, clientPool *pool.Pool, chainID string, rules []chain.Rule, cnrID cid.ID) {
ch := chain.Chain{
ID: chain.ID(chainID),
Rules: rules,
}
data, err := ch.MarshalBinary()
require.NoError(t, err)
prmAddAPEChain := pool.PrmAddAPEChain{
Target: ape.ChainTarget{
TargetType: ape.TargetTypeContainer,
Name: cnrID.EncodeToString(),
},
Chain: ape.Chain{Raw: data},
}
err = clientPool.AddAPEChain(ctx, prmAddAPEChain)
require.NoError(t, err)
err = waitForAPEBeApplied(ctx, clientPool, ch, cnrID)
require.NoError(t, err)
}
func createContainerBase(ctx context.Context, t *testing.T, clientPool *pool.Pool, ownerID user.ID, basicACL acl.Basic, apeRules []chain.Rule, name string) (cid.ID, error) {
var policy netmap.PlacementPolicy
err := policy.DecodeString("REP 1")
require.NoError(t, err)
@ -601,6 +733,11 @@ func createContainerBase(ctx context.Context, t *testing.T, clientPool *pool.Poo
}
fmt.Println(CID.String())
if len(apeRules) != 0 {
chainID := "http-aio-" + CID.String()
addAPEChainToContainer(ctx, t, clientPool, chainID, apeRules, CID)
}
return CID, err
}

3
go.mod
View file

@ -8,6 +8,7 @@ require (
git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250317082814-87bb55f992dc
git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250425083815-09ff3bf14991
git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02
github.com/bluele/gcache v0.0.2
github.com/docker/docker v27.1.1+incompatible
@ -68,10 +69,12 @@ require (
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/ipfs/go-cid v0.0.7 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect

2
go.sum
View file

@ -52,6 +52,8 @@ git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8l
git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM=
git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8=
git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972/go.mod h1:2hM42MBrlhvN6XToaW6OWNk5ZLcu1FhaukGgxtfpDDI=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250425083815-09ff3bf14991 h1:eTefR8y2y9cg7X5kybIcXDdmABfk/3A2awdmFD3zOsA=
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250425083815-09ff3bf14991/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A=
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA=
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc=
git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA=