Skip to content

Commit ec77093

Browse files
committed
S3UTILS-211: ft tests for listObjectsByReplicationStatus
1 parent b4a493f commit ec77093

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
const vaultclient = require('vaultclient');
2+
const { promisify } = require('util');
3+
const AWS = require('aws-sdk');
4+
const { Logger } = require('werelogs');
5+
const { listObjectsByReplicationStatus } = require('../../listObjectsByReplicationStatus');
6+
const admincredentials = require('../../node_modules/vaultclient/tests/utils/admincredentials.json');
7+
8+
const log = new Logger('listObjectsByReplicationStatus:test');
9+
10+
const iamHost = process.env.IAM_HOST || 'localhost';
11+
const iamPort = process.env.IAM_PORT || 8600;
12+
const s3Host = process.env.S3_HOST || 'localhost';
13+
const s3Port = process.env.S3_PORT || 8000;
14+
15+
const adminAccessKeyId = process.env.ADMIN_ACCESS_KEY_ID || Object.keys(admincredentials)[0];
16+
const adminSecretAccessKey = process.env.ADMIN_SECRET_ACCESS_KEY || admincredentials[adminAccessKeyId];
17+
const region = 'us-east-1';
18+
19+
describe('listObjectsByReplicationStatus', () => {
20+
let vaultClient;
21+
let accountSource;
22+
let accountDest;
23+
24+
beforeAll(async () => {
25+
vaultClient = new vaultclient.Client(
26+
iamHost,
27+
iamPort,
28+
false,
29+
undefined,
30+
undefined,
31+
undefined,
32+
undefined,
33+
adminAccessKeyId,
34+
adminSecretAccessKey
35+
);
36+
});
37+
38+
beforeEach(async () => {
39+
log.info('Setting up test accounts and buckets');
40+
accountSource = await createTestAccount(vaultClient);
41+
accountDest = await createTestAccount(vaultClient);
42+
log.info(`Account source: ${accountSource.accountName} and dest: ${accountDest.accountName} were created`);
43+
log.info('Configuring CRR between source and destination buckets');
44+
await configureCrr(accountSource, accountDest);
45+
});
46+
47+
afterEach(async () => {
48+
// Clean up resources to prevent Jest from hanging
49+
if (accountSource) {
50+
if (accountSource.s3Client && typeof accountSource.s3Client.destroy === 'function') {
51+
accountSource.s3Client.destroy();
52+
}
53+
if (accountSource.iamClient && typeof accountSource.iamClient.destroy === 'function') {
54+
accountSource.iamClient.destroy();
55+
}
56+
}
57+
if (accountDest) {
58+
if (accountDest.s3Client && typeof accountDest.s3Client.destroy === 'function') {
59+
accountDest.s3Client.destroy();
60+
}
61+
if (accountDest.iamClient && typeof accountDest.iamClient.destroy === 'function') {
62+
accountDest.iamClient.destroy();
63+
}
64+
}
65+
});
66+
67+
it('should list objects by replication status', async () => {
68+
// Add data to source bucket
69+
log.info('Uploading test objects to source bucket');
70+
const testObjects = [
71+
{ Key: 'test-object-1', Body: 'data to replicate 1' },
72+
{ Key: 'test-object-2', Body: 'data to replicate 2' },
73+
{ Key: 'test-object-3', Body: 'data to replicate 3' },
74+
];
75+
76+
for (const obj of testObjects) {
77+
await accountSource.s3Client.putObject({
78+
Bucket: accountSource.bucketName,
79+
Key: obj.Key,
80+
Body: obj.Body,
81+
}).promise();
82+
log.info('Uploaded object', { key: obj.Key });
83+
}
84+
85+
// Give some time for replication status to be set
86+
await new Promise(resolve => setTimeout(resolve, 1000));
87+
88+
// Verify objects have replication status
89+
log.info('Verifying objects have replication status');
90+
for (const obj of testObjects) {
91+
const headResult = await accountSource.s3Client.headObject({
92+
Bucket: accountSource.bucketName,
93+
Key: obj.Key,
94+
}).promise();
95+
log.info('Object metadata', {
96+
key: obj.Key,
97+
replicationStatus: headResult.ReplicationStatus,
98+
versionId: headResult.VersionId
99+
});
100+
}
101+
102+
// Execute the listObjectsByReplicationStatus function directly
103+
log.info('Executing listObjectsByReplicationStatus function');
104+
const endpoint = `http://${s3Host}:${s3Port}`;
105+
106+
// Call the function directly for coverage
107+
await listObjectsByReplicationStatus({
108+
buckets: accountSource.bucketName,
109+
accessKey: accountSource.accountAccessKey,
110+
secretKey: accountSource.accountSecretKey,
111+
endpoint,
112+
replicationStatus: 'PENDING,FAILED,COMPLETED',
113+
logger: log,
114+
});
115+
116+
log.info('Function execution completed successfully');
117+
}, 30000); // Increase timeout for script execution
118+
});
119+
120+
async function configureCrr(accountSource, accountDest) {
121+
// activate bucket versionning on source and destination buckets
122+
log.info('Enabling bucket versioning on source and destination buckets');
123+
await accountSource.s3Client.putBucketVersioning({
124+
Bucket: accountSource.bucketName,
125+
VersioningConfiguration: {
126+
Status: 'Enabled',
127+
},
128+
}).promise();
129+
130+
await accountDest.s3Client.putBucketVersioning({
131+
Bucket: accountDest.bucketName,
132+
VersioningConfiguration: {
133+
Status: 'Enabled',
134+
},
135+
}).promise();
136+
137+
log.info('Creating IAM policies and roles for CRR');
138+
// create policy
139+
const policy = {
140+
Version:'2012-10-17',
141+
Statement:[
142+
{
143+
Effect:'Allow',
144+
Action:[
145+
's3:GetObjectVersion',
146+
's3:GetObjectVersionAcl',
147+
's3:ReplicateObject'
148+
],
149+
Resource:[
150+
`arn:aws:s3:::${accountSource.bucketName}/*`
151+
]
152+
},
153+
{
154+
Effect:'Allow',
155+
Action:[
156+
's3:ListBucket',
157+
's3:GetReplicationConfiguration'
158+
],
159+
Resource:[
160+
'arn:aws:s3:::source'
161+
]
162+
},
163+
{
164+
Effect:'Allow',
165+
Action:[
166+
's3:ReplicateObject',
167+
's3:ReplicateDelete'
168+
],
169+
Resource:`arn:aws:s3:::${accountDest.bucketName}/*`
170+
}
171+
]
172+
};
173+
await accountSource.iamClient.createPolicy({
174+
PolicyName: 'crr-policy',
175+
PolicyDocument: JSON.stringify(policy),
176+
}).promise();
177+
178+
await accountDest.iamClient.createPolicy({
179+
PolicyName: 'crr-policy',
180+
PolicyDocument: JSON.stringify(policy),
181+
}).promise();
182+
183+
log.info('Creating IAM roles');
184+
// create trust
185+
const trust = {
186+
Version:'2012-10-17',
187+
Statement:[
188+
{
189+
Effect:'Allow',
190+
Principal:{
191+
Service:'backbeat'
192+
},
193+
Action:'sts:AssumeRole'
194+
}
195+
]
196+
};
197+
await accountSource.iamClient.createRole({
198+
RoleName: 'crr-trust-role',
199+
AssumeRolePolicyDocument: JSON.stringify(trust),
200+
}).promise();
201+
await accountDest.iamClient.createRole({
202+
RoleName: 'crr-trust-role',
203+
AssumeRolePolicyDocument: JSON.stringify(trust),
204+
}).promise();
205+
206+
log.info('Attaching policies to roles');
207+
// attach role to policy
208+
await accountSource.iamClient.attachRolePolicy({
209+
RoleName: 'crr-trust-role',
210+
PolicyArn: `arn:aws:iam::${accountSource.account.account.id}:policy/crr-policy`,
211+
}).promise();
212+
await accountDest.iamClient.attachRolePolicy({
213+
RoleName: 'crr-trust-role',
214+
PolicyArn: `arn:aws:iam::${accountDest.account.account.id}:policy/crr-policy`,
215+
}).promise();
216+
217+
log.info('Setting bucket replication configuration on source bucket');
218+
const replication = {
219+
Role: `arn:aws:iam::${accountSource.account.account.id}:role/crr-trust-role,arn:aws:iam::${accountDest.account.account.id}:role/crr-trust-role`,
220+
Rules: [
221+
{
222+
Prefix: '',
223+
Status: 'Enabled',
224+
Destination: {
225+
Bucket: `arn:aws:s3:::${accountDest.bucketName}`
226+
}
227+
}
228+
]
229+
};
230+
await accountSource.s3Client.putBucketReplication({
231+
Bucket: accountSource.bucketName,
232+
ReplicationConfiguration: replication
233+
}).promise();
234+
235+
}
236+
237+
async function createTestAccount(vaultClient) {
238+
const iamEndpoint = new AWS.Endpoint(`http://${iamHost}:${iamPort}`);
239+
const s3Endpoint = new AWS.Endpoint(`http://${s3Host}:${s3Port}`);
240+
const accountName = `test-account-${Math.random().toString(36).substring(2, 8)}`;
241+
const accountEmail = `${accountName}@example.com`;
242+
const bucketName = accountName;
243+
const iamUser = `${accountName}-user`;
244+
// Create account with vaultclient
245+
const account = await promisify(vaultClient.createAccount.bind(vaultClient))(
246+
accountName, { email: accountEmail });
247+
// Create account access key
248+
const credentials = await promisify(vaultClient.generateAccountAccessKey.bind(
249+
vaultClient))(accountName);
250+
const accountAccessKey = credentials.id;
251+
const accountSecretKey = credentials.value;
252+
253+
const iamClient = new AWS.IAM({
254+
credentials: {
255+
accessKeyId: accountAccessKey,
256+
secretAccessKey: accountSecretKey
257+
},
258+
endpoint: iamEndpoint.href,
259+
region,
260+
});
261+
262+
const s3Client = new AWS.S3({
263+
accessKeyId: accountAccessKey,
264+
secretAccessKey: accountSecretKey,
265+
region,
266+
endpoint: s3Endpoint.href
267+
});
268+
269+
await s3Client.createBucket({ Bucket: bucketName }).promise();
270+
await iamClient.createUser({ UserName: iamUser }).promise();
271+
272+
return {
273+
accountName,
274+
accountEmail,
275+
account,
276+
bucketName,
277+
accountAccessKey,
278+
accountSecretKey,
279+
iamUser,
280+
iamClient,
281+
s3Client,
282+
};
283+
284+
}

0 commit comments

Comments
 (0)