From 7198f711dc3ae580c5b5ca205acd2f5ca6dfddea Mon Sep 17 00:00:00 2001 From: david-leifker <114954101+david-leifker@users.noreply.github.com> Date: Tue, 31 Dec 2024 08:50:44 -0600 Subject: [PATCH 1/8] fix(ci): further consolidate NODE_OPTIONS (#12217) --- .github/workflows/build-and-test.yml | 4 +- .../workflows/contributor-open-pr-comment.yml | 2 +- .github/workflows/docker-unified.yml | 2 - datahub-web-react/build.gradle | 2 +- datahub-web-react/package.json | 12 +- datahub-web-react/src/Mocks.tsx | 1 + datahub-web-react/vite.config.ts | 8 + datahub-web-react/yarn.lock | 141 ++++++++++++++++-- docs/developers.md | 1 + 9 files changed, 147 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 98071b536a336..784dce0f11b2b 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -109,8 +109,6 @@ jobs: if: ${{ matrix.command == 'frontend' && needs.setup.outputs.frontend_change == 'true' }} run: | ./gradlew :datahub-frontend:build :datahub-web-react:build --parallel - env: - NODE_OPTIONS: "--max-old-space-size=4096" - name: Gradle compile (jdk8) for legacy Spark if: ${{ matrix.command == 'except_metadata_ingestion' && needs.setup.outputs.backend_change == 'true' }} run: | @@ -157,4 +155,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: Event File - path: ${{ github.event_path }} \ No newline at end of file + path: ${{ github.event_path }} diff --git a/.github/workflows/contributor-open-pr-comment.yml b/.github/workflows/contributor-open-pr-comment.yml index 2f700290ee0f2..decc7ab27a411 100644 --- a/.github/workflows/contributor-open-pr-comment.yml +++ b/.github/workflows/contributor-open-pr-comment.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get and Format Username (PR only) if: github.event_name == 'pull_request' diff --git a/.github/workflows/docker-unified.yml b/.github/workflows/docker-unified.yml index 47c26068347c0..a5200c7e917d8 100644 --- a/.github/workflows/docker-unified.yml +++ b/.github/workflows/docker-unified.yml @@ -445,8 +445,6 @@ jobs: run: | ./gradlew :datahub-frontend:dist -x test -x yarnTest -x yarnLint --parallel mv ./datahub-frontend/build/distributions/datahub-frontend-*.zip datahub-frontend.zip - env: - NODE_OPTIONS: "--max-old-space-size=4096" - name: Build and push uses: ./.github/actions/docker-custom-build-and-push with: diff --git a/datahub-web-react/build.gradle b/datahub-web-react/build.gradle index bf1aa401e3f56..3dad778a2b303 100644 --- a/datahub-web-react/build.gradle +++ b/datahub-web-react/build.gradle @@ -79,7 +79,7 @@ task yarnServe(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) { task yarnTest(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) { // Explicitly runs in non-watch mode. - args = ['run', 'test', 'run'] + args = ['run', project.hasProperty('withCoverage') ? 'test-coverage' : 'test', 'run'] } task yarnLint(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) { diff --git a/datahub-web-react/package.json b/datahub-web-react/package.json index 2d1d667a89f14..a608698d7602c 100644 --- a/datahub-web-react/package.json +++ b/datahub-web-react/package.json @@ -89,10 +89,11 @@ "scripts": { "analyze": "source-map-explorer 'dist/assets/*.js'", "start": "yarn run generate && vite", - "ec2-dev": "yarn run generate && CI=true;export CI;vite", - "build": "yarn run generate && NODE_OPTIONS='--max-old-space-size=4096 --openssl-legacy-provider' CI=false vite build", - "test": "vitest", - "generate": "graphql-codegen --config codegen.yml", + "ec2-dev": "yarn run generate && CI=true vite", + "build": "yarn run generate && CI=false NODE_OPTIONS='--max-old-space-size=5120 --openssl-legacy-provider' vite build", + "test": "NODE_OPTIONS='--max-old-space-size=5120 --openssl-legacy-provider' vitest", + "test-coverage": "yarn test run --coverage", + "generate": "NODE_OPTIONS='--max-old-space-size=5120 --openssl-legacy-provider' graphql-codegen --config codegen.yml", "lint": "eslint . --ext .ts,.tsx --quiet && yarn format-check && yarn type-check", "lint-fix": "eslint '*/**/*.{ts,tsx}' --quiet --fix && yarn format", "format-check": "prettier --check src", @@ -100,7 +101,7 @@ "type-check": "tsc --noEmit", "type-watch": "tsc -w --noEmit", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build-storybook": "NODE_OPTIONS='--max-old-space-size=5120 --openssl-legacy-provider' storybook build" }, "browserslist": { "production": [ @@ -135,6 +136,7 @@ "@typescript-eslint/eslint-plugin": "^5.38.1", "@typescript-eslint/parser": "^5.38.1", "@vitejs/plugin-react": "^4.1.1", + "@vitest/coverage-v8": "^0.34.6", "eslint": "^8.2.0", "eslint-config-airbnb": "19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", diff --git a/datahub-web-react/src/Mocks.tsx b/datahub-web-react/src/Mocks.tsx index 73a789030ce6f..2da9e733eb407 100644 --- a/datahub-web-react/src/Mocks.tsx +++ b/datahub-web-react/src/Mocks.tsx @@ -1714,6 +1714,7 @@ export const mlModel = { }, tags: [], properties: { + name: 'trust model', description: 'a ml trust model', date: null, version: '1', diff --git a/datahub-web-react/vite.config.ts b/datahub-web-react/vite.config.ts index 2532b24067754..c43470dee031a 100644 --- a/datahub-web-react/vite.config.ts +++ b/datahub-web-react/vite.config.ts @@ -68,6 +68,11 @@ export default defineConfig(({ mode }) => { envPrefix: 'REACT_APP_', build: { outDir: 'dist', + target: 'esnext', + minify: 'esbuild', + reportCompressedSize: false, + // Limit number of worker threads to reduce CPU pressure + workers: 3, // default is number of CPU cores }, server: { open: false, @@ -92,8 +97,11 @@ export default defineConfig(({ mode }) => { css: true, // reporters: ['verbose'], coverage: { + enabled: true, + provider: 'v8', reporter: ['text', 'json', 'html'], include: ['src/**/*'], + reportsDirectory: '../build/coverage-reports/datahub-web-react/', exclude: [], }, }, diff --git a/datahub-web-react/yarn.lock b/datahub-web-react/yarn.lock index dc7260efd183f..f16e8aa506e2c 100644 --- a/datahub-web-react/yarn.lock +++ b/datahub-web-react/yarn.lock @@ -20,6 +20,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.2.1": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@analytics/amplitude@0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@analytics/amplitude/-/amplitude-0.0.3.tgz#15ccb76094d6f1003979a4f3aa5d3263781bd776" @@ -1017,6 +1025,11 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@ctrl/tinycolor@^3.3.1", "@ctrl/tinycolor@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f" @@ -1941,6 +1954,11 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -2009,6 +2027,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.18" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" @@ -2017,14 +2043,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@linaria/core@3.0.0-beta.13": version "3.0.0-beta.13" resolved "https://registry.yarnpkg.com/@linaria/core/-/core-3.0.0-beta.13.tgz#049c5be5faa67e341e413a0f6b641d5d78d91056" @@ -3974,6 +3992,11 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + "@types/js-cookie@^2.2.6": version "2.2.6" resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f" @@ -4714,6 +4737,23 @@ "@types/babel__core" "^7.20.3" react-refresh "^0.14.0" +"@vitest/coverage-v8@^0.34.6": + version "0.34.6" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-0.34.6.tgz#931d9223fa738474e00c08f52b84e0f39cedb6d1" + integrity sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw== + dependencies: + "@ampproject/remapping" "^2.2.1" + "@bcoe/v8-coverage" "^0.2.3" + istanbul-lib-coverage "^3.2.0" + istanbul-lib-report "^3.0.1" + istanbul-lib-source-maps "^4.0.1" + istanbul-reports "^3.1.5" + magic-string "^0.30.1" + picocolors "^1.0.0" + std-env "^3.3.3" + test-exclude "^6.0.0" + v8-to-istanbul "^9.1.0" + "@vitest/expect@0.34.6": version "0.34.6" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.34.6.tgz#608a7b7a9aa3de0919db99b4cc087340a03ea77e" @@ -7282,6 +7322,18 @@ glob@^7.0.5, glob@^7.1.1, glob@^7.1.3, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -7612,6 +7664,11 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" @@ -8154,6 +8211,37 @@ isomorphic.js@^0.2.4: resolved "https://registry.yarnpkg.com/isomorphic.js/-/isomorphic.js-0.2.5.tgz#13eecf36f2dba53e85d355e11bf9d4208c6f7f88" integrity sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.5: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + jake@^10.8.5: version "10.8.7" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f" @@ -8542,6 +8630,13 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" @@ -8819,7 +8914,7 @@ min-indent@^1.0.0, min-indent@^1.0.1: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@3.0.5, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2, minimatch@^4.2.3, minimatch@^5.0.1: +minimatch@3.0.5, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2, minimatch@^4.2.3, minimatch@^5.0.1: version "3.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== @@ -10891,6 +10986,11 @@ semver@^7.3.7: dependencies: lru-cache "^6.0.0" +semver@^7.5.3, semver@^7.6.2: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -10898,11 +10998,6 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" -semver@^7.6.2: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - sentence-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" @@ -11381,6 +11476,15 @@ temp@^0.9.4: mkdirp "^0.5.1" rimraf "~2.6.2" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -11873,6 +11977,15 @@ uuid@^9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== +v8-to-istanbul@^9.1.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + value-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" diff --git a/docs/developers.md b/docs/developers.md index 401169490dd4b..0d398e6232b23 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -9,6 +9,7 @@ title: "Local Development" - [Java 17 JDK](https://openjdk.org/projects/jdk/17/) - [Python 3.10](https://www.python.org/downloads/release/python-3100/) - [Docker](https://www.docker.com/) +- [Node 22.x](https://nodejs.org/en/about/previous-releases) - [Docker Compose >=2.20](https://docs.docker.com/compose/) - Docker engine with at least 8GB of memory to run tests. From 4ed128cf28513d97961e551b4235ecf50d04955c Mon Sep 17 00:00:00 2001 From: Aseem Bansal Date: Tue, 31 Dec 2024 21:36:25 +0530 Subject: [PATCH 2/8] chore: cleanup extra lines (#12248) --- smoke-test/tests/cypress/integration_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/smoke-test/tests/cypress/integration_test.py b/smoke-test/tests/cypress/integration_test.py index 33c67a923c278..fa7274158f9e2 100644 --- a/smoke-test/tests/cypress/integration_test.py +++ b/smoke-test/tests/cypress/integration_test.py @@ -212,9 +212,6 @@ def test_run_cypress(auth_session): else: record_arg = " " - rest_specs = set(os.listdir("tests/cypress/cypress/e2e")) - cypress_suite1_specs = {"mutations", "search", "views"} - rest_specs.difference_update(set(cypress_suite1_specs)) print(f"test strategy is {test_strategy}") test_spec_arg = "" specs_str = ",".join([f"**/{f}" for f in _get_cypress_tests_batch()]) From f5ecee1501e7646f6dc0a5a13202d32c7b096ba8 Mon Sep 17 00:00:00 2001 From: Jay <159848059+jayacryl@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:56:32 -0500 Subject: [PATCH 3/8] fix(docs-site) hero image typo (#12250) --- docs-website/static/img/hero.png | Bin 380503 -> 380547 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs-website/static/img/hero.png b/docs-website/static/img/hero.png index 44b11c2781143f106c6929cc439d5d21feff18ce..a520a6d8a6b6ff8208291bbd79e0f1df58036267 100644 GIT binary patch delta 97725 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 z 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%0ArFY9f1A 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 =#wbo)^Yo|d^EgT}7mR@P_690J`7 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 YS50-W!7YgK9n7aBrzTte>Rs^v0fa-$2LJ#7 From 554a37a5514c9c0afbbea0fdea99244873a38ee4 Mon Sep 17 00:00:00 2001 From: Jonny Dixon <45681293+acrylJonny@users.noreply.github.com> Date: Wed, 1 Jan 2025 09:19:27 +0000 Subject: [PATCH 4/8] fix(ingest/aws_common): update tests execution on EC2 instance (#12252) --- .../tests/unit/test_aws_common.py | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/metadata-ingestion/tests/unit/test_aws_common.py b/metadata-ingestion/tests/unit/test_aws_common.py index 9291fb91134b1..dd1f06cf9bfd5 100644 --- a/metadata-ingestion/tests/unit/test_aws_common.py +++ b/metadata-ingestion/tests/unit/test_aws_common.py @@ -17,6 +17,14 @@ ) +@pytest.fixture +def mock_disable_ec2_metadata(): + """Disable EC2 metadata detection""" + with patch("requests.put") as mock_put: + mock_put.return_value.status_code = 404 + yield mock_put + + @pytest.fixture def mock_aws_config(): return AwsConnectionConfig( @@ -27,17 +35,19 @@ def mock_aws_config(): class TestAwsCommon: - def test_environment_detection_no_environment(self): + def test_environment_detection_no_environment(self, mock_disable_ec2_metadata): """Test environment detection when no AWS environment is present""" with patch.dict(os.environ, {}, clear=True): assert detect_aws_environment() == AwsEnvironment.UNKNOWN - def test_environment_detection_lambda(self): + def test_environment_detection_lambda(self, mock_disable_ec2_metadata): """Test Lambda environment detection""" with patch.dict(os.environ, {"AWS_LAMBDA_FUNCTION_NAME": "test-function"}): assert detect_aws_environment() == AwsEnvironment.LAMBDA - def test_environment_detection_lambda_cloudformation(self): + def test_environment_detection_lambda_cloudformation( + self, mock_disable_ec2_metadata + ): """Test CloudFormation Lambda environment detection""" with patch.dict( os.environ, @@ -48,7 +58,7 @@ def test_environment_detection_lambda_cloudformation(self): ): assert detect_aws_environment() == AwsEnvironment.CLOUD_FORMATION - def test_environment_detection_eks(self): + def test_environment_detection_eks(self, mock_disable_ec2_metadata): """Test EKS environment detection""" with patch.dict( os.environ, @@ -59,19 +69,19 @@ def test_environment_detection_eks(self): ): assert detect_aws_environment() == AwsEnvironment.EKS - def test_environment_detection_app_runner(self): + def test_environment_detection_app_runner(self, mock_disable_ec2_metadata): """Test App Runner environment detection""" with patch.dict(os.environ, {"AWS_APP_RUNNER_SERVICE_ID": "service-id"}): assert detect_aws_environment() == AwsEnvironment.APP_RUNNER - def test_environment_detection_ecs(self): + def test_environment_detection_ecs(self, mock_disable_ec2_metadata): """Test ECS environment detection""" with patch.dict( os.environ, {"ECS_CONTAINER_METADATA_URI_V4": "http://169.254.170.2/v4"} ): assert detect_aws_environment() == AwsEnvironment.ECS - def test_environment_detection_beanstalk(self): + def test_environment_detection_beanstalk(self, mock_disable_ec2_metadata): """Test Elastic Beanstalk environment detection""" with patch.dict(os.environ, {"ELASTIC_BEANSTALK_ENVIRONMENT_NAME": "my-env"}): assert detect_aws_environment() == AwsEnvironment.BEANSTALK @@ -103,6 +113,7 @@ def test_ec2_metadata_token_failure(self, mock_put): @patch("requests.put") def test_is_running_on_ec2(self, mock_put, mock_get): """Test EC2 instance detection with IMDSv2""" + # Explicitly mock EC2 metadata responses mock_put.return_value.status_code = 200 mock_put.return_value.text = "token123" mock_get.return_value.status_code = 200 @@ -322,7 +333,9 @@ def test_aws_connection_config_validation_error(self): ), ], ) - def test_environment_detection_parametrized(self, env_vars, expected_environment): + def test_environment_detection_parametrized( + self, mock_disable_ec2_metadata, env_vars, expected_environment + ): """Parametrized test for environment detection with different configurations""" with patch.dict(os.environ, env_vars, clear=True): assert detect_aws_environment() == expected_environment From ea249caee1bffadd237ee7031c4502dac0f87af6 Mon Sep 17 00:00:00 2001 From: Aseem Bansal Date: Wed, 1 Jan 2025 16:52:17 +0530 Subject: [PATCH 5/8] fix(ingest): json serializable fix (#12246) --- .../datahub_ingestion_run_summary_provider.py | 45 +++++- .../test_datahub_ingestion_reporter.py | 135 ++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) diff --git a/metadata-ingestion/src/datahub/ingestion/reporting/datahub_ingestion_run_summary_provider.py b/metadata-ingestion/src/datahub/ingestion/reporting/datahub_ingestion_run_summary_provider.py index 28def68ccf3f5..c143a8b49f4b7 100644 --- a/metadata-ingestion/src/datahub/ingestion/reporting/datahub_ingestion_run_summary_provider.py +++ b/metadata-ingestion/src/datahub/ingestion/reporting/datahub_ingestion_run_summary_provider.py @@ -146,12 +146,55 @@ def __init__(self, sink: Sink, report_recipe: bool, ctx: PipelineContext) -> Non aspect_value=source_info_aspect, ) + @staticmethod + def _convert_sets_to_lists(obj: Any) -> Any: + """ + Recursively converts all sets to lists in a Python object. + Works with nested dictionaries, lists, and sets. + + Args: + obj: Any Python object that might contain sets + + Returns: + The object with all sets converted to lists + """ + if isinstance(obj, dict): + return { + key: DatahubIngestionRunSummaryProvider._convert_sets_to_lists(value) + for key, value in obj.items() + } + elif isinstance(obj, list): + return [ + DatahubIngestionRunSummaryProvider._convert_sets_to_lists(element) + for element in obj + ] + elif isinstance(obj, set): + return [ + DatahubIngestionRunSummaryProvider._convert_sets_to_lists(element) + for element in obj + ] + elif isinstance(obj, tuple): + return tuple( + DatahubIngestionRunSummaryProvider._convert_sets_to_lists(element) + for element in obj + ) + else: + return obj + def _get_recipe_to_report(self, ctx: PipelineContext) -> str: assert ctx.pipeline_config if not self.report_recipe or not ctx.pipeline_config.get_raw_dict(): return "" else: - return json.dumps(redact_raw_config(ctx.pipeline_config.get_raw_dict())) + redacted_recipe = redact_raw_config(ctx.pipeline_config.get_raw_dict()) + # This is required otherwise json dumps will fail + # with a TypeError: Object of type set is not JSON serializable + converted_recipe = ( + DatahubIngestionRunSummaryProvider._convert_sets_to_lists( + redacted_recipe + ) + ) + return json.dumps(converted_recipe) def _emit_aspect(self, entity_urn: Urn, aspect_value: _Aspect) -> None: self.sink.write_record_async( diff --git a/metadata-ingestion/tests/unit/reporting/test_datahub_ingestion_reporter.py b/metadata-ingestion/tests/unit/reporting/test_datahub_ingestion_reporter.py index 749ea03a7f20a..2ab6208e2dcc6 100644 --- a/metadata-ingestion/tests/unit/reporting/test_datahub_ingestion_reporter.py +++ b/metadata-ingestion/tests/unit/reporting/test_datahub_ingestion_reporter.py @@ -1,3 +1,5 @@ +from typing import Any, Dict, List, Set, Tuple, Union + import pytest from datahub.ingestion.reporting.datahub_ingestion_run_summary_provider import ( @@ -50,3 +52,136 @@ def test_default_config(): typed_config = DatahubIngestionRunSummaryProviderConfig.parse_obj({}) assert typed_config.sink is None assert typed_config.report_recipe is True + + +def test_simple_set() -> None: + """Test conversion of a simple set""" + input_data: Set[int] = {1, 2, 3} + expected: List[int] = [1, 2, 3] + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + assert sorted(result) == sorted(expected) + assert isinstance(result, list) + + +def test_nested_dict_with_sets() -> None: + """Test conversion of nested dictionary containing sets""" + input_data: Dict[str, Union[Set[int], Dict[str, Set[str]]]] = { + "set1": {1, 2, 3}, + "dict1": {"set2": {"a", "b"}}, + } + expected = { + "set1": [1, 2, 3], + "dict1": {"set2": ["a", "b"]}, + } + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + + def sort_nested_lists(d): + return { + k: ( + sorted(v) + if isinstance(v, list) + else (sort_nested_lists(v) if isinstance(v, dict) else v) + ) + for k, v in d.items() + } + + assert sort_nested_lists(result) == sort_nested_lists(expected) + + +def test_nested_lists_with_sets() -> None: + """Test conversion of nested lists containing sets""" + input_data = [{1, 2}, [{3, 4}, {5, 6}]] + expected = [[1, 2], [[3, 4], [5, 6]]] + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + assert [ + sorted(x) + if isinstance(x, list) and len(x) > 0 and not isinstance(x[0], list) + else x + for x in result + ] == [ + sorted(x) + if isinstance(x, list) and len(x) > 0 and not isinstance(x[0], list) + else x + for x in expected + ] + + +def test_tuple_with_sets() -> None: + """Test conversion of tuples containing sets""" + input_data = (1, {2, 3}, 4) + expected = (1, [2, 3], 4) + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + assert (result[0], sorted(result[1]), result[2]) == ( + expected[0], + sorted(expected[1]), + expected[2], + ) + assert isinstance(result, tuple) + + +def test_mixed_nested_structure() -> None: + """Test conversion of a complex nested structure""" + input_data = { + "simple_set": {1, 2, 3}, + "nested_dict": { + "another_set": {"a", "b", "c"}, + "mixed_list": [1, {2, 3}, {"x", "y"}], + }, + "tuple_with_set": (1, {4, 5}, 6), + "list_of_sets": [{1, 2}, {3, 4}], + } + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + + # Verify structure types + assert isinstance(result["simple_set"], list) + assert isinstance(result["nested_dict"]["another_set"], list) + assert isinstance(result["nested_dict"]["mixed_list"][1], list) + assert isinstance(result["nested_dict"]["mixed_list"][2], list) + assert isinstance(result["tuple_with_set"], tuple) + assert isinstance(result["tuple_with_set"][1], list) + assert isinstance(result["list_of_sets"][0], list) + + +def test_non_set_data() -> None: + """Test that non-set data remains unchanged""" + input_data = { + "string": "hello", + "int": 42, + "float": 3.14, + "bool": True, + "none": None, + "list": [1, 2, 3], + "dict": {"a": 1, "b": 2}, + } + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + assert result == input_data + + +def test_empty_structures() -> None: + """Test handling of empty structures""" + input_data: Dict[ + str, Union[Set[Any], Dict[Any, Any], List[Any], Tuple[Any, ...]] + ] = {"empty_set": set(), "empty_dict": {}, "empty_list": [], "empty_tuple": ()} + expected: Dict[ + str, Union[List[Any], Dict[Any, Any], List[Any], Tuple[Any, ...]] + ] = {"empty_set": [], "empty_dict": {}, "empty_list": [], "empty_tuple": ()} + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + assert result == expected + + +def test_json_serializable() -> None: + """Test that the converted structure is JSON serializable""" + import json + + input_data = { + "set": {1, 2, 3}, + "nested": {"set": {"a", "b"}}, + "mixed": [1, {2, 3}, {"x"}], + } + result = DatahubIngestionRunSummaryProvider._convert_sets_to_lists(input_data) + try: + json.dumps(result) + serializable = True + except TypeError: + serializable = False + assert serializable From 67ef55efc7a65485b944722fb4895ea54e644f1d Mon Sep 17 00:00:00 2001 From: Aseem Bansal Date: Thu, 2 Jan 2025 15:11:35 +0530 Subject: [PATCH 6/8] fix(ingest/gc): soft deletion loop fix (#12255) --- .../source/gc/dataprocess_cleanup.py | 8 +- .../source/gc/soft_deleted_entity_cleanup.py | 230 ++++++++++++------ 2 files changed, 163 insertions(+), 75 deletions(-) diff --git a/metadata-ingestion/src/datahub/ingestion/source/gc/dataprocess_cleanup.py b/metadata-ingestion/src/datahub/ingestion/source/gc/dataprocess_cleanup.py index 3f7a1fc453bcd..64c1a0ad0bfba 100644 --- a/metadata-ingestion/src/datahub/ingestion/source/gc/dataprocess_cleanup.py +++ b/metadata-ingestion/src/datahub/ingestion/source/gc/dataprocess_cleanup.py @@ -167,7 +167,7 @@ class DataJobEntity: class DataProcessCleanupReport(SourceReport): num_aspects_removed: int = 0 num_aspect_removed_by_type: TopKDict[str, int] = field(default_factory=TopKDict) - sample_removed_aspects_by_type: TopKDict[str, LossyList[str]] = field( + sample_soft_deleted_aspects_by_type: TopKDict[str, LossyList[str]] = field( default_factory=TopKDict ) num_data_flows_found: int = 0 @@ -286,9 +286,9 @@ def delete_entity(self, urn: str, type: str) -> None: self.report.num_aspect_removed_by_type[type] = ( self.report.num_aspect_removed_by_type.get(type, 0) + 1 ) - if type not in self.report.sample_removed_aspects_by_type: - self.report.sample_removed_aspects_by_type[type] = LossyList() - self.report.sample_removed_aspects_by_type[type].append(urn) + if type not in self.report.sample_soft_deleted_aspects_by_type: + self.report.sample_soft_deleted_aspects_by_type[type] = LossyList() + self.report.sample_soft_deleted_aspects_by_type[type].append(urn) if self.dry_run: logger.info( diff --git a/metadata-ingestion/src/datahub/ingestion/source/gc/soft_deleted_entity_cleanup.py b/metadata-ingestion/src/datahub/ingestion/source/gc/soft_deleted_entity_cleanup.py index 93f004ab675ed..4c0355834f9b4 100644 --- a/metadata-ingestion/src/datahub/ingestion/source/gc/soft_deleted_entity_cleanup.py +++ b/metadata-ingestion/src/datahub/ingestion/source/gc/soft_deleted_entity_cleanup.py @@ -1,9 +1,10 @@ import logging import time -from concurrent.futures import ThreadPoolExecutor, as_completed +from concurrent.futures import FIRST_COMPLETED, Future, ThreadPoolExecutor, wait from dataclasses import dataclass, field from datetime import datetime, timezone -from typing import List, Optional +from threading import Lock +from typing import Dict, Iterable, List, Optional from pydantic import Field @@ -18,12 +19,28 @@ logger = logging.getLogger(__name__) +QUERY_QUERY_ENTITY = """ +query listQueries($input: ScrollAcrossEntitiesInput!) { + scrollAcrossEntities(input: $input) { + nextScrollId + count + searchResults { + entity { + ... on QueryEntity { + urn + } + } + } + } +} +""" + class SoftDeletedEntitiesCleanupConfig(ConfigModel): enabled: bool = Field( default=True, description="Whether to do soft deletion cleanup." ) - retention_days: Optional[int] = Field( + retention_days: int = Field( 10, description="Number of days to retain metadata in DataHub", ) @@ -62,23 +79,30 @@ class SoftDeletedEntitiesCleanupConfig(ConfigModel): default=None, description="Query to filter entities", ) + limit_entities_delete: Optional[int] = Field( 25000, description="Max number of entities to delete." ) - runtime_limit_seconds: Optional[int] = Field( - None, + futures_max_at_time: int = Field( + 1000, description="Max number of futures to have at a time." + ) + + runtime_limit_seconds: int = Field( + 7200, # 2 hours by default description="Runtime limit in seconds", ) @dataclass class SoftDeletedEntitiesReport(SourceReport): - num_soft_deleted_entity_removed: int = 0 - num_soft_deleted_entity_removed_by_type: TopKDict[str, int] = field( - default_factory=TopKDict - ) - sample_soft_deleted_removed_aspects_by_type: TopKDict[str, LossyList[str]] = field( + num_queries_found: int = 0 + num_soft_deleted_entity_processed: int = 0 + num_soft_deleted_retained_due_to_age: int = 0 + num_soft_deleted_entity_removal_started: int = 0 + num_hard_deleted: int = 0 + num_hard_deleted_by_type: TopKDict[str, int] = field(default_factory=TopKDict) + sample_hard_deleted_aspects_by_type: TopKDict[str, LossyList[str]] = field( default_factory=TopKDict ) @@ -103,48 +127,53 @@ def __init__( self.config = config self.report = report self.dry_run = dry_run + self.start_time = 0.0 + self._report_lock: Lock = Lock() + self.last_print_time = 0.0 + + def _increment_retained_count(self) -> None: + """Thread-safe method to update report fields""" + with self._report_lock: + self.report.num_soft_deleted_retained_due_to_age += 1 + + def _increment_removal_started_count(self) -> None: + """Thread-safe method to update report fields""" + with self._report_lock: + self.report.num_soft_deleted_entity_removal_started += 1 + + def _update_report(self, urn: str, entity_type: str) -> None: + """Thread-safe method to update report fields""" + with self._report_lock: + self.report.num_hard_deleted += 1 + + current_count = self.report.num_hard_deleted_by_type.get(entity_type, 0) + self.report.num_hard_deleted_by_type[entity_type] = current_count + 1 + if entity_type not in self.report.sample_hard_deleted_aspects_by_type: + self.report.sample_hard_deleted_aspects_by_type[ + entity_type + ] = LossyList() + self.report.sample_hard_deleted_aspects_by_type[entity_type].append(urn) def delete_entity(self, urn: str) -> None: assert self.ctx.graph entity_urn = Urn.from_string(urn) - self.report.num_soft_deleted_entity_removed += 1 - self.report.num_soft_deleted_entity_removed_by_type[entity_urn.entity_type] = ( - self.report.num_soft_deleted_entity_removed_by_type.get( - entity_urn.entity_type, 0 - ) - + 1 - ) - if ( - entity_urn.entity_type - not in self.report.sample_soft_deleted_removed_aspects_by_type - ): - self.report.sample_soft_deleted_removed_aspects_by_type[ - entity_urn.entity_type - ] = LossyList() - self.report.sample_soft_deleted_removed_aspects_by_type[ - entity_urn.entity_type - ].append(urn) - if self.dry_run: logger.info( f"Dry run is on otherwise it would have deleted {urn} with hard deletion" ) return - + self._increment_removal_started_count() self.ctx.graph.delete_entity(urn=urn, hard=True) self.ctx.graph.delete_references_to_urn( urn=urn, dry_run=False, ) + self._update_report(urn, entity_urn.entity_type) def delete_soft_deleted_entity(self, urn: str) -> None: assert self.ctx.graph - if self.config.retention_days is None: - logger.info("Retention days is not set, skipping soft delete cleanup") - return - retention_time = ( int(datetime.now(timezone.utc).timestamp()) - self.config.retention_days * 24 * 60 * 60 @@ -157,15 +186,85 @@ def delete_soft_deleted_entity(self, urn: str) -> None: ]["created"]["time"] < (retention_time * 1000): logger.debug(f"Hard deleting {urn}") self.delete_entity(urn) + else: + self._increment_retained_count() + + def _print_report(self) -> None: + time_taken = round(time.time() - self.last_print_time, 1) + # Print report every 2 minutes + if time_taken > 120: + self.last_print_time = time.time() + logger.info(f"\n{self.report.as_string()}") + + def _process_futures(self, futures: Dict[Future, str]) -> Dict[Future, str]: + done, not_done = wait(futures, return_when=FIRST_COMPLETED) + futures = {future: urn for future, urn in futures.items() if future in not_done} + + for future in done: + self._print_report() + if future.exception(): + logger.error( + f"Failed to delete entity {futures[future]}: {future.exception()}" + ) + self.report.failure( + f"Failed to delete entity {futures[future]}", + exc=future.exception(), + ) + self.report.num_soft_deleted_entity_processed += 1 + if ( + self.report.num_soft_deleted_entity_processed % self.config.batch_size + == 0 + ): + if self.config.delay: + logger.debug( + f"Sleeping for {self.config.delay} seconds before further processing batch" + ) + time.sleep(self.config.delay) + return futures - def cleanup_soft_deleted_entities(self) -> None: - if not self.config.enabled: - return + def _get_soft_deleted_queries(self) -> Iterable[str]: assert self.ctx.graph - start_time = time.time() - - deleted_count_retention = 0 - urns = self.ctx.graph.get_urns_by_filter( + scroll_id: Optional[str] = None + while True: + try: + result = self.ctx.graph.execute_graphql( + QUERY_QUERY_ENTITY, + { + "input": { + "types": ["QUERY"], + "query": "*", + "scrollId": scroll_id if scroll_id else None, + "count": self.config.batch_size, + "orFilters": [ + { + "and": [ + { + "field": "removed", + "values": ["true"], + "condition": "EQUAL", + } + ] + } + ], + } + }, + ) + except Exception as e: + self.report.failure( + f"While trying to get queries with {scroll_id}", exc=e + ) + break + scroll_across_entities = result.get("scrollAcrossEntities") + if not scroll_across_entities: + break + scroll_id = scroll_across_entities.get("nextScrollId") + self.report.num_queries_found += scroll_across_entities.get("count") + for query in scroll_across_entities.get("searchResults"): + yield query["entity"]["urn"] + + def _get_urns(self) -> Iterable[str]: + assert self.ctx.graph + yield from self.ctx.graph.get_urns_by_filter( entity_types=self.config.entity_types, platform=self.config.platform, env=self.config.env, @@ -173,52 +272,41 @@ def cleanup_soft_deleted_entities(self) -> None: status=RemovedStatusFilter.ONLY_SOFT_DELETED, batch_size=self.config.batch_size, ) + yield from self._get_soft_deleted_queries() + + def cleanup_soft_deleted_entities(self) -> None: + if not self.config.enabled: + return + self.start_time = time.time() - futures = {} + futures: Dict[Future, str] = dict() with ThreadPoolExecutor(max_workers=self.config.max_workers) as executor: - num_urns_submitted = 0 - for urn in urns: - num_urns_submitted += 1 + for urn in self._get_urns(): + self._print_report() + while len(futures) >= self.config.futures_max_at_time: + futures = self._process_futures(futures) if ( self.config.limit_entities_delete - and num_urns_submitted > self.config.limit_entities_delete + and self.report.num_hard_deleted > self.config.limit_entities_delete ): logger.info( - f"Limit of {self.config.limit_entities_delete} entities reached. Stopping" + f"Limit of {self.config.limit_entities_delete} entities reached. Stopped adding more." ) break if ( self.config.runtime_limit_seconds - and time.time() - start_time > self.config.runtime_limit_seconds + and time.time() - self.start_time + > self.config.runtime_limit_seconds ): logger.info( - f"Runtime limit of {self.config.runtime_limit_seconds} seconds reached. Stopping" + f"Runtime limit of {self.config.runtime_limit_seconds} seconds reached. Not submitting more futures." ) break future = executor.submit(self.delete_soft_deleted_entity, urn) futures[future] = urn - if not futures: - return - for future in as_completed(futures): - if future.exception(): - logger.error( - f"Failed to delete entity {futures[future]}: {future.exception()}" - ) - self.report.failure( - f"Failed to delete entity {futures[future]}", - exc=future.exception(), - ) - deleted_count_retention += 1 - - if deleted_count_retention % self.config.batch_size == 0: - logger.info( - f"Processed {deleted_count_retention} soft deleted entity and deleted {self.report.num_soft_deleted_entity_removed} entities so far" - ) - - if self.config.delay: - logger.debug( - f"Sleeping for {self.config.delay} seconds before getting next batch" - ) - time.sleep(self.config.delay) + logger.info(f"Waiting for {len(futures)} futures to complete") + while len(futures) > 0: + self._print_report() + futures = self._process_futures(futures) From a814cb389f364ab4a4782d3f4987fe047d07962a Mon Sep 17 00:00:00 2001 From: sagar-salvi-apptware <159135491+sagar-salvi-apptware@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:59:22 +0530 Subject: [PATCH 7/8] fix(ingest/bigquery): All View generation when queries_v2 is turned off (#12181) Co-authored-by: Mayuri Nehate <33225191+mayurinehate@users.noreply.github.com> --- docs/how/updating-datahub.md | 1 + .../ingestion/source/bigquery_v2/bigquery.py | 28 +- .../source/bigquery_v2/bigquery_config.py | 12 +- .../source/bigquery_v2/bigquery_schema_gen.py | 28 +- .../ingestion/source/bigquery_v2/lineage.py | 31 +- .../bigquery_mcp_lineage_golden_1.json | 977 +++++++++++++++ .../bigquery_mcp_lineage_golden_2.json | 1064 +++++++++++++++++ .../integration/bigquery_v2/test_bigquery.py | 145 +++ 8 files changed, 2220 insertions(+), 66 deletions(-) create mode 100644 metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_1.json create mode 100644 metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_2.json diff --git a/docs/how/updating-datahub.md b/docs/how/updating-datahub.md index d6620fde0bf79..19261da23bcf9 100644 --- a/docs/how/updating-datahub.md +++ b/docs/how/updating-datahub.md @@ -18,6 +18,7 @@ This file documents any backwards-incompatible changes in DataHub and assists pe ## Next - #12191 - Configs `include_view_lineage` and `include_view_column_lineage` are removed from snowflake ingestion source. View and External Table DDL lineage will always be ingested when definitions are available. +- #12181 - Configs `include_view_lineage`, `include_view_column_lineage` and `lineage_parse_view_ddl` are removed from bigquery ingestion source. View and Snapshot lineage will always be ingested when definitions are available. - #11560 - The PowerBI ingestion source configuration option include_workspace_name_in_dataset_urn determines whether the workspace name is included in the PowerBI dataset's URN.
PowerBI allows to have identical name of semantic model and their tables across the workspace, It will overwrite the semantic model in-case of multi-workspace ingestion.
Entity urn with `include_workspace_name_in_dataset_urn: false` diff --git a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery.py b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery.py index 16a5268a2dea7..38eab3606b7e9 100644 --- a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery.py +++ b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery.py @@ -206,9 +206,7 @@ def test_connection(config_dict: dict) -> TestConnectionReport: def _init_schema_resolver(self) -> SchemaResolver: schema_resolution_required = ( - self.config.use_queries_v2 - or self.config.lineage_parse_view_ddl - or self.config.lineage_use_sql_parser + self.config.use_queries_v2 or self.config.lineage_use_sql_parser ) schema_ingestion_enabled = ( self.config.include_schema_metadata @@ -255,18 +253,16 @@ def get_workunits_internal(self) -> Iterable[MetadataWorkUnit]: for project in projects: yield from self.bq_schema_extractor.get_project_workunits(project) - if self.config.use_queries_v2: - # Always ingest View and Snapshot lineage with schema ingestion - self.report.set_ingestion_stage("*", "View and Snapshot Lineage") - - yield from self.lineage_extractor.get_lineage_workunits_for_views_and_snapshots( - [p.id for p in projects], - self.bq_schema_extractor.view_refs_by_project, - self.bq_schema_extractor.view_definitions, - self.bq_schema_extractor.snapshot_refs_by_project, - self.bq_schema_extractor.snapshots_by_ref, - ) + self.report.set_ingestion_stage("*", "View and Snapshot Lineage") + yield from self.lineage_extractor.get_lineage_workunits_for_views_and_snapshots( + [p.id for p in projects], + self.bq_schema_extractor.view_refs_by_project, + self.bq_schema_extractor.view_definitions, + self.bq_schema_extractor.snapshot_refs_by_project, + self.bq_schema_extractor.snapshots_by_ref, + ) + if self.config.use_queries_v2: # if both usage and lineage are disabled then skip queries extractor piece if ( not self.config.include_usage_statistics @@ -306,10 +302,6 @@ def get_workunits_internal(self) -> Iterable[MetadataWorkUnit]: if self.config.include_table_lineage: yield from self.lineage_extractor.get_lineage_workunits( [p.id for p in projects], - self.bq_schema_extractor.view_refs_by_project, - self.bq_schema_extractor.view_definitions, - self.bq_schema_extractor.snapshot_refs_by_project, - self.bq_schema_extractor.snapshots_by_ref, self.bq_schema_extractor.table_refs, ) diff --git a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_config.py b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_config.py index 4af41921c9fa3..ef323260b014e 100644 --- a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_config.py +++ b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_config.py @@ -463,10 +463,6 @@ def have_table_data_read_permission(self) -> bool: default=True, description="Use sql parser to resolve view/table lineage.", ) - lineage_parse_view_ddl: bool = Field( - default=True, - description="Sql parse view ddl to get lineage.", - ) lineage_sql_parser_use_raw_names: bool = Field( default=False, @@ -572,11 +568,9 @@ def have_table_data_read_permission(self) -> bool: "See [this](https://cloud.google.com/bigquery/docs/information-schema-jobs#scope_and_syntax) for details.", ) - # include_view_lineage and include_view_column_lineage are inherited from SQLCommonConfig - # but not used in bigquery so we hide them from docs. - include_view_lineage: bool = Field(default=True, hidden_from_docs=True) - - include_view_column_lineage: bool = Field(default=True, hidden_from_docs=True) + _include_view_lineage = pydantic_removed_field("include_view_lineage") + _include_view_column_lineage = pydantic_removed_field("include_view_column_lineage") + _lineage_parse_view_ddl = pydantic_removed_field("lineage_parse_view_ddl") @root_validator(pre=True) def set_include_schema_metadata(cls, values: Dict) -> Dict: diff --git a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_schema_gen.py b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_schema_gen.py index 4a3b47f6b543a..bc2688e6b481a 100644 --- a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_schema_gen.py +++ b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/bigquery_schema_gen.py @@ -653,14 +653,11 @@ def _process_view( self.report.report_dropped(table_identifier.raw_table_name()) return - if self.store_table_refs: - table_ref = str( - BigQueryTableRef(table_identifier).get_sanitized_table_ref() - ) - self.table_refs.add(table_ref) - if self.config.lineage_parse_view_ddl and view.view_definition: - self.view_refs_by_project[project_id].add(table_ref) - self.view_definitions[table_ref] = view.view_definition + table_ref = str(BigQueryTableRef(table_identifier).get_sanitized_table_ref()) + self.table_refs.add(table_ref) + if view.view_definition: + self.view_refs_by_project[project_id].add(table_ref) + self.view_definitions[table_ref] = view.view_definition view.column_count = len(columns) if not view.column_count: @@ -701,14 +698,11 @@ def _process_snapshot( f"Snapshot doesn't have any column or unable to get columns for snapshot: {table_identifier}" ) - if self.store_table_refs: - table_ref = str( - BigQueryTableRef(table_identifier).get_sanitized_table_ref() - ) - self.table_refs.add(table_ref) - if snapshot.base_table_identifier: - self.snapshot_refs_by_project[project_id].add(table_ref) - self.snapshots_by_ref[table_ref] = snapshot + table_ref = str(BigQueryTableRef(table_identifier).get_sanitized_table_ref()) + self.table_refs.add(table_ref) + if snapshot.base_table_identifier: + self.snapshot_refs_by_project[project_id].add(table_ref) + self.snapshots_by_ref[table_ref] = snapshot yield from self.gen_snapshot_dataset_workunits( table=snapshot, @@ -1148,7 +1142,7 @@ def gen_schema_metadata( foreignKeys=foreign_keys if foreign_keys else None, ) - if self.config.lineage_parse_view_ddl or self.config.lineage_use_sql_parser: + if self.config.lineage_use_sql_parser: self.sql_parser_schema_resolver.add_schema_metadata( dataset_urn, schema_metadata ) diff --git a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/lineage.py b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/lineage.py index 321b1b6207fab..ba3357aa8ca20 100644 --- a/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/lineage.py +++ b/metadata-ingestion/src/datahub/ingestion/source/bigquery_v2/lineage.py @@ -291,16 +291,15 @@ def get_lineage_workunits_for_views_and_snapshots( snapshots_by_ref: FileBackedDict[BigqueryTableSnapshot], ) -> Iterable[MetadataWorkUnit]: for project in projects: - if self.config.lineage_parse_view_ddl: - for view in view_refs_by_project[project]: - self.datasets_skip_audit_log_lineage.add(view) - self.aggregator.add_view_definition( - view_urn=self.identifiers.gen_dataset_urn_from_raw_ref( - BigQueryTableRef.from_string_name(view) - ), - view_definition=view_definitions[view], - default_db=project, - ) + for view in view_refs_by_project[project]: + self.datasets_skip_audit_log_lineage.add(view) + self.aggregator.add_view_definition( + view_urn=self.identifiers.gen_dataset_urn_from_raw_ref( + BigQueryTableRef.from_string_name(view) + ), + view_definition=view_definitions[view], + default_db=project, + ) for snapshot_ref in snapshot_refs_by_project[project]: snapshot = snapshots_by_ref[snapshot_ref] @@ -322,23 +321,11 @@ def get_lineage_workunits_for_views_and_snapshots( def get_lineage_workunits( self, projects: List[str], - view_refs_by_project: Dict[str, Set[str]], - view_definitions: FileBackedDict[str], - snapshot_refs_by_project: Dict[str, Set[str]], - snapshots_by_ref: FileBackedDict[BigqueryTableSnapshot], table_refs: Set[str], ) -> Iterable[MetadataWorkUnit]: if not self._should_ingest_lineage(): return - yield from self.get_lineage_workunits_for_views_and_snapshots( - projects, - view_refs_by_project, - view_definitions, - snapshot_refs_by_project, - snapshots_by_ref, - ) - if self.config.use_exported_bigquery_audit_metadata: projects = ["*"] # project_id not used when using exported metadata diff --git a/metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_1.json b/metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_1.json new file mode 100644 index 0000000000000..8f411ca513771 --- /dev/null +++ b/metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_1.json @@ -0,0 +1,977 @@ +[ +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "containerProperties", + "aspect": { + "json": { + "customProperties": { + "platform": "bigquery", + "env": "PROD", + "project_id": "project-id-1" + }, + "name": "project-id-1", + "env": "PROD" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Project" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "containerProperties", + "aspect": { + "json": { + "customProperties": { + "platform": "bigquery", + "env": "PROD", + "project_id": "project-id-1", + "dataset_id": "bigquery-dataset-1", + "location": "US" + }, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m4!1m3!3m2!1sproject-id-1!2sbigquery-dataset-1", + "name": "bigquery-dataset-1", + "env": "PROD" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Dataset" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "schemaMetadata", + "aspect": { + "json": { + "schemaName": "project-id-1.bigquery-dataset-1.table-1", + "platform": "urn:li:dataPlatform:bigquery", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "age", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.NumberType": {} + } + }, + "nativeDataType": "INT", + "recursive": false, + "globalTags": { + "tags": [ + { + "tag": "urn:li:tag:Test Policy Tag" + } + ] + }, + "isPartOfKey": false, + "isPartitioningKey": false + }, + { + "fieldPath": "email", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.StringType": {} + } + }, + "nativeDataType": "STRING", + "recursive": false, + "globalTags": { + "tags": [] + }, + "isPartOfKey": false, + "isPartitioningKey": false + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetProperties", + "aspect": { + "json": { + "customProperties": {}, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m5!1m4!4m3!1sproject-id-1!2sbigquery-dataset-1!3stable-1", + "name": "table-1", + "qualifiedName": "project-id-1.bigquery-dataset-1.table-1", + "description": "", + "tags": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery", + "instance": "urn:li:dataPlatformInstance:(urn:li:dataPlatform:bigquery,project-id-1)" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Table" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + }, + { + "id": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "urn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "schemaMetadata", + "aspect": { + "json": { + "schemaName": "project-id-1.bigquery-dataset-1.view-1", + "platform": "urn:li:dataPlatform:bigquery", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "age", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.NumberType": {} + } + }, + "nativeDataType": "INT", + "recursive": false, + "globalTags": { + "tags": [ + { + "tag": "urn:li:tag:Test Policy Tag" + } + ] + }, + "isPartOfKey": false, + "isPartitioningKey": false + }, + { + "fieldPath": "email", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.StringType": {} + } + }, + "nativeDataType": "STRING", + "recursive": false, + "globalTags": { + "tags": [] + }, + "isPartOfKey": false, + "isPartitioningKey": false + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetProperties", + "aspect": { + "json": { + "customProperties": {}, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m5!1m4!4m3!1sproject-id-1!2sbigquery-dataset-1!3sview-1", + "name": "view-1", + "qualifiedName": "project-id-1.bigquery-dataset-1.view-1", + "description": "", + "tags": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery", + "instance": "urn:li:dataPlatformInstance:(urn:li:dataPlatform:bigquery,project-id-1)" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "View" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "viewProperties", + "aspect": { + "json": { + "materialized": false, + "viewLogic": "create view `bigquery-dataset-1.view-1` as select email from `bigquery-dataset-1.table-1`", + "viewLanguage": "SQL" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + }, + { + "id": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "urn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "schemaMetadata", + "aspect": { + "json": { + "schemaName": "project-id-1.bigquery-dataset-1.snapshot-table-1", + "platform": "urn:li:dataPlatform:bigquery", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "age", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.NumberType": {} + } + }, + "nativeDataType": "INT", + "recursive": false, + "globalTags": { + "tags": [ + { + "tag": "urn:li:tag:Test Policy Tag" + } + ] + }, + "isPartOfKey": false, + "isPartitioningKey": false + }, + { + "fieldPath": "email", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.StringType": {} + } + }, + "nativeDataType": "STRING", + "recursive": false, + "globalTags": { + "tags": [] + }, + "isPartOfKey": false, + "isPartitioningKey": false + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetProperties", + "aspect": { + "json": { + "customProperties": {}, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m5!1m4!4m3!1sproject-id-1!2sbigquery-dataset-1!3ssnapshot-table-1", + "name": "snapshot-table-1", + "qualifiedName": "project-id-1.bigquery-dataset-1.snapshot-table-1", + "description": "", + "tags": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery", + "instance": "urn:li:dataPlatformInstance:(urn:li:dataPlatform:bigquery,project-id-1)" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Bigquery Table Snapshot" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1643871600000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "type": "COPY" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),age)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD),age)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),email)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD),email)" + ], + "confidenceScore": 1.0 + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + }, + { + "id": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "urn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1643871600000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "type": "VIEW", + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),email)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD),email)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "queryProperties", + "aspect": { + "json": { + "statement": { + "value": "CREATE VIEW `bigquery-dataset-1.view-1` AS\nSELECT\n email\nFROM `bigquery-dataset-1.table-1`", + "language": "SQL" + }, + "source": "SYSTEM", + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "lastModified": { + "time": 1643871600000, + "actor": "urn:li:corpuser:_ingestion" + } + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "querySubjects", + "aspect": { + "json": { + "subjects": [ + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),email)" + }, + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD),email)" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "tag", + "entityUrn": "urn:li:tag:Test Policy Tag", + "changeType": "UPSERT", + "aspectName": "tagKey", + "aspect": { + "json": { + "name": "Test Policy Tag" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-0mn4n3", + "lastRunId": "no-run-id-provided" + } +} +] \ No newline at end of file diff --git a/metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_2.json b/metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_2.json new file mode 100644 index 0000000000000..26abc09569ccf --- /dev/null +++ b/metadata-ingestion/tests/integration/bigquery_v2/bigquery_mcp_lineage_golden_2.json @@ -0,0 +1,1064 @@ +[ +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "containerProperties", + "aspect": { + "json": { + "customProperties": { + "platform": "bigquery", + "env": "PROD", + "project_id": "project-id-1" + }, + "name": "project-id-1", + "env": "PROD" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Project" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "containerProperties", + "aspect": { + "json": { + "customProperties": { + "platform": "bigquery", + "env": "PROD", + "project_id": "project-id-1", + "dataset_id": "bigquery-dataset-1", + "location": "US" + }, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m4!1m3!3m2!1sproject-id-1!2sbigquery-dataset-1", + "name": "bigquery-dataset-1", + "env": "PROD" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Dataset" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "schemaMetadata", + "aspect": { + "json": { + "schemaName": "project-id-1.bigquery-dataset-1.table-1", + "platform": "urn:li:dataPlatform:bigquery", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "age", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.NumberType": {} + } + }, + "nativeDataType": "INT", + "recursive": false, + "globalTags": { + "tags": [ + { + "tag": "urn:li:tag:Test Policy Tag" + } + ] + }, + "isPartOfKey": false, + "isPartitioningKey": false + }, + { + "fieldPath": "email", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.StringType": {} + } + }, + "nativeDataType": "STRING", + "recursive": false, + "globalTags": { + "tags": [] + }, + "isPartOfKey": false, + "isPartitioningKey": false + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetProperties", + "aspect": { + "json": { + "customProperties": {}, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m5!1m4!4m3!1sproject-id-1!2sbigquery-dataset-1!3stable-1", + "name": "table-1", + "qualifiedName": "project-id-1.bigquery-dataset-1.table-1", + "description": "", + "tags": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery", + "instance": "urn:li:dataPlatformInstance:(urn:li:dataPlatform:bigquery,project-id-1)" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Table" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + }, + { + "id": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "urn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "schemaMetadata", + "aspect": { + "json": { + "schemaName": "project-id-1.bigquery-dataset-1.view-1", + "platform": "urn:li:dataPlatform:bigquery", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "age", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.NumberType": {} + } + }, + "nativeDataType": "INT", + "recursive": false, + "globalTags": { + "tags": [ + { + "tag": "urn:li:tag:Test Policy Tag" + } + ] + }, + "isPartOfKey": false, + "isPartitioningKey": false + }, + { + "fieldPath": "email", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.StringType": {} + } + }, + "nativeDataType": "STRING", + "recursive": false, + "globalTags": { + "tags": [] + }, + "isPartOfKey": false, + "isPartitioningKey": false + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetProperties", + "aspect": { + "json": { + "customProperties": {}, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m5!1m4!4m3!1sproject-id-1!2sbigquery-dataset-1!3sview-1", + "name": "view-1", + "qualifiedName": "project-id-1.bigquery-dataset-1.view-1", + "description": "", + "tags": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery", + "instance": "urn:li:dataPlatformInstance:(urn:li:dataPlatform:bigquery,project-id-1)" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "View" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "viewProperties", + "aspect": { + "json": { + "materialized": false, + "viewLogic": "create view `bigquery-dataset-1.view-1` as select email from `bigquery-dataset-1.table-1`", + "viewLanguage": "SQL" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + }, + { + "id": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "urn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "schemaMetadata", + "aspect": { + "json": { + "schemaName": "project-id-1.bigquery-dataset-1.snapshot-table-1", + "platform": "urn:li:dataPlatform:bigquery", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "age", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.NumberType": {} + } + }, + "nativeDataType": "INT", + "recursive": false, + "globalTags": { + "tags": [ + { + "tag": "urn:li:tag:Test Policy Tag" + } + ] + }, + "isPartOfKey": false, + "isPartitioningKey": false + }, + { + "fieldPath": "email", + "nullable": false, + "description": "comment", + "type": { + "type": { + "com.linkedin.schema.StringType": {} + } + }, + "nativeDataType": "STRING", + "recursive": false, + "globalTags": { + "tags": [] + }, + "isPartOfKey": false, + "isPartitioningKey": false + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetProperties", + "aspect": { + "json": { + "customProperties": {}, + "externalUrl": "https://console.cloud.google.com/bigquery?project=project-id-1&ws=!1m5!1m4!4m3!1sproject-id-1!2sbigquery-dataset-1!3ssnapshot-table-1", + "name": "snapshot-table-1", + "qualifiedName": "project-id-1.bigquery-dataset-1.snapshot-table-1", + "description": "", + "tags": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery", + "instance": "urn:li:dataPlatformInstance:(urn:li:dataPlatform:bigquery,project-id-1)" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Bigquery Table Snapshot" + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1643871600000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "type": "COPY" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),age)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD),age)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),email)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD),email)" + ], + "confidenceScore": 1.0 + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:068bd9323110994a40019fcf6cfc60d3", + "urn": "urn:li:container:068bd9323110994a40019fcf6cfc60d3" + }, + { + "id": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0", + "urn": "urn:li:container:8df46c5e3ded05a3122b0015822c0ef0" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1643871600000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "type": "VIEW", + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),email)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD),email)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "queryProperties", + "aspect": { + "json": { + "statement": { + "value": "CREATE VIEW `bigquery-dataset-1.view-1` AS\nSELECT\n email\nFROM `bigquery-dataset-1.table-1`", + "language": "SQL" + }, + "source": "SYSTEM", + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "lastModified": { + "time": 1643871600000, + "actor": "urn:li:corpuser:_ingestion" + } + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "querySubjects", + "aspect": { + "json": { + "subjects": [ + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD),email)" + }, + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD),email)" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:bigquery" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.snapshot-table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetUsageStatistics", + "aspect": { + "json": { + "timestampMillis": 1643760000000, + "eventGranularity": { + "unit": "DAY", + "multiple": 1 + }, + "partitionSpec": { + "partition": "FULL_TABLE_SNAPSHOT", + "type": "FULL_TABLE" + }, + "uniqueUserCount": 0, + "totalSqlQueries": 0, + "topSqlQueries": [], + "userCounts": [], + "fieldCounts": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.view-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetUsageStatistics", + "aspect": { + "json": { + "timestampMillis": 1643760000000, + "eventGranularity": { + "unit": "DAY", + "multiple": 1 + }, + "partitionSpec": { + "partition": "FULL_TABLE_SNAPSHOT", + "type": "FULL_TABLE" + }, + "uniqueUserCount": 0, + "totalSqlQueries": 0, + "topSqlQueries": [], + "userCounts": [], + "fieldCounts": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:bigquery,project-id-1.bigquery-dataset-1.table-1,PROD)", + "changeType": "UPSERT", + "aspectName": "datasetUsageStatistics", + "aspect": { + "json": { + "timestampMillis": 1643760000000, + "eventGranularity": { + "unit": "DAY", + "multiple": 1 + }, + "partitionSpec": { + "partition": "FULL_TABLE_SNAPSHOT", + "type": "FULL_TABLE" + }, + "uniqueUserCount": 0, + "totalSqlQueries": 0, + "topSqlQueries": [], + "userCounts": [], + "fieldCounts": [] + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Abigquery%2Cproject-id-1.bigquery-dataset-1.view-1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "tag", + "entityUrn": "urn:li:tag:Test Policy Tag", + "changeType": "UPSERT", + "aspectName": "tagKey", + "aspect": { + "json": { + "name": "Test Policy Tag" + } + }, + "systemMetadata": { + "lastObserved": 1643871600000, + "runId": "bigquery-2022_02_03-07_00_00-k4o1z9", + "lastRunId": "no-run-id-provided" + } +} +] \ No newline at end of file diff --git a/metadata-ingestion/tests/integration/bigquery_v2/test_bigquery.py b/metadata-ingestion/tests/integration/bigquery_v2/test_bigquery.py index 1f14688636161..2dd320041a113 100644 --- a/metadata-ingestion/tests/integration/bigquery_v2/test_bigquery.py +++ b/metadata-ingestion/tests/integration/bigquery_v2/test_bigquery.py @@ -4,6 +4,7 @@ from typing import Any, Dict, Optional from unittest.mock import MagicMock, patch +import pytest from freezegun import freeze_time from google.cloud.bigquery.table import TableListItem @@ -577,3 +578,147 @@ def test_bigquery_queries_v2_lineage_usage_ingest( output_path=mcp_output_path, golden_path=mcp_golden_path, ) + + +@freeze_time(FROZEN_TIME) +@patch.object(BigQuerySchemaApi, "get_snapshots_for_dataset") +@patch.object(BigQuerySchemaApi, "get_views_for_dataset") +@patch.object(BigQuerySchemaApi, "get_tables_for_dataset") +@patch.object(BigQuerySchemaGenerator, "get_core_table_details") +@patch.object(BigQuerySchemaApi, "get_datasets_for_project_id") +@patch.object(BigQuerySchemaApi, "get_columns_for_dataset") +@patch.object(BigQueryDataReader, "get_sample_data_for_table") +@patch("google.cloud.bigquery.Client") +@patch("google.cloud.datacatalog_v1.PolicyTagManagerClient") +@patch("google.cloud.resourcemanager_v3.ProjectsClient") +@pytest.mark.parametrize( + "use_queries_v2, include_table_lineage, include_usage_statistics, golden_file", + [ + (True, False, False, "bigquery_mcp_lineage_golden_1.json"), + (True, True, False, "bigquery_mcp_lineage_golden_1.json"), + (False, False, True, "bigquery_mcp_lineage_golden_2.json"), + (False, True, True, "bigquery_mcp_lineage_golden_2.json"), + ], +) +def test_bigquery_lineage_v2_ingest_view_snapshots( + client, + policy_tag_manager_client, + projects_client, + get_sample_data_for_table, + get_columns_for_dataset, + get_datasets_for_project_id, + get_core_table_details, + get_tables_for_dataset, + get_views_for_dataset, + get_snapshots_for_dataset, + pytestconfig, + tmp_path, + use_queries_v2, + include_table_lineage, + include_usage_statistics, + golden_file, +): + test_resources_dir = pytestconfig.rootpath / "tests/integration/bigquery_v2" + mcp_golden_path = f"{test_resources_dir}/{golden_file}" + mcp_output_path = "{}/{}_output.json".format(tmp_path, golden_file) + + dataset_name = "bigquery-dataset-1" + get_datasets_for_project_id.return_value = [ + BigqueryDataset(name=dataset_name, location="US") + ] + + table_list_item = TableListItem( + {"tableReference": {"projectId": "", "datasetId": "", "tableId": ""}} + ) + table_name = "table-1" + snapshot_table_name = "snapshot-table-1" + view_name = "view-1" + get_core_table_details.return_value = {table_name: table_list_item} + columns = [ + BigqueryColumn( + name="age", + ordinal_position=1, + is_nullable=False, + field_path="col_1", + data_type="INT", + comment="comment", + is_partition_column=False, + cluster_column_position=None, + policy_tags=["Test Policy Tag"], + ), + BigqueryColumn( + name="email", + ordinal_position=1, + is_nullable=False, + field_path="col_2", + data_type="STRING", + comment="comment", + is_partition_column=False, + cluster_column_position=None, + ), + ] + + get_columns_for_dataset.return_value = { + table_name: columns, + snapshot_table_name: columns, + view_name: columns, + } + get_sample_data_for_table.return_value = { + "age": [random.randint(1, 80) for i in range(20)], + "email": [random_email() for i in range(20)], + } + + bigquery_table = BigqueryTable( + name=table_name, + comment=None, + created=None, + last_altered=None, + size_in_bytes=None, + rows_count=None, + ) + get_tables_for_dataset.return_value = iter([bigquery_table]) + + bigquery_view = BigqueryView( + name=view_name, + comment=None, + created=None, + view_definition=f"create view `{dataset_name}.view-1` as select email from `{dataset_name}.table-1`", + last_altered=None, + size_in_bytes=None, + rows_count=None, + materialized=False, + ) + + get_views_for_dataset.return_value = iter([bigquery_view]) + snapshot_table = BigqueryTableSnapshot( + name=snapshot_table_name, + comment=None, + created=None, + last_altered=None, + size_in_bytes=None, + rows_count=None, + base_table_identifier=BigqueryTableIdentifier( + project_id="project-id-1", + dataset="bigquery-dataset-1", + table="table-1", + ), + ) + get_snapshots_for_dataset.return_value = iter([snapshot_table]) + + pipeline_config_dict: Dict[str, Any] = recipe( + mcp_output_path=mcp_output_path, + source_config_override={ + "use_queries_v2": use_queries_v2, + "include_table_lineage": include_table_lineage, + "include_usage_statistics": include_usage_statistics, + "classification": {"enabled": False}, + }, + ) + + run_and_get_pipeline(pipeline_config_dict) + + mce_helpers.check_golden_file( + pytestconfig, + output_path=mcp_output_path, + golden_path=mcp_golden_path, + ) From 7f64ffd2f7541900bbcd2b7b5b3f6dde237a8667 Mon Sep 17 00:00:00 2001 From: sagar-salvi-apptware <159135491+sagar-salvi-apptware@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:44:45 +0530 Subject: [PATCH 8/8] test(ingest/athena): add connector integration tests (#12256) --- .../integration/athena/athena_mce_golden.json | 1362 +++++++++++++++++ .../integration/athena/test_athena_source.py | 163 ++ 2 files changed, 1525 insertions(+) create mode 100644 metadata-ingestion/tests/integration/athena/athena_mce_golden.json create mode 100644 metadata-ingestion/tests/integration/athena/test_athena_source.py diff --git a/metadata-ingestion/tests/integration/athena/athena_mce_golden.json b/metadata-ingestion/tests/integration/athena/athena_mce_golden.json new file mode 100644 index 0000000000000..1b3fdb0bdb253 --- /dev/null +++ b/metadata-ingestion/tests/integration/athena/athena_mce_golden.json @@ -0,0 +1,1362 @@ +[ +{ + "entityType": "container", + "entityUrn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "changeType": "UPSERT", + "aspectName": "containerProperties", + "aspect": { + "json": { + "customProperties": { + "platform": "athena", + "env": "PROD", + "database": "test_schema" + }, + "name": "test_schema", + "env": "PROD" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:athena" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Database" + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "container", + "entityUrn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "proposedSnapshot": { + "com.linkedin.pegasus2avro.metadata.snapshot.DatasetSnapshot": { + "urn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)", + "aspects": [ + { + "com.linkedin.pegasus2avro.common.Status": { + "removed": false + } + }, + { + "com.linkedin.pegasus2avro.dataset.DatasetProperties": { + "customProperties": { + "key": "value", + "table_type": "EXTERNAL_TABLE", + "is_view": "True", + "view_definition": "CREATE VIEW \"test_schema\".test_view_1 AS\nSELECT *\nFROM\n \"test_schema\".\"test_table\"" + }, + "name": "test_table", + "description": "Test table description", + "tags": [] + } + }, + { + "com.linkedin.pegasus2avro.schema.SchemaMetadata": { + "schemaName": "test_schema.test_table", + "platform": "urn:li:dataPlatform:athena", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.pegasus2avro.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "[version=2.0].[type=string].employee_id", + "nullable": false, + "description": "Unique identifier for the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": false}" + }, + { + "fieldPath": "[version=2.0].[type=long].annual_salary", + "nullable": true, + "description": "Annual salary of the employee in USD", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.NumberType": {} + } + }, + "nativeDataType": "BIGINT", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"BIGINT\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=string].employee_name", + "nullable": false, + "description": "Full name of the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": false}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history", + "nullable": true, + "description": "Job history map: year to details (company, role)", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.MapType": { + "keyType": "string", + "valueType": "record" + } + } + }, + "nativeDataType": "MapType(String(), STRUCT(year=INTEGER(), company=String(), role=String()))", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"MapType(String(), STRUCT(year=INTEGER(), company=String(), role=String()))\", \"key_type\": {\"type\": \"string\", \"native_data_type\": \"VARCHAR\", \"_nullable\": true}, \"key_native_data_type\": \"VARCHAR\"}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=int].year", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.NumberType": {} + } + }, + "nativeDataType": "INTEGER", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"INTEGER\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=string].company", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=string].role", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=long].department_budgets", + "nullable": true, + "description": "Map of department names to their respective budgets", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.MapType": { + "keyType": "string", + "valueType": "long" + } + } + }, + "nativeDataType": "MapType(String(), BIGINT())", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"MapType(String(), BIGINT())\", \"key_type\": {\"type\": \"string\", \"native_data_type\": \"VARCHAR\", \"_nullable\": true}, \"key_native_data_type\": \"VARCHAR\"}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=array].[type=string].skills", + "nullable": true, + "description": "List of skills possessed by the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.ArrayType": { + "nestedType": [ + "string" + ] + } + } + }, + "nativeDataType": "array", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"array\"}" + } + ] + } + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "Table" + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "urn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "proposedSnapshot": { + "com.linkedin.pegasus2avro.metadata.snapshot.DatasetSnapshot": { + "urn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "aspects": [ + { + "com.linkedin.pegasus2avro.common.Status": { + "removed": false + } + }, + { + "com.linkedin.pegasus2avro.dataset.DatasetProperties": { + "customProperties": { + "key": "value", + "table_type": "EXTERNAL_TABLE", + "is_view": "True", + "view_definition": "CREATE VIEW \"test_schema\".test_view_2 AS\nSELECT employee_id, employee_name, skills\nFROM\n \"test_schema\".\"test_view_1\"" + }, + "name": "test_view_1", + "description": "Test table description", + "tags": [] + } + }, + { + "com.linkedin.pegasus2avro.schema.SchemaMetadata": { + "schemaName": "test_schema.test_view_1", + "platform": "urn:li:dataPlatform:athena", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.pegasus2avro.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "[version=2.0].[type=string].employee_id", + "nullable": false, + "description": "Unique identifier for the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": false}" + }, + { + "fieldPath": "[version=2.0].[type=long].annual_salary", + "nullable": true, + "description": "Annual salary of the employee in USD", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.NumberType": {} + } + }, + "nativeDataType": "BIGINT", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"BIGINT\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=string].employee_name", + "nullable": false, + "description": "Full name of the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": false}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history", + "nullable": true, + "description": "Job history map: year to details (company, role)", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.MapType": { + "keyType": "string", + "valueType": "record" + } + } + }, + "nativeDataType": "MapType(String(), STRUCT(year=INTEGER(), company=String(), role=String()))", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"MapType(String(), STRUCT(year=INTEGER(), company=String(), role=String()))\", \"key_type\": {\"type\": \"string\", \"native_data_type\": \"VARCHAR\", \"_nullable\": true}, \"key_native_data_type\": \"VARCHAR\"}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=int].year", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.NumberType": {} + } + }, + "nativeDataType": "INTEGER", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"INTEGER\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=string].company", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=string].role", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=long].department_budgets", + "nullable": true, + "description": "Map of department names to their respective budgets", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.MapType": { + "keyType": "string", + "valueType": "long" + } + } + }, + "nativeDataType": "MapType(String(), BIGINT())", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"MapType(String(), BIGINT())\", \"key_type\": {\"type\": \"string\", \"native_data_type\": \"VARCHAR\", \"_nullable\": true}, \"key_native_data_type\": \"VARCHAR\"}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=array].[type=string].skills", + "nullable": true, + "description": "List of skills possessed by the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.ArrayType": { + "nestedType": [ + "string" + ] + } + } + }, + "nativeDataType": "array", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"array\"}" + } + ] + } + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "View" + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "changeType": "UPSERT", + "aspectName": "viewProperties", + "aspect": { + "json": { + "materialized": false, + "viewLogic": "CREATE VIEW \"test_schema\".test_view_1 AS\nSELECT *\nFROM\n \"test_schema\".\"test_table\"", + "viewLanguage": "SQL" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "urn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)", + "changeType": "UPSERT", + "aspectName": "container", + "aspect": { + "json": { + "container": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "proposedSnapshot": { + "com.linkedin.pegasus2avro.metadata.snapshot.DatasetSnapshot": { + "urn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)", + "aspects": [ + { + "com.linkedin.pegasus2avro.common.Status": { + "removed": false + } + }, + { + "com.linkedin.pegasus2avro.dataset.DatasetProperties": { + "customProperties": { + "key": "value", + "table_type": "EXTERNAL_TABLE", + "is_view": "True", + "view_definition": "CREATE VIEW \"test_schema\".test_view_2 AS\nSELECT employee_id, employee_name, skills\nFROM\n \"test_schema\".\"test_view_1\"" + }, + "name": "test_view_2", + "description": "Test table description", + "tags": [] + } + }, + { + "com.linkedin.pegasus2avro.schema.SchemaMetadata": { + "schemaName": "test_schema.test_view_2", + "platform": "urn:li:dataPlatform:athena", + "version": 0, + "created": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "lastModified": { + "time": 0, + "actor": "urn:li:corpuser:unknown" + }, + "hash": "", + "platformSchema": { + "com.linkedin.pegasus2avro.schema.MySqlDDL": { + "tableSchema": "" + } + }, + "fields": [ + { + "fieldPath": "[version=2.0].[type=string].employee_id", + "nullable": false, + "description": "Unique identifier for the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": false}" + }, + { + "fieldPath": "[version=2.0].[type=long].annual_salary", + "nullable": true, + "description": "Annual salary of the employee in USD", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.NumberType": {} + } + }, + "nativeDataType": "BIGINT", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"BIGINT\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=string].employee_name", + "nullable": false, + "description": "Full name of the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": false}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history", + "nullable": true, + "description": "Job history map: year to details (company, role)", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.MapType": { + "keyType": "string", + "valueType": "record" + } + } + }, + "nativeDataType": "MapType(String(), STRUCT(year=INTEGER(), company=String(), role=String()))", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"MapType(String(), STRUCT(year=INTEGER(), company=String(), role=String()))\", \"key_type\": {\"type\": \"string\", \"native_data_type\": \"VARCHAR\", \"_nullable\": true}, \"key_native_data_type\": \"VARCHAR\"}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=int].year", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.NumberType": {} + } + }, + "nativeDataType": "INTEGER", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"INTEGER\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=string].company", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=struct].job_history.[type=string].role", + "nullable": true, + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.StringType": {} + } + }, + "nativeDataType": "VARCHAR", + "recursive": false, + "isPartOfKey": false, + "jsonProps": "{\"native_data_type\": \"VARCHAR\", \"_nullable\": true}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=map].[type=long].department_budgets", + "nullable": true, + "description": "Map of department names to their respective budgets", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.MapType": { + "keyType": "string", + "valueType": "long" + } + } + }, + "nativeDataType": "MapType(String(), BIGINT())", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"MapType(String(), BIGINT())\", \"key_type\": {\"type\": \"string\", \"native_data_type\": \"VARCHAR\", \"_nullable\": true}, \"key_native_data_type\": \"VARCHAR\"}" + }, + { + "fieldPath": "[version=2.0].[type=struct].[type=array].[type=string].skills", + "nullable": true, + "description": "List of skills possessed by the employee", + "type": { + "type": { + "com.linkedin.pegasus2avro.schema.ArrayType": { + "nestedType": [ + "string" + ] + } + } + }, + "nativeDataType": "array", + "recursive": false, + "isPartOfKey": false, + "isPartitioningKey": false, + "jsonProps": "{\"native_data_type\": \"array\"}" + } + ] + } + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)", + "changeType": "UPSERT", + "aspectName": "subTypes", + "aspect": { + "json": { + "typeNames": [ + "View" + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)", + "changeType": "UPSERT", + "aspectName": "viewProperties", + "aspect": { + "json": { + "materialized": false, + "viewLogic": "CREATE VIEW \"test_schema\".test_view_2 AS\nSELECT employee_id, employee_name, skills\nFROM\n \"test_schema\".\"test_view_1\"", + "viewLanguage": "SQL" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)", + "changeType": "UPSERT", + "aspectName": "browsePathsV2", + "aspect": { + "json": { + "path": [ + { + "id": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67", + "urn": "urn:li:container:28d9272f625e7a366dfdc276b6ce4a67" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1671098400000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD)", + "type": "COPY" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD),employee_id)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),employee_id)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD),annual_salary)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),annual_salary)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD),employee_name)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),employee_name)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD),job_history)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),job_history)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD),department_budgets)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),department_budgets)" + ], + "confidenceScore": 1.0 + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:s3,test-bucket/test_table,PROD),skills)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),skills)" + ], + "confidenceScore": 1.0 + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1671098400000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)", + "type": "VIEW", + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),employee_id)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_id)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),annual_salary)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),annual_salary)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),employee_name)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_name)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),job_history)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),job_history)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),department_budgets)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),department_budgets)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),skills)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),skills)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "queryProperties", + "aspect": { + "json": { + "statement": { + "value": "CREATE VIEW \"test_schema\".test_view_1 AS\nSELECT\n *\nFROM \"test_schema\".\"test_table\"", + "language": "SQL" + }, + "source": "SYSTEM", + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "lastModified": { + "time": 1671098400000, + "actor": "urn:li:corpuser:_ingestion" + } + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "querySubjects", + "aspect": { + "json": { + "subjects": [ + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),annual_salary)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),department_budgets)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),employee_id)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),employee_name)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),job_history)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_table,PROD),skills)" + }, + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_id)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),annual_salary)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_name)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),job_history)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),department_budgets)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),skills)" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:athena" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "dataset", + "entityUrn": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)", + "changeType": "UPSERT", + "aspectName": "upstreamLineage", + "aspect": { + "json": { + "upstreams": [ + { + "auditStamp": { + "time": 1671098400000, + "actor": "urn:li:corpuser:_ingestion" + }, + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "dataset": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)", + "type": "VIEW", + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29" + } + ], + "fineGrainedLineages": [ + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_id)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD),employee_id)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_name)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD),employee_name)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29" + }, + { + "upstreamType": "FIELD_SET", + "upstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),skills)" + ], + "downstreamType": "FIELD", + "downstreams": [ + "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD),skills)" + ], + "confidenceScore": 0.9, + "query": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "queryProperties", + "aspect": { + "json": { + "statement": { + "value": "CREATE VIEW \"test_schema\".test_view_2 AS\nSELECT\n employee_id,\n employee_name,\n skills\nFROM \"test_schema\".\"test_view_1\"", + "language": "SQL" + }, + "source": "SYSTEM", + "created": { + "time": 0, + "actor": "urn:li:corpuser:_ingestion" + }, + "lastModified": { + "time": 1671098400000, + "actor": "urn:li:corpuser:_ingestion" + } + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "querySubjects", + "aspect": { + "json": { + "subjects": [ + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_id)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),employee_name)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_1,PROD),skills)" + }, + { + "entity": "urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD),employee_id)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD),employee_name)" + }, + { + "entity": "urn:li:schemaField:(urn:li:dataset:(urn:li:dataPlatform:athena,test_schema.test_view_2,PROD),skills)" + } + ] + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "dataPlatformInstance", + "aspect": { + "json": { + "platform": "urn:li:dataPlatform:athena" + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_1%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +}, +{ + "entityType": "query", + "entityUrn": "urn:li:query:view_urn%3Ali%3Adataset%3A%28urn%3Ali%3AdataPlatform%3Aathena%2Ctest_schema.test_view_2%2CPROD%29", + "changeType": "UPSERT", + "aspectName": "status", + "aspect": { + "json": { + "removed": false + } + }, + "systemMetadata": { + "lastObserved": 1671098400000, + "runId": "athena-test", + "lastRunId": "no-run-id-provided" + } +} +] \ No newline at end of file diff --git a/metadata-ingestion/tests/integration/athena/test_athena_source.py b/metadata-ingestion/tests/integration/athena/test_athena_source.py new file mode 100644 index 0000000000000..56e7cbe6b3e2d --- /dev/null +++ b/metadata-ingestion/tests/integration/athena/test_athena_source.py @@ -0,0 +1,163 @@ +from unittest.mock import MagicMock, patch + +from freezegun import freeze_time +from sqlalchemy import ARRAY, BIGINT, INTEGER, String +from sqlalchemy_bigquery import STRUCT + +from datahub.ingestion.run.pipeline import Pipeline +from datahub.ingestion.source.aws.s3_util import make_s3_urn +from datahub.ingestion.source.sql.athena import AthenaSource +from datahub.utilities.sqlalchemy_type_converter import MapType +from tests.test_helpers import ( # Ensure mce_helpers is available for validation. + mce_helpers, +) + +FROZEN_TIME = "2022-12-15 10:00:00" + + +@freeze_time(FROZEN_TIME) +def test_athena_source_ingestion(pytestconfig, tmp_path): + """Test Athena source ingestion and generate MCP JSON file for validation.""" + output_file_name = "athena_mce_output.json" + golden_file_name = "athena_mce_golden.json" + test_resources_dir = pytestconfig.rootpath / "tests/integration/athena" + + # Mock dependencies + with patch.object( + AthenaSource, "get_inspectors" + ) as mock_get_inspectors, patch.object( + AthenaSource, "get_table_properties" + ) as mock_get_table_properties: + # Mock engine and inspectors + mock_inspector = MagicMock() + mock_get_inspectors.return_value = [mock_inspector] + mock_engine_instance = MagicMock() + mock_engine_instance.url.database = "" + mock_inspector.engine = mock_engine_instance + + # Mock schema and table names + mock_inspector.get_schema_names.return_value = ["test_schema"] + mock_inspector.get_table_names.return_value = ["test_table"] + mock_inspector.get_view_names.return_value = ["test_view_1", "test_view_2"] + + # Mock view definitions + def mock_get_view_definition(view_name, schema): + if view_name == "test_view_1": + return ( + 'CREATE VIEW "test_schema".test_view_1 AS\n' + "SELECT *\n" + "FROM\n" + ' "test_schema"."test_table"' + ) + elif view_name == "test_view_2": + return ( + 'CREATE VIEW "test_schema".test_view_2 AS\n' + "SELECT employee_id, employee_name, skills\n" + "FROM\n" + ' "test_schema"."test_view_1"' + ) + return "" + + mock_inspector.get_view_definition.side_effect = mock_get_view_definition + + mock_inspector.get_columns.return_value = [ + { + "name": "employee_id", + "type": String(), + "nullable": False, + "default": None, + "autoincrement": False, + "comment": "Unique identifier for the employee", + "dialect_options": {"awsathena_partition": None}, + }, + { + "name": "annual_salary", + "type": BIGINT(), + "nullable": True, + "default": None, + "autoincrement": False, + "comment": "Annual salary of the employee in USD", + "dialect_options": {"awsathena_partition": None}, + }, + { + "name": "employee_name", + "type": String(), + "nullable": False, + "default": None, + "autoincrement": False, + "comment": "Full name of the employee", + "dialect_options": {"awsathena_partition": None}, + }, + { + "name": "job_history", + "type": MapType( + String(), STRUCT(year=INTEGER(), company=String(), role=String()) + ), + "nullable": True, + "default": None, + "autoincrement": False, + "comment": "Job history map: year to details (company, role)", + "dialect_options": {"awsathena_partition": None}, + }, + { + "name": "department_budgets", + "type": MapType(String(), BIGINT()), + "nullable": True, + "default": None, + "autoincrement": False, + "comment": "Map of department names to their respective budgets", + "dialect_options": {"awsathena_partition": None}, + }, + { + "name": "skills", + "type": ARRAY(String()), + "nullable": True, + "default": None, + "autoincrement": False, + "comment": "List of skills possessed by the employee", + "dialect_options": {"awsathena_partition": None}, + }, + ] + # Mock table properties + mock_get_table_properties.return_value = ( + "Test table description", + {"key": "value", "table_type": "EXTERNAL_TABLE"}, + make_s3_urn("s3://test-bucket/test_table", "PROD"), + ) + + # Define the pipeline configuration + config_dict = { + "run_id": "athena-test", + "source": { + "type": "athena", + "config": { + "aws_region": "us-east-1", + "work_group": "primary", + "query_result_location": "s3://athena-query-results/", + "catalog_name": "awsdatacatalog", + "include_views": True, + "include_tables": True, + "profiling": { + "enabled": False, + }, + }, + }, + "sink": { + "type": "file", + "config": { + "filename": f"{tmp_path}/{output_file_name}", + }, + }, + } + + # Create and run the pipeline + pipeline = Pipeline.create(config_dict) + pipeline.run() + pipeline.raise_from_status() + + # Validate the output with the golden file + mce_helpers.check_golden_file( + pytestconfig=pytestconfig, + output_path=f"{tmp_path}/{output_file_name}", + golden_path=f"{test_resources_dir}/{golden_file_name}", + )