Skip to content

Commit

Permalink
Merge branch 'w/2.8/improvement/ZENKO-4890' into w/2.9/improvement/ZE…
Browse files Browse the repository at this point in the history
  • Loading branch information
francoisferrand committed Sep 6, 2024
2 parents 0255834 + e5c7eb5 commit 95b8dbd
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 13 deletions.
8 changes: 8 additions & 0 deletions .github/scripts/end2end/configs/keycloak_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
"realm" : "${OIDC_REALM}",
"enabled" : true,
"groups" : [
{
"name": "AccountTest::DataAccessor",
"path": "/AccountTest::DataAccessor",
"attributes": {},
"realmRoles": [],
"clientRoles": {},
"subGroups": []
},
{
"name": "AccountTest::DataConsumer",
"path": "/AccountTest::DataConsumer",
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/end2end/configs/zenko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ spec:
size: 20Gi
storageClassName: "standard"
kafkaCleaner:
interval: 30s
interval: 1m
minPartitionSizeBytes: 0Mi
minBatchSize: 0
keepAtLeast: 0
Expand Down
4 changes: 3 additions & 1 deletion .github/scripts/end2end/run-e2e-ctst.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ADMIN_PRA_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-ad
STORAGE_MANAGER_USER_NAME="ctst_storage_manager"
STORAGE_ACCOUNT_OWNER_USER_NAME="ctst_storage_account_owner"
DATA_CONSUMER_USER_NAME="ctst_data_consumer"
DATA_ACCESSOR_USER_NAME="ctst_data_accessor"
VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.local"
ZENKO_PORT="80"
KEYCLOAK_TEST_USER=${OIDC_USERNAME}
Expand Down Expand Up @@ -98,6 +99,7 @@ WORLD_PARAMETERS="$(jq -c <<EOF
"StorageManagerUsername":"${STORAGE_MANAGER_USER_NAME}",
"StorageAccountOwnerUsername":"${STORAGE_ACCOUNT_OWNER_USER_NAME}",
"DataConsumerUsername":"${DATA_CONSUMER_USER_NAME}",
"DataAccessorUsername":"${DATA_ACCESSOR_USER_NAME}",
"ServiceUsersCredentials":${SERVICE_USERS_CREDENTIALS},
"AzureAccountName":"${AZURE_ACCOUNT_NAME}",
"AzureAccountKey":"${AZURE_SECRET_KEY}",
Expand Down Expand Up @@ -138,7 +140,7 @@ docker run \
--rm \
--network=host \
"${E2E_IMAGE}" /bin/bash \
-c "SUBDOMAIN=${SUBDOMAIN} CONTROL_PLANE_INGRESS_ENDPOINT=${OIDC_ENDPOINT} ACCOUNT=${ZENKO_ACCOUNT_NAME} KEYCLOAK_REALM=${KEYCLOAK_TEST_REALM_NAME} STORAGE_MANAGER=${STORAGE_MANAGER_USER_NAME} STORAGE_ACCOUNT_OWNER=${STORAGE_ACCOUNT_OWNER_USER_NAME} DATA_CONSUMER=${DATA_CONSUMER_USER_NAME} /ctst/bin/seedKeycloak.sh"; [[ $? -eq 1 ]] && exit 1 || echo 'Keycloak Configured!'
-c "SUBDOMAIN=${SUBDOMAIN} CONTROL_PLANE_INGRESS_ENDPOINT=${OIDC_ENDPOINT} ACCOUNT=${ZENKO_ACCOUNT_NAME} KEYCLOAK_REALM=${KEYCLOAK_TEST_REALM_NAME} STORAGE_MANAGER=${STORAGE_MANAGER_USER_NAME} STORAGE_ACCOUNT_OWNER=${STORAGE_ACCOUNT_OWNER_USER_NAME} DATA_CONSUMER=${DATA_CONSUMER_USER_NAME} DATA_ACCESSOR=${DATA_ACCESSOR_USER_NAME} /ctst/bin/seedKeycloak.sh"; [[ $? -eq 1 ]] && exit 1 || echo 'Keycloak Configured!'

# Grant access to Kube API (insecure, only for testing)
kubectl create clusterrolebinding serviceaccounts-cluster-admin \
Expand Down
2 changes: 1 addition & 1 deletion solution/deps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ cloudserver:
sourceRegistry: ghcr.io/scality
dashboard: cloudserver/cloudserver-dashboards
image: cloudserver
tag: 8.8.31
tag: 8.8.32
envsubst: CLOUDSERVER_TAG
drctl:
sourceRegistry: ghcr.io/scality
Expand Down
6 changes: 6 additions & 0 deletions tests/ctst/features/pra.feature
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Feature: PRA operations

# Check that objects are transitioned in the DR site
Given access keys for the replicated account

Then object "obj-1" should "" be "transitioned" and have the storage class "e2e-cold" on "DR" site
And object "obj-2" should "" be "transitioned" and have the storage class "e2e-cold" on "DR" site

Expand All @@ -35,6 +36,11 @@ Feature: PRA operations
Then object "obj-1" should "" be "restored" and have the storage class "e2e-cold" on "Primary" site
And object "obj-1" should "" be "transitioned" and have the storage class "e2e-cold" on "DR" site

# Test the readonly
When the "vault-check-seeds" cronjobs completes without error on "Primary" site
And the DATA_ACCESSOR user tries to perform PutObject on "DR" site
Then it "should not" pass Vault authentication

# Restore on DR site
When i restore object "obj2-1" for 2 days on "DR" site
Then object "obj2-1" should "" be "restored" and have the storage class "e2e-cold" on "DR" site
Expand Down
2 changes: 1 addition & 1 deletion tests/ctst/features/quotas/CountItems.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ Feature: CountItems measures the utilization metrics
Scenario Outline: Countitems runs without error and compute utilization metrics
Given an existing bucket "" "without" versioning, "without" ObjectLock "without" retention mode
And an object "" that "exists"
When the "CountItems" cronjobs completes without error
When the "count-items" cronjobs completes without error
Then the operation finished without error
23 changes: 16 additions & 7 deletions tests/ctst/steps/cronjobs/countItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@ import { When } from '@cucumber/cucumber';
import Zenko from '../../world/Zenko';
import { createJobAndWaitForCompletion } from 'steps/utils/kubernetes';

When('the {string} cronjobs completes without error', { timeout: 1200000 }, async function (this: Zenko, job: string) {
switch (job) {
case 'CountItems':
await createJobAndWaitForCompletion(this, 'end2end-ops-count-items');
break;
default:
throw new Error(`Unknown job: ${job}`);
async function runCronjob(this: Zenko, job: string, site?: string) {
let zenkoName = 'end2end';

if (site === 'DR') {
zenkoName += '-pra';
}

await createJobAndWaitForCompletion(this, `${zenkoName}-ops-${job}`);
}

When('the {string} cronjobs completes without error', { timeout: 1200000 }, async function (this: Zenko, job: string) {
await runCronjob.call(this, job);
});

When('the {string} cronjobs completes without error on {string} site', { timeout: 1200000 },
async function (this: Zenko, job: string, site: string) {
await runCronjob.call(this, job, site);
});
31 changes: 30 additions & 1 deletion tests/ctst/steps/pra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import {
restoreObject,
verifyObjectLocation,
} from 'steps/utils/utils';
import { Constants, Identity, IdentityEnum, SuperAdmin, Utils } from 'cli-testing';
import { Constants, Identity, IdentityEnum, S3, SuperAdmin, Utils } from 'cli-testing';
import { safeJsonParse } from 'common/utils';
import assert from 'assert';
import { EntityType } from 'world/Zenko';

enum ZenkoDrSinkPhases {
ZenkoDRSinkPhaseNew = 'New',
Expand Down Expand Up @@ -274,6 +275,34 @@ Then('object {string} should {string} be {string} and have the storage class {st
}
});

When('the DATA_ACCESSOR user tries to perform PutObject on {string} site', { timeout: 5 * 60 * 1000 },
async function (this: Zenko, site: string) {
if (site === 'DR') {
Identity.useIdentity(IdentityEnum.ACCOUNT, `${Zenko.sites['source'].accountName}-replicated`);
} else {
Identity.useIdentity(IdentityEnum.ACCOUNT, Zenko.sites['source'].accountName);
}
this.resetCommand();
this.addToSaved('accountName', Zenko.sites['source'].accountName);

// At this point, the role may take some time to be propagated
// so, tolerate up to 5m of retries
let conditionOk = false;
while (!conditionOk) {
try {
await this.setupEntity(EntityType.DATA_ACCESSOR);
conditionOk = true;
} catch (err) {
this.logger.error('Failed to setup entity', { err });
}
}

this.addCommandParameter({ bucket: this.getSaved<string>('bucketName') });
this.addCommandParameter({ key: `${Utils.randomString()}` });

this.setResult(await S3.putObject(this.getCommandParameters()));
});

Then('the kafka DR volume exists', { timeout: 60000 }, async function (this: Zenko) {
const volumeClaim = await getPVCFromLabel(this, 'kafka_cr', 'end2end-pra-sink-base-queue');
this.logger.debug('kafka volume claim', { volumeClaim });
Expand Down
9 changes: 8 additions & 1 deletion tests/ctst/world/Zenko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export enum EntityType {
STORAGE_MANAGER = 'STORAGE_MANAGER',
STORAGE_ACCOUNT_OWNER = 'STORAGE_ACCOUNT_OWNER',
DATA_CONSUMER = 'DATA_CONSUMER',
DATA_ACCESSOR = 'DATA_ACCESSOR',
ASSUME_ROLE_USER = 'ASSUME_ROLE_USER',
ASSUME_ROLE_USER_CROSS_ACCOUNT = 'ASSUME_ROLE_USER_CROSS_ACCOUNT',
}
Expand Down Expand Up @@ -65,6 +66,7 @@ export interface ZenkoWorldParameters extends ClientOptions {
StorageManagerUsername: string;
StorageAccountOwnerUsername: string;
DataConsumerUsername: string;
DataAccessorUsername: string;
ServiceUsersCredentials: string;
KeycloakTestPassword: string;
AzureAccountName: string;
Expand Down Expand Up @@ -224,7 +226,7 @@ export default class Zenko extends World<ZenkoWorldParameters> {
* entity provided to let the test run the AWS CLI command using this particular
* type of entity.
* @param {ScenarioCallerType} entityType - type of entity, can be 'account', 'storage manager',
* 'storage account owner', 'data consumer' or 'iam user'
* 'storage account owner', 'data consumer', 'data accessor' or 'iam user'
* @returns {undefined}
*/
async setupEntity(entityType: string): Promise<void> {
Expand All @@ -250,6 +252,10 @@ export default class Zenko extends World<ZenkoWorldParameters> {
await this.prepareARWWI(this.parameters.DataConsumerUsername || 'data_consumer',
'data-consumer-role', this.parameters.KeycloakTestPassword);
break;
case EntityType.DATA_ACCESSOR:
await this.prepareARWWI(this.parameters.DataAccessorUsername || 'data_accessor',
'data-accessor-role', this.parameters.KeycloakTestPassword);
break;
case EntityType.ASSUME_ROLE_USER:
await this.prepareAssumeRole(false);
break;
Expand Down Expand Up @@ -326,6 +332,7 @@ export default class Zenko extends World<ZenkoWorldParameters> {

nextMarker = GRFWIResponse.data.IsTruncated ? GRFWIResponse.data.Marker : undefined;
callNumber++;
await Utils.sleep(500);
} while (callNumber < 100);

// Ensure we can assume at least one role
Expand Down

0 comments on commit 95b8dbd

Please sign in to comment.