🌳
pt0/deployF/testsF/dockImgCacheSuiteAI.mts
1import * as _ from 'lodash-es'
14// build is possible when the configured builder is usable:
15// - docker/podman: local daemon responds to `info`
16// - kanikojob: builds run in-cluster, so a cluster context suffices (the job surfaces infra failures)
17const isBuildCapable = async () => {
18 const dockName = getDockName()
19 if (dockName === 'kanikojob') return !!getKlusterCtx().cluster_name
20 return (await do2ExecFile({cmdA: [dockName, 'info']})).isSuccess
23// quick reachability probe so the build test skips gracefully where the registry isn't accessible
24// (200 and 401 both mean the registry answered; 401 just means it wants auth)
25const isRegReachable = async (host: string) => {
26 try {
27 const resp = await fetch(`https://${host}/v2/`, {signal: AbortSignal.timeout(3000)})
28 return resp.status === 200 || resp.status === 401
29 } catch { return false }
32// independently derive the registry manifest URL for a repo_name_tag — must match the push target
33// (registryPool[0]), not getDockerPushHost, so the check queries where the image was actually pushed
34const deriveManifestUrl = (repo_name_tag: string) => {
35 const {dockreg_host, dockregPoolA} = getKlusterCtx()
36 const {repoPath, tag} = parseRepoNameTag(repo_name_tag)
37 return mkManifestUrl(dockregPoolA?.[0] ?? dockreg_host, repoPath, tag)
40export const runDockImgCacheSuite: SuiteRunner = async ({ptenv}) => {
41 if (ptenv !== ptenvLocal) return skipSuite('dockimgcache only runs with --ptenv=testlocal')
43 const tests = [{
44 name: 'dockimgcache.pureFns: manifest url parse + format + digest',
45 fn: async () => {
46 const cases = [
47 {input: 'reg.io/repo:tag', expected: {repoPath: 'repo', tag: 'tag'}},
48 {input: 'reg.io:5000/repo/sub:tag', expected: {repoPath: 'repo/sub', tag: 'tag'}},
49 {input: 'reg.io/repo@sha256:abc', expected: {repoPath: 'repo', tag: 'sha256:abc'}},
50 ]
51 for (const {input, expected} of cases) {
52 const got = parseRepoNameTag(input)
53 if (!_.isEqual(got, expected)) return {passed: false, msg: `${input} -> ${JSON.stringify(got)} (expected ${JSON.stringify(expected)})`}
54 }
55 const mk = mkManifestUrl('reg.io', 'repo', 'tag')
56 if (mk !== 'https://reg.io/v2/repo/manifests/tag') return {passed: false, msg: `mkManifestUrl mismatch: ${mk}`}
57 return {passed: true, msg: 'parse + format + digest ok'}
58 },
59 }]
61 const {dockreg_host, cluster_name} = getKlusterCtx()
62 if (dockreg_host && await isRegReachable(dockreg_host) && await isBuildCapable()) {
63 const suffix = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
64 const repo_name_tag = `${dockreg_host}/imgcache-test:${suffix}`
65 // embed suffix in the Dockerfile so df_sha (and thus the kaniko job name) is unique per run;
66 // otherwise kaniko reuses a succeeded job from a prior run that pushed a different tag
67 const dockerfileContent = `# run=${suffix}\nFROM alpine`
69 tests.push({
70 name: 'dockimgcache.customTagBuildReuse: build+push then reuse at custom tag',
71 fn: async () => {
72 const r1 = await dockerBuildPush({repo_name_tag, dockerfileContent, dockreg_host, cluster_name, reqDockPush: true, action: 'apply', name: 'imgcache-test'})
73 if (r1?.imageReused) return {passed: false, msg: `first build reported imageReused on a fresh tag ${repo_name_tag}`}
74 const exists = await doesDockImg2Exist({repo_name_tag, reqDockPush: true})
75 if (!exists) return {passed: false, msg: `doesDockImg2Exist=false after build (checked wrong tag?) ${repo_name_tag}`}
76 const manifest_url = deriveManifestUrl(repo_name_tag)
77 const health = await checkDockImgHealth({manifest_url, verifyBlobs: true})
78 if (!health.exists) return {passed: false, msg: `image not reachable at tag after push: ${health.reason} ${manifest_url}`}
79 const r2 = await dockerBuildPush({repo_name_tag, dockerfileContent, dockreg_host, cluster_name, reqDockPush: true, action: 'apply', name: 'imgcache-test'})
80 if (!r2?.imageReused) return {passed: false, msg: `second build did not reuse (cache check queried wrong tag?) ${repo_name_tag}`}
81 const cleanup = await deleteDockImgByTag({manifest_url}).catch((e: unknown) => ({deleted: false, reason: (e as Error).message}))
82 const cleanupMsg = cleanup.deleted ? ' (cleaned up)' : ` (cleanup: ${cleanup.reason})`
83 return {passed: true, msg: `built+pushed then reused ${repo_name_tag}${cleanupMsg}`}
84 },
85 })
86 }
88 return runTestsWithProgress({tests, suiteName: 'dockimgcache'})
91export const dockImgCacheSuiteConfig: SuiteConfig = {name: 'dockimgcache', runner: runDockImgCacheSuite, deps: [] as const}