mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 10:32:40 +08:00
feat(ql3): govern release version transitions
This commit is contained in:
@@ -12,9 +12,13 @@ const {
|
||||
reviewedOperatorManifest,
|
||||
verifyImageIds,
|
||||
} = require('../../scripts/ql3-cloudnativepg-live-contract.cjs');
|
||||
const {
|
||||
readReleaseIdentity,
|
||||
} = require('../../scripts/lib/ql3-release-identity.cjs');
|
||||
|
||||
const INDEX = `sha256:${'a'.repeat(64)}`;
|
||||
const PLATFORM = `sha256:${'b'.repeat(64)}`;
|
||||
const VERSION = readReleaseIdentity(path.resolve(__dirname, '../..')).version;
|
||||
|
||||
function pods(...imageIds) {
|
||||
return imageIds.map((imageID) => ({
|
||||
@@ -23,10 +27,7 @@ function pods(...imageIds) {
|
||||
}
|
||||
|
||||
test('extracts only one exact digest-pinned image reference', () => {
|
||||
assert.equal(
|
||||
imageDigest(`registry.example/operand:18.4@${INDEX}`),
|
||||
INDEX,
|
||||
);
|
||||
assert.equal(imageDigest(`registry.example/operand:18.4@${INDEX}`), INDEX);
|
||||
assert.throws(() => imageDigest('registry.example/operand:18.4'));
|
||||
assert.throws(() => imageDigest(`registry.example/operand@${INDEX}:tag`));
|
||||
});
|
||||
@@ -41,16 +42,16 @@ test('derives a normal tagged preload reference from a reviewed image', () => {
|
||||
});
|
||||
|
||||
test('replaces exactly one fail-closed application image only in live rendering', () => {
|
||||
const placeholder = `registry.example.com/qinglong/qinglong3-cluster-control@sha256:${'0'.repeat(64)}`;
|
||||
const placeholder = `registry.example.com/qinglong/qinglong3-cluster-control@sha256:${'0'.repeat(
|
||||
64,
|
||||
)}`;
|
||||
const rendered = `kind: Deployment\nspec:\n image: ${placeholder}\n`;
|
||||
assert.equal(
|
||||
localApplicationManifest(rendered),
|
||||
'kind: Deployment\nspec:\n image: registry.example.com/qinglong/qinglong3-cluster-control:3.0.0-alpha.0\n',
|
||||
`kind: Deployment\nspec:\n image: registry.example.com/qinglong/qinglong3-cluster-control:${VERSION}\n`,
|
||||
);
|
||||
assert.throws(() => localApplicationManifest('kind: Deployment\n'));
|
||||
assert.throws(() =>
|
||||
localApplicationManifest(`${rendered}---\n${rendered}`),
|
||||
);
|
||||
assert.throws(() => localApplicationManifest(`${rendered}---\n${rendered}`));
|
||||
});
|
||||
|
||||
test('accepts uniform runtime reporting of the reviewed index or platform digest', () => {
|
||||
@@ -74,7 +75,8 @@ test('accepts uniform runtime reporting of the reviewed index or platform digest
|
||||
|
||||
test('rejects tags, unknown digests, missing status and widened reviewed sets', () => {
|
||||
for (const invoke of [
|
||||
() => verifyImageIds(pods('registry.example/operand:18.4'), [INDEX], 'operand'),
|
||||
() =>
|
||||
verifyImageIds(pods('registry.example/operand:18.4'), [INDEX], 'operand'),
|
||||
() =>
|
||||
verifyImageIds(
|
||||
pods(`registry.example/operand@sha256:${'c'.repeat(64)}`),
|
||||
@@ -82,7 +84,12 @@ test('rejects tags, unknown digests, missing status and widened reviewed sets',
|
||||
'operand',
|
||||
),
|
||||
() => verifyImageIds([{ status: {} }], [INDEX], 'operand'),
|
||||
() => verifyImageIds(pods(`registry.example/operand@${INDEX}`), ['*'], 'operand'),
|
||||
() =>
|
||||
verifyImageIds(
|
||||
pods(`registry.example/operand@${INDEX}`),
|
||||
['*'],
|
||||
'operand',
|
||||
),
|
||||
]) {
|
||||
assert.throws(invoke);
|
||||
}
|
||||
@@ -90,7 +97,10 @@ test('rejects tags, unknown digests, missing status and widened reviewed sets',
|
||||
|
||||
test('creates the namespaced control identity before the migration Job', () => {
|
||||
const source = fs.readFileSync(
|
||||
path.resolve(__dirname, '../../scripts/ql3-cloudnativepg-live-contract.cjs'),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
'../../scripts/ql3-cloudnativepg-live-contract.cjs',
|
||||
),
|
||||
'utf8',
|
||||
);
|
||||
const namespace = source.indexOf(
|
||||
@@ -105,10 +115,7 @@ test('creates the namespaced control identity before the migration Job', () => {
|
||||
assert.ok(namespace >= 0);
|
||||
assert.ok(serviceAccount > namespace);
|
||||
assert.ok(migration > serviceAccount);
|
||||
assert.match(
|
||||
source.slice(namespace, serviceAccount),
|
||||
/kubectl\(\[/,
|
||||
);
|
||||
assert.match(source.slice(namespace, serviceAccount), /kubectl\(\[/);
|
||||
assert.match(
|
||||
source.slice(namespace, migration),
|
||||
/'-n',\s*NAMESPACE,\s*'apply',\s*'-f',\s*'deploy\/kubernetes\/ql3-cluster\/base\/service-account\.yaml'/,
|
||||
@@ -117,7 +124,10 @@ test('creates the namespaced control identity before the migration Job', () => {
|
||||
|
||||
test('provisions the fail-closed worker ingress identity and derives all role evidence from one set', () => {
|
||||
const source = fs.readFileSync(
|
||||
path.resolve(__dirname, '../../scripts/ql3-cloudnativepg-live-contract.cjs'),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
'../../scripts/ql3-cloudnativepg-live-contract.cjs',
|
||||
),
|
||||
'utf8',
|
||||
);
|
||||
assert.match(source, /const roleList = ROLE_NAMES\.map/);
|
||||
@@ -144,7 +154,10 @@ test('provisions the fail-closed worker ingress identity and derives all role ev
|
||||
|
||||
test('preloads both lock-owned images before applying the operator manifest', () => {
|
||||
const source = fs.readFileSync(
|
||||
path.resolve(__dirname, '../../scripts/ql3-cloudnativepg-live-contract.cjs'),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
'../../scripts/ql3-cloudnativepg-live-contract.cjs',
|
||||
),
|
||||
'utf8',
|
||||
);
|
||||
const preload = source.indexOf(
|
||||
@@ -158,14 +171,8 @@ test('preloads both lock-owned images before applying the operator manifest', ()
|
||||
const contract = source.slice(preload, manifest);
|
||||
assert.match(contract, /docker\(\['pull', reviewedImage\]\)/);
|
||||
assert.match(contract, /imageDigest\(reviewedImage\)/);
|
||||
assert.match(
|
||||
contract,
|
||||
/const preloadTag = imageTag\(reviewedImage\)/,
|
||||
);
|
||||
assert.match(
|
||||
contract,
|
||||
/docker\(\['tag', reviewedImage, preloadTag\]\)/,
|
||||
);
|
||||
assert.match(contract, /const preloadTag = imageTag\(reviewedImage\)/);
|
||||
assert.match(contract, /docker\(\['tag', reviewedImage, preloadTag\]\)/);
|
||||
assert.match(
|
||||
contract,
|
||||
/kind\(\['load', 'docker-image', preloadTag, '--name', clusterName\]\)/,
|
||||
@@ -195,12 +202,18 @@ test('rejects a canonical but checksum-unreviewed operator manifest', () => {
|
||||
|
||||
test('bounds remote manifest retries and removes disposable temporary state', () => {
|
||||
const source = fs.readFileSync(
|
||||
path.resolve(__dirname, '../../scripts/ql3-cloudnativepg-live-contract.cjs'),
|
||||
path.resolve(
|
||||
__dirname,
|
||||
'../../scripts/ql3-cloudnativepg-live-contract.cjs',
|
||||
),
|
||||
'utf8',
|
||||
);
|
||||
assert.match(source, /'--http1\.1'/);
|
||||
assert.match(source, /'--retry-max-time',\s*'300'/);
|
||||
assert.match(source, /reviewedOperatorManifest\(downloadedOperatorManifest\)/);
|
||||
assert.match(
|
||||
source,
|
||||
/reviewedOperatorManifest\(downloadedOperatorManifest\)/,
|
||||
);
|
||||
assert.match(
|
||||
source,
|
||||
/fs\.rmSync\(tempDirectory, \{ recursive: true, force: true \}\)/,
|
||||
|
||||
Reference in New Issue
Block a user