mirror of
https://github.com/neondatabase/neon.git
synced 2026-06-30 18:50:36 +00:00
Compare commits
7 Commits
ps_communi
...
parameteri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3208220456 | ||
|
|
ea1e84b585 | ||
|
|
4afd53c8b2 | ||
|
|
4df5b7631c | ||
|
|
6a28a47708 | ||
|
|
3c880f6bb3 | ||
|
|
33751f2805 |
@@ -3,16 +3,6 @@
|
|||||||
# by the RUSTDOCFLAGS env var in CI.
|
# by the RUSTDOCFLAGS env var in CI.
|
||||||
rustdocflags = ["-Arustdoc::private_intra_doc_links"]
|
rustdocflags = ["-Arustdoc::private_intra_doc_links"]
|
||||||
|
|
||||||
# Enable frame pointers. This may have a minor performance overhead, but makes it easier and more
|
|
||||||
# efficient to obtain stack traces (and thus CPU/heap profiles). It may also avoid seg faults that
|
|
||||||
# we've seen with libunwind-based profiling. See also:
|
|
||||||
#
|
|
||||||
# * <https://www.brendangregg.com/blog/2024-03-17/the-return-of-the-frame-pointers.html>
|
|
||||||
# * <https://github.com/rust-lang/rust/pull/122646>
|
|
||||||
#
|
|
||||||
# NB: the RUSTFLAGS envvar will replace this. Make sure to update e.g. Dockerfile as well.
|
|
||||||
rustflags = ["-Cforce-frame-pointers=yes"]
|
|
||||||
|
|
||||||
[alias]
|
[alias]
|
||||||
build_testing = ["build", "--features", "testing"]
|
build_testing = ["build", "--features", "testing"]
|
||||||
neon = ["run", "--bin", "neon_local"]
|
neon = ["run", "--bin", "neon_local"]
|
||||||
|
|||||||
@@ -46,9 +46,6 @@ workspace-members = [
|
|||||||
"utils",
|
"utils",
|
||||||
"wal_craft",
|
"wal_craft",
|
||||||
"walproposer",
|
"walproposer",
|
||||||
"postgres-protocol2",
|
|
||||||
"postgres-types2",
|
|
||||||
"tokio-postgres2",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Write out exact versions rather than a semver range. (Defaults to false.)
|
# Write out exact versions rather than a semver range. (Defaults to false.)
|
||||||
|
|||||||
@@ -24,4 +24,3 @@
|
|||||||
!storage_controller/
|
!storage_controller/
|
||||||
!vendor/postgres-*/
|
!vendor/postgres-*/
|
||||||
!workspace_hack/
|
!workspace_hack/
|
||||||
!build_tools/patches
|
|
||||||
|
|||||||
1
.github/ISSUE_TEMPLATE/bug-template.md
vendored
1
.github/ISSUE_TEMPLATE/bug-template.md
vendored
@@ -3,7 +3,6 @@ name: Bug Template
|
|||||||
about: Used for describing bugs
|
about: Used for describing bugs
|
||||||
title: ''
|
title: ''
|
||||||
labels: t/bug
|
labels: t/bug
|
||||||
type: Bug
|
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
1
.github/ISSUE_TEMPLATE/epic-template.md
vendored
1
.github/ISSUE_TEMPLATE/epic-template.md
vendored
@@ -4,7 +4,6 @@ about: A set of related tasks contributing towards specific outcome, comprising
|
|||||||
more than 1 week of work.
|
more than 1 week of work.
|
||||||
title: 'Epic: '
|
title: 'Epic: '
|
||||||
labels: t/Epic
|
labels: t/Epic
|
||||||
type: Epic
|
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
8
.github/actionlint.yml
vendored
8
.github/actionlint.yml
vendored
@@ -4,7 +4,6 @@ self-hosted-runner:
|
|||||||
- large
|
- large
|
||||||
- large-arm64
|
- large-arm64
|
||||||
- small
|
- small
|
||||||
- small-metal
|
|
||||||
- small-arm64
|
- small-arm64
|
||||||
- us-east-2
|
- us-east-2
|
||||||
config-variables:
|
config-variables:
|
||||||
@@ -21,10 +20,3 @@ config-variables:
|
|||||||
- REMOTE_STORAGE_AZURE_REGION
|
- REMOTE_STORAGE_AZURE_REGION
|
||||||
- SLACK_UPCOMING_RELEASE_CHANNEL_ID
|
- SLACK_UPCOMING_RELEASE_CHANNEL_ID
|
||||||
- DEV_AWS_OIDC_ROLE_ARN
|
- DEV_AWS_OIDC_ROLE_ARN
|
||||||
- BENCHMARK_INGEST_TARGET_PROJECTID
|
|
||||||
- PGREGRESS_PG16_PROJECT_ID
|
|
||||||
- PGREGRESS_PG17_PROJECT_ID
|
|
||||||
- SLACK_ON_CALL_QA_STAGING_STREAM
|
|
||||||
- DEV_AWS_OIDC_ROLE_MANAGE_BENCHMARK_EC2_VMS_ARN
|
|
||||||
- SLACK_ON_CALL_STORAGE_STAGING_STREAM
|
|
||||||
- SLACK_CICD_CHANNEL_ID
|
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ inputs:
|
|||||||
type: boolean
|
type: boolean
|
||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
aws-oicd-role-arn:
|
|
||||||
description: 'OIDC role arn to interract with S3'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
base-url:
|
base-url:
|
||||||
@@ -42,8 +39,7 @@ runs:
|
|||||||
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH" || true)
|
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH" || true)
|
||||||
if [ "${PR_NUMBER}" != "null" ]; then
|
if [ "${PR_NUMBER}" != "null" ]; then
|
||||||
BRANCH_OR_PR=pr-${PR_NUMBER}
|
BRANCH_OR_PR=pr-${PR_NUMBER}
|
||||||
elif [ "${GITHUB_REF_NAME}" = "main" ] || [ "${GITHUB_REF_NAME}" = "release" ] || \
|
elif [ "${GITHUB_REF_NAME}" = "main" ] || [ "${GITHUB_REF_NAME}" = "release" ] || [ "${GITHUB_REF_NAME}" = "release-proxy" ]; then
|
||||||
[ "${GITHUB_REF_NAME}" = "release-proxy" ] || [ "${GITHUB_REF_NAME}" = "release-compute" ]; then
|
|
||||||
# Shortcut for special branches
|
# Shortcut for special branches
|
||||||
BRANCH_OR_PR=${GITHUB_REF_NAME}
|
BRANCH_OR_PR=${GITHUB_REF_NAME}
|
||||||
else
|
else
|
||||||
@@ -83,13 +79,6 @@ runs:
|
|||||||
ALLURE_VERSION: 2.27.0
|
ALLURE_VERSION: 2.27.0
|
||||||
ALLURE_ZIP_SHA256: b071858fb2fa542c65d8f152c5c40d26267b2dfb74df1f1608a589ecca38e777
|
ALLURE_ZIP_SHA256: b071858fb2fa542c65d8f152c5c40d26267b2dfb74df1f1608a589ecca38e777
|
||||||
|
|
||||||
- uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
role-duration-seconds: 3600 # 1 hour should be more than enough to upload report
|
|
||||||
|
|
||||||
# Potentially we could have several running build for the same key (for example, for the main branch), so we use improvised lock for this
|
# Potentially we could have several running build for the same key (for example, for the main branch), so we use improvised lock for this
|
||||||
- name: Acquire lock
|
- name: Acquire lock
|
||||||
shell: bash -euxo pipefail {0}
|
shell: bash -euxo pipefail {0}
|
||||||
@@ -232,8 +221,6 @@ runs:
|
|||||||
REPORT_URL: ${{ steps.generate-report.outputs.report-url }}
|
REPORT_URL: ${{ steps.generate-report.outputs.report-url }}
|
||||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
with:
|
with:
|
||||||
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
|
||||||
retries: 5
|
|
||||||
script: |
|
script: |
|
||||||
const { REPORT_URL, COMMIT_SHA } = process.env
|
const { REPORT_URL, COMMIT_SHA } = process.env
|
||||||
|
|
||||||
|
|||||||
13
.github/actions/allure-report-store/action.yml
vendored
13
.github/actions/allure-report-store/action.yml
vendored
@@ -8,9 +8,6 @@ inputs:
|
|||||||
unique-key:
|
unique-key:
|
||||||
description: 'string to distinguish different results in the same run'
|
description: 'string to distinguish different results in the same run'
|
||||||
required: true
|
required: true
|
||||||
aws-oicd-role-arn:
|
|
||||||
description: 'OIDC role arn to interract with S3'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
@@ -22,8 +19,7 @@ runs:
|
|||||||
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH" || true)
|
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH" || true)
|
||||||
if [ "${PR_NUMBER}" != "null" ]; then
|
if [ "${PR_NUMBER}" != "null" ]; then
|
||||||
BRANCH_OR_PR=pr-${PR_NUMBER}
|
BRANCH_OR_PR=pr-${PR_NUMBER}
|
||||||
elif [ "${GITHUB_REF_NAME}" = "main" ] || [ "${GITHUB_REF_NAME}" = "release" ] || \
|
elif [ "${GITHUB_REF_NAME}" = "main" ] || [ "${GITHUB_REF_NAME}" = "release" ] || [ "${GITHUB_REF_NAME}" = "release-proxy" ]; then
|
||||||
[ "${GITHUB_REF_NAME}" = "release-proxy" ] || [ "${GITHUB_REF_NAME}" = "release-compute" ]; then
|
|
||||||
# Shortcut for special branches
|
# Shortcut for special branches
|
||||||
BRANCH_OR_PR=${GITHUB_REF_NAME}
|
BRANCH_OR_PR=${GITHUB_REF_NAME}
|
||||||
else
|
else
|
||||||
@@ -35,13 +31,6 @@ runs:
|
|||||||
env:
|
env:
|
||||||
REPORT_DIR: ${{ inputs.report-dir }}
|
REPORT_DIR: ${{ inputs.report-dir }}
|
||||||
|
|
||||||
- uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
role-duration-seconds: 3600 # 1 hour should be more than enough to upload report
|
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
shell: bash -euxo pipefail {0}
|
shell: bash -euxo pipefail {0}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
9
.github/actions/download/action.yml
vendored
9
.github/actions/download/action.yml
vendored
@@ -15,19 +15,10 @@ inputs:
|
|||||||
prefix:
|
prefix:
|
||||||
description: "S3 prefix. Default is '${GITHUB_RUN_ID}/${GITHUB_RUN_ATTEMPT}'"
|
description: "S3 prefix. Default is '${GITHUB_RUN_ID}/${GITHUB_RUN_ATTEMPT}'"
|
||||||
required: false
|
required: false
|
||||||
aws-oicd-role-arn:
|
|
||||||
description: 'OIDC role arn to interract with S3'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
id: download-artifact
|
id: download-artifact
|
||||||
shell: bash -euxo pipefail {0}
|
shell: bash -euxo pipefail {0}
|
||||||
|
|||||||
54
.github/actions/neon-project-create/action.yml
vendored
54
.github/actions/neon-project-create/action.yml
vendored
@@ -17,34 +17,6 @@ inputs:
|
|||||||
compute_units:
|
compute_units:
|
||||||
description: '[Min, Max] compute units'
|
description: '[Min, Max] compute units'
|
||||||
default: '[1, 1]'
|
default: '[1, 1]'
|
||||||
# settings below only needed if you want the project to be sharded from the beginning
|
|
||||||
shard_split_project:
|
|
||||||
description: 'by default new projects are not shard-split, specify true to shard-split'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
admin_api_key:
|
|
||||||
description: 'Admin API Key needed for shard-splitting. Must be specified if shard_split_project is true'
|
|
||||||
required: false
|
|
||||||
shard_count:
|
|
||||||
description: 'Number of shards to split the project into, only applies if shard_split_project is true'
|
|
||||||
required: false
|
|
||||||
default: '8'
|
|
||||||
stripe_size:
|
|
||||||
description: 'Stripe size, optional, in 8kiB pages. e.g. set 2048 for 16MB stripes. Default is 128 MiB, only applies if shard_split_project is true'
|
|
||||||
required: false
|
|
||||||
default: '32768'
|
|
||||||
psql_path:
|
|
||||||
description: 'Path to psql binary - it is caller responsibility to provision the psql binary'
|
|
||||||
required: false
|
|
||||||
default: '/tmp/neon/pg_install/v16/bin/psql'
|
|
||||||
libpq_lib_path:
|
|
||||||
description: 'Path to directory containing libpq library - it is caller responsibility to provision the libpq library'
|
|
||||||
required: false
|
|
||||||
default: '/tmp/neon/pg_install/v16/lib'
|
|
||||||
project_settings:
|
|
||||||
description: 'A JSON object with project settings'
|
|
||||||
required: false
|
|
||||||
default: '{}'
|
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
dsn:
|
dsn:
|
||||||
@@ -76,7 +48,7 @@ runs:
|
|||||||
\"provisioner\": \"k8s-neonvm\",
|
\"provisioner\": \"k8s-neonvm\",
|
||||||
\"autoscaling_limit_min_cu\": ${MIN_CU},
|
\"autoscaling_limit_min_cu\": ${MIN_CU},
|
||||||
\"autoscaling_limit_max_cu\": ${MAX_CU},
|
\"autoscaling_limit_max_cu\": ${MAX_CU},
|
||||||
\"settings\": ${PROJECT_SETTINGS}
|
\"settings\": { }
|
||||||
}
|
}
|
||||||
}")
|
}")
|
||||||
|
|
||||||
@@ -91,23 +63,6 @@ runs:
|
|||||||
echo "project_id=${project_id}" >> $GITHUB_OUTPUT
|
echo "project_id=${project_id}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
echo "Project ${project_id} has been created"
|
echo "Project ${project_id} has been created"
|
||||||
|
|
||||||
if [ "${SHARD_SPLIT_PROJECT}" = "true" ]; then
|
|
||||||
# determine tenant ID
|
|
||||||
TENANT_ID=`${PSQL} ${dsn} -t -A -c "SHOW neon.tenant_id"`
|
|
||||||
|
|
||||||
echo "Splitting project ${project_id} with tenant_id ${TENANT_ID} into $((SHARD_COUNT)) shards with stripe size $((STRIPE_SIZE))"
|
|
||||||
|
|
||||||
echo "Sending PUT request to https://${API_HOST}/regions/${REGION_ID}/api/v1/admin/storage/proxy/control/v1/tenant/${TENANT_ID}/shard_split"
|
|
||||||
echo "with body {\"new_shard_count\": $((SHARD_COUNT)), \"new_stripe_size\": $((STRIPE_SIZE))}"
|
|
||||||
|
|
||||||
# we need an ADMIN API KEY to invoke storage controller API for shard splitting (bash -u above checks that the variable is set)
|
|
||||||
curl -X PUT \
|
|
||||||
"https://${API_HOST}/regions/${REGION_ID}/api/v1/admin/storage/proxy/control/v1/tenant/${TENANT_ID}/shard_split" \
|
|
||||||
-H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer ${ADMIN_API_KEY}" \
|
|
||||||
-d "{\"new_shard_count\": $SHARD_COUNT, \"new_stripe_size\": $STRIPE_SIZE}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
API_HOST: ${{ inputs.api_host }}
|
API_HOST: ${{ inputs.api_host }}
|
||||||
API_KEY: ${{ inputs.api_key }}
|
API_KEY: ${{ inputs.api_key }}
|
||||||
@@ -115,10 +70,3 @@ runs:
|
|||||||
POSTGRES_VERSION: ${{ inputs.postgres_version }}
|
POSTGRES_VERSION: ${{ inputs.postgres_version }}
|
||||||
MIN_CU: ${{ fromJSON(inputs.compute_units)[0] }}
|
MIN_CU: ${{ fromJSON(inputs.compute_units)[0] }}
|
||||||
MAX_CU: ${{ fromJSON(inputs.compute_units)[1] }}
|
MAX_CU: ${{ fromJSON(inputs.compute_units)[1] }}
|
||||||
SHARD_SPLIT_PROJECT: ${{ inputs.shard_split_project }}
|
|
||||||
ADMIN_API_KEY: ${{ inputs.admin_api_key }}
|
|
||||||
SHARD_COUNT: ${{ inputs.shard_count }}
|
|
||||||
STRIPE_SIZE: ${{ inputs.stripe_size }}
|
|
||||||
PSQL: ${{ inputs.psql_path }}
|
|
||||||
LD_LIBRARY_PATH: ${{ inputs.libpq_lib_path }}
|
|
||||||
PROJECT_SETTINGS: ${{ inputs.project_settings }}
|
|
||||||
|
|||||||
34
.github/actions/run-python-test-set/action.yml
vendored
34
.github/actions/run-python-test-set/action.yml
vendored
@@ -36,8 +36,8 @@ inputs:
|
|||||||
description: 'Region name for real s3 tests'
|
description: 'Region name for real s3 tests'
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
rerun_failed:
|
rerun_flaky:
|
||||||
description: 'Whether to rerun failed tests'
|
description: 'Whether to rerun flaky tests'
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'false'
|
||||||
pg_version:
|
pg_version:
|
||||||
@@ -48,9 +48,6 @@ inputs:
|
|||||||
description: 'benchmark durations JSON'
|
description: 'benchmark durations JSON'
|
||||||
required: false
|
required: false
|
||||||
default: '{}'
|
default: '{}'
|
||||||
aws-oicd-role-arn:
|
|
||||||
description: 'OIDC role arn to interract with S3'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
@@ -61,7 +58,6 @@ runs:
|
|||||||
with:
|
with:
|
||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ inputs.build_type }}-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ inputs.build_type }}-artifact
|
||||||
path: /tmp/neon
|
path: /tmp/neon
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|
||||||
- name: Download Neon binaries for the previous release
|
- name: Download Neon binaries for the previous release
|
||||||
if: inputs.build_type != 'remote'
|
if: inputs.build_type != 'remote'
|
||||||
@@ -70,7 +66,6 @@ runs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ inputs.build_type }}-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ inputs.build_type }}-artifact
|
||||||
path: /tmp/neon-previous
|
path: /tmp/neon-previous
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|
||||||
- name: Download compatibility snapshot
|
- name: Download compatibility snapshot
|
||||||
if: inputs.build_type != 'remote'
|
if: inputs.build_type != 'remote'
|
||||||
@@ -82,7 +77,6 @@ runs:
|
|||||||
# The lack of compatibility snapshot (for example, for the new Postgres version)
|
# The lack of compatibility snapshot (for example, for the new Postgres version)
|
||||||
# shouldn't fail the whole job. Only relevant test should fail.
|
# shouldn't fail the whole job. Only relevant test should fail.
|
||||||
skip-if-does-not-exist: true
|
skip-if-does-not-exist: true
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
if: inputs.needs_postgres_source == 'true'
|
if: inputs.needs_postgres_source == 'true'
|
||||||
@@ -110,7 +104,7 @@ runs:
|
|||||||
COMPATIBILITY_SNAPSHOT_DIR: /tmp/compatibility_snapshot_pg${{ inputs.pg_version }}
|
COMPATIBILITY_SNAPSHOT_DIR: /tmp/compatibility_snapshot_pg${{ inputs.pg_version }}
|
||||||
ALLOW_BACKWARD_COMPATIBILITY_BREAKAGE: contains(github.event.pull_request.labels.*.name, 'backward compatibility breakage')
|
ALLOW_BACKWARD_COMPATIBILITY_BREAKAGE: contains(github.event.pull_request.labels.*.name, 'backward compatibility breakage')
|
||||||
ALLOW_FORWARD_COMPATIBILITY_BREAKAGE: contains(github.event.pull_request.labels.*.name, 'forward compatibility breakage')
|
ALLOW_FORWARD_COMPATIBILITY_BREAKAGE: contains(github.event.pull_request.labels.*.name, 'forward compatibility breakage')
|
||||||
RERUN_FAILED: ${{ inputs.rerun_failed }}
|
RERUN_FLAKY: ${{ inputs.rerun_flaky }}
|
||||||
PG_VERSION: ${{ inputs.pg_version }}
|
PG_VERSION: ${{ inputs.pg_version }}
|
||||||
shell: bash -euxo pipefail {0}
|
shell: bash -euxo pipefail {0}
|
||||||
run: |
|
run: |
|
||||||
@@ -121,8 +115,6 @@ runs:
|
|||||||
export DEFAULT_PG_VERSION=${PG_VERSION#v}
|
export DEFAULT_PG_VERSION=${PG_VERSION#v}
|
||||||
export LD_LIBRARY_PATH=${POSTGRES_DISTRIB_DIR}/v${DEFAULT_PG_VERSION}/lib
|
export LD_LIBRARY_PATH=${POSTGRES_DISTRIB_DIR}/v${DEFAULT_PG_VERSION}/lib
|
||||||
export BENCHMARK_CONNSTR=${BENCHMARK_CONNSTR:-}
|
export BENCHMARK_CONNSTR=${BENCHMARK_CONNSTR:-}
|
||||||
export ASAN_OPTIONS=detect_leaks=0:detect_stack_use_after_return=0:abort_on_error=1:strict_string_checks=1:check_initialization_order=1:strict_init_order=1
|
|
||||||
export UBSAN_OPTIONS=abort_on_error=1:print_stacktrace=1
|
|
||||||
|
|
||||||
if [ "${BUILD_TYPE}" = "remote" ]; then
|
if [ "${BUILD_TYPE}" = "remote" ]; then
|
||||||
export REMOTE_ENV=1
|
export REMOTE_ENV=1
|
||||||
@@ -158,8 +150,15 @@ runs:
|
|||||||
EXTRA_PARAMS="--out-dir $PERF_REPORT_DIR $EXTRA_PARAMS"
|
EXTRA_PARAMS="--out-dir $PERF_REPORT_DIR $EXTRA_PARAMS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${RERUN_FAILED}" == "true" ]; then
|
if [ "${RERUN_FLAKY}" == "true" ]; then
|
||||||
EXTRA_PARAMS="--reruns 2 $EXTRA_PARAMS"
|
mkdir -p $TEST_OUTPUT
|
||||||
|
poetry run ./scripts/flaky_tests.py "${TEST_RESULT_CONNSTR}" \
|
||||||
|
--days 7 \
|
||||||
|
--output "$TEST_OUTPUT/flaky.json" \
|
||||||
|
--pg-version "${DEFAULT_PG_VERSION}" \
|
||||||
|
--build-type "${BUILD_TYPE}"
|
||||||
|
|
||||||
|
EXTRA_PARAMS="--flaky-tests-json $TEST_OUTPUT/flaky.json $EXTRA_PARAMS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We use pytest-split plugin to run benchmarks in parallel on different CI runners
|
# We use pytest-split plugin to run benchmarks in parallel on different CI runners
|
||||||
@@ -222,14 +221,6 @@ runs:
|
|||||||
# The lack of compatibility snapshot shouldn't fail the job
|
# The lack of compatibility snapshot shouldn't fail the job
|
||||||
# (for example if we didn't run the test for non build-and-test workflow)
|
# (for example if we didn't run the test for non build-and-test workflow)
|
||||||
skip-if-does-not-exist: true
|
skip-if-does-not-exist: true
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|
||||||
- uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
role-duration-seconds: 3600 # 1 hour should be more than enough to upload report
|
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
@@ -237,4 +228,3 @@ runs:
|
|||||||
with:
|
with:
|
||||||
report-dir: /tmp/test_output/allure/results
|
report-dir: /tmp/test_output/allure/results
|
||||||
unique-key: ${{ inputs.build_type }}-${{ inputs.pg_version }}
|
unique-key: ${{ inputs.build_type }}-${{ inputs.pg_version }}
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ runs:
|
|||||||
name: coverage-data-artifact
|
name: coverage-data-artifact
|
||||||
path: /tmp/coverage
|
path: /tmp/coverage
|
||||||
skip-if-does-not-exist: true # skip if there's no previous coverage to download
|
skip-if-does-not-exist: true # skip if there's no previous coverage to download
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|
||||||
- name: Upload coverage data
|
- name: Upload coverage data
|
||||||
uses: ./.github/actions/upload
|
uses: ./.github/actions/upload
|
||||||
with:
|
with:
|
||||||
name: coverage-data-artifact
|
name: coverage-data-artifact
|
||||||
path: /tmp/coverage
|
path: /tmp/coverage
|
||||||
aws-oicd-role-arn: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
|
|||||||
36
.github/actions/set-docker-config-dir/action.yml
vendored
Normal file
36
.github/actions/set-docker-config-dir/action.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
name: "Set custom docker config directory"
|
||||||
|
description: "Create a directory for docker config and set DOCKER_CONFIG"
|
||||||
|
|
||||||
|
# Use custom DOCKER_CONFIG directory to avoid conflicts with default settings
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Show warning on GitHub-hosted runners
|
||||||
|
if: runner.environment == 'github-hosted'
|
||||||
|
shell: bash -euo pipefail {0}
|
||||||
|
run: |
|
||||||
|
# Using the following environment variables to find a path to the workflow file
|
||||||
|
# ${GITHUB_WORKFLOW_REF} - octocat/hello-world/.github/workflows/my-workflow.yml@refs/heads/my_branch
|
||||||
|
# ${GITHUB_REPOSITORY} - octocat/hello-world
|
||||||
|
# ${GITHUB_REF} - refs/heads/my_branch
|
||||||
|
# From https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/variables
|
||||||
|
|
||||||
|
filename_with_ref=${GITHUB_WORKFLOW_REF#"$GITHUB_REPOSITORY/"}
|
||||||
|
filename=${filename_with_ref%"@$GITHUB_REF"}
|
||||||
|
|
||||||
|
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-a-warning-message
|
||||||
|
title='Unnecessary usage of `.github/actions/set-docker-config-dir`'
|
||||||
|
message='No need to use `.github/actions/set-docker-config-dir` action on GitHub-hosted runners'
|
||||||
|
echo "::warning file=${filename},title=${title}::${message}"
|
||||||
|
|
||||||
|
- uses: pyTooling/Actions/with-post-step@74afc5a42a17a046c90c68cb5cfa627e5c6c5b6b # v1.0.7
|
||||||
|
env:
|
||||||
|
DOCKER_CONFIG: .docker-custom-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
|
with:
|
||||||
|
main: |
|
||||||
|
mkdir -p "${DOCKER_CONFIG}"
|
||||||
|
echo DOCKER_CONFIG=${DOCKER_CONFIG} | tee -a $GITHUB_ENV
|
||||||
|
post: |
|
||||||
|
if [ -d "${DOCKER_CONFIG}" ]; then
|
||||||
|
rm -r "${DOCKER_CONFIG}"
|
||||||
|
fi
|
||||||
11
.github/actions/upload/action.yml
vendored
11
.github/actions/upload/action.yml
vendored
@@ -14,10 +14,6 @@ inputs:
|
|||||||
prefix:
|
prefix:
|
||||||
description: "S3 prefix. Default is '${GITHUB_SHA}/${GITHUB_RUN_ID}/${GITHUB_RUN_ATTEMPT}'"
|
description: "S3 prefix. Default is '${GITHUB_SHA}/${GITHUB_RUN_ID}/${GITHUB_RUN_ATTEMPT}'"
|
||||||
required: false
|
required: false
|
||||||
aws-oicd-role-arn:
|
|
||||||
description: "the OIDC role arn for aws auth"
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
@@ -57,13 +53,6 @@ runs:
|
|||||||
|
|
||||||
echo 'SKIPPED=false' >> $GITHUB_OUTPUT
|
echo 'SKIPPED=false' >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ inputs.aws-oicd-role-arn }}
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
if: ${{ steps.prepare-artifact.outputs.SKIPPED == 'false' }}
|
if: ${{ steps.prepare-artifact.outputs.SKIPPED == 'false' }}
|
||||||
shell: bash -euxo pipefail {0}
|
shell: bash -euxo pipefail {0}
|
||||||
|
|||||||
13
.github/file-filters.yaml
vendored
13
.github/file-filters.yaml
vendored
@@ -1,13 +0,0 @@
|
|||||||
rust_code: ['**/*.rs', '**/Cargo.toml', '**/Cargo.lock']
|
|
||||||
rust_dependencies: ['**/Cargo.lock']
|
|
||||||
|
|
||||||
v14: ['vendor/postgres-v14/**', 'Makefile', 'pgxn/**']
|
|
||||||
v15: ['vendor/postgres-v15/**', 'Makefile', 'pgxn/**']
|
|
||||||
v16: ['vendor/postgres-v16/**', 'Makefile', 'pgxn/**']
|
|
||||||
v17: ['vendor/postgres-v17/**', 'Makefile', 'pgxn/**']
|
|
||||||
|
|
||||||
rebuild_neon_extra:
|
|
||||||
- .github/workflows/neon_extra_builds.yml
|
|
||||||
|
|
||||||
rebuild_macos:
|
|
||||||
- .github/workflows/build-macos.yml
|
|
||||||
11
.github/pull_request_template.md
vendored
11
.github/pull_request_template.md
vendored
@@ -1,3 +1,14 @@
|
|||||||
## Problem
|
## Problem
|
||||||
|
|
||||||
## Summary of changes
|
## Summary of changes
|
||||||
|
|
||||||
|
## Checklist before requesting a review
|
||||||
|
|
||||||
|
- [ ] I have performed a self-review of my code.
|
||||||
|
- [ ] If it is a core feature, I have added thorough tests.
|
||||||
|
- [ ] Do we need to implement analytics? if so did you add the relevant metrics to the dashboard?
|
||||||
|
- [ ] If this PR requires public announcement, mark it with /release-notes label and add several sentences in this section.
|
||||||
|
|
||||||
|
## Checklist before merging
|
||||||
|
|
||||||
|
- [ ] Do not forget to reformat commit message to not include the above checklist
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [ aws-rds-postgres, aws-aurora-serverless-v2-postgres, neon, neon_pg17 ]
|
platform: [ aws-rds-postgres, aws-aurora-serverless-v2-postgres, neon ]
|
||||||
database: [ clickbench, tpch, userexample ]
|
database: [ clickbench, tpch, userexample ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -41,9 +41,6 @@ jobs:
|
|||||||
neon)
|
neon)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_CONNSTR }}
|
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_CONNSTR }}
|
||||||
;;
|
;;
|
||||||
neon_pg17)
|
|
||||||
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_CONNSTR_PG17 }}
|
|
||||||
;;
|
|
||||||
aws-rds-postgres)
|
aws-rds-postgres)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_RDS_POSTGRES_CONNSTR }}
|
CONNSTR=${{ secrets.BENCHMARK_RDS_POSTGRES_CONNSTR }}
|
||||||
;;
|
;;
|
||||||
@@ -73,7 +70,6 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
# we create a table that has one row for each database that we want to restore with the status whether the restore is done
|
# we create a table that has one row for each database that we want to restore with the status whether the restore is done
|
||||||
- name: Create benchmark_restore_status table if it does not exist
|
- name: Create benchmark_restore_status table if it does not exist
|
||||||
|
|||||||
100
.github/workflows/_build-and-test-locally.yml
vendored
100
.github/workflows/_build-and-test-locally.yml
vendored
@@ -19,15 +19,10 @@ on:
|
|||||||
description: 'debug or release'
|
description: 'debug or release'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
test-cfg:
|
pg-versions:
|
||||||
description: 'a json object of postgres versions and lfc states to run regression tests on'
|
description: 'a json array of postgres versions to run regression tests on'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
sanitizers:
|
|
||||||
description: 'enabled or disabled'
|
|
||||||
required: false
|
|
||||||
default: 'disabled'
|
|
||||||
type: string
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -36,13 +31,12 @@ defaults:
|
|||||||
env:
|
env:
|
||||||
RUST_BACKTRACE: 1
|
RUST_BACKTRACE: 1
|
||||||
COPT: '-Werror'
|
COPT: '-Werror'
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-neon:
|
build-neon:
|
||||||
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', inputs.arch == 'arm64' && 'large-arm64' || 'large')) }}
|
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', inputs.arch == 'arm64' && 'large-arm64' || 'large')) }}
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
contents: read
|
|
||||||
container:
|
container:
|
||||||
image: ${{ inputs.build-tools-image }}
|
image: ${{ inputs.build-tools-image }}
|
||||||
credentials:
|
credentials:
|
||||||
@@ -92,7 +86,6 @@ jobs:
|
|||||||
- name: Set env variables
|
- name: Set env variables
|
||||||
env:
|
env:
|
||||||
ARCH: ${{ inputs.arch }}
|
ARCH: ${{ inputs.arch }}
|
||||||
SANITIZERS: ${{ inputs.sanitizers }}
|
|
||||||
run: |
|
run: |
|
||||||
CARGO_FEATURES="--features testing"
|
CARGO_FEATURES="--features testing"
|
||||||
if [[ $BUILD_TYPE == "debug" && $ARCH == 'x64' ]]; then
|
if [[ $BUILD_TYPE == "debug" && $ARCH == 'x64' ]]; then
|
||||||
@@ -105,14 +98,8 @@ jobs:
|
|||||||
cov_prefix=""
|
cov_prefix=""
|
||||||
CARGO_FLAGS="--locked --release"
|
CARGO_FLAGS="--locked --release"
|
||||||
fi
|
fi
|
||||||
if [[ $SANITIZERS == 'enabled' ]]; then
|
|
||||||
make_vars="WITH_SANITIZERS=yes"
|
|
||||||
else
|
|
||||||
make_vars=""
|
|
||||||
fi
|
|
||||||
{
|
{
|
||||||
echo "cov_prefix=${cov_prefix}"
|
echo "cov_prefix=${cov_prefix}"
|
||||||
echo "make_vars=${make_vars}"
|
|
||||||
echo "CARGO_FEATURES=${CARGO_FEATURES}"
|
echo "CARGO_FEATURES=${CARGO_FEATURES}"
|
||||||
echo "CARGO_FLAGS=${CARGO_FLAGS}"
|
echo "CARGO_FLAGS=${CARGO_FLAGS}"
|
||||||
echo "CARGO_HOME=${GITHUB_WORKSPACE}/.cargo"
|
echo "CARGO_HOME=${GITHUB_WORKSPACE}/.cargo"
|
||||||
@@ -148,39 +135,37 @@ jobs:
|
|||||||
|
|
||||||
- name: Build postgres v14
|
- name: Build postgres v14
|
||||||
if: steps.cache_pg_14.outputs.cache-hit != 'true'
|
if: steps.cache_pg_14.outputs.cache-hit != 'true'
|
||||||
run: mold -run make ${make_vars} postgres-v14 -j$(nproc)
|
run: mold -run make postgres-v14 -j$(nproc)
|
||||||
|
|
||||||
- name: Build postgres v15
|
- name: Build postgres v15
|
||||||
if: steps.cache_pg_15.outputs.cache-hit != 'true'
|
if: steps.cache_pg_15.outputs.cache-hit != 'true'
|
||||||
run: mold -run make ${make_vars} postgres-v15 -j$(nproc)
|
run: mold -run make postgres-v15 -j$(nproc)
|
||||||
|
|
||||||
- name: Build postgres v16
|
- name: Build postgres v16
|
||||||
if: steps.cache_pg_16.outputs.cache-hit != 'true'
|
if: steps.cache_pg_16.outputs.cache-hit != 'true'
|
||||||
run: mold -run make ${make_vars} postgres-v16 -j$(nproc)
|
run: mold -run make postgres-v16 -j$(nproc)
|
||||||
|
|
||||||
- name: Build postgres v17
|
- name: Build postgres v17
|
||||||
if: steps.cache_pg_17.outputs.cache-hit != 'true'
|
if: steps.cache_pg_17.outputs.cache-hit != 'true'
|
||||||
run: mold -run make ${make_vars} postgres-v17 -j$(nproc)
|
run: mold -run make postgres-v17 -j$(nproc)
|
||||||
|
|
||||||
- name: Build neon extensions
|
- name: Build neon extensions
|
||||||
run: mold -run make ${make_vars} neon-pg-ext -j$(nproc)
|
run: mold -run make neon-pg-ext -j$(nproc)
|
||||||
|
|
||||||
- name: Build walproposer-lib
|
- name: Build walproposer-lib
|
||||||
run: mold -run make ${make_vars} walproposer-lib -j$(nproc)
|
run: mold -run make walproposer-lib -j$(nproc)
|
||||||
|
|
||||||
- name: Run cargo build
|
- name: Run cargo build
|
||||||
env:
|
|
||||||
WITH_TESTS: ${{ inputs.sanitizers != 'enabled' && '--tests' || '' }}
|
|
||||||
run: |
|
run: |
|
||||||
export ASAN_OPTIONS=detect_leaks=0
|
PQ_LIB_DIR=$(pwd)/pg_install/v16/lib
|
||||||
${cov_prefix} mold -run cargo build $CARGO_FLAGS $CARGO_FEATURES --bins ${WITH_TESTS}
|
export PQ_LIB_DIR
|
||||||
|
${cov_prefix} mold -run cargo build $CARGO_FLAGS $CARGO_FEATURES --bins --tests
|
||||||
|
|
||||||
# Do install *before* running rust tests because they might recompile the
|
# Do install *before* running rust tests because they might recompile the
|
||||||
# binaries with different features/flags.
|
# binaries with different features/flags.
|
||||||
- name: Install rust binaries
|
- name: Install rust binaries
|
||||||
env:
|
env:
|
||||||
ARCH: ${{ inputs.arch }}
|
ARCH: ${{ inputs.arch }}
|
||||||
SANITIZERS: ${{ inputs.sanitizers }}
|
|
||||||
run: |
|
run: |
|
||||||
# Install target binaries
|
# Install target binaries
|
||||||
mkdir -p /tmp/neon/bin/
|
mkdir -p /tmp/neon/bin/
|
||||||
@@ -195,7 +180,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Install test executables and write list of all binaries (for code coverage)
|
# Install test executables and write list of all binaries (for code coverage)
|
||||||
if [[ $BUILD_TYPE == "debug" && $ARCH == 'x64' && $SANITIZERS != 'enabled' ]]; then
|
if [[ $BUILD_TYPE == "debug" && $ARCH == 'x64' ]]; then
|
||||||
# Keep bloated coverage data files away from the rest of the artifact
|
# Keep bloated coverage data files away from the rest of the artifact
|
||||||
mkdir -p /tmp/coverage/
|
mkdir -p /tmp/coverage/
|
||||||
|
|
||||||
@@ -220,18 +205,12 @@ jobs:
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
role-duration-seconds: 18000 # 5 hours
|
|
||||||
|
|
||||||
- name: Run rust tests
|
- name: Run rust tests
|
||||||
if: ${{ inputs.sanitizers != 'enabled' }}
|
|
||||||
env:
|
env:
|
||||||
NEXTEST_RETRIES: 3
|
NEXTEST_RETRIES: 3
|
||||||
run: |
|
run: |
|
||||||
|
PQ_LIB_DIR=$(pwd)/pg_install/v16/lib
|
||||||
|
export PQ_LIB_DIR
|
||||||
LD_LIBRARY_PATH=$(pwd)/pg_install/v17/lib
|
LD_LIBRARY_PATH=$(pwd)/pg_install/v17/lib
|
||||||
export LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH
|
||||||
|
|
||||||
@@ -242,13 +221,8 @@ jobs:
|
|||||||
${cov_prefix} cargo nextest run $CARGO_FLAGS $CARGO_FEATURES -E '!package(pageserver)'
|
${cov_prefix} cargo nextest run $CARGO_FLAGS $CARGO_FEATURES -E '!package(pageserver)'
|
||||||
|
|
||||||
# run pageserver tests with different settings
|
# run pageserver tests with different settings
|
||||||
for get_vectored_concurrent_io in sequential sidecar-task; do
|
for io_engine in std-fs tokio-epoll-uring ; do
|
||||||
for io_engine in std-fs tokio-epoll-uring ; do
|
NEON_PAGESERVER_UNIT_TEST_VIRTUAL_FILE_IOENGINE=$io_engine ${cov_prefix} cargo nextest run $CARGO_FLAGS $CARGO_FEATURES -E 'package(pageserver)'
|
||||||
NEON_PAGESERVER_UNIT_TEST_GET_VECTORED_CONCURRENT_IO=$get_vectored_concurrent_io \
|
|
||||||
NEON_PAGESERVER_UNIT_TEST_VIRTUAL_FILE_IOENGINE=$io_engine \
|
|
||||||
${cov_prefix} \
|
|
||||||
cargo nextest run $CARGO_FLAGS $CARGO_FEATURES -E 'package(pageserver)'
|
|
||||||
done
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Run separate tests for real S3
|
# Run separate tests for real S3
|
||||||
@@ -282,28 +256,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ inputs.build-type }}-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ inputs.build-type }}-artifact
|
||||||
path: /tmp/neon
|
path: /tmp/neon
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Check diesel schema
|
|
||||||
if: inputs.build-type == 'release' && inputs.arch == 'x64'
|
|
||||||
env:
|
|
||||||
DATABASE_URL: postgresql://localhost:1235/storage_controller
|
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
|
||||||
run: |
|
|
||||||
export ASAN_OPTIONS=detect_leaks=0
|
|
||||||
/tmp/neon/bin/neon_local init
|
|
||||||
/tmp/neon/bin/neon_local storage_controller start
|
|
||||||
|
|
||||||
diesel print-schema > storage_controller/src/schema.rs
|
|
||||||
|
|
||||||
if [ -n "$(git diff storage_controller/src/schema.rs)" ]; then
|
|
||||||
echo >&2 "Uncommitted changes in diesel schema"
|
|
||||||
|
|
||||||
git diff .
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
/tmp/neon/bin/neon_local storage_controller stop
|
|
||||||
|
|
||||||
# XXX: keep this after the binaries.list is formed, so the coverage can properly work later
|
# XXX: keep this after the binaries.list is formed, so the coverage can properly work later
|
||||||
- name: Merge and upload coverage data
|
- name: Merge and upload coverage data
|
||||||
@@ -313,10 +265,6 @@ jobs:
|
|||||||
regress-tests:
|
regress-tests:
|
||||||
# Don't run regression tests on debug arm64 builds
|
# Don't run regression tests on debug arm64 builds
|
||||||
if: inputs.build-type != 'debug' || inputs.arch != 'arm64'
|
if: inputs.build-type != 'debug' || inputs.arch != 'arm64'
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
contents: read
|
|
||||||
statuses: write
|
|
||||||
needs: [ build-neon ]
|
needs: [ build-neon ]
|
||||||
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', inputs.arch == 'arm64' && 'large-arm64' || 'large')) }}
|
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', inputs.arch == 'arm64' && 'large-arm64' || 'large')) }}
|
||||||
container:
|
container:
|
||||||
@@ -328,16 +276,16 @@ jobs:
|
|||||||
options: --init --shm-size=512mb --ulimit memlock=67108864:67108864
|
options: --init --shm-size=512mb --ulimit memlock=67108864:67108864
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJSON(format('{{"include":{0}}}', inputs.test-cfg)) }}
|
matrix:
|
||||||
|
pg_version: ${{ fromJson(inputs.pg-versions) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Pytest regression tests
|
- name: Pytest regression tests
|
||||||
continue-on-error: ${{ matrix.lfc_state == 'with-lfc' && inputs.build-type == 'debug' }}
|
|
||||||
uses: ./.github/actions/run-python-test-set
|
uses: ./.github/actions/run-python-test-set
|
||||||
timeout-minutes: ${{ inputs.sanitizers != 'enabled' && 60 || 180 }}
|
timeout-minutes: 60
|
||||||
with:
|
with:
|
||||||
build_type: ${{ inputs.build-type }}
|
build_type: ${{ inputs.build-type }}
|
||||||
test_selection: regress
|
test_selection: regress
|
||||||
@@ -345,17 +293,13 @@ jobs:
|
|||||||
run_with_real_s3: true
|
run_with_real_s3: true
|
||||||
real_s3_bucket: neon-github-ci-tests
|
real_s3_bucket: neon-github-ci-tests
|
||||||
real_s3_region: eu-central-1
|
real_s3_region: eu-central-1
|
||||||
rerun_failed: true
|
rerun_flaky: true
|
||||||
pg_version: ${{ matrix.pg_version }}
|
pg_version: ${{ matrix.pg_version }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
TEST_RESULT_CONNSTR: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
TEST_RESULT_CONNSTR: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
||||||
CHECK_ONDISK_DATA_COMPATIBILITY: nonempty
|
CHECK_ONDISK_DATA_COMPATIBILITY: nonempty
|
||||||
BUILD_TAG: ${{ inputs.build-tag }}
|
BUILD_TAG: ${{ inputs.build-tag }}
|
||||||
PAGESERVER_VIRTUAL_FILE_IO_ENGINE: tokio-epoll-uring
|
PAGESERVER_VIRTUAL_FILE_IO_ENGINE: tokio-epoll-uring
|
||||||
PAGESERVER_GET_VECTORED_CONCURRENT_IO: sidecar-task
|
|
||||||
USE_LFC: ${{ matrix.lfc_state == 'with-lfc' && 'true' || 'false' }}
|
|
||||||
SANITIZERS: ${{ inputs.sanitizers }}
|
|
||||||
|
|
||||||
# Temporary disable this step until we figure out why it's so flaky
|
# Temporary disable this step until we figure out why it's so flaky
|
||||||
# Ref https://github.com/neondatabase/neon/issues/4540
|
# Ref https://github.com/neondatabase/neon/issues/4540
|
||||||
|
|||||||
37
.github/workflows/_check-codestyle-python.yml
vendored
37
.github/workflows/_check-codestyle-python.yml
vendored
@@ -1,37 +0,0 @@
|
|||||||
name: Check Codestyle Python
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
build-tools-image:
|
|
||||||
description: 'build-tools image'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euxo pipefail {0}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-codestyle-python:
|
|
||||||
runs-on: [ self-hosted, small ]
|
|
||||||
container:
|
|
||||||
image: ${{ inputs.build-tools-image }}
|
|
||||||
credentials:
|
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
options: --init
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: ~/.cache/pypoetry/virtualenvs
|
|
||||||
key: v2-${{ runner.os }}-${{ runner.arch }}-python-deps-bookworm-${{ hashFiles('poetry.lock') }}
|
|
||||||
|
|
||||||
- run: ./scripts/pysync
|
|
||||||
|
|
||||||
- run: poetry run ruff check .
|
|
||||||
- run: poetry run ruff format --check .
|
|
||||||
- run: poetry run mypy .
|
|
||||||
89
.github/workflows/_check-codestyle-rust.yml
vendored
89
.github/workflows/_check-codestyle-rust.yml
vendored
@@ -1,89 +0,0 @@
|
|||||||
name: Check Codestyle Rust
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
build-tools-image:
|
|
||||||
description: "build-tools image"
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
archs:
|
|
||||||
description: "Json array of architectures to run on"
|
|
||||||
type: string
|
|
||||||
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euxo pipefail {0}
|
|
||||||
|
|
||||||
# No permission for GITHUB_TOKEN by default; the **minimal required** set of permissions should be granted in each job.
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-codestyle-rust:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: ${{ fromJson(inputs.archs) }}
|
|
||||||
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', matrix.arch == 'arm64' && 'small-arm64' || 'small')) }}
|
|
||||||
|
|
||||||
container:
|
|
||||||
image: ${{ inputs.build-tools-image }}
|
|
||||||
credentials:
|
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
options: --init
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Cache cargo deps
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry
|
|
||||||
!~/.cargo/registry/src
|
|
||||||
~/.cargo/git
|
|
||||||
target
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('./Cargo.lock') }}-${{ hashFiles('./rust-toolchain.toml') }}-rust
|
|
||||||
|
|
||||||
# Some of our rust modules use FFI and need those to be checked
|
|
||||||
- name: Get postgres headers
|
|
||||||
run: make postgres-headers -j$(nproc)
|
|
||||||
|
|
||||||
# cargo hack runs the given cargo subcommand (clippy in this case) for all feature combinations.
|
|
||||||
# This will catch compiler & clippy warnings in all feature combinations.
|
|
||||||
# TODO: use cargo hack for build and test as well, but, that's quite expensive.
|
|
||||||
# NB: keep clippy args in sync with ./run_clippy.sh
|
|
||||||
#
|
|
||||||
# The only difference between "clippy --debug" and "clippy --release" is that in --release mode,
|
|
||||||
# #[cfg(debug_assertions)] blocks are not built. It's not worth building everything for second
|
|
||||||
# time just for that, so skip "clippy --release".
|
|
||||||
- run: |
|
|
||||||
CLIPPY_COMMON_ARGS="$( source .neon_clippy_args; echo "$CLIPPY_COMMON_ARGS")"
|
|
||||||
if [ "$CLIPPY_COMMON_ARGS" = "" ]; then
|
|
||||||
echo "No clippy args found in .neon_clippy_args"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "CLIPPY_COMMON_ARGS=${CLIPPY_COMMON_ARGS}" >> $GITHUB_ENV
|
|
||||||
- name: Run cargo clippy (debug)
|
|
||||||
run: cargo hack --features default --ignore-unknown-features --feature-powerset clippy $CLIPPY_COMMON_ARGS
|
|
||||||
|
|
||||||
- name: Check documentation generation
|
|
||||||
run: cargo doc --workspace --no-deps --document-private-items
|
|
||||||
env:
|
|
||||||
RUSTDOCFLAGS: "-Dwarnings -Arustdoc::private_intra_doc_links"
|
|
||||||
|
|
||||||
# Use `${{ !cancelled() }}` to run quck tests after the longer clippy run
|
|
||||||
- name: Check formatting
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
run: cargo fmt --all -- --check
|
|
||||||
|
|
||||||
# https://github.com/facebookincubator/cargo-guppy/tree/bec4e0eb29dcd1faac70b1b5360267fc02bf830e/tools/cargo-hakari#2-keep-the-workspace-hack-up-to-date-in-ci
|
|
||||||
- name: Check rust dependencies
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
run: |
|
|
||||||
cargo hakari generate --diff # workspace-hack Cargo.toml is up-to-date
|
|
||||||
cargo hakari manage-deps --dry-run # all workspace crates depend on workspace-hack
|
|
||||||
79
.github/workflows/_create-release-pr.yml
vendored
79
.github/workflows/_create-release-pr.yml
vendored
@@ -1,79 +0,0 @@
|
|||||||
name: Create Release PR
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
component-name:
|
|
||||||
description: 'Component name'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
release-branch:
|
|
||||||
description: 'Release branch'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
secrets:
|
|
||||||
ci-access-token:
|
|
||||||
description: 'CI access token'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euo pipefail {0}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
create-release-branch:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write # for `git push`
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: main
|
|
||||||
|
|
||||||
- name: Set variables
|
|
||||||
id: vars
|
|
||||||
env:
|
|
||||||
COMPONENT_NAME: ${{ inputs.component-name }}
|
|
||||||
RELEASE_BRANCH: ${{ inputs.release-branch }}
|
|
||||||
run: |
|
|
||||||
today=$(date +'%Y-%m-%d')
|
|
||||||
echo "title=${COMPONENT_NAME} release ${today}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
echo "rc-branch=rc/${RELEASE_BRANCH}/${today}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
|
|
||||||
- name: Configure git
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
- name: Create RC branch
|
|
||||||
env:
|
|
||||||
RC_BRANCH: ${{ steps.vars.outputs.rc-branch }}
|
|
||||||
TITLE: ${{ steps.vars.outputs.title }}
|
|
||||||
run: |
|
|
||||||
git checkout -b "${RC_BRANCH}"
|
|
||||||
|
|
||||||
# create an empty commit to distinguish workflow runs
|
|
||||||
# from other possible releases from the same commit
|
|
||||||
git commit --allow-empty -m "${TITLE}"
|
|
||||||
|
|
||||||
git push origin "${RC_BRANCH}"
|
|
||||||
|
|
||||||
- name: Create a PR into ${{ inputs.release-branch }}
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.ci-access-token }}
|
|
||||||
RC_BRANCH: ${{ steps.vars.outputs.rc-branch }}
|
|
||||||
RELEASE_BRANCH: ${{ inputs.release-branch }}
|
|
||||||
TITLE: ${{ steps.vars.outputs.title }}
|
|
||||||
run: |
|
|
||||||
cat << EOF > body.md
|
|
||||||
## ${TITLE}
|
|
||||||
|
|
||||||
**Please merge this Pull Request using 'Create a merge commit' button**
|
|
||||||
EOF
|
|
||||||
|
|
||||||
gh pr create --title "${TITLE}" \
|
|
||||||
--body-file "body.md" \
|
|
||||||
--head "${RC_BRANCH}" \
|
|
||||||
--base "${RELEASE_BRANCH}"
|
|
||||||
56
.github/workflows/_push-to-acr.yml
vendored
Normal file
56
.github/workflows/_push-to-acr.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
name: Push images to ACR
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
client_id:
|
||||||
|
description: Client ID of Azure managed identity or Entra app
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
image_tag:
|
||||||
|
description: Tag for the container image
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
images:
|
||||||
|
description: Images to push
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
registry_name:
|
||||||
|
description: Name of the container registry
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
subscription_id:
|
||||||
|
description: Azure subscription ID
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
tenant_id:
|
||||||
|
description: Azure tenant ID
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push-to-acr:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
permissions:
|
||||||
|
contents: read # This is required for actions/checkout
|
||||||
|
id-token: write # This is required for Azure Login to work.
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Azure login
|
||||||
|
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # @v2.1.1
|
||||||
|
with:
|
||||||
|
client-id: ${{ inputs.client_id }}
|
||||||
|
subscription-id: ${{ inputs.subscription_id }}
|
||||||
|
tenant-id: ${{ inputs.tenant_id }}
|
||||||
|
|
||||||
|
- name: Login to ACR
|
||||||
|
run: |
|
||||||
|
az acr login --name=${{ inputs.registry_name }}
|
||||||
|
|
||||||
|
- name: Copy docker images to ACR ${{ inputs.registry_name }}
|
||||||
|
run: |
|
||||||
|
images='${{ inputs.images }}'
|
||||||
|
for image in ${images}; do
|
||||||
|
docker buildx imagetools create \
|
||||||
|
-t ${{ inputs.registry_name }}.azurecr.io/neondatabase/${image}:${{ inputs.image_tag }} \
|
||||||
|
neondatabase/${image}:${{ inputs.image_tag }}
|
||||||
|
done
|
||||||
101
.github/workflows/_push-to-container-registry.yml
vendored
101
.github/workflows/_push-to-container-registry.yml
vendored
@@ -1,101 +0,0 @@
|
|||||||
name: Push images to Container Registry
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
# Example: {"docker.io/neondatabase/neon:13196061314":["369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:13196061314","neoneastus2.azurecr.io/neondatabase/neon:13196061314"]}
|
|
||||||
image-map:
|
|
||||||
description: JSON map of images, mapping from a source image to an array of target images that should be pushed.
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
aws-region:
|
|
||||||
description: AWS region to log in to. Required when pushing to ECR.
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
aws-account-ids:
|
|
||||||
description: Comma separated AWS account IDs to log in to for pushing to ECR. Required when pushing to ECR.
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
azure-client-id:
|
|
||||||
description: Client ID of Azure managed identity or Entra app. Required when pushing to ACR.
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
azure-subscription-id:
|
|
||||||
description: Azure subscription ID. Required when pushing to ACR.
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
azure-tenant-id:
|
|
||||||
description: Azure tenant ID. Required when pushing to ACR.
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
acr-registry-name:
|
|
||||||
description: ACR registry name. Required when pushing to ACR.
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
secrets:
|
|
||||||
docker-hub-username:
|
|
||||||
description: Docker Hub username. Required when pushing to Docker Hub.
|
|
||||||
required: false
|
|
||||||
docker-hub-password:
|
|
||||||
description: Docker Hub password. Required when pushing to Docker Hub.
|
|
||||||
required: false
|
|
||||||
aws-role-to-assume:
|
|
||||||
description: AWS role to assume. Required when pushing to ECR.
|
|
||||||
required: false
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euo pipefail {0}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
push-to-container-registry:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
permissions:
|
|
||||||
id-token: write # Required for aws/azure login
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
sparse-checkout: scripts/push_with_image_map.py
|
|
||||||
sparse-checkout-cone-mode: false
|
|
||||||
|
|
||||||
- name: Print image-map
|
|
||||||
run: echo '${{ inputs.image-map }}' | jq
|
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
|
||||||
if: contains(inputs.image-map, 'amazonaws.com/')
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: "${{ inputs.aws-region }}"
|
|
||||||
role-to-assume: "${{ secrets.aws-role-to-assume }}"
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Login to ECR
|
|
||||||
if: contains(inputs.image-map, 'amazonaws.com/')
|
|
||||||
uses: aws-actions/amazon-ecr-login@v2
|
|
||||||
with:
|
|
||||||
registries: "${{ inputs.aws-account-ids }}"
|
|
||||||
|
|
||||||
- name: Configure Azure credentials
|
|
||||||
if: contains(inputs.image-map, 'azurecr.io/')
|
|
||||||
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # @v2.1.1
|
|
||||||
with:
|
|
||||||
client-id: ${{ inputs.azure-client-id }}
|
|
||||||
subscription-id: ${{ inputs.azure-subscription-id }}
|
|
||||||
tenant-id: ${{ inputs.azure-tenant-id }}
|
|
||||||
|
|
||||||
- name: Login to ACR
|
|
||||||
if: contains(inputs.image-map, 'azurecr.io/')
|
|
||||||
run: |
|
|
||||||
az acr login --name=${{ inputs.acr-registry-name }}
|
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.docker-hub-username }}
|
|
||||||
password: ${{ secrets.docker-hub-password }}
|
|
||||||
|
|
||||||
- name: Copy docker images to target registries
|
|
||||||
run: python scripts/push_with_image_map.py
|
|
||||||
env:
|
|
||||||
IMAGE_MAP: ${{ inputs.image-map }}
|
|
||||||
2
.github/workflows/actionlint.yml
vendored
2
.github/workflows/actionlint.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
# SC2086 - Double quote to prevent globbing and word splitting. - https://www.shellcheck.net/wiki/SC2086
|
# SC2086 - Double quote to prevent globbing and word splitting. - https://www.shellcheck.net/wiki/SC2086
|
||||||
SHELLCHECK_OPTS: --exclude=SC2046,SC2086
|
SHELLCHECK_OPTS: --exclude=SC2046,SC2086
|
||||||
with:
|
with:
|
||||||
fail_level: error
|
fail_on_error: true
|
||||||
filter_mode: nofilter
|
filter_mode: nofilter
|
||||||
level: error
|
level: error
|
||||||
|
|
||||||
|
|||||||
12
.github/workflows/approved-for-ci-run.yml
vendored
12
.github/workflows/approved-for-ci-run.yml
vendored
@@ -67,9 +67,9 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: main
|
||||||
token: ${{ secrets.CI_ACCESS_TOKEN }}
|
token: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
|
||||||
- name: Look for existing PR
|
- name: Look for existing PR
|
||||||
id: get-pr
|
id: get-pr
|
||||||
env:
|
env:
|
||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
ALREADY_CREATED="$(gh pr --repo ${GITHUB_REPOSITORY} list --head ${BRANCH} --base main --json number --jq '.[].number')"
|
ALREADY_CREATED="$(gh pr --repo ${GITHUB_REPOSITORY} list --head ${BRANCH} --base main --json number --jq '.[].number')"
|
||||||
echo "ALREADY_CREATED=${ALREADY_CREATED}" >> ${GITHUB_OUTPUT}
|
echo "ALREADY_CREATED=${ALREADY_CREATED}" >> ${GITHUB_OUTPUT}
|
||||||
|
|
||||||
- name: Get changed labels
|
- name: Get changed labels
|
||||||
id: get-labels
|
id: get-labels
|
||||||
if: steps.get-pr.outputs.ALREADY_CREATED != ''
|
if: steps.get-pr.outputs.ALREADY_CREATED != ''
|
||||||
@@ -94,6 +94,8 @@ jobs:
|
|||||||
echo "LABELS_TO_ADD=${LABELS_TO_ADD}" >> ${GITHUB_OUTPUT}
|
echo "LABELS_TO_ADD=${LABELS_TO_ADD}" >> ${GITHUB_OUTPUT}
|
||||||
echo "LABELS_TO_REMOVE=${LABELS_TO_REMOVE}" >> ${GITHUB_OUTPUT}
|
echo "LABELS_TO_REMOVE=${LABELS_TO_REMOVE}" >> ${GITHUB_OUTPUT}
|
||||||
|
|
||||||
|
- run: gh pr checkout "${PR_NUMBER}"
|
||||||
|
|
||||||
- run: git checkout -b "${BRANCH}"
|
- run: git checkout -b "${BRANCH}"
|
||||||
|
|
||||||
- run: git push --force origin "${BRANCH}"
|
- run: git push --force origin "${BRANCH}"
|
||||||
@@ -101,7 +103,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create a Pull Request for CI run (if required)
|
- name: Create a Pull Request for CI run (if required)
|
||||||
if: steps.get-pr.outputs.ALREADY_CREATED == ''
|
if: steps.get-pr.outputs.ALREADY_CREATED == ''
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
cat << EOF > body.md
|
cat << EOF > body.md
|
||||||
@@ -138,7 +140,7 @@ jobs:
|
|||||||
|
|
||||||
- run: git push --force origin "${BRANCH}"
|
- run: git push --force origin "${BRANCH}"
|
||||||
if: steps.get-pr.outputs.ALREADY_CREATED != ''
|
if: steps.get-pr.outputs.ALREADY_CREATED != ''
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
# Close PRs and delete branchs if the original PR is closed.
|
# Close PRs and delete branchs if the original PR is closed.
|
||||||
|
|
||||||
|
|||||||
246
.github/workflows/benchmarking.yml
vendored
246
.github/workflows/benchmarking.yml
vendored
@@ -63,15 +63,11 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- PG_VERSION: 16
|
- DEFAULT_PG_VERSION: 16
|
||||||
PLATFORM: "neon-staging"
|
PLATFORM: "neon-staging"
|
||||||
region_id: ${{ github.event.inputs.region_id || 'aws-us-east-2' }}
|
region_id: ${{ github.event.inputs.region_id || 'aws-us-east-2' }}
|
||||||
RUNNER: [ self-hosted, us-east-2, x64 ]
|
RUNNER: [ self-hosted, us-east-2, x64 ]
|
||||||
- PG_VERSION: 17
|
- DEFAULT_PG_VERSION: 16
|
||||||
PLATFORM: "neon-staging"
|
|
||||||
region_id: ${{ github.event.inputs.region_id || 'aws-us-east-2' }}
|
|
||||||
RUNNER: [ self-hosted, us-east-2, x64 ]
|
|
||||||
- PG_VERSION: 16
|
|
||||||
PLATFORM: "azure-staging"
|
PLATFORM: "azure-staging"
|
||||||
region_id: 'azure-eastus2'
|
region_id: 'azure-eastus2'
|
||||||
RUNNER: [ self-hosted, eastus2, x64 ]
|
RUNNER: [ self-hosted, eastus2, x64 ]
|
||||||
@@ -79,7 +75,7 @@ jobs:
|
|||||||
TEST_PG_BENCH_DURATIONS_MATRIX: "300"
|
TEST_PG_BENCH_DURATIONS_MATRIX: "300"
|
||||||
TEST_PG_BENCH_SCALES_MATRIX: "10,100"
|
TEST_PG_BENCH_SCALES_MATRIX: "10,100"
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
PG_VERSION: ${{ matrix.PG_VERSION }}
|
DEFAULT_PG_VERSION: ${{ matrix.DEFAULT_PG_VERSION }}
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
BUILD_TYPE: remote
|
BUILD_TYPE: remote
|
||||||
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
||||||
@@ -109,14 +105,13 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Create Neon Project
|
- name: Create Neon Project
|
||||||
id: create-neon-project
|
id: create-neon-project
|
||||||
uses: ./.github/actions/neon-project-create
|
uses: ./.github/actions/neon-project-create
|
||||||
with:
|
with:
|
||||||
region_id: ${{ matrix.region_id }}
|
region_id: ${{ matrix.region_id }}
|
||||||
postgres_version: ${{ env.PG_VERSION }}
|
postgres_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
||||||
|
|
||||||
- name: Run benchmark
|
- name: Run benchmark
|
||||||
@@ -126,8 +121,7 @@ jobs:
|
|||||||
test_selection: performance
|
test_selection: performance
|
||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
# Set --sparse-ordering option of pytest-order plugin
|
# Set --sparse-ordering option of pytest-order plugin
|
||||||
# to ensure tests are running in order of appears in the file.
|
# to ensure tests are running in order of appears in the file.
|
||||||
# It's important for test_perf_pgbench.py::test_pgbench_remote_* tests
|
# It's important for test_perf_pgbench.py::test_pgbench_remote_* tests
|
||||||
@@ -139,7 +133,6 @@ jobs:
|
|||||||
--ignore test_runner/performance/test_perf_pgvector_queries.py
|
--ignore test_runner/performance/test_perf_pgvector_queries.py
|
||||||
--ignore test_runner/performance/test_logical_replication.py
|
--ignore test_runner/performance/test_logical_replication.py
|
||||||
--ignore test_runner/performance/test_physical_replication.py
|
--ignore test_runner/performance/test_physical_replication.py
|
||||||
--ignore test_runner/performance/test_perf_ingest_using_pgcopydb.py
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.create-neon-project.outputs.dsn }}
|
BENCHMARK_CONNSTR: ${{ steps.create-neon-project.outputs.dsn }}
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
@@ -156,14 +149,12 @@ jobs:
|
|||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic perf testing: ${{ job.status }}
|
Periodic perf testing: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
@@ -209,7 +200,6 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Run Logical Replication benchmarks
|
- name: Run Logical Replication benchmarks
|
||||||
uses: ./.github/actions/run-python-test-set
|
uses: ./.github/actions/run-python-test-set
|
||||||
@@ -220,7 +210,6 @@ jobs:
|
|||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 5400
|
extra_params: -m remote_cluster --timeout 5400
|
||||||
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
@@ -237,7 +226,6 @@ jobs:
|
|||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 5400
|
extra_params: -m remote_cluster --timeout 5400
|
||||||
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
@@ -249,13 +237,11 @@ jobs:
|
|||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
with:
|
||||||
store-test-results-into-db: true
|
store-test-results-into-db: true
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
||||||
|
|
||||||
# Post both success and failure to the Slack channel
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && !cancelled() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06T9AMNDQQ" # on-call-compute-staging-stream
|
channel-id: "C06T9AMNDQQ" # on-call-compute-staging-stream
|
||||||
@@ -312,16 +298,11 @@ jobs:
|
|||||||
"image": [ "'"$image_default"'" ],
|
"image": [ "'"$image_default"'" ],
|
||||||
"include": [{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-freetier", "db_size": "3gb" ,"runner": '"$runner_default"', "image": "'"$image_default"'" },
|
"include": [{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-freetier", "db_size": "3gb" ,"runner": '"$runner_default"', "image": "'"$image_default"'" },
|
||||||
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new", "db_size": "10gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new", "db_size": "10gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
||||||
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new-many-tables","db_size": "10gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
|
||||||
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new", "db_size": "50gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new", "db_size": "50gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
||||||
{ "pg_version": 16, "region_id": "azure-eastus2", "platform": "neonvm-azure-captest-freetier", "db_size": "3gb" ,"runner": '"$runner_azure"', "image": "neondatabase/build-tools:pinned-bookworm" },
|
{ "pg_version": 16, "region_id": "azure-eastus2", "platform": "neonvm-azure-captest-freetier", "db_size": "3gb" ,"runner": '"$runner_azure"', "image": "neondatabase/build-tools:pinned-bookworm" },
|
||||||
{ "pg_version": 16, "region_id": "azure-eastus2", "platform": "neonvm-azure-captest-new", "db_size": "10gb","runner": '"$runner_azure"', "image": "neondatabase/build-tools:pinned-bookworm" },
|
{ "pg_version": 16, "region_id": "azure-eastus2", "platform": "neonvm-azure-captest-new", "db_size": "10gb","runner": '"$runner_azure"', "image": "neondatabase/build-tools:pinned-bookworm" },
|
||||||
{ "pg_version": 16, "region_id": "azure-eastus2", "platform": "neonvm-azure-captest-new", "db_size": "50gb","runner": '"$runner_azure"', "image": "neondatabase/build-tools:pinned-bookworm" },
|
{ "pg_version": 16, "region_id": "azure-eastus2", "platform": "neonvm-azure-captest-new", "db_size": "50gb","runner": '"$runner_azure"', "image": "neondatabase/build-tools:pinned-bookworm" },
|
||||||
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-sharding-reuse", "db_size": "50gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
{ "pg_version": 16, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-sharding-reuse", "db_size": "50gb","runner": '"$runner_default"', "image": "'"$image_default"'" }]
|
||||||
{ "pg_version": 17, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-freetier", "db_size": "3gb" ,"runner": '"$runner_default"', "image": "'"$image_default"'" },
|
|
||||||
{ "pg_version": 17, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new", "db_size": "10gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
|
||||||
{ "pg_version": 17, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new-many-tables","db_size": "10gb","runner": '"$runner_default"', "image": "'"$image_default"'" },
|
|
||||||
{ "pg_version": 17, "region_id": "'"$region_id_default"'", "platform": "neonvm-captest-new", "db_size": "50gb","runner": '"$runner_default"', "image": "'"$image_default"'" }]
|
|
||||||
}'
|
}'
|
||||||
|
|
||||||
if [ "$(date +%A)" = "Saturday" ] || [ ${RUN_AWS_RDS_AND_AURORA} = "true" ]; then
|
if [ "$(date +%A)" = "Saturday" ] || [ ${RUN_AWS_RDS_AND_AURORA} = "true" ]; then
|
||||||
@@ -337,15 +318,12 @@ jobs:
|
|||||||
matrix='{
|
matrix='{
|
||||||
"platform": [
|
"platform": [
|
||||||
"neonvm-captest-reuse"
|
"neonvm-captest-reuse"
|
||||||
],
|
|
||||||
"pg_version" : [
|
|
||||||
16,17
|
|
||||||
]
|
]
|
||||||
}'
|
}'
|
||||||
|
|
||||||
if [ "$(date +%A)" = "Saturday" ] || [ ${RUN_AWS_RDS_AND_AURORA} = "true" ]; then
|
if [ "$(date +%A)" = "Saturday" ] || [ ${RUN_AWS_RDS_AND_AURORA} = "true" ]; then
|
||||||
matrix=$(echo "$matrix" | jq '.include += [{ "pg_version": 16, "platform": "rds-postgres" },
|
matrix=$(echo "$matrix" | jq '.include += [{ "platform": "rds-postgres" },
|
||||||
{ "pg_version": 16, "platform": "rds-aurora" }]')
|
{ "platform": "rds-aurora" }]')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "matrix=$(echo "$matrix" | jq --compact-output '.')" >> $GITHUB_OUTPUT
|
echo "matrix=$(echo "$matrix" | jq --compact-output '.')" >> $GITHUB_OUTPUT
|
||||||
@@ -357,14 +335,14 @@ jobs:
|
|||||||
"platform": [
|
"platform": [
|
||||||
"neonvm-captest-reuse"
|
"neonvm-captest-reuse"
|
||||||
],
|
],
|
||||||
"pg_version" : [
|
"scale": [
|
||||||
16,17
|
"10"
|
||||||
]
|
]
|
||||||
}'
|
}'
|
||||||
|
|
||||||
if [ "$(date +%A)" = "Saturday" ] || [ ${RUN_AWS_RDS_AND_AURORA} = "true" ]; then
|
if [ "$(date +%A)" = "Saturday" ] || [ ${RUN_AWS_RDS_AND_AURORA} = "true" ]; then
|
||||||
matrix=$(echo "$matrix" | jq '.include += [{ "pg_version": 16, "platform": "rds-postgres" },
|
matrix=$(echo "$matrix" | jq '.include += [{ "platform": "rds-postgres", "scale": "10" },
|
||||||
{ "pg_version": 16, "platform": "rds-aurora" }]')
|
{ "platform": "rds-aurora", "scale": "10" }]')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "matrix=$(echo "$matrix" | jq --compact-output '.')" >> $GITHUB_OUTPUT
|
echo "matrix=$(echo "$matrix" | jq --compact-output '.')" >> $GITHUB_OUTPUT
|
||||||
@@ -389,7 +367,7 @@ jobs:
|
|||||||
TEST_PG_BENCH_DURATIONS_MATRIX: "60m"
|
TEST_PG_BENCH_DURATIONS_MATRIX: "60m"
|
||||||
TEST_PG_BENCH_SCALES_MATRIX: ${{ matrix.db_size }}
|
TEST_PG_BENCH_SCALES_MATRIX: ${{ matrix.db_size }}
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
PG_VERSION: ${{ matrix.pg_version }}
|
DEFAULT_PG_VERSION: ${{ matrix.pg_version }}
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
BUILD_TYPE: remote
|
BUILD_TYPE: remote
|
||||||
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
||||||
@@ -419,15 +397,14 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Create Neon Project
|
- name: Create Neon Project
|
||||||
if: contains(fromJson('["neonvm-captest-new", "neonvm-captest-new-many-tables", "neonvm-captest-freetier", "neonvm-azure-captest-freetier", "neonvm-azure-captest-new"]'), matrix.platform)
|
if: contains(fromJson('["neonvm-captest-new", "neonvm-captest-freetier", "neonvm-azure-captest-freetier", "neonvm-azure-captest-new"]'), matrix.platform)
|
||||||
id: create-neon-project
|
id: create-neon-project
|
||||||
uses: ./.github/actions/neon-project-create
|
uses: ./.github/actions/neon-project-create
|
||||||
with:
|
with:
|
||||||
region_id: ${{ matrix.region_id }}
|
region_id: ${{ matrix.region_id }}
|
||||||
postgres_version: ${{ env.PG_VERSION }}
|
postgres_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
||||||
compute_units: ${{ (contains(matrix.platform, 'captest-freetier') && '[0.25, 0.25]') || '[1, 1]' }}
|
compute_units: ${{ (contains(matrix.platform, 'captest-freetier') && '[0.25, 0.25]') || '[1, 1]' }}
|
||||||
|
|
||||||
@@ -441,7 +418,7 @@ jobs:
|
|||||||
neonvm-captest-sharding-reuse)
|
neonvm-captest-sharding-reuse)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_SHARDING_CONNSTR }}
|
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_SHARDING_CONNSTR }}
|
||||||
;;
|
;;
|
||||||
neonvm-captest-new | neonvm-captest-new-many-tables | neonvm-captest-freetier | neonvm-azure-captest-new | neonvm-azure-captest-freetier)
|
neonvm-captest-new | neonvm-captest-freetier | neonvm-azure-captest-new | neonvm-azure-captest-freetier)
|
||||||
CONNSTR=${{ steps.create-neon-project.outputs.dsn }}
|
CONNSTR=${{ steps.create-neon-project.outputs.dsn }}
|
||||||
;;
|
;;
|
||||||
rds-aurora)
|
rds-aurora)
|
||||||
@@ -458,26 +435,6 @@ jobs:
|
|||||||
|
|
||||||
echo "connstr=${CONNSTR}" >> $GITHUB_OUTPUT
|
echo "connstr=${CONNSTR}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# we want to compare Neon project OLTP throughput and latency at scale factor 10 GB
|
|
||||||
# without (neonvm-captest-new)
|
|
||||||
# and with (neonvm-captest-new-many-tables) many relations in the database
|
|
||||||
- name: Create many relations before the run
|
|
||||||
if: contains(fromJson('["neonvm-captest-new-many-tables"]'), matrix.platform)
|
|
||||||
uses: ./.github/actions/run-python-test-set
|
|
||||||
with:
|
|
||||||
build_type: ${{ env.BUILD_TYPE }}
|
|
||||||
test_selection: performance
|
|
||||||
run_in_parallel: false
|
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_perf_many_relations
|
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
|
||||||
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
|
||||||
TEST_NUM_RELATIONS: 10000
|
|
||||||
|
|
||||||
- name: Benchmark init
|
- name: Benchmark init
|
||||||
uses: ./.github/actions/run-python-test-set
|
uses: ./.github/actions/run-python-test-set
|
||||||
with:
|
with:
|
||||||
@@ -486,8 +443,7 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_init
|
extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_init
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
@@ -501,8 +457,7 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_simple_update
|
extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_simple_update
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
@@ -516,8 +471,7 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_select_only
|
extra_params: -m remote_cluster --timeout 21600 -k test_pgbench_remote_select_only
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
@@ -534,14 +488,12 @@ jobs:
|
|||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
Periodic perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
@@ -560,19 +512,14 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- PLATFORM: "neonvm-captest-pgvector"
|
- PLATFORM: "neonvm-captest-pgvector"
|
||||||
RUNNER: [ self-hosted, us-east-2, x64 ]
|
RUNNER: [ self-hosted, us-east-2, x64 ]
|
||||||
postgres_version: 16
|
|
||||||
- PLATFORM: "neonvm-captest-pgvector-pg17"
|
|
||||||
RUNNER: [ self-hosted, us-east-2, x64 ]
|
|
||||||
postgres_version: 17
|
|
||||||
- PLATFORM: "azure-captest-pgvector"
|
- PLATFORM: "azure-captest-pgvector"
|
||||||
RUNNER: [ self-hosted, eastus2, x64 ]
|
RUNNER: [ self-hosted, eastus2, x64 ]
|
||||||
postgres_version: 16
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
TEST_PG_BENCH_DURATIONS_MATRIX: "15m"
|
TEST_PG_BENCH_DURATIONS_MATRIX: "15m"
|
||||||
TEST_PG_BENCH_SCALES_MATRIX: "1"
|
TEST_PG_BENCH_SCALES_MATRIX: "1"
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
PG_VERSION: ${{ matrix.postgres_version }}
|
DEFAULT_PG_VERSION: 16
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
BUILD_TYPE: remote
|
BUILD_TYPE: remote
|
||||||
|
|
||||||
@@ -581,7 +528,7 @@ jobs:
|
|||||||
|
|
||||||
runs-on: ${{ matrix.RUNNER }}
|
runs-on: ${{ matrix.RUNNER }}
|
||||||
container:
|
container:
|
||||||
image: neondatabase/build-tools:pinned-bookworm
|
image: neondatabase/build-tools:pinned
|
||||||
credentials:
|
credentials:
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
@@ -590,20 +537,32 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
# until https://github.com/neondatabase/neon/issues/8275 is fixed we temporarily install postgresql-16
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
# instead of using Neon artifacts containing pgbench
|
||||||
with:
|
- name: Install postgresql-16 where pytest expects it
|
||||||
aws-region: eu-central-1
|
run: |
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
# Just to make it easier to test things locally on macOS (with arm64)
|
||||||
role-duration-seconds: 18000 # 5 hours
|
arch=$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')
|
||||||
|
|
||||||
- name: Download Neon artifact
|
cd /home/nonroot
|
||||||
uses: ./.github/actions/download
|
wget -q "https://apt.postgresql.org/pub/repos/apt/pool/main/p/postgresql-17/libpq5_17.0-1.pgdg110+1_${arch}.deb"
|
||||||
with:
|
wget -q "https://apt.postgresql.org/pub/repos/apt/pool/main/p/postgresql-16/postgresql-client-16_16.4-1.pgdg110+2_${arch}.deb"
|
||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
wget -q "https://apt.postgresql.org/pub/repos/apt/pool/main/p/postgresql-16/postgresql-16_16.4-1.pgdg110+2_${arch}.deb"
|
||||||
path: /tmp/neon/
|
dpkg -x libpq5_17.0-1.pgdg110+1_${arch}.deb pg
|
||||||
prefix: latest
|
dpkg -x postgresql-16_16.4-1.pgdg110+2_${arch}.deb pg
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
dpkg -x postgresql-client-16_16.4-1.pgdg110+2_${arch}.deb pg
|
||||||
|
|
||||||
|
mkdir -p /tmp/neon/pg_install/v16/bin
|
||||||
|
ln -s /home/nonroot/pg/usr/lib/postgresql/16/bin/pgbench /tmp/neon/pg_install/v16/bin/pgbench
|
||||||
|
ln -s /home/nonroot/pg/usr/lib/postgresql/16/bin/psql /tmp/neon/pg_install/v16/bin/psql
|
||||||
|
ln -s /home/nonroot/pg/usr/lib/$(uname -m)-linux-gnu /tmp/neon/pg_install/v16/lib
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH="/home/nonroot/pg/usr/lib/$(uname -m)-linux-gnu:${LD_LIBRARY_PATH:-}"
|
||||||
|
export LD_LIBRARY_PATH
|
||||||
|
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> ${GITHUB_ENV}
|
||||||
|
|
||||||
|
/tmp/neon/pg_install/v16/bin/pgbench --version
|
||||||
|
/tmp/neon/pg_install/v16/bin/psql --version
|
||||||
|
|
||||||
- name: Set up Connection String
|
- name: Set up Connection String
|
||||||
id: set-up-connstr
|
id: set-up-connstr
|
||||||
@@ -612,9 +571,6 @@ jobs:
|
|||||||
neonvm-captest-pgvector)
|
neonvm-captest-pgvector)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_PGVECTOR_CONNSTR }}
|
CONNSTR=${{ secrets.BENCHMARK_PGVECTOR_CONNSTR }}
|
||||||
;;
|
;;
|
||||||
neonvm-captest-pgvector-pg17)
|
|
||||||
CONNSTR=${{ secrets.BENCHMARK_PGVECTOR_CONNSTR_PG17 }}
|
|
||||||
;;
|
|
||||||
azure-captest-pgvector)
|
azure-captest-pgvector)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_PGVECTOR_CONNSTR_AZURE }}
|
CONNSTR=${{ secrets.BENCHMARK_PGVECTOR_CONNSTR_AZURE }}
|
||||||
;;
|
;;
|
||||||
@@ -626,6 +582,13 @@ jobs:
|
|||||||
|
|
||||||
echo "connstr=${CONNSTR}" >> $GITHUB_OUTPUT
|
echo "connstr=${CONNSTR}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Configure AWS credentials
|
||||||
|
uses: aws-actions/configure-aws-credentials@v4
|
||||||
|
with:
|
||||||
|
aws-region: eu-central-1
|
||||||
|
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
||||||
|
role-duration-seconds: 18000 # 5 hours
|
||||||
|
|
||||||
- name: Benchmark pgvector hnsw indexing
|
- name: Benchmark pgvector hnsw indexing
|
||||||
uses: ./.github/actions/run-python-test-set
|
uses: ./.github/actions/run-python-test-set
|
||||||
with:
|
with:
|
||||||
@@ -634,8 +597,7 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_pgvector_indexing
|
extra_params: -m remote_cluster --timeout 21600 -k test_pgvector_indexing
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
@@ -649,8 +611,7 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600
|
extra_params: -m remote_cluster --timeout 21600
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
@@ -660,14 +621,12 @@ jobs:
|
|||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic perf testing on ${{ env.PLATFORM }}: ${{ job.status }}
|
Periodic perf testing on ${{ env.PLATFORM }}: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
@@ -696,7 +655,7 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
PG_VERSION: ${{ matrix.pg_version }}
|
DEFAULT_PG_VERSION: 16
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
TEST_OLAP_COLLECT_EXPLAIN: ${{ github.event.inputs.collect_olap_explain }}
|
TEST_OLAP_COLLECT_EXPLAIN: ${{ github.event.inputs.collect_olap_explain }}
|
||||||
TEST_OLAP_COLLECT_PG_STAT_STATEMENTS: ${{ github.event.inputs.collect_pg_stat_statements }}
|
TEST_OLAP_COLLECT_PG_STAT_STATEMENTS: ${{ github.event.inputs.collect_pg_stat_statements }}
|
||||||
@@ -712,10 +671,6 @@ jobs:
|
|||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
options: --init
|
options: --init
|
||||||
|
|
||||||
# Increase timeout to 12h, default timeout is 6h
|
|
||||||
# we have regression in clickbench causing it to run 2-3x longer
|
|
||||||
timeout-minutes: 720
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -732,25 +687,13 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Set up Connection String
|
- name: Set up Connection String
|
||||||
id: set-up-connstr
|
id: set-up-connstr
|
||||||
run: |
|
run: |
|
||||||
case "${PLATFORM}" in
|
case "${PLATFORM}" in
|
||||||
neonvm-captest-reuse)
|
neonvm-captest-reuse)
|
||||||
case "${PG_VERSION}" in
|
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_CLICKBENCH_10M_CONNSTR }}
|
||||||
16)
|
|
||||||
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_CLICKBENCH_10M_CONNSTR }}
|
|
||||||
;;
|
|
||||||
17)
|
|
||||||
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_CLICKBENCH_CONNSTR_PG17 }}
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo >&2 "Unsupported PG_VERSION=${PG_VERSION} for PLATFORM=${PLATFORM}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
;;
|
||||||
rds-aurora)
|
rds-aurora)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_RDS_AURORA_CLICKBENCH_10M_CONNSTR }}
|
CONNSTR=${{ secrets.BENCHMARK_RDS_AURORA_CLICKBENCH_10M_CONNSTR }}
|
||||||
@@ -773,9 +716,8 @@ jobs:
|
|||||||
test_selection: performance/test_perf_olap.py
|
test_selection: performance/test_perf_olap.py
|
||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 43200 -k test_clickbench
|
extra_params: -m remote_cluster --timeout 21600 -k test_clickbench
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
@@ -788,14 +730,12 @@ jobs:
|
|||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic OLAP perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
Periodic OLAP perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
@@ -810,7 +750,7 @@ jobs:
|
|||||||
# We might change it after https://github.com/neondatabase/neon/issues/2900.
|
# We might change it after https://github.com/neondatabase/neon/issues/2900.
|
||||||
#
|
#
|
||||||
# *_TPCH_S10_CONNSTR: DB generated with scale factor 10 (~10 GB)
|
# *_TPCH_S10_CONNSTR: DB generated with scale factor 10 (~10 GB)
|
||||||
# if: ${{ !cancelled() && (github.event.inputs.run_only_pgvector_tests == 'false' || github.event.inputs.run_only_pgvector_tests == null) }}
|
if: ${{ !cancelled() && (github.event.inputs.run_only_pgvector_tests == 'false' || github.event.inputs.run_only_pgvector_tests == null) }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
statuses: write
|
statuses: write
|
||||||
@@ -823,11 +763,12 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
PG_VERSION: ${{ matrix.pg_version }}
|
DEFAULT_PG_VERSION: 16
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
BUILD_TYPE: remote
|
BUILD_TYPE: remote
|
||||||
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
||||||
PLATFORM: ${{ matrix.platform }}
|
PLATFORM: ${{ matrix.platform }}
|
||||||
|
TEST_OLAP_SCALE: ${{ matrix.scale }}
|
||||||
|
|
||||||
runs-on: [ self-hosted, us-east-2, x64 ]
|
runs-on: [ self-hosted, us-east-2, x64 ]
|
||||||
container:
|
container:
|
||||||
@@ -853,30 +794,18 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Get Connstring Secret Name
|
- name: Get Connstring Secret Name
|
||||||
run: |
|
run: |
|
||||||
case "${PLATFORM}" in
|
case "${PLATFORM}" in
|
||||||
neonvm-captest-reuse)
|
neonvm-captest-reuse)
|
||||||
case "${PG_VERSION}" in
|
ENV_PLATFORM=CAPTEST_TPCH
|
||||||
16)
|
|
||||||
CONNSTR_SECRET_NAME="BENCHMARK_CAPTEST_TPCH_S10_CONNSTR"
|
|
||||||
;;
|
|
||||||
17)
|
|
||||||
CONNSTR_SECRET_NAME="BENCHMARK_CAPTEST_TPCH_CONNSTR_PG17"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo >&2 "Unsupported PG_VERSION=${PG_VERSION} for PLATFORM=${PLATFORM}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
;;
|
||||||
rds-aurora)
|
rds-aurora)
|
||||||
CONNSTR_SECRET_NAME="BENCHMARK_RDS_AURORA_TPCH_S10_CONNSTR"
|
ENV_PLATFORM=RDS_AURORA_TPCH
|
||||||
;;
|
;;
|
||||||
rds-postgres)
|
rds-postgres)
|
||||||
CONNSTR_SECRET_NAME="BENCHMARK_RDS_POSTGRES_TPCH_S10_CONNSTR"
|
ENV_PLATFORM=RDS_POSTGRES_TPCH
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo >&2 "Unknown PLATFORM=${PLATFORM}. Allowed only 'neonvm-captest-reuse', 'rds-aurora', or 'rds-postgres'"
|
echo >&2 "Unknown PLATFORM=${PLATFORM}. Allowed only 'neonvm-captest-reuse', 'rds-aurora', or 'rds-postgres'"
|
||||||
@@ -884,6 +813,7 @@ jobs:
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
CONNSTR_SECRET_NAME="BENCHMARK_${ENV_PLATFORM}_S${TEST_OLAP_SCALE}_CONNSTR"
|
||||||
echo "CONNSTR_SECRET_NAME=${CONNSTR_SECRET_NAME}" >> $GITHUB_ENV
|
echo "CONNSTR_SECRET_NAME=${CONNSTR_SECRET_NAME}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set up Connection String
|
- name: Set up Connection String
|
||||||
@@ -901,26 +831,23 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_tpch
|
extra_params: -m remote_cluster --timeout 21600 -k test_tpch
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
BENCHMARK_CONNSTR: ${{ steps.set-up-connstr.outputs.connstr }}
|
||||||
TEST_OLAP_SCALE: 10
|
TEST_OLAP_SCALE: ${{ matrix.scale }}
|
||||||
|
|
||||||
- name: Create Allure report
|
- name: Create Allure report
|
||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic TPC-H perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
Periodic TPC-H perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
@@ -929,7 +856,7 @@ jobs:
|
|||||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||||
|
|
||||||
user-examples-compare:
|
user-examples-compare:
|
||||||
# if: ${{ !cancelled() && (github.event.inputs.run_only_pgvector_tests == 'false' || github.event.inputs.run_only_pgvector_tests == null) }}
|
if: ${{ !cancelled() && (github.event.inputs.run_only_pgvector_tests == 'false' || github.event.inputs.run_only_pgvector_tests == null) }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
statuses: write
|
statuses: write
|
||||||
@@ -942,7 +869,7 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
PG_VERSION: ${{ matrix.pg_version }}
|
DEFAULT_PG_VERSION: 16
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
BUILD_TYPE: remote
|
BUILD_TYPE: remote
|
||||||
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
SAVE_PERF_REPORT: ${{ github.event.inputs.save_perf_report || ( github.ref_name == 'main' ) }}
|
||||||
@@ -972,25 +899,13 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Set up Connection String
|
- name: Set up Connection String
|
||||||
id: set-up-connstr
|
id: set-up-connstr
|
||||||
run: |
|
run: |
|
||||||
case "${PLATFORM}" in
|
case "${PLATFORM}" in
|
||||||
neonvm-captest-reuse)
|
neonvm-captest-reuse)
|
||||||
case "${PG_VERSION}" in
|
CONNSTR=${{ secrets.BENCHMARK_USER_EXAMPLE_CAPTEST_CONNSTR }}
|
||||||
16)
|
|
||||||
CONNSTR=${{ secrets.BENCHMARK_USER_EXAMPLE_CAPTEST_CONNSTR }}
|
|
||||||
;;
|
|
||||||
17)
|
|
||||||
CONNSTR=${{ secrets.BENCHMARK_CAPTEST_USER_EXAMPLE_CONNSTR_PG17 }}
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo >&2 "Unsupported PG_VERSION=${PG_VERSION} for PLATFORM=${PLATFORM}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
;;
|
||||||
rds-aurora)
|
rds-aurora)
|
||||||
CONNSTR=${{ secrets.BENCHMARK_USER_EXAMPLE_RDS_AURORA_CONNSTR }}
|
CONNSTR=${{ secrets.BENCHMARK_USER_EXAMPLE_RDS_AURORA_CONNSTR }}
|
||||||
@@ -1014,8 +929,7 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
save_perf_report: ${{ env.SAVE_PERF_REPORT }}
|
||||||
extra_params: -m remote_cluster --timeout 21600 -k test_user_examples
|
extra_params: -m remote_cluster --timeout 21600 -k test_user_examples
|
||||||
pg_version: ${{ env.PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
@@ -1025,14 +939,12 @@ jobs:
|
|||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic TPC-H perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
Periodic TPC-H perf testing on ${{ matrix.platform }}: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
|
|||||||
110
.github/workflows/build-build-tools-image.yml
vendored
110
.github/workflows/build-build-tools-image.yml
vendored
@@ -3,23 +3,17 @@ name: Build build-tools image
|
|||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
archs:
|
image-tag:
|
||||||
description: "Json array of architectures to build"
|
description: "build-tools image tag"
|
||||||
# Default values are set in `check-image` job, `set-variables` step
|
required: true
|
||||||
type: string
|
type: string
|
||||||
required: false
|
|
||||||
debians:
|
|
||||||
description: "Json array of Debian versions to build"
|
|
||||||
# Default values are set in `check-image` job, `set-variables` step
|
|
||||||
type: string
|
|
||||||
required: false
|
|
||||||
outputs:
|
outputs:
|
||||||
image-tag:
|
image-tag:
|
||||||
description: "build-tools tag"
|
description: "build-tools tag"
|
||||||
value: ${{ jobs.check-image.outputs.tag }}
|
value: ${{ inputs.image-tag }}
|
||||||
image:
|
image:
|
||||||
description: "build-tools image"
|
description: "build-tools image"
|
||||||
value: neondatabase/build-tools:${{ jobs.check-image.outputs.tag }}
|
value: neondatabase/build-tools:${{ inputs.image-tag }}
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -41,48 +35,7 @@ permissions: {}
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-image:
|
check-image:
|
||||||
runs-on: ubuntu-22.04
|
uses: ./.github/workflows/check-build-tools-image.yml
|
||||||
outputs:
|
|
||||||
archs: ${{ steps.set-variables.outputs.archs }}
|
|
||||||
debians: ${{ steps.set-variables.outputs.debians }}
|
|
||||||
tag: ${{ steps.set-variables.outputs.image-tag }}
|
|
||||||
everything: ${{ steps.set-more-variables.outputs.everything }}
|
|
||||||
found: ${{ steps.set-more-variables.outputs.found }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set variables
|
|
||||||
id: set-variables
|
|
||||||
env:
|
|
||||||
ARCHS: ${{ inputs.archs || '["x64","arm64"]' }}
|
|
||||||
DEBIANS: ${{ inputs.debians || '["bullseye","bookworm"]' }}
|
|
||||||
IMAGE_TAG: |
|
|
||||||
${{ hashFiles('build-tools.Dockerfile',
|
|
||||||
'.github/workflows/build-build-tools-image.yml') }}
|
|
||||||
run: |
|
|
||||||
echo "archs=${ARCHS}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
echo "debians=${DEBIANS}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
echo "image-tag=${IMAGE_TAG}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
|
|
||||||
- name: Set more variables
|
|
||||||
id: set-more-variables
|
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ steps.set-variables.outputs.image-tag }}
|
|
||||||
EVERYTHING: |
|
|
||||||
${{ contains(fromJson(steps.set-variables.outputs.archs), 'x64') &&
|
|
||||||
contains(fromJson(steps.set-variables.outputs.archs), 'arm64') &&
|
|
||||||
contains(fromJson(steps.set-variables.outputs.debians), 'bullseye') &&
|
|
||||||
contains(fromJson(steps.set-variables.outputs.debians), 'bookworm') }}
|
|
||||||
run: |
|
|
||||||
if docker manifest inspect neondatabase/build-tools:${IMAGE_TAG}; then
|
|
||||||
found=true
|
|
||||||
else
|
|
||||||
found=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "everything=${EVERYTHING}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
echo "found=${found}" | tee -a ${GITHUB_OUTPUT}
|
|
||||||
|
|
||||||
build-image:
|
build-image:
|
||||||
needs: [ check-image ]
|
needs: [ check-image ]
|
||||||
@@ -90,15 +43,28 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
arch: ${{ fromJson(needs.check-image.outputs.archs) }}
|
debian-version: [ bullseye, bookworm ]
|
||||||
debian: ${{ fromJson(needs.check-image.outputs.debians) }}
|
arch: [ x64, arm64 ]
|
||||||
|
|
||||||
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', matrix.arch == 'arm64' && 'large-arm64' || 'large')) }}
|
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', matrix.arch == 'arm64' && 'large-arm64' || 'large')) }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_TAG: ${{ inputs.image-tag }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Check `input.tag` is correct
|
||||||
|
env:
|
||||||
|
INPUTS_IMAGE_TAG: ${{ inputs.image-tag }}
|
||||||
|
CHECK_IMAGE_TAG : ${{ needs.check-image.outputs.image-tag }}
|
||||||
|
run: |
|
||||||
|
if [ "${INPUTS_IMAGE_TAG}" != "${CHECK_IMAGE_TAG}" ]; then
|
||||||
|
echo "'inputs.image-tag' (${INPUTS_IMAGE_TAG}) does not match the tag of the latest build-tools image 'inputs.image-tag' (${CHECK_IMAGE_TAG})"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: neondatabase/dev-actions/set-docker-config-dir@6094485bf440001c94a94a3f9e221e81ff6b6193
|
- uses: ./.github/actions/set-docker-config-dir
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
cache-binary: false
|
cache-binary: false
|
||||||
@@ -122,14 +88,14 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
pull: true
|
pull: true
|
||||||
build-args: |
|
build-args: |
|
||||||
DEBIAN_VERSION=${{ matrix.debian }}
|
DEBIAN_VERSION=${{ matrix.debian-version }}
|
||||||
cache-from: type=registry,ref=cache.neon.build/build-tools:cache-${{ matrix.debian }}-${{ matrix.arch }}
|
cache-from: type=registry,ref=cache.neon.build/build-tools:cache-${{ matrix.debian-version }}-${{ matrix.arch }}
|
||||||
cache-to: ${{ github.ref_name == 'main' && format('type=registry,ref=cache.neon.build/build-tools:cache-{0}-{1},mode=max', matrix.debian, matrix.arch) || '' }}
|
cache-to: ${{ github.ref_name == 'main' && format('type=registry,ref=cache.neon.build/build-tools:cache-{0}-{1},mode=max', matrix.debian-version, matrix.arch) || '' }}
|
||||||
tags: |
|
tags: |
|
||||||
neondatabase/build-tools:${{ needs.check-image.outputs.tag }}-${{ matrix.debian }}-${{ matrix.arch }}
|
neondatabase/build-tools:${{ inputs.image-tag }}-${{ matrix.debian-version }}-${{ matrix.arch }}
|
||||||
|
|
||||||
merge-images:
|
merge-images:
|
||||||
needs: [ check-image, build-image ]
|
needs: [ build-image ]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -140,22 +106,16 @@ jobs:
|
|||||||
|
|
||||||
- name: Create multi-arch image
|
- name: Create multi-arch image
|
||||||
env:
|
env:
|
||||||
DEFAULT_DEBIAN_VERSION: bookworm
|
DEFAULT_DEBIAN_VERSION: bullseye
|
||||||
ARCHS: ${{ join(fromJson(needs.check-image.outputs.archs), ' ') }}
|
IMAGE_TAG: ${{ inputs.image-tag }}
|
||||||
DEBIANS: ${{ join(fromJson(needs.check-image.outputs.debians), ' ') }}
|
|
||||||
EVERYTHING: ${{ needs.check-image.outputs.everything }}
|
|
||||||
IMAGE_TAG: ${{ needs.check-image.outputs.tag }}
|
|
||||||
run: |
|
run: |
|
||||||
for debian in ${DEBIANS}; do
|
for debian_version in bullseye bookworm; do
|
||||||
tags=("-t" "neondatabase/build-tools:${IMAGE_TAG}-${debian}")
|
tags=("-t" "neondatabase/build-tools:${IMAGE_TAG}-${debian_version}")
|
||||||
|
if [ "${debian_version}" == "${DEFAULT_DEBIAN_VERSION}" ]; then
|
||||||
if [ "${EVERYTHING}" == "true" ] && [ "${debian}" == "${DEFAULT_DEBIAN_VERSION}" ]; then
|
|
||||||
tags+=("-t" "neondatabase/build-tools:${IMAGE_TAG}")
|
tags+=("-t" "neondatabase/build-tools:${IMAGE_TAG}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for arch in ${ARCHS}; do
|
docker buildx imagetools create "${tags[@]}" \
|
||||||
tags+=("neondatabase/build-tools:${IMAGE_TAG}-${debian}-${arch}")
|
neondatabase/build-tools:${IMAGE_TAG}-${debian_version}-x64 \
|
||||||
done
|
neondatabase/build-tools:${IMAGE_TAG}-${debian_version}-arm64
|
||||||
|
|
||||||
docker buildx imagetools create "${tags[@]}"
|
|
||||||
done
|
done
|
||||||
|
|||||||
241
.github/workflows/build-macos.yml
vendored
241
.github/workflows/build-macos.yml
vendored
@@ -1,241 +0,0 @@
|
|||||||
name: Check neon with MacOS builds
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
pg_versions:
|
|
||||||
description: "Array of the pg versions to build for, for example: ['v14', 'v17']"
|
|
||||||
type: string
|
|
||||||
default: '[]'
|
|
||||||
required: false
|
|
||||||
rebuild_rust_code:
|
|
||||||
description: "Rebuild Rust code"
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
required: false
|
|
||||||
rebuild_everything:
|
|
||||||
description: "If true, rebuild for all versions"
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
required: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
COPT: '-Werror'
|
|
||||||
|
|
||||||
# TODO: move `check-*` and `files-changed` jobs to the "Caller" Workflow
|
|
||||||
# We should care about that as Github has limitations:
|
|
||||||
# - You can connect up to four levels of workflows
|
|
||||||
# - You can call a maximum of 20 unique reusable workflows from a single workflow file.
|
|
||||||
# https://docs.github.com/en/actions/sharing-automations/reusing-workflows#limitations
|
|
||||||
jobs:
|
|
||||||
build-pgxn:
|
|
||||||
if: |
|
|
||||||
(inputs.pg_versions != '[]' || inputs.rebuild_everything) && (
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-macos') ||
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
|
||||||
github.ref_name == 'main'
|
|
||||||
)
|
|
||||||
timeout-minutes: 30
|
|
||||||
runs-on: macos-15
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
postgres-version: ${{ inputs.rebuild_everything && fromJson('["v14", "v15", "v16", "v17"]') || fromJSON(inputs.pg_versions) }}
|
|
||||||
env:
|
|
||||||
# Use release build only, to have less debug info around
|
|
||||||
# Hence keeping target/ (and general cache size) smaller
|
|
||||||
BUILD_TYPE: release
|
|
||||||
steps:
|
|
||||||
- name: Checkout main repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set pg ${{ matrix.postgres-version }} for caching
|
|
||||||
id: pg_rev
|
|
||||||
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-${{ matrix.postgres-version }}) | tee -a "${GITHUB_OUTPUT}"
|
|
||||||
|
|
||||||
- name: Cache postgres ${{ matrix.postgres-version }} build
|
|
||||||
id: cache_pg
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/${{ matrix.postgres-version }}
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-${{ matrix.postgres-version }}-${{ steps.pg_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
|
|
||||||
- name: Checkout submodule vendor/postgres-${{ matrix.postgres-version }}
|
|
||||||
if: steps.cache_pg.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
git submodule init vendor/postgres-${{ matrix.postgres-version }}
|
|
||||||
git submodule update --depth 1 --recursive
|
|
||||||
|
|
||||||
- name: Install build dependencies
|
|
||||||
if: steps.cache_pg.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
brew install flex bison openssl protobuf icu4c
|
|
||||||
|
|
||||||
- name: Set extra env for macOS
|
|
||||||
if: steps.cache_pg.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo 'LDFLAGS=-L/usr/local/opt/openssl@3/lib' >> $GITHUB_ENV
|
|
||||||
echo 'CPPFLAGS=-I/usr/local/opt/openssl@3/include' >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Build Postgres ${{ matrix.postgres-version }}
|
|
||||||
if: steps.cache_pg.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
make postgres-${{ matrix.postgres-version }} -j$(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
- name: Build Neon Pg Ext ${{ matrix.postgres-version }}
|
|
||||||
if: steps.cache_pg.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
make "neon-pg-ext-${{ matrix.postgres-version }}" -j$(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
- name: Get postgres headers ${{ matrix.postgres-version }}
|
|
||||||
if: steps.cache_pg.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
make postgres-headers-${{ matrix.postgres-version }} -j$(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
build-walproposer-lib:
|
|
||||||
if: |
|
|
||||||
(inputs.pg_versions != '[]' || inputs.rebuild_everything) && (
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-macos') ||
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
|
||||||
github.ref_name == 'main'
|
|
||||||
)
|
|
||||||
timeout-minutes: 30
|
|
||||||
runs-on: macos-15
|
|
||||||
needs: [build-pgxn]
|
|
||||||
env:
|
|
||||||
# Use release build only, to have less debug info around
|
|
||||||
# Hence keeping target/ (and general cache size) smaller
|
|
||||||
BUILD_TYPE: release
|
|
||||||
steps:
|
|
||||||
- name: Checkout main repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set pg v17 for caching
|
|
||||||
id: pg_rev
|
|
||||||
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v17) | tee -a "${GITHUB_OUTPUT}"
|
|
||||||
|
|
||||||
- name: Cache postgres v17 build
|
|
||||||
id: cache_pg
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/v17
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-v17-${{ steps.pg_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
|
|
||||||
- name: Cache walproposer-lib
|
|
||||||
id: cache_walproposer_lib
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/build/walproposer-lib
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-walproposer_lib-v17-${{ steps.pg_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
|
|
||||||
- name: Checkout submodule vendor/postgres-v17
|
|
||||||
if: steps.cache_walproposer_lib.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
git submodule init vendor/postgres-v17
|
|
||||||
git submodule update --depth 1 --recursive
|
|
||||||
|
|
||||||
- name: Install build dependencies
|
|
||||||
if: steps.cache_walproposer_lib.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
brew install flex bison openssl protobuf icu4c
|
|
||||||
|
|
||||||
- name: Set extra env for macOS
|
|
||||||
if: steps.cache_walproposer_lib.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo 'LDFLAGS=-L/usr/local/opt/openssl@3/lib' >> $GITHUB_ENV
|
|
||||||
echo 'CPPFLAGS=-I/usr/local/opt/openssl@3/include' >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Build walproposer-lib (only for v17)
|
|
||||||
if: steps.cache_walproposer_lib.outputs.cache-hit != 'true'
|
|
||||||
run:
|
|
||||||
make walproposer-lib -j$(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
cargo-build:
|
|
||||||
if: |
|
|
||||||
(inputs.pg_versions != '[]' || inputs.rebuild_rust_code || inputs.rebuild_everything) && (
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-macos') ||
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
|
||||||
github.ref_name == 'main'
|
|
||||||
)
|
|
||||||
timeout-minutes: 30
|
|
||||||
runs-on: macos-15
|
|
||||||
needs: [build-pgxn, build-walproposer-lib]
|
|
||||||
env:
|
|
||||||
# Use release build only, to have less debug info around
|
|
||||||
# Hence keeping target/ (and general cache size) smaller
|
|
||||||
BUILD_TYPE: release
|
|
||||||
steps:
|
|
||||||
- name: Checkout main repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Set pg v14 for caching
|
|
||||||
id: pg_rev_v14
|
|
||||||
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v14) | tee -a "${GITHUB_OUTPUT}"
|
|
||||||
- name: Set pg v15 for caching
|
|
||||||
id: pg_rev_v15
|
|
||||||
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v15) | tee -a "${GITHUB_OUTPUT}"
|
|
||||||
- name: Set pg v16 for caching
|
|
||||||
id: pg_rev_v16
|
|
||||||
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v16) | tee -a "${GITHUB_OUTPUT}"
|
|
||||||
- name: Set pg v17 for caching
|
|
||||||
id: pg_rev_v17
|
|
||||||
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v17) | tee -a "${GITHUB_OUTPUT}"
|
|
||||||
|
|
||||||
- name: Cache postgres v14 build
|
|
||||||
id: cache_pg
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/v14
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-v14-${{ steps.pg_rev_v14.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
- name: Cache postgres v15 build
|
|
||||||
id: cache_pg_v15
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/v15
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-v15-${{ steps.pg_rev_v15.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
- name: Cache postgres v16 build
|
|
||||||
id: cache_pg_v16
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/v16
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-v16-${{ steps.pg_rev_v16.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
- name: Cache postgres v17 build
|
|
||||||
id: cache_pg_v17
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/v17
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-v17-${{ steps.pg_rev_v17.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
|
|
||||||
- name: Cache cargo deps (only for v17)
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry
|
|
||||||
!~/.cargo/registry/src
|
|
||||||
~/.cargo/git
|
|
||||||
target
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('./Cargo.lock') }}-${{ hashFiles('./rust-toolchain.toml') }}-rust
|
|
||||||
|
|
||||||
- name: Cache walproposer-lib
|
|
||||||
id: cache_walproposer_lib
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: pg_install/build/walproposer-lib
|
|
||||||
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-walproposer_lib-v17-${{ steps.pg_rev_v17.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
|
||||||
|
|
||||||
- name: Install build dependencies
|
|
||||||
run: |
|
|
||||||
brew install flex bison openssl protobuf icu4c
|
|
||||||
|
|
||||||
- name: Set extra env for macOS
|
|
||||||
run: |
|
|
||||||
echo 'LDFLAGS=-L/usr/local/opt/openssl@3/lib' >> $GITHUB_ENV
|
|
||||||
echo 'CPPFLAGS=-I/usr/local/opt/openssl@3/include' >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Run cargo build (only for v17)
|
|
||||||
run: cargo build --all --release -j$(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
- name: Check that no warnings are produced (only for v17)
|
|
||||||
run: ./run_clippy.sh
|
|
||||||
694
.github/workflows/build_and_test.yml
vendored
694
.github/workflows/build_and_test.yml
vendored
@@ -6,7 +6,6 @@ on:
|
|||||||
- main
|
- main
|
||||||
- release
|
- release
|
||||||
- release-proxy
|
- release-proxy
|
||||||
- release-compute
|
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
@@ -21,6 +20,8 @@ concurrency:
|
|||||||
env:
|
env:
|
||||||
RUST_BACKTRACE: 1
|
RUST_BACKTRACE: 1
|
||||||
COPT: '-Werror'
|
COPT: '-Werror'
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
# A concurrency group that we use for e2e-tests runs, matches `concurrency.group` above with `github.repository` as a prefix
|
# A concurrency group that we use for e2e-tests runs, matches `concurrency.group` above with `github.repository` as a prefix
|
||||||
E2E_CONCURRENCY_GROUP: ${{ github.repository }}-e2e-tests-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
|
E2E_CONCURRENCY_GROUP: ${{ github.repository }}-e2e-tests-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
|
||||||
|
|
||||||
@@ -45,26 +46,6 @@ jobs:
|
|||||||
run cancel-previous-in-concurrency-group.yml \
|
run cancel-previous-in-concurrency-group.yml \
|
||||||
--field concurrency_group="${{ env.E2E_CONCURRENCY_GROUP }}"
|
--field concurrency_group="${{ env.E2E_CONCURRENCY_GROUP }}"
|
||||||
|
|
||||||
files-changed:
|
|
||||||
needs: [ check-permissions ]
|
|
||||||
runs-on: [ self-hosted, small ]
|
|
||||||
timeout-minutes: 3
|
|
||||||
outputs:
|
|
||||||
check-rust-dependencies: ${{ steps.files-changed.outputs.rust_dependencies }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Check for file changes
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
id: files-changed
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
filters: .github/file-filters.yaml
|
|
||||||
|
|
||||||
tag:
|
tag:
|
||||||
needs: [ check-permissions ]
|
needs: [ check-permissions ]
|
||||||
runs-on: [ self-hosted, small ]
|
runs-on: [ self-hosted, small ]
|
||||||
@@ -89,26 +70,55 @@ jobs:
|
|||||||
echo "tag=release-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
echo "tag=release-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-proxy" ]]; then
|
elif [[ "$GITHUB_REF_NAME" == "release-proxy" ]]; then
|
||||||
echo "tag=release-proxy-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
echo "tag=release-proxy-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-compute" ]]; then
|
|
||||||
echo "tag=release-compute-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
else
|
else
|
||||||
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release', 'release-proxy', 'release-compute'"
|
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'"
|
||||||
echo "tag=$GITHUB_RUN_ID" >> $GITHUB_OUTPUT
|
echo "tag=$GITHUB_RUN_ID" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
shell: bash
|
shell: bash
|
||||||
id: build-tag
|
id: build-tag
|
||||||
|
|
||||||
build-build-tools-image:
|
check-build-tools-image:
|
||||||
needs: [ check-permissions ]
|
needs: [ check-permissions ]
|
||||||
|
uses: ./.github/workflows/check-build-tools-image.yml
|
||||||
|
|
||||||
|
build-build-tools-image:
|
||||||
|
needs: [ check-build-tools-image ]
|
||||||
uses: ./.github/workflows/build-build-tools-image.yml
|
uses: ./.github/workflows/build-build-tools-image.yml
|
||||||
|
with:
|
||||||
|
image-tag: ${{ needs.check-build-tools-image.outputs.image-tag }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
check-codestyle-python:
|
check-codestyle-python:
|
||||||
needs: [ check-permissions, build-build-tools-image ]
|
needs: [ check-permissions, build-build-tools-image ]
|
||||||
uses: ./.github/workflows/_check-codestyle-python.yml
|
runs-on: [ self-hosted, small ]
|
||||||
with:
|
container:
|
||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
||||||
secrets: inherit
|
credentials:
|
||||||
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
|
options: --init
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Cache poetry deps
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pypoetry/virtualenvs
|
||||||
|
key: v2-${{ runner.os }}-${{ runner.arch }}-python-deps-bookworm-${{ hashFiles('poetry.lock') }}
|
||||||
|
|
||||||
|
- name: Install Python deps
|
||||||
|
run: ./scripts/pysync
|
||||||
|
|
||||||
|
- name: Run `ruff check` to ensure code format
|
||||||
|
run: poetry run ruff check .
|
||||||
|
|
||||||
|
- name: Run `ruff format` to ensure code format
|
||||||
|
run: poetry run ruff format --check .
|
||||||
|
|
||||||
|
- name: Run mypy to check types
|
||||||
|
run: poetry run mypy .
|
||||||
|
|
||||||
check-codestyle-jsonnet:
|
check-codestyle-jsonnet:
|
||||||
needs: [ check-permissions, build-build-tools-image ]
|
needs: [ check-permissions, build-build-tools-image ]
|
||||||
@@ -131,7 +141,6 @@ jobs:
|
|||||||
# Check that the vendor/postgres-* submodules point to the
|
# Check that the vendor/postgres-* submodules point to the
|
||||||
# corresponding REL_*_STABLE_neon branches.
|
# corresponding REL_*_STABLE_neon branches.
|
||||||
check-submodules:
|
check-submodules:
|
||||||
needs: [ check-permissions ]
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -184,19 +193,77 @@ jobs:
|
|||||||
|
|
||||||
check-codestyle-rust:
|
check-codestyle-rust:
|
||||||
needs: [ check-permissions, build-build-tools-image ]
|
needs: [ check-permissions, build-build-tools-image ]
|
||||||
uses: ./.github/workflows/_check-codestyle-rust.yml
|
strategy:
|
||||||
with:
|
matrix:
|
||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
arch: [ x64, arm64 ]
|
||||||
archs: '["x64", "arm64"]'
|
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', matrix.arch == 'arm64' && 'small-arm64' || 'small')) }}
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
check-dependencies-rust:
|
container:
|
||||||
needs: [ files-changed, build-build-tools-image ]
|
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
||||||
if: ${{ needs.files-changed.outputs.check-rust-dependencies == 'true' }}
|
credentials:
|
||||||
uses: ./.github/workflows/cargo-deny.yml
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
with:
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
options: --init
|
||||||
secrets: inherit
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Cache cargo deps
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
!~/.cargo/registry/src
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: v1-${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('./Cargo.lock') }}-${{ hashFiles('./rust-toolchain.toml') }}-rust
|
||||||
|
|
||||||
|
# Some of our rust modules use FFI and need those to be checked
|
||||||
|
- name: Get postgres headers
|
||||||
|
run: make postgres-headers -j$(nproc)
|
||||||
|
|
||||||
|
# cargo hack runs the given cargo subcommand (clippy in this case) for all feature combinations.
|
||||||
|
# This will catch compiler & clippy warnings in all feature combinations.
|
||||||
|
# TODO: use cargo hack for build and test as well, but, that's quite expensive.
|
||||||
|
# NB: keep clippy args in sync with ./run_clippy.sh
|
||||||
|
#
|
||||||
|
# The only difference between "clippy --debug" and "clippy --release" is that in --release mode,
|
||||||
|
# #[cfg(debug_assertions)] blocks are not built. It's not worth building everything for second
|
||||||
|
# time just for that, so skip "clippy --release".
|
||||||
|
- run: |
|
||||||
|
CLIPPY_COMMON_ARGS="$( source .neon_clippy_args; echo "$CLIPPY_COMMON_ARGS")"
|
||||||
|
if [ "$CLIPPY_COMMON_ARGS" = "" ]; then
|
||||||
|
echo "No clippy args found in .neon_clippy_args"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "CLIPPY_COMMON_ARGS=${CLIPPY_COMMON_ARGS}" >> $GITHUB_ENV
|
||||||
|
- name: Run cargo clippy (debug)
|
||||||
|
run: cargo hack --feature-powerset clippy $CLIPPY_COMMON_ARGS
|
||||||
|
|
||||||
|
- name: Check documentation generation
|
||||||
|
run: cargo doc --workspace --no-deps --document-private-items
|
||||||
|
env:
|
||||||
|
RUSTDOCFLAGS: "-Dwarnings -Arustdoc::private_intra_doc_links"
|
||||||
|
|
||||||
|
# Use `${{ !cancelled() }}` to run quck tests after the longer clippy run
|
||||||
|
- name: Check formatting
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
# https://github.com/facebookincubator/cargo-guppy/tree/bec4e0eb29dcd1faac70b1b5360267fc02bf830e/tools/cargo-hakari#2-keep-the-workspace-hack-up-to-date-in-ci
|
||||||
|
- name: Check rust dependencies
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
run: |
|
||||||
|
cargo hakari generate --diff # workspace-hack Cargo.toml is up-to-date
|
||||||
|
cargo hakari manage-deps --dry-run # all workspace crates depend on workspace-hack
|
||||||
|
|
||||||
|
# https://github.com/EmbarkStudios/cargo-deny
|
||||||
|
- name: Check rust licenses/bans/advisories/sources
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
run: cargo deny check --hide-inclusion-graph
|
||||||
|
|
||||||
build-and-test-locally:
|
build-and-test-locally:
|
||||||
needs: [ tag, build-build-tools-image ]
|
needs: [ tag, build-build-tools-image ]
|
||||||
@@ -215,15 +282,8 @@ jobs:
|
|||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
||||||
build-tag: ${{ needs.tag.outputs.build-tag }}
|
build-tag: ${{ needs.tag.outputs.build-tag }}
|
||||||
build-type: ${{ matrix.build-type }}
|
build-type: ${{ matrix.build-type }}
|
||||||
# Run tests on all Postgres versions in release builds and only on the latest version in debug builds.
|
# Run tests on all Postgres versions in release builds and only on the latest version in debug builds
|
||||||
# Run without LFC on v17 release and debug builds only. For all the other cases LFC is enabled.
|
pg-versions: ${{ matrix.build-type == 'release' && '["v14", "v15", "v16", "v17"]' || '["v17"]' }}
|
||||||
test-cfg: |
|
|
||||||
${{ matrix.build-type == 'release' && '[{"pg_version":"v14", "lfc_state": "with-lfc"},
|
|
||||||
{"pg_version":"v15", "lfc_state": "with-lfc"},
|
|
||||||
{"pg_version":"v16", "lfc_state": "with-lfc"},
|
|
||||||
{"pg_version":"v17", "lfc_state": "with-lfc"},
|
|
||||||
{"pg_version":"v17", "lfc_state": "without-lfc"}]'
|
|
||||||
|| '[{"pg_version":"v17", "lfc_state": "without-lfc" }]' }}
|
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
# Keep `benchmarks` job outside of `build-and-test-locally` workflow to make job failures non-blocking
|
# Keep `benchmarks` job outside of `build-and-test-locally` workflow to make job failures non-blocking
|
||||||
@@ -263,15 +323,9 @@ jobs:
|
|||||||
echo "json=$(jq --compact-output '.' /tmp/benchmark_durations.json)" >> $GITHUB_OUTPUT
|
echo "json=$(jq --compact-output '.' /tmp/benchmark_durations.json)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
benchmarks:
|
benchmarks:
|
||||||
# `!failure() && !cancelled()` is required because the workflow depends on the job that can be skipped: `deploy` in PRs
|
if: github.ref_name == 'main' || contains(github.event.pull_request.labels.*.name, 'run-benchmarks')
|
||||||
if: github.ref_name == 'main' || (contains(github.event.pull_request.labels.*.name, 'run-benchmarks') && !failure() && !cancelled())
|
needs: [ check-permissions, build-and-test-locally, build-build-tools-image, get-benchmarks-durations ]
|
||||||
needs: [ check-permissions, build-build-tools-image, get-benchmarks-durations, deploy ]
|
runs-on: [ self-hosted, small ]
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: [ self-hosted, small-metal ]
|
|
||||||
container:
|
container:
|
||||||
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
||||||
credentials:
|
credentials:
|
||||||
@@ -299,7 +353,6 @@ jobs:
|
|||||||
extra_params: --splits 5 --group ${{ matrix.pytest_split_group }}
|
extra_params: --splits 5 --group ${{ matrix.pytest_split_group }}
|
||||||
benchmark_durations: ${{ needs.get-benchmarks-durations.outputs.json }}
|
benchmark_durations: ${{ needs.get-benchmarks-durations.outputs.json }}
|
||||||
pg_version: v16
|
pg_version: v16
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
VIP_VAP_ACCESS_TOKEN: "${{ secrets.VIP_VAP_ACCESS_TOKEN }}"
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
||||||
@@ -309,31 +362,24 @@ jobs:
|
|||||||
# XXX: no coverage data handling here, since benchmarks are run on release builds,
|
# XXX: no coverage data handling here, since benchmarks are run on release builds,
|
||||||
# while coverage is currently collected for the debug ones
|
# while coverage is currently collected for the debug ones
|
||||||
|
|
||||||
report-benchmarks-results-to-slack:
|
report-benchmarks-failures:
|
||||||
needs: [ benchmarks, create-test-report ]
|
needs: [ benchmarks, create-test-report ]
|
||||||
if: github.ref_name == 'main' && !cancelled() && contains(fromJSON('["success", "failure"]'), needs.benchmarks.result)
|
if: github.ref_name == 'main' && failure() && needs.benchmarks.result == 'failure'
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: slackapi/slack-github-action@v2
|
- uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
method: chat.postMessage
|
channel-id: C060CNA47S9 # on-call-staging-storage-stream
|
||||||
token: ${{ secrets.SLACK_BOT_TOKEN }}
|
slack-message: |
|
||||||
payload: |
|
Benchmarks failed on main <${{ github.event.head_commit.url }}|${{ github.sha }}>
|
||||||
channel: "${{ vars.SLACK_ON_CALL_STORAGE_STAGING_STREAM }}"
|
<${{ needs.create-test-report.outputs.report-url }}|Allure report>
|
||||||
text: |
|
env:
|
||||||
Benchmarks on main: *${{ needs.benchmarks.result }}*
|
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||||
- <${{ needs.create-test-report.outputs.report-url }}|Allure report>
|
|
||||||
- <${{ github.event.head_commit.url }}|${{ github.sha }}>
|
|
||||||
|
|
||||||
create-test-report:
|
create-test-report:
|
||||||
needs: [ check-permissions, build-and-test-locally, coverage-report, build-build-tools-image, benchmarks ]
|
needs: [ check-permissions, build-and-test-locally, coverage-report, build-build-tools-image, benchmarks ]
|
||||||
if: ${{ !cancelled() && contains(fromJSON('["skipped", "success"]'), needs.check-permissions.result) }}
|
if: ${{ !cancelled() && contains(fromJSON('["skipped", "success"]'), needs.check-permissions.result) }}
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
outputs:
|
outputs:
|
||||||
report-url: ${{ steps.create-allure-report.outputs.report-url }}
|
report-url: ${{ steps.create-allure-report.outputs.report-url }}
|
||||||
|
|
||||||
@@ -354,7 +400,6 @@ jobs:
|
|||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
with:
|
||||||
store-test-results-into-db: true
|
store-test-results-into-db: true
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
||||||
|
|
||||||
@@ -386,10 +431,6 @@ jobs:
|
|||||||
coverage-report:
|
coverage-report:
|
||||||
if: ${{ !startsWith(github.ref_name, 'release') }}
|
if: ${{ !startsWith(github.ref_name, 'release') }}
|
||||||
needs: [ check-permissions, build-build-tools-image, build-and-test-locally ]
|
needs: [ check-permissions, build-build-tools-image, build-and-test-locally ]
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
runs-on: [ self-hosted, small ]
|
runs-on: [ self-hosted, small ]
|
||||||
container:
|
container:
|
||||||
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
||||||
@@ -416,14 +457,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ matrix.build_type }}-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-${{ matrix.build_type }}-artifact
|
||||||
path: /tmp/neon
|
path: /tmp/neon
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Get coverage artifact
|
- name: Get coverage artifact
|
||||||
uses: ./.github/actions/download
|
uses: ./.github/actions/download
|
||||||
with:
|
with:
|
||||||
name: coverage-data-artifact
|
name: coverage-data-artifact
|
||||||
path: /tmp/coverage
|
path: /tmp/coverage
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Merge coverage data
|
- name: Merge coverage data
|
||||||
run: scripts/coverage "--profraw-prefix=$GITHUB_JOB" --dir=/tmp/coverage merge
|
run: scripts/coverage "--profraw-prefix=$GITHUB_JOB" --dir=/tmp/coverage merge
|
||||||
@@ -482,8 +521,6 @@ jobs:
|
|||||||
REPORT_URL_NEW: ${{ steps.upload-coverage-report-new.outputs.report-url }}
|
REPORT_URL_NEW: ${{ steps.upload-coverage-report-new.outputs.report-url }}
|
||||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
with:
|
with:
|
||||||
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
|
||||||
retries: 5
|
|
||||||
script: |
|
script: |
|
||||||
const { REPORT_URL_NEW, COMMIT_SHA } = process.env
|
const { REPORT_URL_NEW, COMMIT_SHA } = process.env
|
||||||
|
|
||||||
@@ -497,8 +534,8 @@ jobs:
|
|||||||
})
|
})
|
||||||
|
|
||||||
trigger-e2e-tests:
|
trigger-e2e-tests:
|
||||||
if: ${{ !github.event.pull_request.draft || contains( github.event.pull_request.labels.*.name, 'run-e2e-tests-in-draft') || github.ref_name == 'main' || github.ref_name == 'release' || github.ref_name == 'release-proxy' || github.ref_name == 'release-compute' }}
|
if: ${{ !github.event.pull_request.draft || contains( github.event.pull_request.labels.*.name, 'run-e2e-tests-in-draft') || github.ref_name == 'main' || github.ref_name == 'release' || github.ref_name == 'release-proxy' }}
|
||||||
needs: [ check-permissions, push-neon-image-dev, push-compute-image-dev, tag ]
|
needs: [ check-permissions, promote-images, tag ]
|
||||||
uses: ./.github/workflows/trigger-e2e-tests.yml
|
uses: ./.github/workflows/trigger-e2e-tests.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
@@ -515,7 +552,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- uses: neondatabase/dev-actions/set-docker-config-dir@6094485bf440001c94a94a3f9e221e81ff6b6193
|
- uses: ./.github/actions/set-docker-config-dir
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
cache-binary: false
|
cache-binary: false
|
||||||
@@ -554,10 +591,6 @@ jobs:
|
|||||||
neon-image:
|
neon-image:
|
||||||
needs: [ neon-image-arch, tag ]
|
needs: [ neon-image-arch, tag ]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: docker/login-action@v3
|
- uses: docker/login-action@v3
|
||||||
@@ -572,12 +605,19 @@ jobs:
|
|||||||
neondatabase/neon:${{ needs.tag.outputs.build-tag }}-bookworm-x64 \
|
neondatabase/neon:${{ needs.tag.outputs.build-tag }}-bookworm-x64 \
|
||||||
neondatabase/neon:${{ needs.tag.outputs.build-tag }}-bookworm-arm64
|
neondatabase/neon:${{ needs.tag.outputs.build-tag }}-bookworm-arm64
|
||||||
|
|
||||||
|
- uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: 369495373322.dkr.ecr.eu-central-1.amazonaws.com
|
||||||
|
username: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
password: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
|
|
||||||
|
- name: Push multi-arch image to ECR
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create -t 369495373322.dkr.ecr.eu-central-1.amazonaws.com/neon:${{ needs.tag.outputs.build-tag }} \
|
||||||
|
neondatabase/neon:${{ needs.tag.outputs.build-tag }}
|
||||||
|
|
||||||
compute-node-image-arch:
|
compute-node-image-arch:
|
||||||
needs: [ check-permissions, build-build-tools-image, tag ]
|
needs: [ check-permissions, build-build-tools-image, tag ]
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: read
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -603,7 +643,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- uses: neondatabase/dev-actions/set-docker-config-dir@6094485bf440001c94a94a3f9e221e81ff6b6193
|
- uses: ./.github/actions/set-docker-config-dir
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
cache-binary: false
|
cache-binary: false
|
||||||
@@ -618,6 +658,12 @@ jobs:
|
|||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: 369495373322.dkr.ecr.eu-central-1.amazonaws.com
|
||||||
|
username: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
password: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
|
|
||||||
- uses: docker/login-action@v3
|
- uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: cache.neon.build
|
registry: cache.neon.build
|
||||||
@@ -644,7 +690,7 @@ jobs:
|
|||||||
neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-${{ matrix.arch }}
|
neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-${{ matrix.arch }}
|
||||||
|
|
||||||
- name: Build neon extensions test image
|
- name: Build neon extensions test image
|
||||||
if: matrix.version.pg >= 'v16'
|
if: matrix.version.pg == 'v16'
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
@@ -658,17 +704,38 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
pull: true
|
pull: true
|
||||||
file: compute/compute-node.Dockerfile
|
file: compute/compute-node.Dockerfile
|
||||||
target: extension-tests
|
target: neon-pg-ext-test
|
||||||
cache-from: type=registry,ref=cache.neon.build/compute-node-${{ matrix.version.pg }}:cache-${{ matrix.version.debian }}-${{ matrix.arch }}
|
cache-from: type=registry,ref=cache.neon.build/neon-test-extensions-${{ matrix.version.pg }}:cache-${{ matrix.version.debian }}-${{ matrix.arch }}
|
||||||
|
cache-to: ${{ github.ref_name == 'main' && format('type=registry,ref=cache.neon.build/neon-test-extensions-{0}:cache-{1}-{2},mode=max', matrix.version.pg, matrix.version.debian, matrix.arch) || '' }}
|
||||||
tags: |
|
tags: |
|
||||||
neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{needs.tag.outputs.build-tag}}-${{ matrix.version.debian }}-${{ matrix.arch }}
|
neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{needs.tag.outputs.build-tag}}-${{ matrix.version.debian }}-${{ matrix.arch }}
|
||||||
|
|
||||||
|
- name: Build compute-tools image
|
||||||
|
# compute-tools are Postgres independent, so build it only once
|
||||||
|
# We pick 16, because that builds on debian 11 with older glibc (and is
|
||||||
|
# thus compatible with newer glibc), rather than 17 on Debian 12, as
|
||||||
|
# that isn't guaranteed to be compatible with Debian 11
|
||||||
|
if: matrix.version.pg == 'v16'
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
target: compute-tools-image
|
||||||
|
context: .
|
||||||
|
build-args: |
|
||||||
|
GIT_VERSION=${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
BUILD_TAG=${{ needs.tag.outputs.build-tag }}
|
||||||
|
TAG=${{ needs.build-build-tools-image.outputs.image-tag }}-${{ matrix.version.debian }}
|
||||||
|
DEBIAN_VERSION=${{ matrix.version.debian }}
|
||||||
|
provenance: false
|
||||||
|
push: true
|
||||||
|
pull: true
|
||||||
|
file: compute/compute-node.Dockerfile
|
||||||
|
cache-from: type=registry,ref=cache.neon.build/neon-test-extensions-${{ matrix.version.pg }}:cache-${{ matrix.version.debian }}-${{ matrix.arch }}
|
||||||
|
cache-to: ${{ github.ref_name == 'main' && format('type=registry,ref=cache.neon.build/compute-tools-{0}:cache-{1}-{2},mode=max', matrix.version.pg, matrix.version.debian, matrix.arch) || '' }}
|
||||||
|
tags: |
|
||||||
|
neondatabase/compute-tools:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-${{ matrix.arch }}
|
||||||
|
|
||||||
compute-node-image:
|
compute-node-image:
|
||||||
needs: [ compute-node-image-arch, tag ]
|
needs: [ compute-node-image-arch, tag ]
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: read
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
@@ -698,13 +765,38 @@ jobs:
|
|||||||
neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-arm64
|
neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-arm64
|
||||||
|
|
||||||
- name: Create multi-arch neon-test-extensions image
|
- name: Create multi-arch neon-test-extensions image
|
||||||
if: matrix.version.pg >= 'v16'
|
if: matrix.version.pg == 'v16'
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools create -t neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }} \
|
docker buildx imagetools create -t neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }} \
|
||||||
-t neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }} \
|
-t neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }} \
|
||||||
neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-x64 \
|
neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-x64 \
|
||||||
neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-arm64
|
neondatabase/neon-test-extensions-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-arm64
|
||||||
|
|
||||||
|
- name: Create multi-arch compute-tools image
|
||||||
|
if: matrix.version.pg == 'v16'
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create -t neondatabase/compute-tools:${{ needs.tag.outputs.build-tag }} \
|
||||||
|
-t neondatabase/compute-tools:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }} \
|
||||||
|
neondatabase/compute-tools:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-x64 \
|
||||||
|
neondatabase/compute-tools:${{ needs.tag.outputs.build-tag }}-${{ matrix.version.debian }}-arm64
|
||||||
|
|
||||||
|
- uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: 369495373322.dkr.ecr.eu-central-1.amazonaws.com
|
||||||
|
username: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
password: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
|
|
||||||
|
- name: Push multi-arch compute-node-${{ matrix.version.pg }} image to ECR
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create -t 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }} \
|
||||||
|
neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}
|
||||||
|
|
||||||
|
- name: Push multi-arch compute-tools image to ECR
|
||||||
|
if: matrix.version.pg == 'v16'
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create -t 369495373322.dkr.ecr.eu-central-1.amazonaws.com/compute-tools:${{ needs.tag.outputs.build-tag }} \
|
||||||
|
neondatabase/compute-tools:${{ needs.tag.outputs.build-tag }}
|
||||||
|
|
||||||
vm-compute-node-image:
|
vm-compute-node-image:
|
||||||
needs: [ check-permissions, tag, compute-node-image ]
|
needs: [ check-permissions, tag, compute-node-image ]
|
||||||
runs-on: [ self-hosted, large ]
|
runs-on: [ self-hosted, large ]
|
||||||
@@ -722,7 +814,7 @@ jobs:
|
|||||||
- pg: v17
|
- pg: v17
|
||||||
debian: bookworm
|
debian: bookworm
|
||||||
env:
|
env:
|
||||||
VM_BUILDER_VERSION: v0.37.1
|
VM_BUILDER_VERSION: v0.35.0
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -732,7 +824,7 @@ jobs:
|
|||||||
curl -fL https://github.com/neondatabase/autoscaling/releases/download/$VM_BUILDER_VERSION/vm-builder -o vm-builder
|
curl -fL https://github.com/neondatabase/autoscaling/releases/download/$VM_BUILDER_VERSION/vm-builder -o vm-builder
|
||||||
chmod +x vm-builder
|
chmod +x vm-builder
|
||||||
|
|
||||||
- uses: neondatabase/dev-actions/set-docker-config-dir@6094485bf440001c94a94a3f9e221e81ff6b6193
|
- uses: ./.github/actions/set-docker-config-dir
|
||||||
- uses: docker/login-action@v3
|
- uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
@@ -747,7 +839,6 @@ jobs:
|
|||||||
- name: Build vm image
|
- name: Build vm image
|
||||||
run: |
|
run: |
|
||||||
./vm-builder \
|
./vm-builder \
|
||||||
-size=2G \
|
|
||||||
-spec=compute/vm-image-spec-${{ matrix.version.debian }}.yaml \
|
-spec=compute/vm-image-spec-${{ matrix.version.debian }}.yaml \
|
||||||
-src=neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }} \
|
-src=neondatabase/compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }} \
|
||||||
-dst=neondatabase/vm-compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}
|
-dst=neondatabase/vm-compute-node-${{ matrix.version.pg }}:${{ needs.tag.outputs.build-tag }}
|
||||||
@@ -762,30 +853,18 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
arch: [ x64, arm64 ]
|
arch: [ x64, arm64 ]
|
||||||
pg_version: [v16, v17]
|
|
||||||
|
|
||||||
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', matrix.arch == 'arm64' && 'small-arm64' || 'small')) }}
|
runs-on: ${{ fromJson(format('["self-hosted", "{0}"]', matrix.arch == 'arm64' && 'small-arm64' || 'small')) }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: neondatabase/dev-actions/set-docker-config-dir@6094485bf440001c94a94a3f9e221e81ff6b6193
|
- uses: ./.github/actions/set-docker-config-dir
|
||||||
- uses: docker/login-action@v3
|
- uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
- name: Get the last compute release tag
|
|
||||||
id: get-last-compute-release-tag
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
|
||||||
run: |
|
|
||||||
tag=$(gh api -q '[.[].tag_name | select(startswith("release-compute"))][0]'\
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
||||||
"/repos/${{ github.repository }}/releases")
|
|
||||||
echo tag=${tag} >> ${GITHUB_OUTPUT}
|
|
||||||
|
|
||||||
# `neondatabase/neon` contains multiple binaries, all of them use the same input for the version into the same version formatting library.
|
# `neondatabase/neon` contains multiple binaries, all of them use the same input for the version into the same version formatting library.
|
||||||
# Pick pageserver as currently the only binary with extra "version" features printed in the string to verify.
|
# Pick pageserver as currently the only binary with extra "version" features printed in the string to verify.
|
||||||
# Regular pageserver version string looks like
|
# Regular pageserver version string looks like
|
||||||
@@ -812,143 +891,114 @@ jobs:
|
|||||||
|
|
||||||
- name: Verify docker-compose example and test extensions
|
- name: Verify docker-compose example and test extensions
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
env:
|
run: env TAG=${{needs.tag.outputs.build-tag}} ./docker-compose/docker_compose_test.sh
|
||||||
TAG: ${{needs.tag.outputs.build-tag}}
|
|
||||||
TEST_VERSION_ONLY: ${{ matrix.pg_version }}
|
|
||||||
run: ./docker-compose/docker_compose_test.sh
|
|
||||||
|
|
||||||
- name: Print logs and clean up docker-compose test
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
docker compose --profile test-extensions -f ./docker-compose/docker-compose.yml logs || true
|
|
||||||
docker compose --profile test-extensions -f ./docker-compose/docker-compose.yml down
|
|
||||||
|
|
||||||
- name: Test extension upgrade
|
|
||||||
timeout-minutes: 20
|
|
||||||
if: ${{ needs.tag.outputs.build-tag == github.run_id }}
|
|
||||||
env:
|
|
||||||
NEWTAG: ${{ needs.tag.outputs.build-tag }}
|
|
||||||
OLDTAG: ${{ steps.get-last-compute-release-tag.outputs.tag }}
|
|
||||||
run: ./docker-compose/test_extensions_upgrade.sh
|
|
||||||
|
|
||||||
- name: Print logs and clean up
|
- name: Print logs and clean up
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
docker compose --profile test-extensions -f ./docker-compose/docker-compose.yml logs || true
|
docker compose -f ./docker-compose/docker-compose.yml logs || 0
|
||||||
docker compose --profile test-extensions -f ./docker-compose/docker-compose.yml down
|
docker compose -f ./docker-compose/docker-compose.yml down
|
||||||
|
|
||||||
generate-image-maps:
|
promote-images:
|
||||||
needs: [ tag ]
|
needs: [ check-permissions, tag, test-images, vm-compute-node-image ]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
outputs:
|
|
||||||
neon-dev: ${{ steps.generate.outputs.neon-dev }}
|
permissions:
|
||||||
neon-prod: ${{ steps.generate.outputs.neon-prod }}
|
id-token: write # for `aws-actions/configure-aws-credentials`
|
||||||
compute-dev: ${{ steps.generate.outputs.compute-dev }}
|
|
||||||
compute-prod: ${{ steps.generate.outputs.compute-prod }}
|
env:
|
||||||
|
VERSIONS: v14 v15 v16 v17
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
sparse-checkout: scripts/generate_image_maps.py
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
sparse-checkout-cone-mode: false
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
- name: Generate Image Maps
|
- name: Login to dev ECR
|
||||||
id: generate
|
uses: docker/login-action@v3
|
||||||
run: python scripts/generate_image_maps.py
|
with:
|
||||||
env:
|
registry: 369495373322.dkr.ecr.eu-central-1.amazonaws.com
|
||||||
BUILD_TAG: "${{ needs.tag.outputs.build-tag }}"
|
username: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
BRANCH: "${{ github.ref_name }}"
|
password: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
DEV_ACR: "${{ vars.AZURE_DEV_REGISTRY_NAME }}"
|
|
||||||
PROD_ACR: "${{ vars.AZURE_PROD_REGISTRY_NAME }}"
|
|
||||||
|
|
||||||
push-neon-image-dev:
|
- name: Copy vm-compute-node images to ECR
|
||||||
needs: [ generate-image-maps, neon-image ]
|
run: |
|
||||||
uses: ./.github/workflows/_push-to-container-registry.yml
|
for version in ${VERSIONS}; do
|
||||||
with:
|
docker buildx imagetools create -t 369495373322.dkr.ecr.eu-central-1.amazonaws.com/vm-compute-node-${version}:${{ needs.tag.outputs.build-tag }} \
|
||||||
image-map: '${{ needs.generate-image-maps.outputs.neon-dev }}'
|
neondatabase/vm-compute-node-${version}:${{ needs.tag.outputs.build-tag }}
|
||||||
aws-region: eu-central-1
|
done
|
||||||
aws-account-ids: "369495373322"
|
|
||||||
azure-client-id: ${{ vars.AZURE_DEV_CLIENT_ID }}
|
|
||||||
azure-subscription-id: ${{ vars.AZURE_DEV_SUBSCRIPTION_ID }}
|
|
||||||
azure-tenant-id: ${{ vars.AZURE_TENANT_ID }}
|
|
||||||
acr-registry-name: ${{ vars.AZURE_DEV_REGISTRY_NAME }}
|
|
||||||
secrets:
|
|
||||||
aws-role-to-assume: "${{ vars.DEV_AWS_OIDC_ROLE_ARN }}"
|
|
||||||
docker-hub-username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
docker-hub-password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
|
|
||||||
push-compute-image-dev:
|
- name: Add latest tag to images
|
||||||
needs: [ generate-image-maps, vm-compute-node-image ]
|
if: github.ref_name == 'main'
|
||||||
uses: ./.github/workflows/_push-to-container-registry.yml
|
run: |
|
||||||
with:
|
for repo in neondatabase 369495373322.dkr.ecr.eu-central-1.amazonaws.com; do
|
||||||
image-map: '${{ needs.generate-image-maps.outputs.compute-dev }}'
|
docker buildx imagetools create -t $repo/neon:latest \
|
||||||
aws-region: eu-central-1
|
$repo/neon:${{ needs.tag.outputs.build-tag }}
|
||||||
aws-account-ids: "369495373322"
|
|
||||||
azure-client-id: ${{ vars.AZURE_DEV_CLIENT_ID }}
|
|
||||||
azure-subscription-id: ${{ vars.AZURE_DEV_SUBSCRIPTION_ID }}
|
|
||||||
azure-tenant-id: ${{ vars.AZURE_TENANT_ID }}
|
|
||||||
acr-registry-name: ${{ vars.AZURE_DEV_REGISTRY_NAME }}
|
|
||||||
secrets:
|
|
||||||
aws-role-to-assume: "${{ vars.DEV_AWS_OIDC_ROLE_ARN }}"
|
|
||||||
docker-hub-username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
docker-hub-password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
|
|
||||||
push-neon-image-prod:
|
docker buildx imagetools create -t $repo/compute-tools:latest \
|
||||||
if: github.ref_name == 'release' || github.ref_name == 'release-proxy' || github.ref_name == 'release-compute'
|
$repo/compute-tools:${{ needs.tag.outputs.build-tag }}
|
||||||
needs: [ generate-image-maps, neon-image, test-images ]
|
|
||||||
uses: ./.github/workflows/_push-to-container-registry.yml
|
|
||||||
with:
|
|
||||||
image-map: '${{ needs.generate-image-maps.outputs.neon-prod }}'
|
|
||||||
aws-region: eu-central-1
|
|
||||||
aws-account-ids: "093970136003"
|
|
||||||
azure-client-id: ${{ vars.AZURE_PROD_CLIENT_ID }}
|
|
||||||
azure-subscription-id: ${{ vars.AZURE_PROD_SUBSCRIPTION_ID }}
|
|
||||||
azure-tenant-id: ${{ vars.AZURE_TENANT_ID }}
|
|
||||||
acr-registry-name: ${{ vars.AZURE_PROD_REGISTRY_NAME }}
|
|
||||||
secrets:
|
|
||||||
aws-role-to-assume: "${{ secrets.PROD_GHA_OIDC_ROLE }}"
|
|
||||||
docker-hub-username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
docker-hub-password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
|
|
||||||
push-compute-image-prod:
|
for version in ${VERSIONS}; do
|
||||||
if: github.ref_name == 'release' || github.ref_name == 'release-proxy' || github.ref_name == 'release-compute'
|
docker buildx imagetools create -t $repo/compute-node-${version}:latest \
|
||||||
needs: [ generate-image-maps, vm-compute-node-image, test-images ]
|
$repo/compute-node-${version}:${{ needs.tag.outputs.build-tag }}
|
||||||
uses: ./.github/workflows/_push-to-container-registry.yml
|
|
||||||
with:
|
|
||||||
image-map: '${{ needs.generate-image-maps.outputs.compute-prod }}'
|
|
||||||
aws-region: eu-central-1
|
|
||||||
aws-account-ids: "093970136003"
|
|
||||||
azure-client-id: ${{ vars.AZURE_PROD_CLIENT_ID }}
|
|
||||||
azure-subscription-id: ${{ vars.AZURE_PROD_SUBSCRIPTION_ID }}
|
|
||||||
azure-tenant-id: ${{ vars.AZURE_TENANT_ID }}
|
|
||||||
acr-registry-name: ${{ vars.AZURE_PROD_REGISTRY_NAME }}
|
|
||||||
secrets:
|
|
||||||
aws-role-to-assume: "${{ secrets.PROD_GHA_OIDC_ROLE }}"
|
|
||||||
docker-hub-username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
docker-hub-password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
|
|
||||||
# This is a bit of a special case so we're not using a generated image map.
|
docker buildx imagetools create -t $repo/vm-compute-node-${version}:latest \
|
||||||
add-latest-tag-to-neon-extensions-test-image:
|
$repo/vm-compute-node-${version}:${{ needs.tag.outputs.build-tag }}
|
||||||
|
done
|
||||||
|
done
|
||||||
|
docker buildx imagetools create -t neondatabase/neon-test-extensions-v16:latest \
|
||||||
|
neondatabase/neon-test-extensions-v16:${{ needs.tag.outputs.build-tag }}
|
||||||
|
|
||||||
|
- name: Configure AWS-prod credentials
|
||||||
|
if: github.ref_name == 'release'|| github.ref_name == 'release-proxy'
|
||||||
|
uses: aws-actions/configure-aws-credentials@v4
|
||||||
|
with:
|
||||||
|
aws-region: eu-central-1
|
||||||
|
mask-aws-account-id: true
|
||||||
|
role-to-assume: ${{ secrets.PROD_GHA_OIDC_ROLE }}
|
||||||
|
|
||||||
|
- name: Login to prod ECR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
if: github.ref_name == 'release'|| github.ref_name == 'release-proxy'
|
||||||
|
with:
|
||||||
|
registry: 093970136003.dkr.ecr.eu-central-1.amazonaws.com
|
||||||
|
|
||||||
|
- name: Copy all images to prod ECR
|
||||||
|
if: github.ref_name == 'release'|| github.ref_name == 'release-proxy'
|
||||||
|
run: |
|
||||||
|
for image in neon compute-tools {vm-,}compute-node-{v14,v15,v16,v17}; do
|
||||||
|
docker buildx imagetools create -t 093970136003.dkr.ecr.eu-central-1.amazonaws.com/${image}:${{ needs.tag.outputs.build-tag }} \
|
||||||
|
369495373322.dkr.ecr.eu-central-1.amazonaws.com/${image}:${{ needs.tag.outputs.build-tag }}
|
||||||
|
done
|
||||||
|
|
||||||
|
push-to-acr-dev:
|
||||||
if: github.ref_name == 'main'
|
if: github.ref_name == 'main'
|
||||||
needs: [ tag, compute-node-image ]
|
needs: [ tag, promote-images ]
|
||||||
uses: ./.github/workflows/_push-to-container-registry.yml
|
uses: ./.github/workflows/_push-to-acr.yml
|
||||||
with:
|
with:
|
||||||
image-map: |
|
client_id: ${{ vars.AZURE_DEV_CLIENT_ID }}
|
||||||
{
|
image_tag: ${{ needs.tag.outputs.build-tag }}
|
||||||
"docker.io/neondatabase/neon-test-extensions-v16:${{ needs.tag.outputs.build-tag }}": ["docker.io/neondatabase/neon-test-extensions-v16:latest"],
|
images: neon compute-tools vm-compute-node-v14 vm-compute-node-v15 vm-compute-node-v16 vm-compute-node-v17 compute-node-v14 compute-node-v15 compute-node-v16 compute-node-v17
|
||||||
"docker.io/neondatabase/neon-test-extensions-v17:${{ needs.tag.outputs.build-tag }}": ["docker.io/neondatabase/neon-test-extensions-v17:latest"]
|
registry_name: ${{ vars.AZURE_DEV_REGISTRY_NAME }}
|
||||||
}
|
subscription_id: ${{ vars.AZURE_DEV_SUBSCRIPTION_ID }}
|
||||||
secrets:
|
tenant_id: ${{ vars.AZURE_TENANT_ID }}
|
||||||
docker-hub-username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
docker-hub-password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
push-to-acr-prod:
|
||||||
|
if: github.ref_name == 'release'|| github.ref_name == 'release-proxy'
|
||||||
|
needs: [ tag, promote-images ]
|
||||||
|
uses: ./.github/workflows/_push-to-acr.yml
|
||||||
|
with:
|
||||||
|
client_id: ${{ vars.AZURE_PROD_CLIENT_ID }}
|
||||||
|
image_tag: ${{ needs.tag.outputs.build-tag }}
|
||||||
|
images: neon compute-tools vm-compute-node-v14 vm-compute-node-v15 vm-compute-node-v16 vm-compute-node-v17 compute-node-v14 compute-node-v15 compute-node-v16 compute-node-v17
|
||||||
|
registry_name: ${{ vars.AZURE_PROD_REGISTRY_NAME }}
|
||||||
|
subscription_id: ${{ vars.AZURE_PROD_SUBSCRIPTION_ID }}
|
||||||
|
tenant_id: ${{ vars.AZURE_TENANT_ID }}
|
||||||
|
|
||||||
trigger-custom-extensions-build-and-wait:
|
trigger-custom-extensions-build-and-wait:
|
||||||
needs: [ check-permissions, tag ]
|
needs: [ check-permissions, tag ]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set PR's status to pending and request a remote CI test
|
- name: Set PR's status to pending and request a remote CI test
|
||||||
run: |
|
run: |
|
||||||
@@ -1021,114 +1071,15 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
needs: [ check-permissions, push-neon-image-prod, push-compute-image-prod, tag, build-and-test-locally, trigger-custom-extensions-build-and-wait ]
|
needs: [ check-permissions, promote-images, tag, build-and-test-locally, trigger-custom-extensions-build-and-wait, push-to-acr-dev, push-to-acr-prod ]
|
||||||
# `!failure() && !cancelled()` is required because the workflow depends on the job that can be skipped: `push-to-acr-dev` and `push-to-acr-prod`
|
# `!failure() && !cancelled()` is required because the workflow depends on the job that can be skipped: `push-to-acr-dev` and `push-to-acr-prod`
|
||||||
if: (github.ref_name == 'main' || github.ref_name == 'release' || github.ref_name == 'release-proxy' || github.ref_name == 'release-compute') && !failure() && !cancelled()
|
if: (github.ref_name == 'main' || github.ref_name == 'release' || github.ref_name == 'release-proxy') && !failure() && !cancelled()
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
runs-on: [ self-hosted, small ]
|
runs-on: [ self-hosted, small ]
|
||||||
container: 369495373322.dkr.ecr.eu-central-1.amazonaws.com/ansible:latest
|
container: 369495373322.dkr.ecr.eu-central-1.amazonaws.com/ansible:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Create git tag and GitHub release
|
|
||||||
if: github.ref_name == 'release' || github.ref_name == 'release-proxy' || github.ref_name == 'release-compute'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
retries: 5
|
|
||||||
script: |
|
|
||||||
const tag = "${{ needs.tag.outputs.build-tag }}";
|
|
||||||
const branch = "${{ github.ref_name }}";
|
|
||||||
|
|
||||||
try {
|
|
||||||
const existingRef = await github.rest.git.getRef({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
ref: `tags/${tag}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existingRef.data.object.sha !== context.sha) {
|
|
||||||
throw new Error(`Tag ${tag} already exists but points to a different commit (expected: ${context.sha}, actual: ${existingRef.data.object.sha}).`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Tag ${tag} already exists and points to ${context.sha} as expected.`);
|
|
||||||
} catch (error) {
|
|
||||||
if (error.status !== 404) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Tag ${tag} does not exist. Creating it...`);
|
|
||||||
await github.rest.git.createRef({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
ref: `refs/tags/${tag}`,
|
|
||||||
sha: context.sha,
|
|
||||||
});
|
|
||||||
console.log(`Tag ${tag} created successfully.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const existingRelease = await github.rest.repos.getReleaseByTag({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
tag: tag,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Release for tag ${tag} already exists (ID: ${existingRelease.data.id}).`);
|
|
||||||
} catch (error) {
|
|
||||||
if (error.status !== 404) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Release for tag ${tag} does not exist. Creating it...`);
|
|
||||||
|
|
||||||
// Find the PR number using the commit SHA
|
|
||||||
const pullRequests = await github.rest.pulls.list({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
state: 'closed',
|
|
||||||
base: branch,
|
|
||||||
});
|
|
||||||
|
|
||||||
const pr = pullRequests.data.find(pr => pr.merge_commit_sha === context.sha);
|
|
||||||
const prNumber = pr ? pr.number : null;
|
|
||||||
|
|
||||||
// Find the previous release on the branch
|
|
||||||
const releases = await github.rest.repos.listReleases({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
per_page: 100,
|
|
||||||
});
|
|
||||||
|
|
||||||
const branchReleases = releases.data
|
|
||||||
.filter((release) => {
|
|
||||||
const regex = new RegExp(`^${branch}-\\d+$`);
|
|
||||||
return regex.test(release.tag_name) && !release.draft && !release.prerelease;
|
|
||||||
})
|
|
||||||
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
|
||||||
|
|
||||||
const previousTag = branchReleases.length > 0 ? branchReleases[0].tag_name : null;
|
|
||||||
|
|
||||||
const releaseNotes = [
|
|
||||||
prNumber
|
|
||||||
? `Release PR https://github.com/${context.repo.owner}/${context.repo.repo}/pull/${prNumber}.`
|
|
||||||
: 'Release PR not found.',
|
|
||||||
previousTag
|
|
||||||
? `Diff with the previous release https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${previousTag}...${tag}.`
|
|
||||||
: `No previous release found on branch ${branch}.`,
|
|
||||||
].join('\n\n');
|
|
||||||
|
|
||||||
await github.rest.repos.createRelease({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
tag_name: tag,
|
|
||||||
body: releaseNotes,
|
|
||||||
});
|
|
||||||
console.log(`Release for tag ${tag} created successfully.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Trigger deploy workflow
|
- name: Trigger deploy workflow
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
@@ -1167,24 +1118,48 @@ jobs:
|
|||||||
-f deployPgSniRouter=true \
|
-f deployPgSniRouter=true \
|
||||||
-f deployProxyLink=true \
|
-f deployProxyLink=true \
|
||||||
-f deployPrivatelinkProxy=true \
|
-f deployPrivatelinkProxy=true \
|
||||||
|
-f deployLegacyProxyScram=true \
|
||||||
-f deployProxyScram=true \
|
-f deployProxyScram=true \
|
||||||
-f deployProxyAuthBroker=true \
|
-f deployProxyAuthBroker=true \
|
||||||
-f branch=main \
|
-f branch=main \
|
||||||
-f dockerTag=${{needs.tag.outputs.build-tag}}
|
-f dockerTag=${{needs.tag.outputs.build-tag}}
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-compute" ]]; then
|
|
||||||
gh workflow --repo neondatabase/infra run deploy-compute-dev.yml --ref main -f dockerTag=${{needs.tag.outputs.build-tag}}
|
|
||||||
else
|
else
|
||||||
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main', 'release', 'release-proxy' or 'release-compute'"
|
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Create git tag
|
||||||
|
if: github.ref_name == 'release' || github.ref_name == 'release-proxy'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
||||||
|
retries: 5
|
||||||
|
script: |
|
||||||
|
await github.rest.git.createRef({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
ref: "refs/tags/${{ needs.tag.outputs.build-tag }}",
|
||||||
|
sha: context.sha,
|
||||||
|
})
|
||||||
|
|
||||||
|
# TODO: check how GitHub releases looks for proxy releases and enable it if it's ok
|
||||||
|
- name: Create GitHub release
|
||||||
|
if: github.ref_name == 'release'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
||||||
|
retries: 5
|
||||||
|
script: |
|
||||||
|
await github.rest.repos.createRelease({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
tag_name: "${{ needs.tag.outputs.build-tag }}",
|
||||||
|
generate_release_notes: true,
|
||||||
|
})
|
||||||
|
|
||||||
# The job runs on `release` branch and copies compatibility data and Neon artifact from the last *release PR* to the latest directory
|
# The job runs on `release` branch and copies compatibility data and Neon artifact from the last *release PR* to the latest directory
|
||||||
promote-compatibility-data:
|
promote-compatibility-data:
|
||||||
needs: [ deploy ]
|
needs: [ deploy ]
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: read
|
|
||||||
# `!failure() && !cancelled()` is required because the workflow transitively depends on the job that can be skipped: `push-to-acr-dev` and `push-to-acr-prod`
|
# `!failure() && !cancelled()` is required because the workflow transitively depends on the job that can be skipped: `push-to-acr-dev` and `push-to-acr-prod`
|
||||||
if: github.ref_name == 'release' && !failure() && !cancelled()
|
if: github.ref_name == 'release' && !failure() && !cancelled()
|
||||||
|
|
||||||
@@ -1221,12 +1196,6 @@ jobs:
|
|||||||
echo "run-id=${run_id}" | tee -a ${GITHUB_OUTPUT}
|
echo "run-id=${run_id}" | tee -a ${GITHUB_OUTPUT}
|
||||||
echo "commit-sha=${last_commit_sha}" | tee -a ${GITHUB_OUTPUT}
|
echo "commit-sha=${last_commit_sha}" | tee -a ${GITHUB_OUTPUT}
|
||||||
|
|
||||||
- uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Promote compatibility snapshot and Neon artifact
|
- name: Promote compatibility snapshot and Neon artifact
|
||||||
env:
|
env:
|
||||||
BUCKET: neon-github-public-dev
|
BUCKET: neon-github-public-dev
|
||||||
@@ -1274,7 +1243,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
pin-build-tools-image:
|
pin-build-tools-image:
|
||||||
needs: [ build-build-tools-image, push-compute-image-prod, push-neon-image-prod, build-and-test-locally ]
|
needs: [ build-build-tools-image, promote-images, build-and-test-locally ]
|
||||||
if: github.ref_name == 'main'
|
if: github.ref_name == 'main'
|
||||||
uses: ./.github/workflows/pin-build-tools-image.yml
|
uses: ./.github/workflows/pin-build-tools-image.yml
|
||||||
with:
|
with:
|
||||||
@@ -1297,10 +1266,7 @@ jobs:
|
|||||||
- build-and-test-locally
|
- build-and-test-locally
|
||||||
- check-codestyle-python
|
- check-codestyle-python
|
||||||
- check-codestyle-rust
|
- check-codestyle-rust
|
||||||
- check-dependencies-rust
|
- promote-images
|
||||||
- files-changed
|
|
||||||
- push-compute-image-dev
|
|
||||||
- push-neon-image-dev
|
|
||||||
- test-images
|
- test-images
|
||||||
- trigger-custom-extensions-build-and-wait
|
- trigger-custom-extensions-build-and-wait
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
@@ -1312,12 +1278,4 @@ jobs:
|
|||||||
if: |
|
if: |
|
||||||
contains(needs.*.result, 'failure')
|
contains(needs.*.result, 'failure')
|
||||||
|| contains(needs.*.result, 'cancelled')
|
|| contains(needs.*.result, 'cancelled')
|
||||||
|| (needs.check-dependencies-rust.result == 'skipped' && needs.files-changed.outputs.check-rust-dependencies == 'true')
|
|| contains(needs.*.result, 'skipped')
|
||||||
|| needs.build-and-test-locally.result == 'skipped'
|
|
||||||
|| needs.check-codestyle-python.result == 'skipped'
|
|
||||||
|| needs.check-codestyle-rust.result == 'skipped'
|
|
||||||
|| needs.files-changed.result == 'skipped'
|
|
||||||
|| needs.push-compute-image-dev.result == 'skipped'
|
|
||||||
|| needs.push-neon-image-dev.result == 'skipped'
|
|
||||||
|| needs.test-images.result == 'skipped'
|
|
||||||
|| needs.trigger-custom-extensions-build-and-wait.result == 'skipped'
|
|
||||||
|
|||||||
134
.github/workflows/build_and_test_with_sanitizers.yml
vendored
134
.github/workflows/build_and_test_with_sanitizers.yml
vendored
@@ -1,134 +0,0 @@
|
|||||||
name: Build and Test with Sanitizers
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# * is a special character in YAML so you have to quote this string
|
|
||||||
# ┌───────────── minute (0 - 59)
|
|
||||||
# │ ┌───────────── hour (0 - 23)
|
|
||||||
# │ │ ┌───────────── day of the month (1 - 31)
|
|
||||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
|
||||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
|
||||||
- cron: '0 1 * * *' # run once a day, timezone is utc
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euxo pipefail {0}
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
# Allow only one workflow per any non-`main` branch.
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
COPT: '-Werror'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tag:
|
|
||||||
runs-on: [ self-hosted, small ]
|
|
||||||
container: 369495373322.dkr.ecr.eu-central-1.amazonaws.com/base:pinned
|
|
||||||
outputs:
|
|
||||||
build-tag: ${{steps.build-tag.outputs.tag}}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Need `fetch-depth: 0` to count the number of commits in the branch
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get build tag
|
|
||||||
run: |
|
|
||||||
echo run:$GITHUB_RUN_ID
|
|
||||||
echo ref:$GITHUB_REF_NAME
|
|
||||||
echo rev:$(git rev-list --count HEAD)
|
|
||||||
if [[ "$GITHUB_REF_NAME" == "main" ]]; then
|
|
||||||
echo "tag=$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release" ]]; then
|
|
||||||
echo "tag=release-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-proxy" ]]; then
|
|
||||||
echo "tag=release-proxy-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-compute" ]]; then
|
|
||||||
echo "tag=release-compute-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release', 'release-proxy', 'release-compute'"
|
|
||||||
echo "tag=$GITHUB_RUN_ID" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
shell: bash
|
|
||||||
id: build-tag
|
|
||||||
|
|
||||||
build-build-tools-image:
|
|
||||||
uses: ./.github/workflows/build-build-tools-image.yml
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
build-and-test-locally:
|
|
||||||
needs: [ tag, build-build-tools-image ]
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
arch: [ x64, arm64 ]
|
|
||||||
build-type: [ release ]
|
|
||||||
uses: ./.github/workflows/_build-and-test-locally.yml
|
|
||||||
with:
|
|
||||||
arch: ${{ matrix.arch }}
|
|
||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
|
||||||
build-tag: ${{ needs.tag.outputs.build-tag }}
|
|
||||||
build-type: ${{ matrix.build-type }}
|
|
||||||
test-cfg: '[{"pg_version":"v17"}]'
|
|
||||||
sanitizers: enabled
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
|
|
||||||
create-test-report:
|
|
||||||
needs: [ build-and-test-locally, build-build-tools-image ]
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
outputs:
|
|
||||||
report-url: ${{ steps.create-allure-report.outputs.report-url }}
|
|
||||||
|
|
||||||
runs-on: [ self-hosted, small ]
|
|
||||||
container:
|
|
||||||
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
|
||||||
credentials:
|
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
options: --init
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Create Allure report
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
id: create-allure-report
|
|
||||||
uses: ./.github/actions/allure-report-generate
|
|
||||||
with:
|
|
||||||
store-test-results-into-db: true
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
|
||||||
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
|
||||||
|
|
||||||
- uses: actions/github-script@v7
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
with:
|
|
||||||
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
|
||||||
retries: 5
|
|
||||||
script: |
|
|
||||||
const report = {
|
|
||||||
reportUrl: "${{ steps.create-allure-report.outputs.report-url }}",
|
|
||||||
reportJsonUrl: "${{ steps.create-allure-report.outputs.report-json-url }}",
|
|
||||||
}
|
|
||||||
|
|
||||||
const coverage = {}
|
|
||||||
|
|
||||||
const script = require("./scripts/comment-test-report.js")
|
|
||||||
await script({
|
|
||||||
github,
|
|
||||||
context,
|
|
||||||
fetch,
|
|
||||||
report,
|
|
||||||
coverage,
|
|
||||||
})
|
|
||||||
57
.github/workflows/cargo-deny.yml
vendored
57
.github/workflows/cargo-deny.yml
vendored
@@ -1,57 +0,0 @@
|
|||||||
name: cargo deny checks
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
build-tools-image:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cargo-deny:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
ref: >-
|
|
||||||
${{
|
|
||||||
fromJSON(
|
|
||||||
github.event_name == 'schedule'
|
|
||||||
&& '["main","release","release-proxy","release-compute"]'
|
|
||||||
|| format('["{0}"]', github.sha)
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
|
|
||||||
runs-on: [self-hosted, small]
|
|
||||||
|
|
||||||
container:
|
|
||||||
image: ${{ inputs.build-tools-image || 'neondatabase/build-tools:pinned' }}
|
|
||||||
credentials:
|
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
options: --init
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ matrix.ref }}
|
|
||||||
|
|
||||||
- name: Check rust licenses/bans/advisories/sources
|
|
||||||
env:
|
|
||||||
CARGO_DENY_TARGET: >-
|
|
||||||
${{ github.event_name == 'schedule' && 'advisories' || 'all' }}
|
|
||||||
run: cargo deny check --hide-inclusion-graph $CARGO_DENY_TARGET
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
|
||||||
if: ${{ github.event_name == 'schedule' && failure() }}
|
|
||||||
uses: slackapi/slack-github-action@v2
|
|
||||||
with:
|
|
||||||
method: chat.postMessage
|
|
||||||
token: ${{ secrets.SLACK_BOT_TOKEN }}
|
|
||||||
payload: |
|
|
||||||
channel: ${{ vars.SLACK_CICD_CHANNEL_ID }}
|
|
||||||
text: |
|
|
||||||
Periodic cargo-deny on ${{ matrix.ref }}: ${{ job.status }}
|
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
|
||||||
Pinging @oncall-devprod.
|
|
||||||
51
.github/workflows/check-build-tools-image.yml
vendored
Normal file
51
.github/workflows/check-build-tools-image.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: Check build-tools image
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
outputs:
|
||||||
|
image-tag:
|
||||||
|
description: "build-tools image tag"
|
||||||
|
value: ${{ jobs.check-image.outputs.tag }}
|
||||||
|
found:
|
||||||
|
description: "Whether the image is found in the registry"
|
||||||
|
value: ${{ jobs.check-image.outputs.found }}
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash -euo pipefail {0}
|
||||||
|
|
||||||
|
# No permission for GITHUB_TOKEN by default; the **minimal required** set of permissions should be granted in each job.
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-image:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
outputs:
|
||||||
|
tag: ${{ steps.get-build-tools-tag.outputs.image-tag }}
|
||||||
|
found: ${{ steps.check-image.outputs.found }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Get build-tools image tag for the current commit
|
||||||
|
id: get-build-tools-tag
|
||||||
|
env:
|
||||||
|
IMAGE_TAG: |
|
||||||
|
${{ hashFiles('build-tools.Dockerfile',
|
||||||
|
'.github/workflows/check-build-tools-image.yml',
|
||||||
|
'.github/workflows/build-build-tools-image.yml') }}
|
||||||
|
run: |
|
||||||
|
echo "image-tag=${IMAGE_TAG}" | tee -a $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Check if such tag found in the registry
|
||||||
|
id: check-image
|
||||||
|
env:
|
||||||
|
IMAGE_TAG: ${{ steps.get-build-tools-tag.outputs.image-tag }}
|
||||||
|
run: |
|
||||||
|
if docker manifest inspect neondatabase/build-tools:${IMAGE_TAG}; then
|
||||||
|
found=true
|
||||||
|
else
|
||||||
|
found=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "found=${found}" | tee -a $GITHUB_OUTPUT
|
||||||
46
.github/workflows/cloud-regress.yml
vendored
46
.github/workflows/cloud-regress.yml
vendored
@@ -19,21 +19,15 @@ concurrency:
|
|||||||
group: ${{ github.workflow }}
|
group: ${{ github.workflow }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
regress:
|
regress:
|
||||||
env:
|
env:
|
||||||
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
POSTGRES_DISTRIB_DIR: /tmp/neon/pg_install
|
||||||
|
DEFAULT_PG_VERSION: 16
|
||||||
TEST_OUTPUT: /tmp/test_output
|
TEST_OUTPUT: /tmp/test_output
|
||||||
BUILD_TYPE: remote
|
BUILD_TYPE: remote
|
||||||
strategy:
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
fail-fast: false
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
matrix:
|
|
||||||
pg-version: [16, 17]
|
|
||||||
|
|
||||||
runs-on: us-east-2
|
runs-on: us-east-2
|
||||||
container:
|
container:
|
||||||
@@ -46,11 +40,9 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Patch the test
|
- name: Patch the test
|
||||||
env:
|
|
||||||
PG_VERSION: ${{matrix.pg-version}}
|
|
||||||
run: |
|
run: |
|
||||||
cd "vendor/postgres-v${PG_VERSION}"
|
cd "vendor/postgres-v${DEFAULT_PG_VERSION}"
|
||||||
patch -p1 < "../../compute/patches/cloud_regress_pg${PG_VERSION}.patch"
|
patch -p1 < "../../compute/patches/cloud_regress_pg${DEFAULT_PG_VERSION}.patch"
|
||||||
|
|
||||||
- name: Generate a random password
|
- name: Generate a random password
|
||||||
id: pwgen
|
id: pwgen
|
||||||
@@ -63,9 +55,8 @@ jobs:
|
|||||||
- name: Change tests according to the generated password
|
- name: Change tests according to the generated password
|
||||||
env:
|
env:
|
||||||
DBPASS: ${{ steps.pwgen.outputs.DBPASS }}
|
DBPASS: ${{ steps.pwgen.outputs.DBPASS }}
|
||||||
PG_VERSION: ${{matrix.pg-version}}
|
|
||||||
run: |
|
run: |
|
||||||
cd vendor/postgres-v"${PG_VERSION}"/src/test/regress
|
cd vendor/postgres-v"${DEFAULT_PG_VERSION}"/src/test/regress
|
||||||
for fname in sql/*.sql expected/*.out; do
|
for fname in sql/*.sql expected/*.out; do
|
||||||
sed -i.bak s/NEON_PASSWORD_PLACEHOLDER/"'${DBPASS}'"/ "${fname}"
|
sed -i.bak s/NEON_PASSWORD_PLACEHOLDER/"'${DBPASS}'"/ "${fname}"
|
||||||
done
|
done
|
||||||
@@ -81,46 +72,27 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Create a new branch
|
|
||||||
id: create-branch
|
|
||||||
uses: ./.github/actions/neon-branch-create
|
|
||||||
with:
|
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
|
||||||
project_id: ${{ vars[format('PGREGRESS_PG{0}_PROJECT_ID', matrix.pg-version)] }}
|
|
||||||
|
|
||||||
- name: Run the regression tests
|
- name: Run the regression tests
|
||||||
uses: ./.github/actions/run-python-test-set
|
uses: ./.github/actions/run-python-test-set
|
||||||
with:
|
with:
|
||||||
build_type: ${{ env.BUILD_TYPE }}
|
build_type: ${{ env.BUILD_TYPE }}
|
||||||
test_selection: cloud_regress
|
test_selection: cloud_regress
|
||||||
pg_version: ${{matrix.pg-version}}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
extra_params: -m remote_cluster
|
extra_params: -m remote_cluster
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{steps.create-branch.outputs.dsn}}
|
BENCHMARK_CONNSTR: ${{ secrets.PG_REGRESS_CONNSTR }}
|
||||||
|
|
||||||
- name: Delete branch
|
|
||||||
if: always()
|
|
||||||
uses: ./.github/actions/neon-branch-delete
|
|
||||||
with:
|
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
|
||||||
project_id: ${{ vars[format('PGREGRESS_PG{0}_PROJECT_ID', matrix.pg-version)] }}
|
|
||||||
branch_id: ${{steps.create-branch.outputs.branch_id}}
|
|
||||||
|
|
||||||
- name: Create Allure report
|
- name: Create Allure report
|
||||||
id: create-allure-report
|
id: create-allure-report
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: ${{ vars.SLACK_ON_CALL_QA_STAGING_STREAM }}
|
channel-id: "C033QLM5P7D" # on-call-staging-stream
|
||||||
slack-message: |
|
slack-message: |
|
||||||
Periodic pg_regress on staging: ${{ job.status }}
|
Periodic pg_regress on staging: ${{ job.status }}
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
name: Force Test Upgrading of Extension
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# * is a special character in YAML so you have to quote this string
|
|
||||||
# ┌───────────── minute (0 - 59)
|
|
||||||
# │ ┌───────────── hour (0 - 23)
|
|
||||||
# │ │ ┌───────────── day of the month (1 - 31)
|
|
||||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
|
||||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
|
||||||
- cron: '45 2 * * *' # run once a day, timezone is utc
|
|
||||||
workflow_dispatch: # adds ability to run this manually
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euxo pipefail {0}
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
# Allow only one workflow
|
|
||||||
group: ${{ github.workflow }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
regress:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
pg-version: [16, 17]
|
|
||||||
|
|
||||||
runs-on: small
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: false
|
|
||||||
|
|
||||||
- name: Get the last compute release tag
|
|
||||||
id: get-last-compute-release-tag
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
tag=$(gh api -q '[.[].tag_name | select(startswith("release-compute"))][0]'\
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
||||||
"/repos/${GITHUB_REPOSITORY}/releases")
|
|
||||||
echo tag=${tag} >> ${GITHUB_OUTPUT}
|
|
||||||
|
|
||||||
- name: Test extension upgrade
|
|
||||||
timeout-minutes: 20
|
|
||||||
env:
|
|
||||||
NEWTAG: latest
|
|
||||||
OLDTAG: ${{ steps.get-last-compute-release-tag.outputs.tag }}
|
|
||||||
PG_VERSION: ${{ matrix.pg-version }}
|
|
||||||
FORCE_ALL_UPGRADE_TESTS: true
|
|
||||||
run: ./docker-compose/test_extensions_upgrade.sh
|
|
||||||
|
|
||||||
- name: Print logs and clean up
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
docker compose --profile test-extensions -f ./docker-compose/docker-compose.yml logs || true
|
|
||||||
docker compose --profile test-extensions -f ./docker-compose/docker-compose.yml down
|
|
||||||
|
|
||||||
- name: Post to the Slack channel
|
|
||||||
if: ${{ github.event.schedule && failure() }}
|
|
||||||
uses: slackapi/slack-github-action@v1
|
|
||||||
with:
|
|
||||||
channel-id: ${{ vars.SLACK_ON_CALL_QA_STAGING_STREAM }}
|
|
||||||
slack-message: |
|
|
||||||
Test upgrading of extensions: ${{ job.status }}
|
|
||||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub Run>
|
|
||||||
env:
|
|
||||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
|
||||||
182
.github/workflows/ingest_benchmark.yml
vendored
182
.github/workflows/ingest_benchmark.yml
vendored
@@ -1,182 +0,0 @@
|
|||||||
name: benchmarking ingest
|
|
||||||
|
|
||||||
on:
|
|
||||||
# uncomment to run on push for debugging your PR
|
|
||||||
# push:
|
|
||||||
# branches: [ your branch ]
|
|
||||||
schedule:
|
|
||||||
# * is a special character in YAML so you have to quote this string
|
|
||||||
# ┌───────────── minute (0 - 59)
|
|
||||||
# │ ┌───────────── hour (0 - 23)
|
|
||||||
# │ │ ┌───────────── day of the month (1 - 31)
|
|
||||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
|
||||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
|
||||||
- cron: '0 9 * * *' # run once a day, timezone is utc
|
|
||||||
workflow_dispatch: # adds ability to run this manually
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euxo pipefail {0}
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
# Allow only one workflow globally because we need dedicated resources which only exist once
|
|
||||||
group: ingest-bench-workflow
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ingest:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false # allow other variants to continue even if one fails
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- target_project: new_empty_project_stripe_size_2048
|
|
||||||
stripe_size: 2048 # 16 MiB
|
|
||||||
postgres_version: 16
|
|
||||||
- target_project: new_empty_project_stripe_size_32768
|
|
||||||
stripe_size: 32768 # 256 MiB # note that this is different from null because using null will shard_split the project only if it reaches the threshold
|
|
||||||
# while here it is sharded from the beginning with a shard size of 256 MiB
|
|
||||||
postgres_version: 16
|
|
||||||
- target_project: new_empty_project
|
|
||||||
stripe_size: null # run with neon defaults which will shard split only when reaching the threshold
|
|
||||||
postgres_version: 16
|
|
||||||
- target_project: new_empty_project
|
|
||||||
stripe_size: null # run with neon defaults which will shard split only when reaching the threshold
|
|
||||||
postgres_version: 17
|
|
||||||
- target_project: large_existing_project
|
|
||||||
stripe_size: null # cannot re-shared or choose different stripe size for existing, already sharded project
|
|
||||||
postgres_version: 16
|
|
||||||
max-parallel: 1 # we want to run each stripe size sequentially to be able to compare the results
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
statuses: write
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
env:
|
|
||||||
PG_CONFIG: /tmp/neon/pg_install/v16/bin/pg_config
|
|
||||||
PSQL: /tmp/neon/pg_install/v16/bin/psql
|
|
||||||
PG_16_LIB_PATH: /tmp/neon/pg_install/v16/lib
|
|
||||||
PGCOPYDB: /pgcopydb/bin/pgcopydb
|
|
||||||
PGCOPYDB_LIB_PATH: /pgcopydb/lib
|
|
||||||
runs-on: [ self-hosted, us-east-2, x64 ]
|
|
||||||
container:
|
|
||||||
image: neondatabase/build-tools:pinned-bookworm
|
|
||||||
credentials:
|
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
|
||||||
options: --init
|
|
||||||
timeout-minutes: 1440
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Configure AWS credentials # necessary to download artefacts
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
role-duration-seconds: 18000 # 5 hours is currently max associated with IAM role
|
|
||||||
|
|
||||||
- name: Download Neon artifact
|
|
||||||
uses: ./.github/actions/download
|
|
||||||
with:
|
|
||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
|
||||||
path: /tmp/neon/
|
|
||||||
prefix: latest
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Create Neon Project
|
|
||||||
if: ${{ startsWith(matrix.target_project, 'new_empty_project') }}
|
|
||||||
id: create-neon-project-ingest-target
|
|
||||||
uses: ./.github/actions/neon-project-create
|
|
||||||
with:
|
|
||||||
region_id: aws-us-east-2
|
|
||||||
postgres_version: ${{ matrix.postgres_version }}
|
|
||||||
compute_units: '[7, 7]' # we want to test large compute here to avoid compute-side bottleneck
|
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
|
||||||
shard_split_project: ${{ matrix.stripe_size != null && 'true' || 'false' }}
|
|
||||||
admin_api_key: ${{ secrets.NEON_STAGING_ADMIN_API_KEY }}
|
|
||||||
shard_count: 8
|
|
||||||
stripe_size: ${{ matrix.stripe_size }}
|
|
||||||
|
|
||||||
- name: Initialize Neon project
|
|
||||||
if: ${{ startsWith(matrix.target_project, 'new_empty_project') }}
|
|
||||||
env:
|
|
||||||
BENCHMARK_INGEST_TARGET_CONNSTR: ${{ steps.create-neon-project-ingest-target.outputs.dsn }}
|
|
||||||
NEW_PROJECT_ID: ${{ steps.create-neon-project-ingest-target.outputs.project_id }}
|
|
||||||
run: |
|
|
||||||
echo "Initializing Neon project with project_id: ${NEW_PROJECT_ID}"
|
|
||||||
export LD_LIBRARY_PATH=${PG_16_LIB_PATH}
|
|
||||||
${PSQL} "${BENCHMARK_INGEST_TARGET_CONNSTR}" -c "CREATE EXTENSION IF NOT EXISTS neon; CREATE EXTENSION IF NOT EXISTS neon_utils;"
|
|
||||||
echo "BENCHMARK_INGEST_TARGET_CONNSTR=${BENCHMARK_INGEST_TARGET_CONNSTR}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Create Neon Branch for large tenant
|
|
||||||
if: ${{ matrix.target_project == 'large_existing_project' }}
|
|
||||||
id: create-neon-branch-ingest-target
|
|
||||||
uses: ./.github/actions/neon-branch-create
|
|
||||||
with:
|
|
||||||
project_id: ${{ vars.BENCHMARK_INGEST_TARGET_PROJECTID }}
|
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
|
||||||
|
|
||||||
- name: Initialize Neon project
|
|
||||||
if: ${{ matrix.target_project == 'large_existing_project' }}
|
|
||||||
env:
|
|
||||||
BENCHMARK_INGEST_TARGET_CONNSTR: ${{ steps.create-neon-branch-ingest-target.outputs.dsn }}
|
|
||||||
NEW_BRANCH_ID: ${{ steps.create-neon-branch-ingest-target.outputs.branch_id }}
|
|
||||||
run: |
|
|
||||||
echo "Initializing Neon branch with branch_id: ${NEW_BRANCH_ID}"
|
|
||||||
export LD_LIBRARY_PATH=${PG_16_LIB_PATH}
|
|
||||||
# Extract the part before the database name
|
|
||||||
base_connstr="${BENCHMARK_INGEST_TARGET_CONNSTR%/*}"
|
|
||||||
# Extract the query parameters (if any) after the database name
|
|
||||||
query_params="${BENCHMARK_INGEST_TARGET_CONNSTR#*\?}"
|
|
||||||
# Reconstruct the new connection string
|
|
||||||
if [ "$query_params" != "$BENCHMARK_INGEST_TARGET_CONNSTR" ]; then
|
|
||||||
new_connstr="${base_connstr}/neondb?${query_params}"
|
|
||||||
else
|
|
||||||
new_connstr="${base_connstr}/neondb"
|
|
||||||
fi
|
|
||||||
${PSQL} "${new_connstr}" -c "drop database ludicrous;"
|
|
||||||
${PSQL} "${new_connstr}" -c "CREATE DATABASE ludicrous;"
|
|
||||||
if [ "$query_params" != "$BENCHMARK_INGEST_TARGET_CONNSTR" ]; then
|
|
||||||
BENCHMARK_INGEST_TARGET_CONNSTR="${base_connstr}/ludicrous?${query_params}"
|
|
||||||
else
|
|
||||||
BENCHMARK_INGEST_TARGET_CONNSTR="${base_connstr}/ludicrous"
|
|
||||||
fi
|
|
||||||
${PSQL} "${BENCHMARK_INGEST_TARGET_CONNSTR}" -c "CREATE EXTENSION IF NOT EXISTS neon; CREATE EXTENSION IF NOT EXISTS neon_utils;"
|
|
||||||
echo "BENCHMARK_INGEST_TARGET_CONNSTR=${BENCHMARK_INGEST_TARGET_CONNSTR}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Invoke pgcopydb
|
|
||||||
uses: ./.github/actions/run-python-test-set
|
|
||||||
with:
|
|
||||||
build_type: remote
|
|
||||||
test_selection: performance/test_perf_ingest_using_pgcopydb.py
|
|
||||||
run_in_parallel: false
|
|
||||||
extra_params: -s -m remote_cluster --timeout 86400 -k test_ingest_performance_using_pgcopydb
|
|
||||||
pg_version: v${{ matrix.postgres_version }}
|
|
||||||
save_perf_report: true
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
|
||||||
BENCHMARK_INGEST_SOURCE_CONNSTR: ${{ secrets.BENCHMARK_INGEST_SOURCE_CONNSTR }}
|
|
||||||
TARGET_PROJECT_TYPE: ${{ matrix.target_project }}
|
|
||||||
# we report PLATFORM in zenbenchmark NeonBenchmarker perf database and want to distinguish between new project and large tenant
|
|
||||||
PLATFORM: "${{ matrix.target_project }}-us-east-2-staging"
|
|
||||||
PERF_TEST_RESULT_CONNSTR: "${{ secrets.PERF_TEST_RESULT_CONNSTR }}"
|
|
||||||
|
|
||||||
- name: show tables sizes after ingest
|
|
||||||
run: |
|
|
||||||
export LD_LIBRARY_PATH=${PG_16_LIB_PATH}
|
|
||||||
${PSQL} "${BENCHMARK_INGEST_TARGET_CONNSTR}" -c "\dt+"
|
|
||||||
|
|
||||||
- name: Delete Neon Project
|
|
||||||
if: ${{ always() && startsWith(matrix.target_project, 'new_empty_project') }}
|
|
||||||
uses: ./.github/actions/neon-project-delete
|
|
||||||
with:
|
|
||||||
project_id: ${{ steps.create-neon-project-ingest-target.outputs.project_id }}
|
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
|
||||||
|
|
||||||
- name: Delete Neon Branch for large tenant
|
|
||||||
if: ${{ always() && matrix.target_project == 'large_existing_project' }}
|
|
||||||
uses: ./.github/actions/neon-branch-delete
|
|
||||||
with:
|
|
||||||
project_id: ${{ vars.BENCHMARK_INGEST_TARGET_PROJECTID }}
|
|
||||||
branch_id: ${{ steps.create-neon-branch-ingest-target.outputs.branch_id }}
|
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
|
||||||
164
.github/workflows/neon_extra_builds.yml
vendored
164
.github/workflows/neon_extra_builds.yml
vendored
@@ -26,20 +26,30 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
github-event-name: ${{ github.event_name}}
|
github-event-name: ${{ github.event_name}}
|
||||||
|
|
||||||
build-build-tools-image:
|
check-build-tools-image:
|
||||||
needs: [ check-permissions ]
|
needs: [ check-permissions ]
|
||||||
|
uses: ./.github/workflows/check-build-tools-image.yml
|
||||||
|
|
||||||
|
build-build-tools-image:
|
||||||
|
needs: [ check-build-tools-image ]
|
||||||
uses: ./.github/workflows/build-build-tools-image.yml
|
uses: ./.github/workflows/build-build-tools-image.yml
|
||||||
|
with:
|
||||||
|
image-tag: ${{ needs.check-build-tools-image.outputs.image-tag }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
files-changed:
|
check-macos-build:
|
||||||
name: Detect what files changed
|
needs: [ check-permissions ]
|
||||||
runs-on: ubuntu-22.04
|
if: |
|
||||||
timeout-minutes: 3
|
contains(github.event.pull_request.labels.*.name, 'run-extra-build-macos') ||
|
||||||
outputs:
|
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
||||||
v17: ${{ steps.files_changed.outputs.v17 }}
|
github.ref_name == 'main'
|
||||||
postgres_changes: ${{ steps.postgres_changes.outputs.changes }}
|
timeout-minutes: 90
|
||||||
rebuild_rust_code: ${{ steps.files_changed.outputs.rust_code }}
|
runs-on: macos-14
|
||||||
rebuild_everything: ${{ steps.files_changed.outputs.rebuild_neon_extra || steps.files_changed.outputs.rebuild_macos }}
|
|
||||||
|
env:
|
||||||
|
# Use release build only, to have less debug info around
|
||||||
|
# Hence keeping target/ (and general cache size) smaller
|
||||||
|
BUILD_TYPE: release
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -47,45 +57,102 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Check for Postgres changes
|
- name: Install macOS postgres dependencies
|
||||||
uses: dorny/paths-filter@1441771bbfdd59dcd748680ee64ebd8faab1a242 #v3
|
run: brew install flex bison openssl protobuf icu4c pkg-config
|
||||||
id: files_changed
|
|
||||||
|
- name: Set pg 14 revision for caching
|
||||||
|
id: pg_v14_rev
|
||||||
|
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v14) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set pg 15 revision for caching
|
||||||
|
id: pg_v15_rev
|
||||||
|
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v15) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set pg 16 revision for caching
|
||||||
|
id: pg_v16_rev
|
||||||
|
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v16) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set pg 17 revision for caching
|
||||||
|
id: pg_v17_rev
|
||||||
|
run: echo pg_rev=$(git rev-parse HEAD:vendor/postgres-v17) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Cache postgres v14 build
|
||||||
|
id: cache_pg_14
|
||||||
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ github.token }}
|
path: pg_install/v14
|
||||||
filters: .github/file-filters.yaml
|
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-${{ steps.pg_v14_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
||||||
base: ${{ github.event_name != 'pull_request' && (github.event.merge_group.base_ref || github.ref_name) || '' }}
|
|
||||||
ref: ${{ github.event_name != 'pull_request' && (github.event.merge_group.head_ref || github.ref) || '' }}
|
|
||||||
|
|
||||||
- name: Filter out only v-string for build matrix
|
- name: Cache postgres v15 build
|
||||||
id: postgres_changes
|
id: cache_pg_15
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: pg_install/v15
|
||||||
|
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-${{ steps.pg_v15_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
||||||
|
|
||||||
|
- name: Cache postgres v16 build
|
||||||
|
id: cache_pg_16
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: pg_install/v16
|
||||||
|
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-${{ steps.pg_v16_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
||||||
|
|
||||||
|
- name: Cache postgres v17 build
|
||||||
|
id: cache_pg_17
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: pg_install/v17
|
||||||
|
key: v1-${{ runner.os }}-${{ runner.arch }}-${{ env.BUILD_TYPE }}-pg-${{ steps.pg_v17_rev.outputs.pg_rev }}-${{ hashFiles('Makefile') }}
|
||||||
|
|
||||||
|
- name: Set extra env for macOS
|
||||||
run: |
|
run: |
|
||||||
v_strings_only_as_json_array=$(echo ${{ steps.files_changed.outputs.chnages }} | jq '.[]|select(test("v\\d+"))' | jq --slurp -c)
|
echo 'LDFLAGS=-L/usr/local/opt/openssl@3/lib' >> $GITHUB_ENV
|
||||||
echo "changes=${v_strings_only_as_json_array}" | tee -a "${GITHUB_OUTPUT}"
|
echo 'CPPFLAGS=-I/usr/local/opt/openssl@3/include' >> $GITHUB_ENV
|
||||||
|
|
||||||
check-macos-build:
|
- name: Cache cargo deps
|
||||||
needs: [ check-permissions, files-changed ]
|
uses: actions/cache@v4
|
||||||
if: |
|
with:
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-macos') ||
|
path: |
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
~/.cargo/registry
|
||||||
github.ref_name == 'main'
|
!~/.cargo/registry/src
|
||||||
uses: ./.github/workflows/build-macos.yml
|
~/.cargo/git
|
||||||
with:
|
target
|
||||||
pg_versions: ${{ needs.files-changed.outputs.postgres_changes }}
|
key: v1-${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('./Cargo.lock') }}-${{ hashFiles('./rust-toolchain.toml') }}-rust
|
||||||
rebuild_rust_code: ${{ needs.files-changed.outputs.rebuild_rust_code }}
|
|
||||||
rebuild_everything: ${{ fromJson(needs.files-changed.outputs.rebuild_everything) }}
|
- name: Build postgres v14
|
||||||
|
if: steps.cache_pg_14.outputs.cache-hit != 'true'
|
||||||
|
run: make postgres-v14 -j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
- name: Build postgres v15
|
||||||
|
if: steps.cache_pg_15.outputs.cache-hit != 'true'
|
||||||
|
run: make postgres-v15 -j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
- name: Build postgres v16
|
||||||
|
if: steps.cache_pg_16.outputs.cache-hit != 'true'
|
||||||
|
run: make postgres-v16 -j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
- name: Build postgres v17
|
||||||
|
if: steps.cache_pg_17.outputs.cache-hit != 'true'
|
||||||
|
run: make postgres-v17 -j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
- name: Build neon extensions
|
||||||
|
run: make neon-pg-ext -j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
- name: Build walproposer-lib
|
||||||
|
run: make walproposer-lib -j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
- name: Run cargo build
|
||||||
|
run: PQ_LIB_DIR=$(pwd)/pg_install/v16/lib cargo build --all --release
|
||||||
|
|
||||||
|
- name: Check that no warnings are produced
|
||||||
|
run: ./run_clippy.sh
|
||||||
|
|
||||||
gather-rust-build-stats:
|
gather-rust-build-stats:
|
||||||
needs: [ check-permissions, build-build-tools-image, files-changed ]
|
needs: [ check-permissions, build-build-tools-image ]
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
if: |
|
if: |
|
||||||
(needs.files-changed.outputs.v17 == 'true' || needs.files-changed.outputs.rebuild_everything == 'true') && (
|
contains(github.event.pull_request.labels.*.name, 'run-extra-build-stats') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-stats') ||
|
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'run-extra-build-*') ||
|
github.ref_name == 'main'
|
||||||
github.ref_name == 'main'
|
|
||||||
)
|
|
||||||
runs-on: [ self-hosted, large ]
|
runs-on: [ self-hosted, large ]
|
||||||
container:
|
container:
|
||||||
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm
|
||||||
@@ -114,20 +181,15 @@ jobs:
|
|||||||
run: make walproposer-lib -j$(nproc)
|
run: make walproposer-lib -j$(nproc)
|
||||||
|
|
||||||
- name: Produce the build stats
|
- name: Produce the build stats
|
||||||
run: cargo build --all --release --timings -j$(nproc)
|
run: PQ_LIB_DIR=$(pwd)/pg_install/v17/lib cargo build --all --release --timings -j$(nproc)
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Upload the build stats
|
- name: Upload the build stats
|
||||||
id: upload-stats
|
id: upload-stats
|
||||||
env:
|
env:
|
||||||
BUCKET: neon-github-public-dev
|
BUCKET: neon-github-public-dev
|
||||||
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
run: |
|
run: |
|
||||||
REPORT_URL=https://${BUCKET}.s3.amazonaws.com/build-stats/${SHA}/${GITHUB_RUN_ID}/cargo-timing.html
|
REPORT_URL=https://${BUCKET}.s3.amazonaws.com/build-stats/${SHA}/${GITHUB_RUN_ID}/cargo-timing.html
|
||||||
aws s3 cp --only-show-errors ./target/cargo-timings/cargo-timing.html "s3://${BUCKET}/build-stats/${SHA}/${GITHUB_RUN_ID}/"
|
aws s3 cp --only-show-errors ./target/cargo-timings/cargo-timing.html "s3://${BUCKET}/build-stats/${SHA}/${GITHUB_RUN_ID}/"
|
||||||
@@ -139,8 +201,6 @@ jobs:
|
|||||||
REPORT_URL: ${{ steps.upload-stats.outputs.report-url }}
|
REPORT_URL: ${{ steps.upload-stats.outputs.report-url }}
|
||||||
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
with:
|
with:
|
||||||
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
|
||||||
retries: 5
|
|
||||||
script: |
|
script: |
|
||||||
const { REPORT_URL, SHA } = process.env
|
const { REPORT_URL, SHA } = process.env
|
||||||
|
|
||||||
|
|||||||
37
.github/workflows/periodic_pagebench.yml
vendored
37
.github/workflows/periodic_pagebench.yml
vendored
@@ -27,14 +27,9 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
trigger_bench_on_ec2_machine_in_eu_central_1:
|
trigger_bench_on_ec2_machine_in_eu_central_1:
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: [ self-hosted, small ]
|
runs-on: [ self-hosted, small ]
|
||||||
container:
|
container:
|
||||||
image: neondatabase/build-tools:pinned-bookworm
|
image: neondatabase/build-tools:pinned
|
||||||
credentials:
|
credentials:
|
||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
@@ -43,6 +38,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
API_KEY: ${{ secrets.PERIODIC_PAGEBENCH_EC2_RUNNER_API_KEY }}
|
API_KEY: ${{ secrets.PERIODIC_PAGEBENCH_EC2_RUNNER_API_KEY }}
|
||||||
RUN_ID: ${{ github.run_id }}
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_EC2_US_TEST_RUNNER_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY : ${{ secrets.AWS_EC2_US_TEST_RUNNER_ACCESS_KEY_SECRET }}
|
||||||
AWS_DEFAULT_REGION : "eu-central-1"
|
AWS_DEFAULT_REGION : "eu-central-1"
|
||||||
AWS_INSTANCE_ID : "i-02a59a3bf86bc7e74"
|
AWS_INSTANCE_ID : "i-02a59a3bf86bc7e74"
|
||||||
steps:
|
steps:
|
||||||
@@ -53,13 +50,6 @@ jobs:
|
|||||||
- name: Show my own (github runner) external IP address - usefull for IP allowlisting
|
- name: Show my own (github runner) external IP address - usefull for IP allowlisting
|
||||||
run: curl https://ifconfig.me
|
run: curl https://ifconfig.me
|
||||||
|
|
||||||
- name: Assume AWS OIDC role that allows to manage (start/stop/describe... EC machine)
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_MANAGE_BENCHMARK_EC2_VMS_ARN }}
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Start EC2 instance and wait for the instance to boot up
|
- name: Start EC2 instance and wait for the instance to boot up
|
||||||
run: |
|
run: |
|
||||||
aws ec2 start-instances --instance-ids $AWS_INSTANCE_ID
|
aws ec2 start-instances --instance-ids $AWS_INSTANCE_ID
|
||||||
@@ -82,7 +72,7 @@ jobs:
|
|||||||
echo "COMMIT_HASH=$INPUT_COMMIT_HASH" >> $GITHUB_ENV
|
echo "COMMIT_HASH=$INPUT_COMMIT_HASH" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Start Bench with run_id
|
- name: Start Bench with run_id
|
||||||
run: |
|
run: |
|
||||||
curl -k -X 'POST' \
|
curl -k -X 'POST' \
|
||||||
"${EC2_MACHINE_URL_US}/start_test/${GITHUB_RUN_ID}" \
|
"${EC2_MACHINE_URL_US}/start_test/${GITHUB_RUN_ID}" \
|
||||||
@@ -126,7 +116,7 @@ jobs:
|
|||||||
-H 'accept: application/gzip' \
|
-H 'accept: application/gzip' \
|
||||||
-H "Authorization: Bearer $API_KEY" \
|
-H "Authorization: Bearer $API_KEY" \
|
||||||
--output "test_log_${GITHUB_RUN_ID}.gz"
|
--output "test_log_${GITHUB_RUN_ID}.gz"
|
||||||
|
|
||||||
- name: Unzip Test Log and Print it into this job's log
|
- name: Unzip Test Log and Print it into this job's log
|
||||||
if: always() && steps.poll_step.outputs.too_many_runs != 'true'
|
if: always() && steps.poll_step.outputs.too_many_runs != 'true'
|
||||||
run: |
|
run: |
|
||||||
@@ -134,22 +124,23 @@ jobs:
|
|||||||
cat "test_log_${GITHUB_RUN_ID}"
|
cat "test_log_${GITHUB_RUN_ID}"
|
||||||
|
|
||||||
- name: Create Allure report
|
- name: Create Allure report
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Post to a Slack channel
|
- name: Post to a Slack channel
|
||||||
if: ${{ github.event.schedule && failure() }}
|
if: ${{ github.event.schedule && failure() }}
|
||||||
uses: slackapi/slack-github-action@v1
|
uses: slackapi/slack-github-action@v1
|
||||||
with:
|
with:
|
||||||
channel-id: "C06KHQVQ7U3" # on-call-qa-staging-stream
|
channel-id: "C033QLM5P7D" # dev-staging-stream
|
||||||
slack-message: "Periodic pagebench testing on dedicated hardware: ${{ job.status }}\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
slack-message: "Periodic pagebench testing on dedicated hardware: ${{ job.status }}\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
env:
|
env:
|
||||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||||
|
|
||||||
- name: Cleanup Test Resources
|
- name: Cleanup Test Resources
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
curl -k -X 'POST' \
|
curl -k -X 'POST' \
|
||||||
"${EC2_MACHINE_URL_US}/cleanup_test/${GITHUB_RUN_ID}" \
|
"${EC2_MACHINE_URL_US}/cleanup_test/${GITHUB_RUN_ID}" \
|
||||||
@@ -157,14 +148,6 @@ jobs:
|
|||||||
-H "Authorization: Bearer $API_KEY" \
|
-H "Authorization: Bearer $API_KEY" \
|
||||||
-d ''
|
-d ''
|
||||||
|
|
||||||
- name: Assume AWS OIDC role that allows to manage (start/stop/describe... EC machine)
|
|
||||||
if: always() && steps.poll_step.outputs.too_many_runs != 'true'
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: eu-central-1
|
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_MANAGE_BENCHMARK_EC2_VMS_ARN }}
|
|
||||||
role-duration-seconds: 3600
|
|
||||||
|
|
||||||
- name: Stop EC2 instance and wait for the instance to be stopped
|
- name: Stop EC2 instance and wait for the instance to be stopped
|
||||||
if: always() && steps.poll_step.outputs.too_many_runs != 'true'
|
if: always() && steps.poll_step.outputs.too_many_runs != 'true'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
26
.github/workflows/pg-clients.yml
vendored
26
.github/workflows/pg-clients.yml
vendored
@@ -12,8 +12,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- '.github/workflows/pg-clients.yml'
|
- '.github/workflows/pg-clients.yml'
|
||||||
- 'test_runner/pg_clients/**/*.py'
|
- 'test_runner/pg_clients/**'
|
||||||
- 'test_runner/logical_repl/**/*.py'
|
- 'test_runner/logical_repl/**'
|
||||||
- 'poetry.lock'
|
- 'poetry.lock'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
@@ -25,13 +25,11 @@ defaults:
|
|||||||
run:
|
run:
|
||||||
shell: bash -euxo pipefail {0}
|
shell: bash -euxo pipefail {0}
|
||||||
|
|
||||||
permissions:
|
|
||||||
id-token: write # aws-actions/configure-aws-credentials
|
|
||||||
statuses: write # require for posting a status update
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEFAULT_PG_VERSION: 16
|
DEFAULT_PG_VERSION: 16
|
||||||
PLATFORM: neon-captest-new
|
PLATFORM: neon-captest-new
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
AWS_DEFAULT_REGION: eu-central-1
|
AWS_DEFAULT_REGION: eu-central-1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -41,9 +39,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
github-event-name: ${{ github.event_name }}
|
github-event-name: ${{ github.event_name }}
|
||||||
|
|
||||||
build-build-tools-image:
|
check-build-tools-image:
|
||||||
needs: [ check-permissions ]
|
needs: [ check-permissions ]
|
||||||
|
uses: ./.github/workflows/check-build-tools-image.yml
|
||||||
|
|
||||||
|
build-build-tools-image:
|
||||||
|
needs: [ check-build-tools-image ]
|
||||||
uses: ./.github/workflows/build-build-tools-image.yml
|
uses: ./.github/workflows/build-build-tools-image.yml
|
||||||
|
with:
|
||||||
|
image-tag: ${{ needs.check-build-tools-image.outputs.image-tag }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
test-logical-replication:
|
test-logical-replication:
|
||||||
@@ -96,7 +100,6 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Create Neon Project
|
- name: Create Neon Project
|
||||||
id: create-neon-project
|
id: create-neon-project
|
||||||
@@ -104,8 +107,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
api_key: ${{ secrets.NEON_STAGING_API_KEY }}
|
||||||
postgres_version: ${{ env.DEFAULT_PG_VERSION }}
|
postgres_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
project_settings: >-
|
|
||||||
{"enable_logical_replication": true}
|
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
uses: ./.github/actions/run-python-test-set
|
uses: ./.github/actions/run-python-test-set
|
||||||
@@ -115,7 +116,6 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
extra_params: -m remote_cluster
|
extra_params: -m remote_cluster
|
||||||
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.create-neon-project.outputs.dsn }}
|
BENCHMARK_CONNSTR: ${{ steps.create-neon-project.outputs.dsn }}
|
||||||
|
|
||||||
@@ -132,7 +132,6 @@ jobs:
|
|||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
with:
|
||||||
store-test-results-into-db: true
|
store-test-results-into-db: true
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
||||||
|
|
||||||
@@ -166,7 +165,6 @@ jobs:
|
|||||||
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
name: neon-${{ runner.os }}-${{ runner.arch }}-release-artifact
|
||||||
path: /tmp/neon/
|
path: /tmp/neon/
|
||||||
prefix: latest
|
prefix: latest
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
|
|
||||||
- name: Create Neon Project
|
- name: Create Neon Project
|
||||||
id: create-neon-project
|
id: create-neon-project
|
||||||
@@ -183,7 +181,6 @@ jobs:
|
|||||||
run_in_parallel: false
|
run_in_parallel: false
|
||||||
extra_params: -m remote_cluster
|
extra_params: -m remote_cluster
|
||||||
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
pg_version: ${{ env.DEFAULT_PG_VERSION }}
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
BENCHMARK_CONNSTR: ${{ steps.create-neon-project.outputs.dsn }}
|
BENCHMARK_CONNSTR: ${{ steps.create-neon-project.outputs.dsn }}
|
||||||
|
|
||||||
@@ -200,7 +197,6 @@ jobs:
|
|||||||
uses: ./.github/actions/allure-report-generate
|
uses: ./.github/actions/allure-report-generate
|
||||||
with:
|
with:
|
||||||
store-test-results-into-db: true
|
store-test-results-into-db: true
|
||||||
aws-oicd-role-arn: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
|
||||||
env:
|
env:
|
||||||
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
REGRESS_TEST_RESULT_CONNSTR_NEW: ${{ secrets.REGRESS_TEST_RESULT_CONNSTR_NEW }}
|
||||||
|
|
||||||
|
|||||||
16
.github/workflows/pin-build-tools-image.yml
vendored
16
.github/workflows/pin-build-tools-image.yml
vendored
@@ -67,7 +67,7 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write # for `azure/login` and aws auth
|
id-token: write # for `azure/login`
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: docker/login-action@v3
|
- uses: docker/login-action@v3
|
||||||
@@ -75,15 +75,11 @@ jobs:
|
|||||||
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
username: ${{ secrets.NEON_DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
- uses: docker/login-action@v3
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
with:
|
||||||
aws-region: eu-central-1
|
registry: 369495373322.dkr.ecr.eu-central-1.amazonaws.com
|
||||||
role-to-assume: ${{ vars.DEV_AWS_OIDC_ROLE_ARN }}
|
username: ${{ secrets.AWS_ACCESS_KEY_DEV }}
|
||||||
role-duration-seconds: 3600
|
password: ${{ secrets.AWS_SECRET_KEY_DEV }}
|
||||||
|
|
||||||
- name: Login to Amazon Dev ECR
|
|
||||||
uses: aws-actions/amazon-ecr-login@v2
|
|
||||||
|
|
||||||
- name: Azure login
|
- name: Azure login
|
||||||
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # @v2.1.1
|
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # @v2.1.1
|
||||||
@@ -98,7 +94,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Tag build-tools with `${{ env.TO_TAG }}` in Docker Hub, ECR, and ACR
|
- name: Tag build-tools with `${{ env.TO_TAG }}` in Docker Hub, ECR, and ACR
|
||||||
env:
|
env:
|
||||||
DEFAULT_DEBIAN_VERSION: bookworm
|
DEFAULT_DEBIAN_VERSION: bullseye
|
||||||
run: |
|
run: |
|
||||||
for debian_version in bullseye bookworm; do
|
for debian_version in bullseye bookworm; do
|
||||||
tags=()
|
tags=()
|
||||||
|
|||||||
135
.github/workflows/pre-merge-checks.yml
vendored
135
.github/workflows/pre-merge-checks.yml
vendored
@@ -1,135 +0,0 @@
|
|||||||
name: Pre-merge checks
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/workflows/_check-codestyle-python.yml
|
|
||||||
- .github/workflows/_check-codestyle-rust.yml
|
|
||||||
- .github/workflows/build-build-tools-image.yml
|
|
||||||
- .github/workflows/pre-merge-checks.yml
|
|
||||||
merge_group:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash -euxo pipefail {0}
|
|
||||||
|
|
||||||
# No permission for GITHUB_TOKEN by default; the **minimal required** set of permissions should be granted in each job.
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
get-changed-files:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
outputs:
|
|
||||||
python-changed: ${{ steps.python-src.outputs.any_changed }}
|
|
||||||
rust-changed: ${{ steps.rust-src.outputs.any_changed }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf # v45.0.4
|
|
||||||
id: python-src
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
.github/workflows/_check-codestyle-python.yml
|
|
||||||
.github/workflows/build-build-tools-image.yml
|
|
||||||
.github/workflows/pre-merge-checks.yml
|
|
||||||
**/**.py
|
|
||||||
poetry.lock
|
|
||||||
pyproject.toml
|
|
||||||
|
|
||||||
- uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf # v45.0.4
|
|
||||||
id: rust-src
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
.github/workflows/_check-codestyle-rust.yml
|
|
||||||
.github/workflows/build-build-tools-image.yml
|
|
||||||
.github/workflows/pre-merge-checks.yml
|
|
||||||
**/**.rs
|
|
||||||
**/Cargo.toml
|
|
||||||
Cargo.toml
|
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
- name: PRINT ALL CHANGED FILES FOR DEBUG PURPOSES
|
|
||||||
env:
|
|
||||||
PYTHON_CHANGED_FILES: ${{ steps.python-src.outputs.all_changed_files }}
|
|
||||||
RUST_CHANGED_FILES: ${{ steps.rust-src.outputs.all_changed_files }}
|
|
||||||
run: |
|
|
||||||
echo "${PYTHON_CHANGED_FILES}"
|
|
||||||
echo "${RUST_CHANGED_FILES}"
|
|
||||||
|
|
||||||
build-build-tools-image:
|
|
||||||
if: |
|
|
||||||
false
|
|
||||||
|| needs.get-changed-files.outputs.python-changed == 'true'
|
|
||||||
|| needs.get-changed-files.outputs.rust-changed == 'true'
|
|
||||||
needs: [ get-changed-files ]
|
|
||||||
uses: ./.github/workflows/build-build-tools-image.yml
|
|
||||||
with:
|
|
||||||
# Build only one combination to save time
|
|
||||||
archs: '["x64"]'
|
|
||||||
debians: '["bookworm"]'
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
check-codestyle-python:
|
|
||||||
if: needs.get-changed-files.outputs.python-changed == 'true'
|
|
||||||
needs: [ get-changed-files, build-build-tools-image ]
|
|
||||||
uses: ./.github/workflows/_check-codestyle-python.yml
|
|
||||||
with:
|
|
||||||
# `-bookworm-x64` suffix should match the combination in `build-build-tools-image`
|
|
||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm-x64
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
check-codestyle-rust:
|
|
||||||
if: needs.get-changed-files.outputs.rust-changed == 'true'
|
|
||||||
needs: [ get-changed-files, build-build-tools-image ]
|
|
||||||
uses: ./.github/workflows/_check-codestyle-rust.yml
|
|
||||||
with:
|
|
||||||
# `-bookworm-x64` suffix should match the combination in `build-build-tools-image`
|
|
||||||
build-tools-image: ${{ needs.build-build-tools-image.outputs.image }}-bookworm-x64
|
|
||||||
archs: '["x64"]'
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
# To get items from the merge queue merged into main we need to satisfy "Status checks that are required".
|
|
||||||
# Currently we require 2 jobs (checks with exact name):
|
|
||||||
# - conclusion
|
|
||||||
# - neon-cloud-e2e
|
|
||||||
conclusion:
|
|
||||||
# Do not run job on Pull Requests as it interferes with the `conclusion` job from the `build_and_test` workflow
|
|
||||||
if: always() && github.event_name == 'merge_group'
|
|
||||||
permissions:
|
|
||||||
statuses: write # for `github.repos.createCommitStatus(...)`
|
|
||||||
contents: write
|
|
||||||
needs:
|
|
||||||
- get-changed-files
|
|
||||||
- check-codestyle-python
|
|
||||||
- check-codestyle-rust
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Create fake `neon-cloud-e2e` check
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
# Retry script for 5XX server errors: https://github.com/actions/github-script#retries
|
|
||||||
retries: 5
|
|
||||||
script: |
|
|
||||||
const { repo, owner } = context.repo;
|
|
||||||
const targetUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`;
|
|
||||||
|
|
||||||
await github.rest.repos.createCommitStatus({
|
|
||||||
owner: owner,
|
|
||||||
repo: repo,
|
|
||||||
sha: context.sha,
|
|
||||||
context: `neon-cloud-e2e`,
|
|
||||||
state: `success`,
|
|
||||||
target_url: targetUrl,
|
|
||||||
description: `fake check for merge queue`,
|
|
||||||
});
|
|
||||||
|
|
||||||
- name: Fail the job if any of the dependencies do not succeed or skipped
|
|
||||||
run: exit 1
|
|
||||||
if: |
|
|
||||||
false
|
|
||||||
|| (needs.check-codestyle-python.result == 'skipped' && needs.get-changed-files.outputs.python-changed == 'true')
|
|
||||||
|| (needs.check-codestyle-rust.result == 'skipped' && needs.get-changed-files.outputs.rust-changed == 'true')
|
|
||||||
|| contains(needs.*.result, 'failure')
|
|
||||||
|| contains(needs.*.result, 'cancelled')
|
|
||||||
102
.github/workflows/release.yml
vendored
102
.github/workflows/release.yml
vendored
@@ -3,9 +3,8 @@ name: Create Release Branch
|
|||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
# It should be kept in sync with if-condition in jobs
|
# It should be kept in sync with if-condition in jobs
|
||||||
|
- cron: '0 6 * * MON' # Storage release
|
||||||
- cron: '0 6 * * THU' # Proxy release
|
- cron: '0 6 * * THU' # Proxy release
|
||||||
- cron: '0 6 * * FRI' # Storage release
|
|
||||||
- cron: '0 7 * * FRI' # Compute release
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
create-storage-release-branch:
|
create-storage-release-branch:
|
||||||
@@ -16,10 +15,6 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
description: 'Create Proxy release PR'
|
description: 'Create Proxy release PR'
|
||||||
required: false
|
required: false
|
||||||
create-compute-release-branch:
|
|
||||||
type: boolean
|
|
||||||
description: 'Create Compute release PR'
|
|
||||||
required: false
|
|
||||||
|
|
||||||
# No permission for GITHUB_TOKEN by default; the **minimal required** set of permissions should be granted in each job.
|
# No permission for GITHUB_TOKEN by default; the **minimal required** set of permissions should be granted in each job.
|
||||||
permissions: {}
|
permissions: {}
|
||||||
@@ -30,40 +25,83 @@ defaults:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
create-storage-release-branch:
|
create-storage-release-branch:
|
||||||
if: ${{ github.event.schedule == '0 6 * * FRI' || inputs.create-storage-release-branch }}
|
if: ${{ github.event.schedule == '0 6 * * MON' || format('{0}', inputs.create-storage-release-branch) == 'true' }}
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write # for `git push`
|
||||||
|
|
||||||
uses: ./.github/workflows/_create-release-pr.yml
|
steps:
|
||||||
with:
|
- name: Check out code
|
||||||
component-name: 'Storage'
|
uses: actions/checkout@v4
|
||||||
release-branch: 'release'
|
with:
|
||||||
secrets:
|
ref: main
|
||||||
ci-access-token: ${{ secrets.CI_ACCESS_TOKEN }}
|
|
||||||
|
- name: Set environment variables
|
||||||
|
run: |
|
||||||
|
echo "RELEASE_DATE=$(date +'%Y-%m-%d')" | tee -a $GITHUB_ENV
|
||||||
|
echo "RELEASE_BRANCH=rc/$(date +'%Y-%m-%d')" | tee -a $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create release branch
|
||||||
|
run: git checkout -b $RELEASE_BRANCH
|
||||||
|
|
||||||
|
- name: Push new branch
|
||||||
|
run: git push origin $RELEASE_BRANCH
|
||||||
|
|
||||||
|
- name: Create pull request into release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
run: |
|
||||||
|
TITLE="Storage & Compute release ${RELEASE_DATE}"
|
||||||
|
|
||||||
|
cat << EOF > body.md
|
||||||
|
## ${TITLE}
|
||||||
|
|
||||||
|
**Please merge this Pull Request using 'Create a merge commit' button**
|
||||||
|
EOF
|
||||||
|
|
||||||
|
gh pr create --title "${TITLE}" \
|
||||||
|
--body-file "body.md" \
|
||||||
|
--head "${RELEASE_BRANCH}" \
|
||||||
|
--base "release"
|
||||||
|
|
||||||
create-proxy-release-branch:
|
create-proxy-release-branch:
|
||||||
if: ${{ github.event.schedule == '0 6 * * THU' || inputs.create-proxy-release-branch }}
|
if: ${{ github.event.schedule == '0 6 * * THU' || format('{0}', inputs.create-proxy-release-branch) == 'true' }}
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write # for `git push`
|
||||||
|
|
||||||
uses: ./.github/workflows/_create-release-pr.yml
|
steps:
|
||||||
with:
|
- name: Check out code
|
||||||
component-name: 'Proxy'
|
uses: actions/checkout@v4
|
||||||
release-branch: 'release-proxy'
|
with:
|
||||||
secrets:
|
ref: main
|
||||||
ci-access-token: ${{ secrets.CI_ACCESS_TOKEN }}
|
|
||||||
|
|
||||||
create-compute-release-branch:
|
- name: Set environment variables
|
||||||
if: ${{ github.event.schedule == '0 7 * * FRI' || inputs.create-compute-release-branch }}
|
run: |
|
||||||
|
echo "RELEASE_DATE=$(date +'%Y-%m-%d')" | tee -a $GITHUB_ENV
|
||||||
|
echo "RELEASE_BRANCH=rc/proxy/$(date +'%Y-%m-%d')" | tee -a $GITHUB_ENV
|
||||||
|
|
||||||
permissions:
|
- name: Create release branch
|
||||||
contents: write
|
run: git checkout -b $RELEASE_BRANCH
|
||||||
|
|
||||||
uses: ./.github/workflows/_create-release-pr.yml
|
- name: Push new branch
|
||||||
with:
|
run: git push origin $RELEASE_BRANCH
|
||||||
component-name: 'Compute'
|
|
||||||
release-branch: 'release-compute'
|
- name: Create pull request into release
|
||||||
secrets:
|
env:
|
||||||
ci-access-token: ${{ secrets.CI_ACCESS_TOKEN }}
|
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
|
run: |
|
||||||
|
TITLE="Proxy release ${RELEASE_DATE}"
|
||||||
|
|
||||||
|
cat << EOF > body.md
|
||||||
|
## ${TITLE}
|
||||||
|
|
||||||
|
**Please merge this Pull Request using 'Create a merge commit' button**
|
||||||
|
EOF
|
||||||
|
|
||||||
|
gh pr create --title "${TITLE}" \
|
||||||
|
--body-file "body.md" \
|
||||||
|
--head "${RELEASE_BRANCH}" \
|
||||||
|
--base "release-proxy"
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
name: Report Workflow Stats Batch
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '*/15 * * * *'
|
|
||||||
- cron: '25 0 * * *'
|
|
||||||
- cron: '25 1 * * 6'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
gh-workflow-stats-batch-2h:
|
|
||||||
name: GitHub Workflow Stats Batch 2 hours
|
|
||||||
if: github.event.schedule == '*/15 * * * *'
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Export Workflow Run for the past 2 hours
|
|
||||||
uses: neondatabase/gh-workflow-stats-action@v0.2.1
|
|
||||||
with:
|
|
||||||
db_uri: ${{ secrets.GH_REPORT_STATS_DB_RW_CONNSTR }}
|
|
||||||
db_table: "gh_workflow_stats_neon"
|
|
||||||
gh_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
duration: '2h'
|
|
||||||
|
|
||||||
gh-workflow-stats-batch-48h:
|
|
||||||
name: GitHub Workflow Stats Batch 48 hours
|
|
||||||
if: github.event.schedule == '25 0 * * *'
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Export Workflow Run for the past 48 hours
|
|
||||||
uses: neondatabase/gh-workflow-stats-action@v0.2.1
|
|
||||||
with:
|
|
||||||
db_uri: ${{ secrets.GH_REPORT_STATS_DB_RW_CONNSTR }}
|
|
||||||
db_table: "gh_workflow_stats_neon"
|
|
||||||
gh_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
duration: '48h'
|
|
||||||
|
|
||||||
gh-workflow-stats-batch-30d:
|
|
||||||
name: GitHub Workflow Stats Batch 30 days
|
|
||||||
if: github.event.schedule == '25 1 * * 6'
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Export Workflow Run for the past 30 days
|
|
||||||
uses: neondatabase/gh-workflow-stats-action@v0.2.1
|
|
||||||
with:
|
|
||||||
db_uri: ${{ secrets.GH_REPORT_STATS_DB_RW_CONNSTR }}
|
|
||||||
db_table: "gh_workflow_stats_neon"
|
|
||||||
gh_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
duration: '720h'
|
|
||||||
41
.github/workflows/report-workflow-stats.yml
vendored
Normal file
41
.github/workflows/report-workflow-stats.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
name: Report Workflow Stats
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows:
|
||||||
|
- Add `external` label to issues and PRs created by external users
|
||||||
|
- Benchmarking
|
||||||
|
- Build and Test
|
||||||
|
- Build and Test Locally
|
||||||
|
- Build build-tools image
|
||||||
|
- Check Permissions
|
||||||
|
- Check build-tools image
|
||||||
|
- Check neon with extra platform builds
|
||||||
|
- Cloud Regression Test
|
||||||
|
- Create Release Branch
|
||||||
|
- Handle `approved-for-ci-run` label
|
||||||
|
- Lint GitHub Workflows
|
||||||
|
- Notify Slack channel about upcoming release
|
||||||
|
- Periodic pagebench performance test on dedicated EC2 machine in eu-central-1 region
|
||||||
|
- Pin build-tools image
|
||||||
|
- Prepare benchmarking databases by restoring dumps
|
||||||
|
- Push images to ACR
|
||||||
|
- Test Postgres client libraries
|
||||||
|
- Trigger E2E Tests
|
||||||
|
- cleanup caches by a branch
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
gh-workflow-stats:
|
||||||
|
name: Github Workflow Stats
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
steps:
|
||||||
|
- name: Export GH Workflow Stats
|
||||||
|
uses: neondatabase/gh-workflow-stats-action@v0.1.4
|
||||||
|
with:
|
||||||
|
DB_URI: ${{ secrets.GH_REPORT_STATS_DB_RW_CONNSTR }}
|
||||||
|
DB_TABLE: "gh_workflow_stats_neon"
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GH_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||||
40
.github/workflows/trigger-e2e-tests.yml
vendored
40
.github/workflows/trigger-e2e-tests.yml
vendored
@@ -15,14 +15,7 @@ env:
|
|||||||
E2E_CONCURRENCY_GROUP: ${{ github.repository }}-e2e-tests-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
|
E2E_CONCURRENCY_GROUP: ${{ github.repository }}-e2e-tests-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-permissions:
|
|
||||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'run-no-ci') }}
|
|
||||||
uses: ./.github/workflows/check-permissions.yml
|
|
||||||
with:
|
|
||||||
github-event-name: ${{ github.event_name }}
|
|
||||||
|
|
||||||
cancel-previous-e2e-tests:
|
cancel-previous-e2e-tests:
|
||||||
needs: [ check-permissions ]
|
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
@@ -36,7 +29,6 @@ jobs:
|
|||||||
--field concurrency_group="${{ env.E2E_CONCURRENCY_GROUP }}"
|
--field concurrency_group="${{ env.E2E_CONCURRENCY_GROUP }}"
|
||||||
|
|
||||||
tag:
|
tag:
|
||||||
needs: [ check-permissions ]
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
outputs:
|
outputs:
|
||||||
build-tag: ${{ steps.build-tag.outputs.tag }}
|
build-tag: ${{ steps.build-tag.outputs.tag }}
|
||||||
@@ -59,8 +51,6 @@ jobs:
|
|||||||
echo "tag=release-$(git rev-list --count HEAD)" | tee -a $GITHUB_OUTPUT
|
echo "tag=release-$(git rev-list --count HEAD)" | tee -a $GITHUB_OUTPUT
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-proxy" ]]; then
|
elif [[ "$GITHUB_REF_NAME" == "release-proxy" ]]; then
|
||||||
echo "tag=release-proxy-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
echo "tag=release-proxy-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
||||||
elif [[ "$GITHUB_REF_NAME" == "release-compute" ]]; then
|
|
||||||
echo "tag=release-compute-$(git rev-list --count HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
else
|
else
|
||||||
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'"
|
echo "GITHUB_REF_NAME (value '$GITHUB_REF_NAME') is not set to either 'main' or 'release'"
|
||||||
BUILD_AND_TEST_RUN_ID=$(gh run list -b $CURRENT_BRANCH -c $CURRENT_SHA -w 'Build and Test' -L 1 --json databaseId --jq '.[].databaseId')
|
BUILD_AND_TEST_RUN_ID=$(gh run list -b $CURRENT_BRANCH -c $CURRENT_SHA -w 'Build and Test' -L 1 --json databaseId --jq '.[].databaseId')
|
||||||
@@ -76,7 +66,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
GH_TOKEN: ${{ secrets.CI_ACCESS_TOKEN }}
|
||||||
TAG: ${{ needs.tag.outputs.build-tag }}
|
TAG: ${{ needs.tag.outputs.build-tag }}
|
||||||
steps:
|
steps:
|
||||||
- name: Wait for `push-{neon,compute}-image-dev` job to finish
|
- name: Wait for `promote-images` job to finish
|
||||||
# It's important to have a timeout here, the script in the step can run infinitely
|
# It's important to have a timeout here, the script in the step can run infinitely
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
run: |
|
run: |
|
||||||
@@ -87,20 +77,20 @@ jobs:
|
|||||||
# For PRs we use the run id as the tag
|
# For PRs we use the run id as the tag
|
||||||
BUILD_AND_TEST_RUN_ID=${TAG}
|
BUILD_AND_TEST_RUN_ID=${TAG}
|
||||||
while true; do
|
while true; do
|
||||||
gh run --repo ${GITHUB_REPOSITORY} view ${BUILD_AND_TEST_RUN_ID} --json jobs --jq '[.jobs[] | select((.name | startswith("push-neon-image-dev")) or (.name | startswith("push-compute-image-dev"))) | {"name": .name, "conclusion": .conclusion, "url": .url}]' > jobs.json
|
conclusion=$(gh run --repo ${GITHUB_REPOSITORY} view ${BUILD_AND_TEST_RUN_ID} --json jobs --jq '.jobs[] | select(.name == "promote-images") | .conclusion')
|
||||||
if [ $(jq '[.[] | select(.conclusion == "success")] | length' jobs.json) -eq 2 ]; then
|
case "$conclusion" in
|
||||||
break
|
success)
|
||||||
fi
|
break
|
||||||
jq -c '.[]' jobs.json | while read -r job; do
|
;;
|
||||||
case $(echo $job | jq .conclusion) in
|
failure | cancelled | skipped)
|
||||||
failure | cancelled | skipped)
|
echo "The 'promote-images' job didn't succeed: '${conclusion}'. Exiting..."
|
||||||
echo "The '$(echo $job | jq .name)' job didn't succeed: '$(echo $job | jq .conclusion)'. See log in '$(echo $job | jq .url)' Exiting..."
|
exit 1
|
||||||
exit 1
|
;;
|
||||||
;;
|
*)
|
||||||
esac
|
echo "The 'promote-images' hasn't succeed yet. Waiting..."
|
||||||
done
|
sleep 60
|
||||||
echo "The 'push-{neon,compute}-image-dev' jobs haven't succeeded yet. Waiting..."
|
;;
|
||||||
sleep 60
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Set e2e-platforms
|
- name: Set e2e-platforms
|
||||||
|
|||||||
31
CODEOWNERS
31
CODEOWNERS
@@ -1,29 +1,14 @@
|
|||||||
# Autoscaling
|
/compute_tools/ @neondatabase/control-plane @neondatabase/compute
|
||||||
/libs/vm_monitor/ @neondatabase/autoscaling
|
|
||||||
|
|
||||||
# DevProd
|
|
||||||
/.github/ @neondatabase/developer-productivity
|
|
||||||
|
|
||||||
# Compute
|
|
||||||
/pgxn/ @neondatabase/compute
|
|
||||||
/vendor/ @neondatabase/compute
|
|
||||||
/compute/ @neondatabase/compute
|
|
||||||
/compute_tools/ @neondatabase/compute
|
|
||||||
|
|
||||||
# Proxy
|
|
||||||
/libs/proxy/ @neondatabase/proxy
|
|
||||||
/proxy/ @neondatabase/proxy
|
|
||||||
|
|
||||||
# Storage
|
|
||||||
/pageserver/ @neondatabase/storage
|
|
||||||
/safekeeper/ @neondatabase/storage
|
|
||||||
/storage_controller @neondatabase/storage
|
/storage_controller @neondatabase/storage
|
||||||
/storage_scrubber @neondatabase/storage
|
/storage_scrubber @neondatabase/storage
|
||||||
/libs/pageserver_api/ @neondatabase/storage
|
/libs/pageserver_api/ @neondatabase/storage
|
||||||
|
/libs/postgres_ffi/ @neondatabase/compute @neondatabase/storage
|
||||||
/libs/remote_storage/ @neondatabase/storage
|
/libs/remote_storage/ @neondatabase/storage
|
||||||
/libs/safekeeper_api/ @neondatabase/storage
|
/libs/safekeeper_api/ @neondatabase/storage
|
||||||
|
/libs/vm_monitor/ @neondatabase/autoscaling
|
||||||
# Shared
|
/pageserver/ @neondatabase/storage
|
||||||
|
/pgxn/ @neondatabase/compute
|
||||||
/pgxn/neon/ @neondatabase/compute @neondatabase/storage
|
/pgxn/neon/ @neondatabase/compute @neondatabase/storage
|
||||||
/libs/compute_api/ @neondatabase/compute @neondatabase/control-plane
|
/proxy/ @neondatabase/proxy
|
||||||
/libs/postgres_ffi/ @neondatabase/compute @neondatabase/storage
|
/safekeeper/ @neondatabase/storage
|
||||||
|
/vendor/ @neondatabase/compute
|
||||||
|
|||||||
2168
Cargo.lock
generated
2168
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
99
Cargo.toml
99
Cargo.toml
@@ -11,14 +11,12 @@ members = [
|
|||||||
"pageserver/pagebench",
|
"pageserver/pagebench",
|
||||||
"proxy",
|
"proxy",
|
||||||
"safekeeper",
|
"safekeeper",
|
||||||
"safekeeper/client",
|
|
||||||
"storage_broker",
|
"storage_broker",
|
||||||
"storage_controller",
|
"storage_controller",
|
||||||
"storage_controller/client",
|
"storage_controller/client",
|
||||||
"storage_scrubber",
|
"storage_scrubber",
|
||||||
"workspace_hack",
|
"workspace_hack",
|
||||||
"libs/compute_api",
|
"libs/compute_api",
|
||||||
"libs/http-utils",
|
|
||||||
"libs/pageserver_api",
|
"libs/pageserver_api",
|
||||||
"libs/postgres_ffi",
|
"libs/postgres_ffi",
|
||||||
"libs/safekeeper_api",
|
"libs/safekeeper_api",
|
||||||
@@ -35,11 +33,6 @@ members = [
|
|||||||
"libs/postgres_ffi/wal_craft",
|
"libs/postgres_ffi/wal_craft",
|
||||||
"libs/vm_monitor",
|
"libs/vm_monitor",
|
||||||
"libs/walproposer",
|
"libs/walproposer",
|
||||||
"libs/wal_decoder",
|
|
||||||
"libs/postgres_initdb",
|
|
||||||
"libs/proxy/postgres-protocol2",
|
|
||||||
"libs/proxy/postgres-types2",
|
|
||||||
"libs/proxy/tokio-postgres2",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
@@ -53,37 +46,37 @@ anyhow = { version = "1.0", features = ["backtrace"] }
|
|||||||
arc-swap = "1.6"
|
arc-swap = "1.6"
|
||||||
async-compression = { version = "0.4.0", features = ["tokio", "gzip", "zstd"] }
|
async-compression = { version = "0.4.0", features = ["tokio", "gzip", "zstd"] }
|
||||||
atomic-take = "1.1.0"
|
atomic-take = "1.1.0"
|
||||||
backtrace = "0.3.74"
|
azure_core = { version = "0.19", default-features = false, features = ["enable_reqwest_rustls", "hmac_rust"] }
|
||||||
|
azure_identity = { version = "0.19", default-features = false, features = ["enable_reqwest_rustls"] }
|
||||||
|
azure_storage = { version = "0.19", default-features = false, features = ["enable_reqwest_rustls"] }
|
||||||
|
azure_storage_blobs = { version = "0.19", default-features = false, features = ["enable_reqwest_rustls"] }
|
||||||
flate2 = "1.0.26"
|
flate2 = "1.0.26"
|
||||||
assert-json-diff = "2"
|
|
||||||
async-stream = "0.3"
|
async-stream = "0.3"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
aws-config = { version = "1.5", default-features = false, features=["rustls", "sso"] }
|
aws-config = { version = "1.5", default-features = false, features=["rustls", "sso"] }
|
||||||
aws-sdk-s3 = "1.52"
|
aws-sdk-s3 = "1.52"
|
||||||
aws-sdk-iam = "1.46.0"
|
aws-sdk-iam = "1.46.0"
|
||||||
aws-sdk-kms = "1.47.0"
|
|
||||||
aws-smithy-async = { version = "1.2.1", default-features = false, features=["rt-tokio"] }
|
aws-smithy-async = { version = "1.2.1", default-features = false, features=["rt-tokio"] }
|
||||||
aws-smithy-types = "1.2"
|
aws-smithy-types = "1.2"
|
||||||
aws-credential-types = "1.2.0"
|
aws-credential-types = "1.2.0"
|
||||||
aws-sigv4 = { version = "1.2", features = ["sign-http"] }
|
aws-sigv4 = { version = "1.2", features = ["sign-http"] }
|
||||||
aws-types = "1.3"
|
aws-types = "1.3"
|
||||||
axum = { version = "0.8.1", features = ["ws"] }
|
axum = { version = "0.7.5", features = ["ws"] }
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
bindgen = "0.70"
|
bindgen = "0.70"
|
||||||
bit_field = "0.10.2"
|
bit_field = "0.10.2"
|
||||||
bstr = "1.0"
|
bstr = "1.0"
|
||||||
byteorder = "1.4"
|
byteorder = "1.4"
|
||||||
bytes = "1.9"
|
bytes = "1.0"
|
||||||
camino = "1.1.6"
|
camino = "1.1.6"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
chrono = { version = "0.4", default-features = false, features = ["clock"] }
|
chrono = { version = "0.4", default-features = false, features = ["clock"] }
|
||||||
clap = { version = "4.0", features = ["derive", "env"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
clashmap = { version = "1.0", features = ["raw-api"] }
|
|
||||||
comfy-table = "7.1"
|
comfy-table = "7.1"
|
||||||
const_format = "0.2"
|
const_format = "0.2"
|
||||||
crc32c = "0.6"
|
crc32c = "0.6"
|
||||||
diatomic-waker = { version = "0.2.3" }
|
dashmap = { version = "5.5.0", features = ["raw-api"] }
|
||||||
either = "1.8"
|
either = "1.8"
|
||||||
enum-map = "2.4.2"
|
enum-map = "2.4.2"
|
||||||
enumset = "1.0.12"
|
enumset = "1.0.12"
|
||||||
@@ -112,11 +105,9 @@ hyper-util = "0.1"
|
|||||||
tokio-tungstenite = "0.21.0"
|
tokio-tungstenite = "0.21.0"
|
||||||
indexmap = "2"
|
indexmap = "2"
|
||||||
indoc = "2"
|
indoc = "2"
|
||||||
inferno = "0.12.0"
|
ipnet = "2.9.0"
|
||||||
ipnet = "2.10.0"
|
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
itoa = "1.0.11"
|
itoa = "1.0.11"
|
||||||
jemalloc_pprof = "0.6"
|
|
||||||
jsonwebtoken = "9"
|
jsonwebtoken = "9"
|
||||||
lasso = "0.7"
|
lasso = "0.7"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
@@ -125,20 +116,19 @@ measured = { version = "0.0.22", features=["lasso"] }
|
|||||||
measured-process = { version = "0.0.22" }
|
measured-process = { version = "0.0.22" }
|
||||||
memoffset = "0.9"
|
memoffset = "0.9"
|
||||||
nix = { version = "0.27", features = ["dir", "fs", "process", "socket", "signal", "poll"] }
|
nix = { version = "0.27", features = ["dir", "fs", "process", "socket", "signal", "poll"] }
|
||||||
notify = "8.0.0"
|
notify = "6.0.0"
|
||||||
num_cpus = "1.15"
|
num_cpus = "1.15"
|
||||||
num-traits = "0.2.15"
|
num-traits = "0.2.15"
|
||||||
once_cell = "1.13"
|
once_cell = "1.13"
|
||||||
opentelemetry = "0.27"
|
opentelemetry = "0.24"
|
||||||
opentelemetry_sdk = "0.27"
|
opentelemetry_sdk = "0.24"
|
||||||
opentelemetry-otlp = { version = "0.27", default-features = false, features = ["http-proto", "trace", "http", "reqwest-client"] }
|
opentelemetry-otlp = { version = "0.17", default-features=false, features = ["http-proto", "trace", "http", "reqwest-client"] }
|
||||||
opentelemetry-semantic-conventions = "0.27"
|
opentelemetry-semantic-conventions = "0.16"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
parquet = { version = "53", default-features = false, features = ["zstd"] }
|
parquet = { version = "53", default-features = false, features = ["zstd"] }
|
||||||
parquet_derive = "53"
|
parquet_derive = "53"
|
||||||
pbkdf2 = { version = "0.12.1", features = ["simple", "std"] }
|
pbkdf2 = { version = "0.12.1", features = ["simple", "std"] }
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
pprof = { version = "0.14", features = ["criterion", "flamegraph", "frame-pointer", "protobuf", "protobuf-codec"] }
|
|
||||||
procfs = "0.16"
|
procfs = "0.16"
|
||||||
prometheus = {version = "0.13", default-features=false, features = ["process"]} # removes protobuf dependency
|
prometheus = {version = "0.13", default-features=false, features = ["process"]} # removes protobuf dependency
|
||||||
prost = "0.13"
|
prost = "0.13"
|
||||||
@@ -146,13 +136,13 @@ rand = "0.8"
|
|||||||
redis = { version = "0.25.2", features = ["tokio-rustls-comp", "keep-alive"] }
|
redis = { version = "0.25.2", features = ["tokio-rustls-comp", "keep-alive"] }
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] }
|
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] }
|
||||||
reqwest-tracing = { version = "0.5", features = ["opentelemetry_0_27"] }
|
reqwest-tracing = { version = "0.5", features = ["opentelemetry_0_24"] }
|
||||||
reqwest-middleware = "0.4"
|
reqwest-middleware = "0.3.0"
|
||||||
reqwest-retry = "0.7"
|
reqwest-retry = "0.5"
|
||||||
routerify = "3"
|
routerify = "3"
|
||||||
rpds = "0.13"
|
rpds = "0.13"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
rustls = { version = "0.23.16", default-features = false }
|
rustls = "0.23"
|
||||||
rustls-pemfile = "2"
|
rustls-pemfile = "2"
|
||||||
scopeguard = "1.1"
|
scopeguard = "1.1"
|
||||||
sysinfo = "0.29.2"
|
sysinfo = "0.29.2"
|
||||||
@@ -162,7 +152,7 @@ sentry = { version = "0.32", default-features = false, features = ["backtrace",
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_path_to_error = "0.1"
|
serde_path_to_error = "0.1"
|
||||||
serde_with = { version = "2.0", features = [ "base64" ] }
|
serde_with = "2.0"
|
||||||
serde_assert = "0.5.0"
|
serde_assert = "0.5.0"
|
||||||
sha2 = "0.10.2"
|
sha2 = "0.10.2"
|
||||||
signal-hook = "0.3"
|
signal-hook = "0.3"
|
||||||
@@ -177,27 +167,23 @@ sync_wrapper = "0.1.2"
|
|||||||
tar = "0.4"
|
tar = "0.4"
|
||||||
test-context = "0.3"
|
test-context = "0.3"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tikv-jemallocator = { version = "0.6", features = ["profiling", "stats", "unprefixed_malloc_on_supported_platforms"] }
|
tikv-jemallocator = "0.5"
|
||||||
tikv-jemalloc-ctl = { version = "0.6", features = ["stats"] }
|
tikv-jemalloc-ctl = "0.5"
|
||||||
tokio = { version = "1.41", features = ["macros"] }
|
tokio = { version = "1.17", features = ["macros"] }
|
||||||
tokio-epoll-uring = { git = "https://github.com/neondatabase/tokio-epoll-uring.git" , branch = "main" }
|
tokio-epoll-uring = { git = "https://github.com/neondatabase/tokio-epoll-uring.git" , branch = "main" }
|
||||||
tokio-io-timeout = "1.2.0"
|
tokio-io-timeout = "1.2.0"
|
||||||
tokio-postgres-rustls = "0.12.0"
|
tokio-postgres-rustls = "0.12.0"
|
||||||
tokio-rustls = { version = "0.26.0", default-features = false, features = ["tls12", "ring"]}
|
tokio-rustls = "0.26"
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
tokio-tar = "0.3"
|
tokio-tar = "0.3"
|
||||||
tokio-util = { version = "0.7.10", features = ["io", "rt"] }
|
tokio-util = { version = "0.7.10", features = ["io", "rt"] }
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
toml_edit = "0.22"
|
toml_edit = "0.22"
|
||||||
tonic = {version = "0.12.3", default-features = false, features = ["channel", "tls", "tls-roots"]}
|
tonic = {version = "0.12.3", features = ["tls", "tls-roots"]}
|
||||||
tower = { version = "0.5.2", default-features = false }
|
tower-service = "0.3.2"
|
||||||
tower-http = { version = "0.6.2", features = ["request-id", "trace"] }
|
|
||||||
tower-service = "0.3.3"
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-error = "0.2"
|
tracing-error = "0.2"
|
||||||
tracing-log = "0.2"
|
tracing-opentelemetry = "0.25"
|
||||||
tracing-opentelemetry = "0.28"
|
|
||||||
tracing-serde = "0.2.0"
|
|
||||||
tracing-subscriber = { version = "0.3", default-features = false, features = ["smallvec", "fmt", "tracing-log", "std", "env-filter", "json"] }
|
tracing-subscriber = { version = "0.3", default-features = false, features = ["smallvec", "fmt", "tracing-log", "std", "env-filter", "json"] }
|
||||||
try-lock = "0.2.5"
|
try-lock = "0.2.5"
|
||||||
twox-hash = { version = "1.6.3", default-features = false }
|
twox-hash = { version = "1.6.3", default-features = false }
|
||||||
@@ -209,41 +195,41 @@ walkdir = "2.3.2"
|
|||||||
rustls-native-certs = "0.8"
|
rustls-native-certs = "0.8"
|
||||||
x509-parser = "0.16"
|
x509-parser = "0.16"
|
||||||
whoami = "1.5.1"
|
whoami = "1.5.1"
|
||||||
zerocopy = { version = "0.7", features = ["derive"] }
|
|
||||||
|
|
||||||
## TODO replace this with tracing
|
## TODO replace this with tracing
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
## Libraries from neondatabase/ git forks, ideally with changes to be upstreamed
|
## Libraries from neondatabase/ git forks, ideally with changes to be upstreamed
|
||||||
postgres = { git = "https://github.com/neondatabase/rust-postgres.git", branch = "neon" }
|
|
||||||
postgres-protocol = { git = "https://github.com/neondatabase/rust-postgres.git", branch = "neon" }
|
|
||||||
postgres-types = { git = "https://github.com/neondatabase/rust-postgres.git", branch = "neon" }
|
|
||||||
tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", branch = "neon" }
|
|
||||||
|
|
||||||
## Azure SDK crates
|
# We want to use the 'neon' branch for these, but there's currently one
|
||||||
azure_core = { git = "https://github.com/neondatabase/azure-sdk-for-rust.git", branch = "neon", default-features = false, features = ["enable_reqwest_rustls", "hmac_rust"] }
|
# incompatible change on the branch. See:
|
||||||
azure_identity = { git = "https://github.com/neondatabase/azure-sdk-for-rust.git", branch = "neon", default-features = false, features = ["enable_reqwest_rustls"] }
|
#
|
||||||
azure_storage = { git = "https://github.com/neondatabase/azure-sdk-for-rust.git", branch = "neon", default-features = false, features = ["enable_reqwest_rustls"] }
|
# - PR #8076 which contained changes that depended on the new changes in
|
||||||
azure_storage_blobs = { git = "https://github.com/neondatabase/azure-sdk-for-rust.git", branch = "neon", default-features = false, features = ["enable_reqwest_rustls"] }
|
# the rust-postgres crate, and
|
||||||
|
# - PR #8654 which reverted those changes and made the code in proxy incompatible
|
||||||
|
# with the tip of the 'neon' branch again.
|
||||||
|
#
|
||||||
|
# When those proxy changes are re-applied (see PR #8747), we can switch using
|
||||||
|
# the tip of the 'neon' branch again.
|
||||||
|
postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "20031d7a9ee1addeae6e0968e3899ae6bf01cee2" }
|
||||||
|
postgres-protocol = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "20031d7a9ee1addeae6e0968e3899ae6bf01cee2" }
|
||||||
|
postgres-types = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "20031d7a9ee1addeae6e0968e3899ae6bf01cee2" }
|
||||||
|
tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "20031d7a9ee1addeae6e0968e3899ae6bf01cee2" }
|
||||||
|
|
||||||
## Local libraries
|
## Local libraries
|
||||||
compute_api = { version = "0.1", path = "./libs/compute_api/" }
|
compute_api = { version = "0.1", path = "./libs/compute_api/" }
|
||||||
consumption_metrics = { version = "0.1", path = "./libs/consumption_metrics/" }
|
consumption_metrics = { version = "0.1", path = "./libs/consumption_metrics/" }
|
||||||
http-utils = { version = "0.1", path = "./libs/http-utils/" }
|
|
||||||
metrics = { version = "0.1", path = "./libs/metrics/" }
|
metrics = { version = "0.1", path = "./libs/metrics/" }
|
||||||
pageserver = { path = "./pageserver" }
|
|
||||||
pageserver_api = { version = "0.1", path = "./libs/pageserver_api/" }
|
pageserver_api = { version = "0.1", path = "./libs/pageserver_api/" }
|
||||||
pageserver_client = { path = "./pageserver/client" }
|
pageserver_client = { path = "./pageserver/client" }
|
||||||
pageserver_compaction = { version = "0.1", path = "./pageserver/compaction/" }
|
pageserver_compaction = { version = "0.1", path = "./pageserver/compaction/" }
|
||||||
postgres_backend = { version = "0.1", path = "./libs/postgres_backend/" }
|
postgres_backend = { version = "0.1", path = "./libs/postgres_backend/" }
|
||||||
postgres_connection = { version = "0.1", path = "./libs/postgres_connection/" }
|
postgres_connection = { version = "0.1", path = "./libs/postgres_connection/" }
|
||||||
postgres_ffi = { version = "0.1", path = "./libs/postgres_ffi/" }
|
postgres_ffi = { version = "0.1", path = "./libs/postgres_ffi/" }
|
||||||
postgres_initdb = { path = "./libs/postgres_initdb" }
|
|
||||||
pq_proto = { version = "0.1", path = "./libs/pq_proto/" }
|
pq_proto = { version = "0.1", path = "./libs/pq_proto/" }
|
||||||
remote_storage = { version = "0.1", path = "./libs/remote_storage/" }
|
remote_storage = { version = "0.1", path = "./libs/remote_storage/" }
|
||||||
safekeeper_api = { version = "0.1", path = "./libs/safekeeper_api" }
|
safekeeper_api = { version = "0.1", path = "./libs/safekeeper_api" }
|
||||||
safekeeper_client = { path = "./safekeeper/client" }
|
|
||||||
desim = { version = "0.1", path = "./libs/desim" }
|
desim = { version = "0.1", path = "./libs/desim" }
|
||||||
storage_broker = { version = "0.1", path = "./storage_broker/" } # Note: main broker code is inside the binary crate, so linking with the library shouldn't be heavy.
|
storage_broker = { version = "0.1", path = "./storage_broker/" } # Note: main broker code is inside the binary crate, so linking with the library shouldn't be heavy.
|
||||||
storage_controller_client = { path = "./storage_controller/client" }
|
storage_controller_client = { path = "./storage_controller/client" }
|
||||||
@@ -252,7 +238,6 @@ tracing-utils = { version = "0.1", path = "./libs/tracing-utils/" }
|
|||||||
utils = { version = "0.1", path = "./libs/utils/" }
|
utils = { version = "0.1", path = "./libs/utils/" }
|
||||||
vm_monitor = { version = "0.1", path = "./libs/vm_monitor/" }
|
vm_monitor = { version = "0.1", path = "./libs/vm_monitor/" }
|
||||||
walproposer = { version = "0.1", path = "./libs/walproposer/" }
|
walproposer = { version = "0.1", path = "./libs/walproposer/" }
|
||||||
wal_decoder = { version = "0.1", path = "./libs/wal_decoder" }
|
|
||||||
|
|
||||||
## Common library dependency
|
## Common library dependency
|
||||||
workspace_hack = { version = "0.1", path = "./workspace_hack/" }
|
workspace_hack = { version = "0.1", path = "./workspace_hack/" }
|
||||||
@@ -267,15 +252,13 @@ tonic-build = "0.12"
|
|||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
|
||||||
# Needed to get `tokio-postgres-rustls` to depend on our fork.
|
# Needed to get `tokio-postgres-rustls` to depend on our fork.
|
||||||
tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", branch = "neon" }
|
tokio-postgres = { git = "https://github.com/neondatabase/rust-postgres.git", rev = "20031d7a9ee1addeae6e0968e3899ae6bf01cee2" }
|
||||||
|
|
||||||
################# Binary contents sections
|
################# Binary contents sections
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
# This is useful for profiling and, to some extent, debug.
|
# This is useful for profiling and, to some extent, debug.
|
||||||
# Besides, debug info should not affect the performance.
|
# Besides, debug info should not affect the performance.
|
||||||
#
|
|
||||||
# NB: we also enable frame pointers for improved profiling, see .cargo/config.toml.
|
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
# disable debug symbols for all packages except this one to decrease binaries size
|
# disable debug symbols for all packages except this one to decrease binaries size
|
||||||
|
|||||||
55
Dockerfile
55
Dockerfile
@@ -7,31 +7,9 @@ ARG IMAGE=build-tools
|
|||||||
ARG TAG=pinned
|
ARG TAG=pinned
|
||||||
ARG DEFAULT_PG_VERSION=17
|
ARG DEFAULT_PG_VERSION=17
|
||||||
ARG STABLE_PG_VERSION=16
|
ARG STABLE_PG_VERSION=16
|
||||||
ARG DEBIAN_VERSION=bookworm
|
ARG DEBIAN_VERSION=bullseye
|
||||||
ARG DEBIAN_FLAVOR=${DEBIAN_VERSION}-slim
|
ARG DEBIAN_FLAVOR=${DEBIAN_VERSION}-slim
|
||||||
|
|
||||||
# Here are the INDEX DIGESTS for the images we use.
|
|
||||||
# You can get them following next steps for now:
|
|
||||||
# 1. Get an authentication token from DockerHub:
|
|
||||||
# TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/debian:pull" | jq -r .token)
|
|
||||||
# 2. Using that token, query index for the given tag:
|
|
||||||
# curl -s -H "Authorization: Bearer $TOKEN" \
|
|
||||||
# -H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
|
|
||||||
# "https://registry.hub.docker.com/v2/library/debian/manifests/bullseye-slim" \
|
|
||||||
# -I | grep -i docker-content-digest
|
|
||||||
# 3. As a next step, TODO(fedordikarev): create script and schedule workflow to run these checks
|
|
||||||
# and updates on regular bases and in automated way.
|
|
||||||
ARG BOOKWORM_SLIM_SHA=sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7
|
|
||||||
ARG BULLSEYE_SLIM_SHA=sha256:e831d9a884d63734fe3dd9c491ed9a5a3d4c6a6d32c5b14f2067357c49b0b7e1
|
|
||||||
|
|
||||||
# Here we use ${var/search/replace} syntax, to check
|
|
||||||
# if base image is one of the images, we pin image index for.
|
|
||||||
# If var will match one the known images, we will replace it with the known sha.
|
|
||||||
# If no match, than value will be unaffected, and will process with no-pinned image.
|
|
||||||
ARG BASE_IMAGE_SHA=debian:${DEBIAN_FLAVOR}
|
|
||||||
ARG BASE_IMAGE_SHA=${BASE_IMAGE_SHA/debian:bookworm-slim/debian@$BOOKWORM_SLIM_SHA}
|
|
||||||
ARG BASE_IMAGE_SHA=${BASE_IMAGE_SHA/debian:bullseye-slim/debian@$BULLSEYE_SLIM_SHA}
|
|
||||||
|
|
||||||
# Build Postgres
|
# Build Postgres
|
||||||
FROM $REPOSITORY/$IMAGE:$TAG AS pg-build
|
FROM $REPOSITORY/$IMAGE:$TAG AS pg-build
|
||||||
WORKDIR /home/nonroot
|
WORKDIR /home/nonroot
|
||||||
@@ -50,14 +28,6 @@ RUN set -e \
|
|||||||
&& rm -rf pg_install/build \
|
&& rm -rf pg_install/build \
|
||||||
&& tar -C pg_install -czf /home/nonroot/postgres_install.tar.gz .
|
&& tar -C pg_install -czf /home/nonroot/postgres_install.tar.gz .
|
||||||
|
|
||||||
# Prepare cargo-chef recipe
|
|
||||||
FROM $REPOSITORY/$IMAGE:$TAG AS plan
|
|
||||||
WORKDIR /home/nonroot
|
|
||||||
|
|
||||||
COPY --chown=nonroot . .
|
|
||||||
|
|
||||||
RUN cargo chef prepare --recipe-path recipe.json
|
|
||||||
|
|
||||||
# Build neon binaries
|
# Build neon binaries
|
||||||
FROM $REPOSITORY/$IMAGE:$TAG AS build
|
FROM $REPOSITORY/$IMAGE:$TAG AS build
|
||||||
WORKDIR /home/nonroot
|
WORKDIR /home/nonroot
|
||||||
@@ -71,17 +41,11 @@ COPY --from=pg-build /home/nonroot/pg_install/v16/include/postgresql/server pg_i
|
|||||||
COPY --from=pg-build /home/nonroot/pg_install/v17/include/postgresql/server pg_install/v17/include/postgresql/server
|
COPY --from=pg-build /home/nonroot/pg_install/v17/include/postgresql/server pg_install/v17/include/postgresql/server
|
||||||
COPY --from=pg-build /home/nonroot/pg_install/v16/lib pg_install/v16/lib
|
COPY --from=pg-build /home/nonroot/pg_install/v16/lib pg_install/v16/lib
|
||||||
COPY --from=pg-build /home/nonroot/pg_install/v17/lib pg_install/v17/lib
|
COPY --from=pg-build /home/nonroot/pg_install/v17/lib pg_install/v17/lib
|
||||||
COPY --from=plan /home/nonroot/recipe.json recipe.json
|
|
||||||
|
|
||||||
ARG ADDITIONAL_RUSTFLAGS=""
|
|
||||||
|
|
||||||
RUN set -e \
|
|
||||||
&& RUSTFLAGS="-Clinker=clang -Clink-arg=-fuse-ld=mold -Clink-arg=-Wl,--no-rosegment -Cforce-frame-pointers=yes ${ADDITIONAL_RUSTFLAGS}" cargo chef cook --locked --release --recipe-path recipe.json
|
|
||||||
|
|
||||||
COPY --chown=nonroot . .
|
COPY --chown=nonroot . .
|
||||||
|
|
||||||
|
ARG ADDITIONAL_RUSTFLAGS
|
||||||
RUN set -e \
|
RUN set -e \
|
||||||
&& RUSTFLAGS="-Clinker=clang -Clink-arg=-fuse-ld=mold -Clink-arg=-Wl,--no-rosegment -Cforce-frame-pointers=yes ${ADDITIONAL_RUSTFLAGS}" cargo build \
|
&& PQ_LIB_DIR=$(pwd)/pg_install/v${STABLE_PG_VERSION}/lib RUSTFLAGS="-Clinker=clang -Clink-arg=-fuse-ld=mold -Clink-arg=-Wl,--no-rosegment ${ADDITIONAL_RUSTFLAGS}" cargo build \
|
||||||
--bin pg_sni_router \
|
--bin pg_sni_router \
|
||||||
--bin pageserver \
|
--bin pageserver \
|
||||||
--bin pagectl \
|
--bin pagectl \
|
||||||
@@ -95,21 +59,16 @@ RUN set -e \
|
|||||||
|
|
||||||
# Build final image
|
# Build final image
|
||||||
#
|
#
|
||||||
FROM $BASE_IMAGE_SHA
|
FROM debian:${DEBIAN_FLAVOR}
|
||||||
ARG DEFAULT_PG_VERSION
|
ARG DEFAULT_PG_VERSION
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
RUN set -e \
|
RUN set -e \
|
||||||
&& echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
|
||||||
&& apt update \
|
&& apt update \
|
||||||
&& apt install -y \
|
&& apt install -y \
|
||||||
libreadline-dev \
|
libreadline-dev \
|
||||||
libseccomp-dev \
|
libseccomp-dev \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
# System postgres for use with client libraries (e.g. in storage controller)
|
|
||||||
postgresql-15 \
|
|
||||||
openssl \
|
|
||||||
&& rm -f /etc/apt/apt.conf.d/80-retries \
|
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
|
||||||
&& useradd -d /data neon \
|
&& useradd -d /data neon \
|
||||||
&& chown -R neon:neon /data
|
&& chown -R neon:neon /data
|
||||||
@@ -142,9 +101,15 @@ RUN mkdir -p /data/.neon/ && \
|
|||||||
> /data/.neon/pageserver.toml && \
|
> /data/.neon/pageserver.toml && \
|
||||||
chown -R neon:neon /data/.neon
|
chown -R neon:neon /data/.neon
|
||||||
|
|
||||||
|
# When running a binary that links with libpq, default to using our most recent postgres version. Binaries
|
||||||
|
# that want a particular postgres version will select it explicitly: this is just a default.
|
||||||
|
ENV LD_LIBRARY_PATH=/usr/local/v${DEFAULT_PG_VERSION}/lib
|
||||||
|
|
||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
USER neon
|
USER neon
|
||||||
EXPOSE 6400
|
EXPOSE 6400
|
||||||
EXPOSE 9898
|
EXPOSE 9898
|
||||||
|
|
||||||
CMD ["/usr/local/bin/pageserver", "-D", "/data/.neon"]
|
CMD ["/usr/local/bin/pageserver", "-D", "/data/.neon"]
|
||||||
|
|
||||||
|
|||||||
25
Makefile
25
Makefile
@@ -3,6 +3,7 @@ ROOT_PROJECT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
|||||||
# Where to install Postgres, default is ./pg_install, maybe useful for package managers
|
# Where to install Postgres, default is ./pg_install, maybe useful for package managers
|
||||||
POSTGRES_INSTALL_DIR ?= $(ROOT_PROJECT_DIR)/pg_install/
|
POSTGRES_INSTALL_DIR ?= $(ROOT_PROJECT_DIR)/pg_install/
|
||||||
|
|
||||||
|
OPENSSL_PREFIX_DIR := /usr/local/openssl
|
||||||
ICU_PREFIX_DIR := /usr/local/icu
|
ICU_PREFIX_DIR := /usr/local/icu
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -10,45 +11,33 @@ ICU_PREFIX_DIR := /usr/local/icu
|
|||||||
# environment variable.
|
# environment variable.
|
||||||
#
|
#
|
||||||
BUILD_TYPE ?= debug
|
BUILD_TYPE ?= debug
|
||||||
WITH_SANITIZERS ?= no
|
|
||||||
ifeq ($(BUILD_TYPE),release)
|
ifeq ($(BUILD_TYPE),release)
|
||||||
PG_CONFIGURE_OPTS = --enable-debug --with-openssl
|
PG_CONFIGURE_OPTS = --enable-debug --with-openssl
|
||||||
PG_CFLAGS = -O2 -g3 $(CFLAGS)
|
PG_CFLAGS = -O2 -g3 $(CFLAGS)
|
||||||
PG_LDFLAGS = $(LDFLAGS)
|
|
||||||
# Unfortunately, `--profile=...` is a nightly feature
|
# Unfortunately, `--profile=...` is a nightly feature
|
||||||
CARGO_BUILD_FLAGS += --release
|
CARGO_BUILD_FLAGS += --release
|
||||||
else ifeq ($(BUILD_TYPE),debug)
|
else ifeq ($(BUILD_TYPE),debug)
|
||||||
PG_CONFIGURE_OPTS = --enable-debug --with-openssl --enable-cassert --enable-depend
|
PG_CONFIGURE_OPTS = --enable-debug --with-openssl --enable-cassert --enable-depend
|
||||||
PG_CFLAGS = -O0 -g3 $(CFLAGS)
|
PG_CFLAGS = -O0 -g3 $(CFLAGS)
|
||||||
PG_LDFLAGS = $(LDFLAGS)
|
|
||||||
else
|
else
|
||||||
$(error Bad build type '$(BUILD_TYPE)', see Makefile for options)
|
$(error Bad build type '$(BUILD_TYPE)', see Makefile for options)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(WITH_SANITIZERS),yes)
|
|
||||||
PG_CFLAGS += -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
|
|
||||||
COPT += -Wno-error # to avoid failing on warnings induced by sanitizers
|
|
||||||
PG_LDFLAGS = -fsanitize=address -fsanitize=undefined -static-libasan -static-libubsan $(LDFLAGS)
|
|
||||||
export CC := gcc
|
|
||||||
export ASAN_OPTIONS := detect_leaks=0
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(shell test -e /home/nonroot/.docker_build && echo -n yes),yes)
|
ifeq ($(shell test -e /home/nonroot/.docker_build && echo -n yes),yes)
|
||||||
# Exclude static build openssl, icu for local build (MacOS, Linux)
|
# Exclude static build openssl, icu for local build (MacOS, Linux)
|
||||||
# Only keep for build type release and debug
|
# Only keep for build type release and debug
|
||||||
|
PG_CFLAGS += -I$(OPENSSL_PREFIX_DIR)/include
|
||||||
PG_CONFIGURE_OPTS += --with-icu
|
PG_CONFIGURE_OPTS += --with-icu
|
||||||
PG_CONFIGURE_OPTS += ICU_CFLAGS='-I/$(ICU_PREFIX_DIR)/include -DU_STATIC_IMPLEMENTATION'
|
PG_CONFIGURE_OPTS += ICU_CFLAGS='-I/$(ICU_PREFIX_DIR)/include -DU_STATIC_IMPLEMENTATION'
|
||||||
PG_CONFIGURE_OPTS += ICU_LIBS='-L$(ICU_PREFIX_DIR)/lib -L$(ICU_PREFIX_DIR)/lib64 -licui18n -licuuc -licudata -lstdc++ -Wl,-Bdynamic -lm'
|
PG_CONFIGURE_OPTS += ICU_LIBS='-L$(ICU_PREFIX_DIR)/lib -L$(ICU_PREFIX_DIR)/lib64 -licui18n -licuuc -licudata -lstdc++ -Wl,-Bdynamic -lm'
|
||||||
|
PG_CONFIGURE_OPTS += LDFLAGS='-L$(OPENSSL_PREFIX_DIR)/lib -L$(OPENSSL_PREFIX_DIR)/lib64 -L$(ICU_PREFIX_DIR)/lib -L$(ICU_PREFIX_DIR)/lib64 -Wl,-Bstatic -lssl -lcrypto -Wl,-Bdynamic -lrt -lm -ldl -lpthread'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
ifeq ($(UNAME_S),Linux)
|
ifeq ($(UNAME_S),Linux)
|
||||||
# Seccomp BPF is only available for Linux
|
# Seccomp BPF is only available for Linux
|
||||||
ifneq ($(WITH_SANITIZERS),yes)
|
PG_CONFIGURE_OPTS += --with-libseccomp
|
||||||
PG_CONFIGURE_OPTS += --with-libseccomp
|
|
||||||
endif
|
|
||||||
else ifeq ($(UNAME_S),Darwin)
|
else ifeq ($(UNAME_S),Darwin)
|
||||||
PG_CFLAGS += -DUSE_PREFETCH
|
|
||||||
ifndef DISABLE_HOMEBREW
|
ifndef DISABLE_HOMEBREW
|
||||||
# macOS with brew-installed openssl requires explicit paths
|
# macOS with brew-installed openssl requires explicit paths
|
||||||
# It can be configured with OPENSSL_PREFIX variable
|
# It can be configured with OPENSSL_PREFIX variable
|
||||||
@@ -77,6 +66,8 @@ CARGO_BUILD_FLAGS += $(filter -j1,$(MAKEFLAGS))
|
|||||||
CARGO_CMD_PREFIX += $(if $(filter n,$(MAKEFLAGS)),,+)
|
CARGO_CMD_PREFIX += $(if $(filter n,$(MAKEFLAGS)),,+)
|
||||||
# Force cargo not to print progress bar
|
# Force cargo not to print progress bar
|
||||||
CARGO_CMD_PREFIX += CARGO_TERM_PROGRESS_WHEN=never CI=1
|
CARGO_CMD_PREFIX += CARGO_TERM_PROGRESS_WHEN=never CI=1
|
||||||
|
# Set PQ_LIB_DIR to make sure `storage_controller` get linked with bundled libpq (through diesel)
|
||||||
|
CARGO_CMD_PREFIX += PQ_LIB_DIR=$(POSTGRES_INSTALL_DIR)/v16/lib
|
||||||
|
|
||||||
CACHEDIR_TAG_CONTENTS := "Signature: 8a477f597d28d172789f06886806bc55"
|
CACHEDIR_TAG_CONTENTS := "Signature: 8a477f597d28d172789f06886806bc55"
|
||||||
|
|
||||||
@@ -119,7 +110,7 @@ $(POSTGRES_INSTALL_DIR)/build/%/config.status:
|
|||||||
EXTRA_VERSION=$$(cd $(ROOT_PROJECT_DIR)/vendor/postgres-$$VERSION && git rev-parse HEAD); \
|
EXTRA_VERSION=$$(cd $(ROOT_PROJECT_DIR)/vendor/postgres-$$VERSION && git rev-parse HEAD); \
|
||||||
(cd $(POSTGRES_INSTALL_DIR)/build/$$VERSION && \
|
(cd $(POSTGRES_INSTALL_DIR)/build/$$VERSION && \
|
||||||
env PATH="$(EXTRA_PATH_OVERRIDES):$$PATH" $(ROOT_PROJECT_DIR)/vendor/postgres-$$VERSION/configure \
|
env PATH="$(EXTRA_PATH_OVERRIDES):$$PATH" $(ROOT_PROJECT_DIR)/vendor/postgres-$$VERSION/configure \
|
||||||
CFLAGS='$(PG_CFLAGS)' LDFLAGS='$(PG_LDFLAGS)' \
|
CFLAGS='$(PG_CFLAGS)' \
|
||||||
$(PG_CONFIGURE_OPTS) --with-extra-version=" ($$EXTRA_VERSION)" \
|
$(PG_CONFIGURE_OPTS) --with-extra-version=" ($$EXTRA_VERSION)" \
|
||||||
--prefix=$(abspath $(POSTGRES_INSTALL_DIR))/$$VERSION > configure.log)
|
--prefix=$(abspath $(POSTGRES_INSTALL_DIR))/$$VERSION > configure.log)
|
||||||
|
|
||||||
@@ -155,8 +146,6 @@ postgres-%: postgres-configure-% \
|
|||||||
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pg_prewarm install
|
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pg_prewarm install
|
||||||
+@echo "Compiling pg_buffercache $*"
|
+@echo "Compiling pg_buffercache $*"
|
||||||
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pg_buffercache install
|
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pg_buffercache install
|
||||||
+@echo "Compiling pg_visibility $*"
|
|
||||||
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pg_visibility install
|
|
||||||
+@echo "Compiling pageinspect $*"
|
+@echo "Compiling pageinspect $*"
|
||||||
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pageinspect install
|
$(MAKE) -C $(POSTGRES_INSTALL_DIR)/build/$*/contrib/pageinspect install
|
||||||
+@echo "Compiling amcheck $*"
|
+@echo "Compiling amcheck $*"
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ The Neon storage engine consists of two major components:
|
|||||||
|
|
||||||
See developer documentation in [SUMMARY.md](/docs/SUMMARY.md) for more information.
|
See developer documentation in [SUMMARY.md](/docs/SUMMARY.md) for more information.
|
||||||
|
|
||||||
## Running a local development environment
|
## Running local installation
|
||||||
|
|
||||||
Neon can be run on a workstation for small experiments and to test code changes, by
|
|
||||||
following these instructions.
|
|
||||||
|
|
||||||
#### Installing dependencies on Linux
|
#### Installing dependencies on Linux
|
||||||
1. Install build dependencies and other applicable packages
|
1. Install build dependencies and other applicable packages
|
||||||
@@ -134,7 +132,7 @@ make -j`sysctl -n hw.logicalcpu` -s
|
|||||||
To run the `psql` client, install the `postgresql-client` package or modify `PATH` and `LD_LIBRARY_PATH` to include `pg_install/bin` and `pg_install/lib`, respectively.
|
To run the `psql` client, install the `postgresql-client` package or modify `PATH` and `LD_LIBRARY_PATH` to include `pg_install/bin` and `pg_install/lib`, respectively.
|
||||||
|
|
||||||
To run the integration tests or Python scripts (not required to use the code), install
|
To run the integration tests or Python scripts (not required to use the code), install
|
||||||
Python (3.11 or higher), and install the python3 packages using `./scripts/pysync` (requires [poetry>=1.8](https://python-poetry.org/)) in the project directory.
|
Python (3.9 or higher), and install the python3 packages using `./scripts/pysync` (requires [poetry>=1.8](https://python-poetry.org/)) in the project directory.
|
||||||
|
|
||||||
|
|
||||||
#### Running neon database
|
#### Running neon database
|
||||||
@@ -240,7 +238,7 @@ postgres=# select * from t;
|
|||||||
> cargo neon stop
|
> cargo neon stop
|
||||||
```
|
```
|
||||||
|
|
||||||
More advanced usages can be found at [Local Development Control Plane (`neon_local`))](./control_plane/README.md).
|
More advanced usages can be found at [Control Plane and Neon Local](./control_plane/README.md).
|
||||||
|
|
||||||
#### Handling build failures
|
#### Handling build failures
|
||||||
|
|
||||||
|
|||||||
@@ -1,105 +1,11 @@
|
|||||||
ARG DEBIAN_VERSION=bookworm
|
ARG DEBIAN_VERSION=bullseye
|
||||||
ARG DEBIAN_FLAVOR=${DEBIAN_VERSION}-slim
|
|
||||||
|
|
||||||
# Here are the INDEX DIGESTS for the images we use.
|
FROM debian:${DEBIAN_VERSION}-slim
|
||||||
# You can get them following next steps for now:
|
|
||||||
# 1. Get an authentication token from DockerHub:
|
|
||||||
# TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/debian:pull" | jq -r .token)
|
|
||||||
# 2. Using that token, query index for the given tag:
|
|
||||||
# curl -s -H "Authorization: Bearer $TOKEN" \
|
|
||||||
# -H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
|
|
||||||
# "https://registry.hub.docker.com/v2/library/debian/manifests/bullseye-slim" \
|
|
||||||
# -I | grep -i docker-content-digest
|
|
||||||
# 3. As a next step, TODO(fedordikarev): create script and schedule workflow to run these checks
|
|
||||||
# and updates on regular bases and in automated way.
|
|
||||||
ARG BOOKWORM_SLIM_SHA=sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7
|
|
||||||
ARG BULLSEYE_SLIM_SHA=sha256:e831d9a884d63734fe3dd9c491ed9a5a3d4c6a6d32c5b14f2067357c49b0b7e1
|
|
||||||
|
|
||||||
# Here we use ${var/search/replace} syntax, to check
|
|
||||||
# if base image is one of the images, we pin image index for.
|
|
||||||
# If var will match one the known images, we will replace it with the known sha.
|
|
||||||
# If no match, than value will be unaffected, and will process with no-pinned image.
|
|
||||||
ARG BASE_IMAGE_SHA=debian:${DEBIAN_FLAVOR}
|
|
||||||
ARG BASE_IMAGE_SHA=${BASE_IMAGE_SHA/debian:bookworm-slim/debian@$BOOKWORM_SLIM_SHA}
|
|
||||||
ARG BASE_IMAGE_SHA=${BASE_IMAGE_SHA/debian:bullseye-slim/debian@$BULLSEYE_SLIM_SHA}
|
|
||||||
|
|
||||||
FROM $BASE_IMAGE_SHA AS pgcopydb_builder
|
|
||||||
ARG DEBIAN_VERSION
|
|
||||||
|
|
||||||
# Use strict mode for bash to catch errors early
|
|
||||||
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
|
|
||||||
|
|
||||||
# By default, /bin/sh used in debian images will treat '\n' as eol,
|
|
||||||
# but as we use bash as SHELL, and built-in echo in bash requires '-e' flag for that.
|
|
||||||
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries && \
|
|
||||||
echo -e "retry_connrefused=on\ntimeout=15\ntries=5\nretry-on-host-error=on\n" > /root/.wgetrc && \
|
|
||||||
echo -e "--retry-connrefused\n--connect-timeout 15\n--retry 5\n--max-time 300\n" > /root/.curlrc
|
|
||||||
|
|
||||||
COPY build_tools/patches/pgcopydbv017.patch /pgcopydbv017.patch
|
|
||||||
|
|
||||||
RUN if [ "${DEBIAN_VERSION}" = "bookworm" ]; then \
|
|
||||||
set -e && \
|
|
||||||
apt update && \
|
|
||||||
apt install -y --no-install-recommends \
|
|
||||||
ca-certificates wget gpg && \
|
|
||||||
wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/postgresql-keyring.gpg && \
|
|
||||||
echo "deb [signed-by=/usr/share/keyrings/postgresql-keyring.gpg] http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
|
|
||||||
apt-get update && \
|
|
||||||
apt install -y --no-install-recommends \
|
|
||||||
build-essential \
|
|
||||||
autotools-dev \
|
|
||||||
libedit-dev \
|
|
||||||
libgc-dev \
|
|
||||||
libpam0g-dev \
|
|
||||||
libreadline-dev \
|
|
||||||
libselinux1-dev \
|
|
||||||
libxslt1-dev \
|
|
||||||
libssl-dev \
|
|
||||||
libkrb5-dev \
|
|
||||||
zlib1g-dev \
|
|
||||||
liblz4-dev \
|
|
||||||
libpq5 \
|
|
||||||
libpq-dev \
|
|
||||||
libzstd-dev \
|
|
||||||
postgresql-16 \
|
|
||||||
postgresql-server-dev-16 \
|
|
||||||
postgresql-common \
|
|
||||||
python3-sphinx && \
|
|
||||||
wget -O /tmp/pgcopydb.tar.gz https://github.com/dimitri/pgcopydb/archive/refs/tags/v0.17.tar.gz && \
|
|
||||||
mkdir /tmp/pgcopydb && \
|
|
||||||
tar -xzf /tmp/pgcopydb.tar.gz -C /tmp/pgcopydb --strip-components=1 && \
|
|
||||||
cd /tmp/pgcopydb && \
|
|
||||||
patch -p1 < /pgcopydbv017.patch && \
|
|
||||||
make -s clean && \
|
|
||||||
make -s -j12 install && \
|
|
||||||
libpq_path=$(find /lib /usr/lib -name "libpq.so.5" | head -n 1) && \
|
|
||||||
mkdir -p /pgcopydb/lib && \
|
|
||||||
cp "$libpq_path" /pgcopydb/lib/; \
|
|
||||||
else \
|
|
||||||
# copy command below will fail if we don't have dummy files, so we create them for other debian versions
|
|
||||||
mkdir -p /usr/lib/postgresql/16/bin && touch /usr/lib/postgresql/16/bin/pgcopydb && \
|
|
||||||
mkdir -p mkdir -p /pgcopydb/lib && touch /pgcopydb/lib/libpq.so.5; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
FROM $BASE_IMAGE_SHA AS build_tools
|
|
||||||
ARG DEBIAN_VERSION
|
ARG DEBIAN_VERSION
|
||||||
|
|
||||||
# Add nonroot user
|
# Add nonroot user
|
||||||
RUN useradd -ms /bin/bash nonroot -b /home
|
RUN useradd -ms /bin/bash nonroot -b /home
|
||||||
# Use strict mode for bash to catch errors early
|
SHELL ["/bin/bash", "-c"]
|
||||||
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
|
|
||||||
|
|
||||||
RUN mkdir -p /pgcopydb/bin && \
|
|
||||||
mkdir -p /pgcopydb/lib && \
|
|
||||||
chmod -R 755 /pgcopydb && \
|
|
||||||
chown -R nonroot:nonroot /pgcopydb
|
|
||||||
|
|
||||||
COPY --from=pgcopydb_builder /usr/lib/postgresql/16/bin/pgcopydb /pgcopydb/bin/pgcopydb
|
|
||||||
COPY --from=pgcopydb_builder /pgcopydb/lib/libpq.so.5 /pgcopydb/lib/libpq.so.5
|
|
||||||
|
|
||||||
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries && \
|
|
||||||
echo -e "retry_connrefused=on\ntimeout=15\ntries=5\nretry-on-host-error=on\n" > /root/.wgetrc && \
|
|
||||||
echo -e "--retry-connrefused\n--connect-timeout 15\n--retry 5\n--max-time 300\n" > /root/.curlrc
|
|
||||||
|
|
||||||
# System deps
|
# System deps
|
||||||
#
|
#
|
||||||
@@ -132,7 +38,7 @@ RUN set -e \
|
|||||||
libseccomp-dev \
|
libseccomp-dev \
|
||||||
libsqlite3-dev \
|
libsqlite3-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
$([[ "${DEBIAN_VERSION}" = "bullseye" ]] && echo libstdc++-10-dev || echo libstdc++-11-dev) \
|
$([[ "${DEBIAN_VERSION}" = "bullseye" ]] && libstdc++-10-dev || libstdc++-11-dev) \
|
||||||
libtool \
|
libtool \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
libxmlsec1-dev \
|
libxmlsec1-dev \
|
||||||
@@ -151,19 +57,6 @@ RUN set -e \
|
|||||||
zstd \
|
zstd \
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
# sql_exporter
|
|
||||||
|
|
||||||
# Keep the version the same as in compute/compute-node.Dockerfile and
|
|
||||||
# test_runner/regress/test_compute_metrics.py.
|
|
||||||
ENV SQL_EXPORTER_VERSION=0.17.0
|
|
||||||
RUN curl -fsSL \
|
|
||||||
"https://github.com/burningalchemist/sql_exporter/releases/download/${SQL_EXPORTER_VERSION}/sql_exporter-${SQL_EXPORTER_VERSION}.linux-$(case "$(uname -m)" in x86_64) echo amd64;; aarch64) echo arm64;; esac).tar.gz" \
|
|
||||||
--output sql_exporter.tar.gz \
|
|
||||||
&& mkdir /tmp/sql_exporter \
|
|
||||||
&& tar xzvf sql_exporter.tar.gz -C /tmp/sql_exporter --strip-components=1 \
|
|
||||||
&& mv /tmp/sql_exporter/sql_exporter /usr/local/bin/sql_exporter \
|
|
||||||
&& rm sql_exporter.tar.gz
|
|
||||||
|
|
||||||
# protobuf-compiler (protoc)
|
# protobuf-compiler (protoc)
|
||||||
ENV PROTOC_VERSION=25.1
|
ENV PROTOC_VERSION=25.1
|
||||||
RUN curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-$(uname -m | sed 's/aarch64/aarch_64/g').zip" -o "protoc.zip" \
|
RUN curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-$(uname -m | sed 's/aarch64/aarch_64/g').zip" -o "protoc.zip" \
|
||||||
@@ -223,20 +116,29 @@ RUN set -e \
|
|||||||
# It includes several bug fixes on top on v2.0 release (https://github.com/linux-test-project/lcov/compare/v2.0...master)
|
# It includes several bug fixes on top on v2.0 release (https://github.com/linux-test-project/lcov/compare/v2.0...master)
|
||||||
# And patches from us:
|
# And patches from us:
|
||||||
# - Generates json file with code coverage summary (https://github.com/neondatabase/lcov/commit/426e7e7a22f669da54278e9b55e6d8caabd00af0.tar.gz)
|
# - Generates json file with code coverage summary (https://github.com/neondatabase/lcov/commit/426e7e7a22f669da54278e9b55e6d8caabd00af0.tar.gz)
|
||||||
RUN set +o pipefail && \
|
RUN for package in Capture::Tiny DateTime Devel::Cover Digest::MD5 File::Spec JSON::XS Memory::Process Time::HiRes JSON; do yes | perl -MCPAN -e "CPAN::Shell->notest('install', '$package')"; done \
|
||||||
for package in Capture::Tiny DateTime Devel::Cover Digest::MD5 File::Spec JSON::XS Memory::Process Time::HiRes JSON; do \
|
&& wget https://github.com/neondatabase/lcov/archive/426e7e7a22f669da54278e9b55e6d8caabd00af0.tar.gz -O lcov.tar.gz \
|
||||||
yes | perl -MCPAN -e "CPAN::Shell->notest('install', '$package')";\
|
|
||||||
done && \
|
|
||||||
set -o pipefail
|
|
||||||
# Split into separate step to debug flaky failures here
|
|
||||||
RUN wget https://github.com/neondatabase/lcov/archive/426e7e7a22f669da54278e9b55e6d8caabd00af0.tar.gz -O lcov.tar.gz \
|
|
||||||
&& ls -laht lcov.tar.gz && sha256sum lcov.tar.gz \
|
|
||||||
&& echo "61a22a62e20908b8b9e27d890bd0ea31f567a7b9668065589266371dcbca0992 lcov.tar.gz" | sha256sum --check \
|
&& echo "61a22a62e20908b8b9e27d890bd0ea31f567a7b9668065589266371dcbca0992 lcov.tar.gz" | sha256sum --check \
|
||||||
&& mkdir -p lcov && tar -xzf lcov.tar.gz -C lcov --strip-components=1 \
|
&& mkdir -p lcov && tar -xzf lcov.tar.gz -C lcov --strip-components=1 \
|
||||||
&& cd lcov \
|
&& cd lcov \
|
||||||
&& make install \
|
&& make install \
|
||||||
&& rm -rf ../lcov.tar.gz
|
&& rm -rf ../lcov.tar.gz
|
||||||
|
|
||||||
|
# Compile and install the static OpenSSL library
|
||||||
|
ENV OPENSSL_VERSION=1.1.1w
|
||||||
|
ENV OPENSSL_PREFIX=/usr/local/openssl
|
||||||
|
RUN wget -O /tmp/openssl-${OPENSSL_VERSION}.tar.gz https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||||
|
echo "cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8 /tmp/openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum --check && \
|
||||||
|
cd /tmp && \
|
||||||
|
tar xzvf /tmp/openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||||
|
rm /tmp/openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||||
|
cd /tmp/openssl-${OPENSSL_VERSION} && \
|
||||||
|
./config --prefix=${OPENSSL_PREFIX} -static --static no-shared -fPIC && \
|
||||||
|
make -j "$(nproc)" && \
|
||||||
|
make install && \
|
||||||
|
cd /tmp && \
|
||||||
|
rm -rf /tmp/openssl-${OPENSSL_VERSION}
|
||||||
|
|
||||||
# Use the same version of libicu as the compute nodes so that
|
# Use the same version of libicu as the compute nodes so that
|
||||||
# clusters created using inidb on pageserver can be used by computes.
|
# clusters created using inidb on pageserver can be used by computes.
|
||||||
#
|
#
|
||||||
@@ -265,10 +167,8 @@ RUN wget -O /tmp/libicu-${ICU_VERSION}.tgz https://github.com/unicode-org/icu/re
|
|||||||
USER nonroot:nonroot
|
USER nonroot:nonroot
|
||||||
WORKDIR /home/nonroot
|
WORKDIR /home/nonroot
|
||||||
|
|
||||||
RUN echo -e "--retry-connrefused\n--connect-timeout 15\n--retry 5\n--max-time 300\n" > /home/nonroot/.curlrc
|
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
ENV PYTHON_VERSION=3.11.10 \
|
ENV PYTHON_VERSION=3.9.19 \
|
||||||
PYENV_ROOT=/home/nonroot/.pyenv \
|
PYENV_ROOT=/home/nonroot/.pyenv \
|
||||||
PATH=/home/nonroot/.pyenv/shims:/home/nonroot/.pyenv/bin:/home/nonroot/.poetry/bin:$PATH
|
PATH=/home/nonroot/.pyenv/shims:/home/nonroot/.pyenv/bin:/home/nonroot/.poetry/bin:$PATH
|
||||||
RUN set -e \
|
RUN set -e \
|
||||||
@@ -292,16 +192,14 @@ WORKDIR /home/nonroot
|
|||||||
|
|
||||||
# Rust
|
# Rust
|
||||||
# Please keep the version of llvm (installed above) in sync with rust llvm (`rustc --version --verbose | grep LLVM`)
|
# Please keep the version of llvm (installed above) in sync with rust llvm (`rustc --version --verbose | grep LLVM`)
|
||||||
ENV RUSTC_VERSION=1.84.1
|
ENV RUSTC_VERSION=1.82.0
|
||||||
ENV RUSTUP_HOME="/home/nonroot/.rustup"
|
ENV RUSTUP_HOME="/home/nonroot/.rustup"
|
||||||
ENV PATH="/home/nonroot/.cargo/bin:${PATH}"
|
ENV PATH="/home/nonroot/.cargo/bin:${PATH}"
|
||||||
ARG RUSTFILT_VERSION=0.2.1
|
ARG RUSTFILT_VERSION=0.2.1
|
||||||
ARG CARGO_HAKARI_VERSION=0.9.33
|
ARG CARGO_HAKARI_VERSION=0.9.30
|
||||||
ARG CARGO_DENY_VERSION=0.16.2
|
ARG CARGO_DENY_VERSION=0.16.1
|
||||||
ARG CARGO_HACK_VERSION=0.6.33
|
ARG CARGO_HACK_VERSION=0.6.31
|
||||||
ARG CARGO_NEXTEST_VERSION=0.9.85
|
ARG CARGO_NEXTEST_VERSION=0.9.72
|
||||||
ARG CARGO_CHEF_VERSION=0.1.71
|
|
||||||
ARG CARGO_DIESEL_CLI_VERSION=2.2.6
|
|
||||||
RUN curl -sSO https://static.rust-lang.org/rustup/dist/$(uname -m)-unknown-linux-gnu/rustup-init && whoami && \
|
RUN curl -sSO https://static.rust-lang.org/rustup/dist/$(uname -m)-unknown-linux-gnu/rustup-init && whoami && \
|
||||||
chmod +x rustup-init && \
|
chmod +x rustup-init && \
|
||||||
./rustup-init -y --default-toolchain ${RUSTC_VERSION} && \
|
./rustup-init -y --default-toolchain ${RUSTC_VERSION} && \
|
||||||
@@ -315,9 +213,6 @@ RUN curl -sSO https://static.rust-lang.org/rustup/dist/$(uname -m)-unknown-linux
|
|||||||
cargo install cargo-deny --locked --version ${CARGO_DENY_VERSION} && \
|
cargo install cargo-deny --locked --version ${CARGO_DENY_VERSION} && \
|
||||||
cargo install cargo-hack --version ${CARGO_HACK_VERSION} && \
|
cargo install cargo-hack --version ${CARGO_HACK_VERSION} && \
|
||||||
cargo install cargo-nextest --version ${CARGO_NEXTEST_VERSION} && \
|
cargo install cargo-nextest --version ${CARGO_NEXTEST_VERSION} && \
|
||||||
cargo install cargo-chef --locked --version ${CARGO_CHEF_VERSION} && \
|
|
||||||
cargo install diesel_cli --version ${CARGO_DIESEL_CLI_VERSION} \
|
|
||||||
--features postgres-bundled --no-default-features && \
|
|
||||||
rm -rf /home/nonroot/.cargo/registry && \
|
rm -rf /home/nonroot/.cargo/registry && \
|
||||||
rm -rf /home/nonroot/.cargo/git
|
rm -rf /home/nonroot/.cargo/git
|
||||||
|
|
||||||
@@ -330,11 +225,5 @@ RUN whoami \
|
|||||||
&& rustc --version --verbose \
|
&& rustc --version --verbose \
|
||||||
&& clang --version
|
&& clang --version
|
||||||
|
|
||||||
RUN if [ "${DEBIAN_VERSION}" = "bookworm" ]; then \
|
|
||||||
LD_LIBRARY_PATH=/pgcopydb/lib /pgcopydb/bin/pgcopydb --version; \
|
|
||||||
else \
|
|
||||||
echo "pgcopydb is not available for ${DEBIAN_VERSION}"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set following flag to check in Makefile if its running in Docker
|
# Set following flag to check in Makefile if its running in Docker
|
||||||
RUN touch /home/nonroot/.docker_build
|
RUN touch /home/nonroot/.docker_build
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
diff --git a/src/bin/pgcopydb/copydb.c b/src/bin/pgcopydb/copydb.c
|
|
||||||
index d730b03..69a9be9 100644
|
|
||||||
--- a/src/bin/pgcopydb/copydb.c
|
|
||||||
+++ b/src/bin/pgcopydb/copydb.c
|
|
||||||
@@ -44,6 +44,7 @@ GUC dstSettings[] = {
|
|
||||||
{ "synchronous_commit", "'off'" },
|
|
||||||
{ "statement_timeout", "0" },
|
|
||||||
{ "lock_timeout", "0" },
|
|
||||||
+ { "idle_in_transaction_session_timeout", "0" },
|
|
||||||
{ NULL, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
diff --git a/src/bin/pgcopydb/pgsql.c b/src/bin/pgcopydb/pgsql.c
|
|
||||||
index 94f2f46..e051ba8 100644
|
|
||||||
--- a/src/bin/pgcopydb/pgsql.c
|
|
||||||
+++ b/src/bin/pgcopydb/pgsql.c
|
|
||||||
@@ -2319,6 +2319,11 @@ pgsql_execute_log_error(PGSQL *pgsql,
|
|
||||||
|
|
||||||
LinesBuffer lbuf = { 0 };
|
|
||||||
|
|
||||||
+ if (message != NULL){
|
|
||||||
+ // make sure message is writable by splitLines
|
|
||||||
+ message = strdup(message);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (!splitLines(&lbuf, message))
|
|
||||||
{
|
|
||||||
/* errors have already been logged */
|
|
||||||
@@ -2332,6 +2337,7 @@ pgsql_execute_log_error(PGSQL *pgsql,
|
|
||||||
PQbackendPID(pgsql->connection),
|
|
||||||
lbuf.lines[lineNumber]);
|
|
||||||
}
|
|
||||||
+ free(message); // free copy of message we created above
|
|
||||||
|
|
||||||
if (pgsql->logSQL)
|
|
||||||
{
|
|
||||||
@@ -3174,11 +3180,18 @@ pgcopy_log_error(PGSQL *pgsql, PGresult *res, const char *context)
|
|
||||||
/* errors have already been logged */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
if (res != NULL)
|
|
||||||
{
|
|
||||||
char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
|
|
||||||
- strlcpy(pgsql->sqlstate, sqlstate, sizeof(pgsql->sqlstate));
|
|
||||||
+ if (sqlstate == NULL)
|
|
||||||
+ {
|
|
||||||
+ // PQresultErrorField returned NULL!
|
|
||||||
+ pgsql->sqlstate[0] = '\0'; // Set to an empty string to avoid segfault
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ strlcpy(pgsql->sqlstate, sqlstate, sizeof(pgsql->sqlstate));
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
char *endpoint =
|
|
||||||
@@ -22,7 +22,6 @@ sql_exporter.yml: $(jsonnet_files)
|
|||||||
--output-file etc/$@ \
|
--output-file etc/$@ \
|
||||||
--tla-str collector_name=neon_collector \
|
--tla-str collector_name=neon_collector \
|
||||||
--tla-str collector_file=neon_collector.yml \
|
--tla-str collector_file=neon_collector.yml \
|
||||||
--tla-str 'connection_string=postgresql://cloud_admin@127.0.0.1:5432/postgres?sslmode=disable&application_name=sql_exporter' \
|
|
||||||
etc/sql_exporter.jsonnet
|
etc/sql_exporter.jsonnet
|
||||||
|
|
||||||
sql_exporter_autoscaling.yml: $(jsonnet_files)
|
sql_exporter_autoscaling.yml: $(jsonnet_files)
|
||||||
@@ -30,7 +29,7 @@ sql_exporter_autoscaling.yml: $(jsonnet_files)
|
|||||||
--output-file etc/$@ \
|
--output-file etc/$@ \
|
||||||
--tla-str collector_name=neon_collector_autoscaling \
|
--tla-str collector_name=neon_collector_autoscaling \
|
||||||
--tla-str collector_file=neon_collector_autoscaling.yml \
|
--tla-str collector_file=neon_collector_autoscaling.yml \
|
||||||
--tla-str 'connection_string=postgresql://cloud_admin@127.0.0.1:5432/postgres?sslmode=disable&application_name=sql_exporter_autoscaling' \
|
--tla-str application_name=sql_exporter_autoscaling \
|
||||||
etc/sql_exporter.jsonnet
|
etc/sql_exporter.jsonnet
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,11 +3,8 @@
|
|||||||
metrics: [
|
metrics: [
|
||||||
import 'sql_exporter/checkpoints_req.libsonnet',
|
import 'sql_exporter/checkpoints_req.libsonnet',
|
||||||
import 'sql_exporter/checkpoints_timed.libsonnet',
|
import 'sql_exporter/checkpoints_timed.libsonnet',
|
||||||
import 'sql_exporter/compute_backpressure_throttling_seconds_total.libsonnet',
|
|
||||||
import 'sql_exporter/compute_current_lsn.libsonnet',
|
import 'sql_exporter/compute_current_lsn.libsonnet',
|
||||||
import 'sql_exporter/compute_logical_snapshot_files.libsonnet',
|
import 'sql_exporter/compute_logical_snapshot_files.libsonnet',
|
||||||
import 'sql_exporter/compute_logical_snapshots_bytes.libsonnet',
|
|
||||||
import 'sql_exporter/compute_max_connections.libsonnet',
|
|
||||||
import 'sql_exporter/compute_receive_lsn.libsonnet',
|
import 'sql_exporter/compute_receive_lsn.libsonnet',
|
||||||
import 'sql_exporter/compute_subscriptions_count.libsonnet',
|
import 'sql_exporter/compute_subscriptions_count.libsonnet',
|
||||||
import 'sql_exporter/connection_counts.libsonnet',
|
import 'sql_exporter/connection_counts.libsonnet',
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
[databases]
|
[databases]
|
||||||
;; pgbouncer propagates application_name (if it's specified) to the server, but some
|
*=host=localhost port=5432 auth_user=cloud_admin
|
||||||
;; clients don't set it. We set default application_name=pgbouncer to make it
|
|
||||||
;; easier to identify pgbouncer connections in Postgres. If client sets
|
|
||||||
;; application_name, it will be used instead.
|
|
||||||
*=host=localhost port=5432 auth_user=cloud_admin application_name=pgbouncer
|
|
||||||
[pgbouncer]
|
[pgbouncer]
|
||||||
listen_port=6432
|
listen_port=6432
|
||||||
listen_addr=0.0.0.0
|
listen_addr=0.0.0.0
|
||||||
@@ -19,12 +15,3 @@ max_prepared_statements=0
|
|||||||
admin_users=postgres
|
admin_users=postgres
|
||||||
unix_socket_dir=/tmp/
|
unix_socket_dir=/tmp/
|
||||||
unix_socket_mode=0777
|
unix_socket_mode=0777
|
||||||
; required for pgbouncer_exporter
|
|
||||||
ignore_startup_parameters=extra_float_digits
|
|
||||||
|
|
||||||
;; Disable connection logging. It produces a lot of logs that no one looks at,
|
|
||||||
;; and we can get similar log entries from the proxy too. We had incidents in
|
|
||||||
;; the past where the logging significantly stressed the log device or pgbouncer
|
|
||||||
;; itself.
|
|
||||||
log_connections=0
|
|
||||||
log_disconnections=0
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
function(collector_name, collector_file, connection_string) {
|
function(collector_name, collector_file, application_name='sql_exporter') {
|
||||||
// Configuration for sql_exporter for autoscaling-agent
|
// Configuration for sql_exporter for autoscaling-agent
|
||||||
// Global defaults.
|
// Global defaults.
|
||||||
global: {
|
global: {
|
||||||
@@ -23,7 +23,7 @@ function(collector_name, collector_file, connection_string) {
|
|||||||
target: {
|
target: {
|
||||||
// Data source name always has a URI schema that matches the driver name. In some cases (e.g. MySQL)
|
// Data source name always has a URI schema that matches the driver name. In some cases (e.g. MySQL)
|
||||||
// the schema gets dropped or replaced to match the driver expected DSN format.
|
// the schema gets dropped or replaced to match the driver expected DSN format.
|
||||||
data_source_name: connection_string,
|
data_source_name: std.format('postgresql://cloud_admin@127.0.0.1:5432/postgres?sslmode=disable&application_name=%s', [application_name]),
|
||||||
|
|
||||||
// Collectors (referenced by name) to execute on the target.
|
// Collectors (referenced by name) to execute on the target.
|
||||||
// Glob patterns are supported (see <https://pkg.go.dev/path/filepath#Match> for syntax).
|
// Glob patterns are supported (see <https://pkg.go.dev/path/filepath#Match> for syntax).
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
metric_name: 'compute_backpressure_throttling_seconds_total',
|
|
||||||
type: 'counter',
|
|
||||||
help: 'Time compute has spent throttled',
|
|
||||||
key_labels: null,
|
|
||||||
values: [
|
|
||||||
'throttled',
|
|
||||||
],
|
|
||||||
query: importstr 'sql_exporter/compute_backpressure_throttling_seconds_total.sql',
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
SELECT (neon.backpressure_throttling_time()::float8 / 1000000) AS throttled;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
SELECT
|
|
||||||
(SELECT current_setting('neon.timeline_id')) AS timeline_id,
|
|
||||||
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
|
||||||
-- These temporary snapshot files are renamed to the actual snapshot files
|
|
||||||
-- after they are completely built. We only WAL-log the completely built
|
|
||||||
-- snapshot files
|
|
||||||
(SELECT COALESCE(sum(size), 0) FROM pg_ls_logicalsnapdir() WHERE name LIKE '%.snap') AS logical_snapshots_bytes;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
local neon = import 'neon.libsonnet';
|
|
||||||
|
|
||||||
local pg_ls_logicalsnapdir = importstr 'sql_exporter/compute_logical_snapshots_bytes.15.sql';
|
|
||||||
local pg_ls_dir = importstr 'sql_exporter/compute_logical_snapshots_bytes.sql';
|
|
||||||
|
|
||||||
{
|
|
||||||
metric_name: 'compute_logical_snapshots_bytes',
|
|
||||||
type: 'gauge',
|
|
||||||
help: 'Size of the pg_logical/snapshots directory, not including temporary files',
|
|
||||||
key_labels: [
|
|
||||||
'timeline_id',
|
|
||||||
],
|
|
||||||
values: [
|
|
||||||
'logical_snapshots_bytes',
|
|
||||||
],
|
|
||||||
query: if neon.PG_MAJORVERSION_NUM < 15 then pg_ls_dir else pg_ls_logicalsnapdir,
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
SELECT
|
|
||||||
(SELECT setting FROM pg_settings WHERE name = 'neon.timeline_id') AS timeline_id,
|
|
||||||
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
|
||||||
-- These temporary snapshot files are renamed to the actual snapshot files
|
|
||||||
-- after they are completely built. We only WAL-log the completely built
|
|
||||||
-- snapshot files
|
|
||||||
(SELECT COALESCE(sum((pg_stat_file('pg_logical/snapshots/' || name, missing_ok => true)).size), 0)
|
|
||||||
FROM (SELECT * FROM pg_ls_dir('pg_logical/snapshots') WHERE pg_ls_dir LIKE '%.snap') AS name
|
|
||||||
) AS logical_snapshots_bytes;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
metric_name: 'compute_max_connections',
|
|
||||||
type: 'gauge',
|
|
||||||
help: 'Max connections allowed for Postgres',
|
|
||||||
key_labels: null,
|
|
||||||
values: [
|
|
||||||
'max_connections',
|
|
||||||
],
|
|
||||||
query: importstr 'sql_exporter/compute_max_connections.sql',
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
SELECT current_setting('max_connections') as max_connections;
|
|
||||||
@@ -147,7 +147,7 @@ index 542c2e098c..0062d3024f 100644
|
|||||||
ALTER TABLE ptnowner1 OWNER TO regress_ptnowner;
|
ALTER TABLE ptnowner1 OWNER TO regress_ptnowner;
|
||||||
ALTER TABLE ptnowner OWNER TO regress_ptnowner;
|
ALTER TABLE ptnowner OWNER TO regress_ptnowner;
|
||||||
diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out
|
diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out
|
||||||
index 3f9a8f539c..0a51b52940 100644
|
index 97bbe53b64..eac3d42a79 100644
|
||||||
--- a/src/test/regress/expected/collate.icu.utf8.out
|
--- a/src/test/regress/expected/collate.icu.utf8.out
|
||||||
+++ b/src/test/regress/expected/collate.icu.utf8.out
|
+++ b/src/test/regress/expected/collate.icu.utf8.out
|
||||||
@@ -1016,7 +1016,7 @@ select * from collate_test1 where b ilike 'ABC';
|
@@ -1016,7 +1016,7 @@ select * from collate_test1 where b ilike 'ABC';
|
||||||
@@ -309,7 +309,7 @@ index b48365ec98..a6ef910055 100644
|
|||||||
-- the wrong partition. This test is *not* guaranteed to trigger that bug, but
|
-- the wrong partition. This test is *not* guaranteed to trigger that bug, but
|
||||||
-- does so when shared_buffers is small enough. To test if we encountered the
|
-- does so when shared_buffers is small enough. To test if we encountered the
|
||||||
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
|
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
|
||||||
index 9a74820ee8..22400a5551 100644
|
index faf1a4d1b0..a44c97db52 100644
|
||||||
--- a/src/test/regress/expected/copy2.out
|
--- a/src/test/regress/expected/copy2.out
|
||||||
+++ b/src/test/regress/expected/copy2.out
|
+++ b/src/test/regress/expected/copy2.out
|
||||||
@@ -553,8 +553,8 @@ select * from check_con_tbl;
|
@@ -553,8 +553,8 @@ select * from check_con_tbl;
|
||||||
@@ -573,7 +573,7 @@ index 93302a07ef..1a73f083ac 100644
|
|||||||
-- that does not match with what's expected.
|
-- that does not match with what's expected.
|
||||||
-- This checks all the object types that include schema qualifications.
|
-- This checks all the object types that include schema qualifications.
|
||||||
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
|
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
|
||||||
index f551624afb..57f1e432d4 100644
|
index f3f8c7b5a2..3e3e54ff4c 100644
|
||||||
--- a/src/test/regress/expected/create_view.out
|
--- a/src/test/regress/expected/create_view.out
|
||||||
+++ b/src/test/regress/expected/create_view.out
|
+++ b/src/test/regress/expected/create_view.out
|
||||||
@@ -18,7 +18,8 @@ CREATE TABLE real_city (
|
@@ -18,7 +18,8 @@ CREATE TABLE real_city (
|
||||||
@@ -700,12 +700,12 @@ index 6ed50fdcfa..caa00a345d 100644
|
|||||||
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
|
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
|
||||||
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
|
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
|
||||||
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
|
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
|
||||||
index 6b8c2f2414..8e13b7fa46 100644
|
index 12e523c737..8872e23935 100644
|
||||||
--- a/src/test/regress/expected/foreign_key.out
|
--- a/src/test/regress/expected/foreign_key.out
|
||||||
+++ b/src/test/regress/expected/foreign_key.out
|
+++ b/src/test/regress/expected/foreign_key.out
|
||||||
@@ -1985,7 +1985,7 @@ ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES
|
@@ -1968,7 +1968,7 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2
|
||||||
ERROR: cannot ALTER TABLE "fk_partitioned_pk_61" because it is being used by active queries in this session
|
FOR VALUES IN (1600);
|
||||||
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
|
-- leave these tables around intentionally
|
||||||
-- test the case when the referenced table is owned by a different user
|
-- test the case when the referenced table is owned by a different user
|
||||||
-create role regress_other_partitioned_fk_owner;
|
-create role regress_other_partitioned_fk_owner;
|
||||||
+create role regress_other_partitioned_fk_owner PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
+create role regress_other_partitioned_fk_owner PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
||||||
@@ -713,7 +713,7 @@ index 6b8c2f2414..8e13b7fa46 100644
|
|||||||
set role regress_other_partitioned_fk_owner;
|
set role regress_other_partitioned_fk_owner;
|
||||||
create table other_partitioned_fk(a int, b int) partition by list (a);
|
create table other_partitioned_fk(a int, b int) partition by list (a);
|
||||||
diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out
|
diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out
|
||||||
index 5881420388..4ae21aa43c 100644
|
index 0f623f7119..b48588a54e 100644
|
||||||
--- a/src/test/regress/expected/generated.out
|
--- a/src/test/regress/expected/generated.out
|
||||||
+++ b/src/test/regress/expected/generated.out
|
+++ b/src/test/regress/expected/generated.out
|
||||||
@@ -534,7 +534,7 @@ CREATE TABLE gtest10a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR
|
@@ -534,7 +534,7 @@ CREATE TABLE gtest10a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR
|
||||||
@@ -762,7 +762,7 @@ index a2036a1597..805d73b9d2 100644
|
|||||||
-- fields, leading to long bucket chains and lots of table expansion.
|
-- fields, leading to long bucket chains and lots of table expansion.
|
||||||
-- this is therefore a stress test of the bucket overflow code (unlike
|
-- this is therefore a stress test of the bucket overflow code (unlike
|
||||||
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
|
diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out
|
||||||
index 1b74958de9..078187b542 100644
|
index cc7772349f..98a08eb48d 100644
|
||||||
--- a/src/test/regress/expected/identity.out
|
--- a/src/test/regress/expected/identity.out
|
||||||
+++ b/src/test/regress/expected/identity.out
|
+++ b/src/test/regress/expected/identity.out
|
||||||
@@ -520,7 +520,7 @@ ALTER TABLE itest7 ALTER COLUMN a SET GENERATED BY DEFAULT;
|
@@ -520,7 +520,7 @@ ALTER TABLE itest7 ALTER COLUMN a SET GENERATED BY DEFAULT;
|
||||||
@@ -775,10 +775,10 @@ index 1b74958de9..078187b542 100644
|
|||||||
GRANT SELECT, INSERT ON itest8 TO regress_identity_user1;
|
GRANT SELECT, INSERT ON itest8 TO regress_identity_user1;
|
||||||
SET ROLE regress_identity_user1;
|
SET ROLE regress_identity_user1;
|
||||||
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
|
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
|
||||||
index 8f831c95c3..ec681b52af 100644
|
index 4943429e9b..0257f22b15 100644
|
||||||
--- a/src/test/regress/expected/inherit.out
|
--- a/src/test/regress/expected/inherit.out
|
||||||
+++ b/src/test/regress/expected/inherit.out
|
+++ b/src/test/regress/expected/inherit.out
|
||||||
@@ -2636,7 +2636,7 @@ create index on permtest_parent (left(c, 3));
|
@@ -2606,7 +2606,7 @@ create index on permtest_parent (left(c, 3));
|
||||||
insert into permtest_parent
|
insert into permtest_parent
|
||||||
select 1, 'a', left(fipshash(i::text), 5) from generate_series(0, 100) i;
|
select 1, 'a', left(fipshash(i::text), 5) from generate_series(0, 100) i;
|
||||||
analyze permtest_parent;
|
analyze permtest_parent;
|
||||||
@@ -981,7 +981,7 @@ index fc42d418bf..e38f517574 100644
|
|||||||
CREATE SCHEMA addr_nsp;
|
CREATE SCHEMA addr_nsp;
|
||||||
SET search_path TO 'addr_nsp';
|
SET search_path TO 'addr_nsp';
|
||||||
diff --git a/src/test/regress/expected/password.out b/src/test/regress/expected/password.out
|
diff --git a/src/test/regress/expected/password.out b/src/test/regress/expected/password.out
|
||||||
index 8475231735..0653946337 100644
|
index 8475231735..1afae5395f 100644
|
||||||
--- a/src/test/regress/expected/password.out
|
--- a/src/test/regress/expected/password.out
|
||||||
+++ b/src/test/regress/expected/password.out
|
+++ b/src/test/regress/expected/password.out
|
||||||
@@ -12,11 +12,11 @@ SET password_encryption = 'md5'; -- ok
|
@@ -12,11 +12,11 @@ SET password_encryption = 'md5'; -- ok
|
||||||
@@ -1006,63 +1006,65 @@ index 8475231735..0653946337 100644
|
|||||||
-----------------+---------------------------------------------------
|
-----------------+---------------------------------------------------
|
||||||
- regress_passwd1 | md5783277baca28003b33453252be4dbb34
|
- regress_passwd1 | md5783277baca28003b33453252be4dbb34
|
||||||
- regress_passwd2 | md54044304ba511dd062133eb5b4b84a2a3
|
- regress_passwd2 | md54044304ba511dd062133eb5b4b84a2a3
|
||||||
+ regress_passwd1 | NEON_MD5_PLACEHOLDER:regress_passwd1
|
+ regress_passwd1 | NEON_MD5_PLACEHOLDER_regress_passwd1
|
||||||
+ regress_passwd2 | NEON_MD5_PLACEHOLDER:regress_passwd2
|
+ regress_passwd2 | NEON_MD5_PLACEHOLDER_regress_passwd2
|
||||||
regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
- regress_passwd4 |
|
- regress_passwd4 |
|
||||||
+ regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
+ regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
-- Rename a role
|
-- Rename a role
|
||||||
@@ -54,24 +54,16 @@ ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
|
@@ -54,24 +54,30 @@ ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
|
||||||
-- passwords.
|
-- passwords.
|
||||||
SET password_encryption = 'md5';
|
SET password_encryption = 'md5';
|
||||||
-- encrypt with MD5
|
-- encrypt with MD5
|
||||||
-ALTER ROLE regress_passwd2 PASSWORD 'foo';
|
-ALTER ROLE regress_passwd2 PASSWORD 'foo';
|
||||||
--- already encrypted, use as they are
|
|
||||||
-ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
|
|
||||||
-ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
|
|
||||||
+ALTER ROLE regress_passwd2 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
+ALTER ROLE regress_passwd2 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
||||||
|
-- already encrypted, use as they are
|
||||||
|
ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
|
||||||
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
|
ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
|
||||||
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
SET password_encryption = 'scram-sha-256';
|
SET password_encryption = 'scram-sha-256';
|
||||||
-- create SCRAM secret
|
-- create SCRAM secret
|
||||||
-ALTER ROLE regress_passwd4 PASSWORD 'foo';
|
-ALTER ROLE regress_passwd4 PASSWORD 'foo';
|
||||||
--- already encrypted with MD5, use as it is
|
|
||||||
-CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
|
|
||||||
--- This looks like a valid SCRAM-SHA-256 secret, but it is not
|
|
||||||
--- so it should be hashed with SCRAM-SHA-256.
|
|
||||||
-CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
|
|
||||||
--- These may look like valid MD5 secrets, but they are not, so they
|
|
||||||
--- should be hashed with SCRAM-SHA-256.
|
|
||||||
--- trailing garbage at the end
|
|
||||||
-CREATE ROLE regress_passwd7 PASSWORD 'md5012345678901234567890123456789zz';
|
|
||||||
--- invalid length
|
|
||||||
-CREATE ROLE regress_passwd8 PASSWORD 'md501234567890123456789012345678901zz';
|
|
||||||
+ALTER ROLE regress_passwd4 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
+ALTER ROLE regress_passwd4 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
||||||
+-- Neon does not support encrypted passwords, use unencrypted instead
|
-- already encrypted with MD5, use as it is
|
||||||
+CREATE ROLE regress_passwd5 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
|
||||||
+-- Neon does not support encrypted passwords, use unencrypted instead
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
+CREATE ROLE regress_passwd6 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
-- This looks like a valid SCRAM-SHA-256 secret, but it is not
|
||||||
+CREATE ROLE regress_passwd7 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
-- so it should be hashed with SCRAM-SHA-256.
|
||||||
+CREATE ROLE regress_passwd8 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
|
||||||
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
|
-- These may look like valid MD5 secrets, but they are not, so they
|
||||||
|
-- should be hashed with SCRAM-SHA-256.
|
||||||
|
-- trailing garbage at the end
|
||||||
|
CREATE ROLE regress_passwd7 PASSWORD 'md5012345678901234567890123456789zz';
|
||||||
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
|
-- invalid length
|
||||||
|
CREATE ROLE regress_passwd8 PASSWORD 'md501234567890123456789012345678901zz';
|
||||||
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
-- Changing the SCRAM iteration count
|
-- Changing the SCRAM iteration count
|
||||||
SET scram_iterations = 1024;
|
SET scram_iterations = 1024;
|
||||||
CREATE ROLE regress_passwd9 PASSWORD 'alterediterationcount';
|
CREATE ROLE regress_passwd9 PASSWORD 'alterediterationcount';
|
||||||
@@ -81,11 +73,11 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
|
@@ -81,63 +87,67 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
|
||||||
ORDER BY rolname, rolpassword;
|
ORDER BY rolname, rolpassword;
|
||||||
rolname | rolpassword_masked
|
rolname | rolpassword_masked
|
||||||
-----------------+---------------------------------------------------
|
-----------------+---------------------------------------------------
|
||||||
- regress_passwd1 | md5cd3578025fe2c3d7ed1b9a9b26238b70
|
- regress_passwd1 | md5cd3578025fe2c3d7ed1b9a9b26238b70
|
||||||
- regress_passwd2 | md5dfa155cadd5f4ad57860162f3fab9cdb
|
- regress_passwd2 | md5dfa155cadd5f4ad57860162f3fab9cdb
|
||||||
+ regress_passwd1 | NEON_MD5_PLACEHOLDER:regress_passwd1
|
+ regress_passwd1 | NEON_MD5_PLACEHOLDER_regress_passwd1
|
||||||
+ regress_passwd2 | NEON_MD5_PLACEHOLDER:regress_passwd2
|
+ regress_passwd2 | NEON_MD5_PLACEHOLDER_regress_passwd2
|
||||||
regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
- regress_passwd5 | md5e73a4b11df52a6068f8b39f90be36023
|
- regress_passwd5 | md5e73a4b11df52a6068f8b39f90be36023
|
||||||
+ regress_passwd5 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
- regress_passwd6 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
regress_passwd6 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
- regress_passwd7 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
regress_passwd7 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
- regress_passwd8 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
||||||
regress_passwd8 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
|
regress_passwd9 | SCRAM-SHA-256$1024:<salt>$<storedkey>:<serverkey>
|
||||||
@@ -95,23 +87,20 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
|
-(9 rows)
|
||||||
|
+(5 rows)
|
||||||
|
|
||||||
-- An empty password is not allowed, in any form
|
-- An empty password is not allowed, in any form
|
||||||
CREATE ROLE regress_passwd_empty PASSWORD '';
|
CREATE ROLE regress_passwd_empty PASSWORD '';
|
||||||
NOTICE: empty string is not a valid password, clearing password
|
NOTICE: empty string is not a valid password, clearing password
|
||||||
@@ -1080,39 +1082,58 @@ index 8475231735..0653946337 100644
|
|||||||
-(1 row)
|
-(1 row)
|
||||||
+(0 rows)
|
+(0 rows)
|
||||||
|
|
||||||
--- Test with invalid stored and server keys.
|
-- Test with invalid stored and server keys.
|
||||||
---
|
--
|
||||||
--- The first is valid, to act as a control. The others have too long
|
-- The first is valid, to act as a control. The others have too long
|
||||||
--- stored/server keys. They will be re-hashed.
|
-- stored/server keys. They will be re-hashed.
|
||||||
-CREATE ROLE regress_passwd_sha_len0 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
|
CREATE ROLE regress_passwd_sha_len0 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
|
||||||
-CREATE ROLE regress_passwd_sha_len1 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96RqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
-CREATE ROLE regress_passwd_sha_len2 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=';
|
CREATE ROLE regress_passwd_sha_len1 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96RqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
|
||||||
+-- Neon does not support encrypted passwords, use unencrypted instead
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
+CREATE ROLE regress_passwd_sha_len0 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
CREATE ROLE regress_passwd_sha_len2 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=';
|
||||||
+CREATE ROLE regress_passwd_sha_len1 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
+ERROR: Received HTTP code 400 from control plane: {"error":"Neon only supports being given plaintext passwords"}
|
||||||
+CREATE ROLE regress_passwd_sha_len2 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
-- Check that the invalid secrets were re-hashed. A re-hashed secret
|
-- Check that the invalid secrets were re-hashed. A re-hashed secret
|
||||||
-- should not contain the original salt.
|
-- should not contain the original salt.
|
||||||
SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassword_rehashed
|
SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassword_rehashed
|
||||||
@@ -120,7 +109,7 @@ SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassw
|
FROM pg_authid
|
||||||
|
WHERE rolname LIKE 'regress_passwd_sha_len%'
|
||||||
ORDER BY rolname;
|
ORDER BY rolname;
|
||||||
rolname | is_rolpassword_rehashed
|
- rolname | is_rolpassword_rehashed
|
||||||
-------------------------+-------------------------
|
--------------------------+-------------------------
|
||||||
- regress_passwd_sha_len0 | f
|
- regress_passwd_sha_len0 | f
|
||||||
+ regress_passwd_sha_len0 | t
|
- regress_passwd_sha_len1 | t
|
||||||
regress_passwd_sha_len1 | t
|
- regress_passwd_sha_len2 | t
|
||||||
regress_passwd_sha_len2 | t
|
-(3 rows)
|
||||||
(3 rows)
|
+ rolname | is_rolpassword_rehashed
|
||||||
@@ -135,6 +124,7 @@ DROP ROLE regress_passwd7;
|
+---------+-------------------------
|
||||||
|
+(0 rows)
|
||||||
|
|
||||||
|
DROP ROLE regress_passwd1;
|
||||||
|
DROP ROLE regress_passwd2;
|
||||||
|
DROP ROLE regress_passwd3;
|
||||||
|
DROP ROLE regress_passwd4;
|
||||||
|
DROP ROLE regress_passwd5;
|
||||||
|
+ERROR: role "regress_passwd5" does not exist
|
||||||
|
DROP ROLE regress_passwd6;
|
||||||
|
+ERROR: role "regress_passwd6" does not exist
|
||||||
|
DROP ROLE regress_passwd7;
|
||||||
|
+ERROR: role "regress_passwd7" does not exist
|
||||||
DROP ROLE regress_passwd8;
|
DROP ROLE regress_passwd8;
|
||||||
|
+ERROR: role "regress_passwd8" does not exist
|
||||||
DROP ROLE regress_passwd9;
|
DROP ROLE regress_passwd9;
|
||||||
DROP ROLE regress_passwd_empty;
|
DROP ROLE regress_passwd_empty;
|
||||||
+ERROR: role "regress_passwd_empty" does not exist
|
+ERROR: role "regress_passwd_empty" does not exist
|
||||||
DROP ROLE regress_passwd_sha_len0;
|
DROP ROLE regress_passwd_sha_len0;
|
||||||
|
+ERROR: role "regress_passwd_sha_len0" does not exist
|
||||||
DROP ROLE regress_passwd_sha_len1;
|
DROP ROLE regress_passwd_sha_len1;
|
||||||
|
+ERROR: role "regress_passwd_sha_len1" does not exist
|
||||||
DROP ROLE regress_passwd_sha_len2;
|
DROP ROLE regress_passwd_sha_len2;
|
||||||
|
+ERROR: role "regress_passwd_sha_len2" does not exist
|
||||||
|
-- all entries should have been removed
|
||||||
|
SELECT rolname, rolpassword
|
||||||
|
FROM pg_authid
|
||||||
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
|
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
|
||||||
index 5b9dba7b32..cc408dad42 100644
|
index fbb0489a4f..2905194e2c 100644
|
||||||
--- a/src/test/regress/expected/privileges.out
|
--- a/src/test/regress/expected/privileges.out
|
||||||
+++ b/src/test/regress/expected/privileges.out
|
+++ b/src/test/regress/expected/privileges.out
|
||||||
@@ -20,19 +20,19 @@ SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3
|
@@ -20,19 +20,19 @@ SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3
|
||||||
@@ -1164,7 +1185,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
GRANT pg_read_all_data TO regress_priv_user6;
|
GRANT pg_read_all_data TO regress_priv_user6;
|
||||||
GRANT pg_write_all_data TO regress_priv_user7;
|
GRANT pg_write_all_data TO regress_priv_user7;
|
||||||
GRANT pg_read_all_settings TO regress_priv_user8 WITH ADMIN OPTION;
|
GRANT pg_read_all_settings TO regress_priv_user8 WITH ADMIN OPTION;
|
||||||
@@ -212,8 +212,8 @@ REVOKE pg_read_all_settings FROM regress_priv_user8;
|
@@ -145,8 +145,8 @@ REVOKE pg_read_all_settings FROM regress_priv_user8;
|
||||||
DROP USER regress_priv_user10;
|
DROP USER regress_priv_user10;
|
||||||
DROP USER regress_priv_user9;
|
DROP USER regress_priv_user9;
|
||||||
DROP USER regress_priv_user8;
|
DROP USER regress_priv_user8;
|
||||||
@@ -1175,7 +1196,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4;
|
ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4;
|
||||||
GRANT regress_priv_group2 TO regress_priv_user2 GRANTED BY regress_priv_user1;
|
GRANT regress_priv_group2 TO regress_priv_user2 GRANTED BY regress_priv_user1;
|
||||||
SET SESSION AUTHORIZATION regress_priv_user1;
|
SET SESSION AUTHORIZATION regress_priv_user1;
|
||||||
@@ -239,12 +239,16 @@ GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regre
|
@@ -172,12 +172,16 @@ GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regre
|
||||||
ERROR: permission denied to grant privileges as role "regress_priv_role"
|
ERROR: permission denied to grant privileges as role "regress_priv_role"
|
||||||
DETAIL: The grantor must have the ADMIN option on role "regress_priv_role".
|
DETAIL: The grantor must have the ADMIN option on role "regress_priv_role".
|
||||||
GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
|
GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
|
||||||
@@ -1192,7 +1213,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
DROP ROLE regress_priv_role;
|
DROP ROLE regress_priv_role;
|
||||||
SET SESSION AUTHORIZATION regress_priv_user1;
|
SET SESSION AUTHORIZATION regress_priv_user1;
|
||||||
SELECT session_user, current_user;
|
SELECT session_user, current_user;
|
||||||
@@ -1776,7 +1780,7 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP
|
@@ -1709,7 +1713,7 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP
|
||||||
|
|
||||||
-- security-restricted operations
|
-- security-restricted operations
|
||||||
\c -
|
\c -
|
||||||
@@ -1201,7 +1222,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
-- Check that index expressions and predicates are run as the table's owner
|
-- Check that index expressions and predicates are run as the table's owner
|
||||||
-- A dummy index function checking current_user
|
-- A dummy index function checking current_user
|
||||||
CREATE FUNCTION sro_ifun(int) RETURNS int AS $$
|
CREATE FUNCTION sro_ifun(int) RETURNS int AS $$
|
||||||
@@ -2668,8 +2672,8 @@ drop cascades to function testns.priv_testagg(integer)
|
@@ -2601,8 +2605,8 @@ drop cascades to function testns.priv_testagg(integer)
|
||||||
drop cascades to function testns.priv_testproc(integer)
|
drop cascades to function testns.priv_testproc(integer)
|
||||||
-- Change owner of the schema & and rename of new schema owner
|
-- Change owner of the schema & and rename of new schema owner
|
||||||
\c -
|
\c -
|
||||||
@@ -1212,7 +1233,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
SET SESSION ROLE regress_schemauser1;
|
SET SESSION ROLE regress_schemauser1;
|
||||||
CREATE SCHEMA testns;
|
CREATE SCHEMA testns;
|
||||||
SELECT nspname, rolname FROM pg_namespace, pg_roles WHERE pg_namespace.nspname = 'testns' AND pg_namespace.nspowner = pg_roles.oid;
|
SELECT nspname, rolname FROM pg_namespace, pg_roles WHERE pg_namespace.nspname = 'testns' AND pg_namespace.nspowner = pg_roles.oid;
|
||||||
@@ -2792,7 +2796,7 @@ DROP USER regress_priv_user7;
|
@@ -2725,7 +2729,7 @@ DROP USER regress_priv_user7;
|
||||||
DROP USER regress_priv_user8; -- does not exist
|
DROP USER regress_priv_user8; -- does not exist
|
||||||
ERROR: role "regress_priv_user8" does not exist
|
ERROR: role "regress_priv_user8" does not exist
|
||||||
-- permissions with LOCK TABLE
|
-- permissions with LOCK TABLE
|
||||||
@@ -1221,7 +1242,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
CREATE TABLE lock_table (a int);
|
CREATE TABLE lock_table (a int);
|
||||||
-- LOCK TABLE and SELECT permission
|
-- LOCK TABLE and SELECT permission
|
||||||
GRANT SELECT ON lock_table TO regress_locktable_user;
|
GRANT SELECT ON lock_table TO regress_locktable_user;
|
||||||
@@ -2874,7 +2878,7 @@ DROP USER regress_locktable_user;
|
@@ -2807,7 +2811,7 @@ DROP USER regress_locktable_user;
|
||||||
-- pg_backend_memory_contexts.
|
-- pg_backend_memory_contexts.
|
||||||
-- switch to superuser
|
-- switch to superuser
|
||||||
\c -
|
\c -
|
||||||
@@ -1230,7 +1251,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no
|
SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no
|
||||||
has_table_privilege
|
has_table_privilege
|
||||||
---------------------
|
---------------------
|
||||||
@@ -2918,10 +2922,10 @@ RESET ROLE;
|
@@ -2851,10 +2855,10 @@ RESET ROLE;
|
||||||
-- clean up
|
-- clean up
|
||||||
DROP ROLE regress_readallstats;
|
DROP ROLE regress_readallstats;
|
||||||
-- test role grantor machinery
|
-- test role grantor machinery
|
||||||
@@ -1245,7 +1266,7 @@ index 5b9dba7b32..cc408dad42 100644
|
|||||||
GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE;
|
GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE;
|
||||||
GRANT regress_group_direct_manager TO regress_group_indirect_manager;
|
GRANT regress_group_direct_manager TO regress_group_indirect_manager;
|
||||||
SET SESSION AUTHORIZATION regress_group_direct_manager;
|
SET SESSION AUTHORIZATION regress_group_direct_manager;
|
||||||
@@ -2950,9 +2954,9 @@ DROP ROLE regress_group_direct_manager;
|
@@ -2883,9 +2887,9 @@ DROP ROLE regress_group_direct_manager;
|
||||||
DROP ROLE regress_group_indirect_manager;
|
DROP ROLE regress_group_indirect_manager;
|
||||||
DROP ROLE regress_group_member;
|
DROP ROLE regress_group_member;
|
||||||
-- test SET and INHERIT options with object ownership changes
|
-- test SET and INHERIT options with object ownership changes
|
||||||
@@ -1792,7 +1813,7 @@ index 5e6969b173..2c4d52237f 100644
|
|||||||
|
|
||||||
-- clean up roles
|
-- clean up roles
|
||||||
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
|
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
|
||||||
index 218c0c2863..f7af0cfb12 100644
|
index 97ca9bf72c..b2a7a6f710 100644
|
||||||
--- a/src/test/regress/expected/rowsecurity.out
|
--- a/src/test/regress/expected/rowsecurity.out
|
||||||
+++ b/src/test/regress/expected/rowsecurity.out
|
+++ b/src/test/regress/expected/rowsecurity.out
|
||||||
@@ -14,13 +14,13 @@ DROP ROLE IF EXISTS regress_rls_group2;
|
@@ -14,13 +14,13 @@ DROP ROLE IF EXISTS regress_rls_group2;
|
||||||
@@ -1896,19 +1917,6 @@ index b79fe9a1c0..e29fab88ab 100644
|
|||||||
ALTER DEFAULT PRIVILEGES FOR ROLE regress_selinto_user
|
ALTER DEFAULT PRIVILEGES FOR ROLE regress_selinto_user
|
||||||
REVOKE INSERT ON TABLES FROM regress_selinto_user;
|
REVOKE INSERT ON TABLES FROM regress_selinto_user;
|
||||||
GRANT ALL ON SCHEMA selinto_schema TO public;
|
GRANT ALL ON SCHEMA selinto_schema TO public;
|
||||||
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
|
|
||||||
index afc6ab08c2..dfcd891af3 100644
|
|
||||||
--- a/src/test/regress/expected/select_parallel.out
|
|
||||||
+++ b/src/test/regress/expected/select_parallel.out
|
|
||||||
@@ -1220,7 +1220,7 @@ SELECT 1 FROM tenk1_vw_sec
|
|
||||||
|
|
||||||
rollback;
|
|
||||||
-- test that function option SET ROLE works in parallel workers.
|
|
||||||
-create role regress_parallel_worker;
|
|
||||||
+create role regress_parallel_worker PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
create function set_and_report_role() returns text as
|
|
||||||
$$ select current_setting('role') $$ language sql parallel safe
|
|
||||||
set role = regress_parallel_worker;
|
|
||||||
diff --git a/src/test/regress/expected/select_views.out b/src/test/regress/expected/select_views.out
|
diff --git a/src/test/regress/expected/select_views.out b/src/test/regress/expected/select_views.out
|
||||||
index 1aeed8452b..7d9427d070 100644
|
index 1aeed8452b..7d9427d070 100644
|
||||||
--- a/src/test/regress/expected/select_views.out
|
--- a/src/test/regress/expected/select_views.out
|
||||||
@@ -2361,7 +2369,7 @@ index 6cb9c926c0..5e689e4062 100644
|
|||||||
ALTER TABLE ptnowner1 OWNER TO regress_ptnowner;
|
ALTER TABLE ptnowner1 OWNER TO regress_ptnowner;
|
||||||
ALTER TABLE ptnowner OWNER TO regress_ptnowner;
|
ALTER TABLE ptnowner OWNER TO regress_ptnowner;
|
||||||
diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql
|
diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql
|
||||||
index 8aa902d5ab..24bb823b86 100644
|
index 3db9e25913..c66d5aa2c2 100644
|
||||||
--- a/src/test/regress/sql/collate.icu.utf8.sql
|
--- a/src/test/regress/sql/collate.icu.utf8.sql
|
||||||
+++ b/src/test/regress/sql/collate.icu.utf8.sql
|
+++ b/src/test/regress/sql/collate.icu.utf8.sql
|
||||||
@@ -353,7 +353,7 @@ reset enable_seqscan;
|
@@ -353,7 +353,7 @@ reset enable_seqscan;
|
||||||
@@ -2524,7 +2532,7 @@ index 43d2e906dd..6c993d70f0 100644
|
|||||||
-- An earlier bug (see commit b1ecb9b3fcf) could end up using a buffer from
|
-- An earlier bug (see commit b1ecb9b3fcf) could end up using a buffer from
|
||||||
-- the wrong partition. This test is *not* guaranteed to trigger that bug, but
|
-- the wrong partition. This test is *not* guaranteed to trigger that bug, but
|
||||||
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
|
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
|
||||||
index cf3828c16e..cf3ca38175 100644
|
index d759635068..d58e50dcc5 100644
|
||||||
--- a/src/test/regress/sql/copy2.sql
|
--- a/src/test/regress/sql/copy2.sql
|
||||||
+++ b/src/test/regress/sql/copy2.sql
|
+++ b/src/test/regress/sql/copy2.sql
|
||||||
@@ -365,8 +365,8 @@ copy check_con_tbl from stdin;
|
@@ -365,8 +365,8 @@ copy check_con_tbl from stdin;
|
||||||
@@ -2766,7 +2774,7 @@ index 1b7064247a..be5b662ce1 100644
|
|||||||
-- Cases where schema creation fails as objects are qualified with a schema
|
-- Cases where schema creation fails as objects are qualified with a schema
|
||||||
-- that does not match with what's expected.
|
-- that does not match with what's expected.
|
||||||
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
|
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
|
||||||
index ae6841308b..47bc792e30 100644
|
index 3a78be1b0c..617d2dc8d6 100644
|
||||||
--- a/src/test/regress/sql/create_view.sql
|
--- a/src/test/regress/sql/create_view.sql
|
||||||
+++ b/src/test/regress/sql/create_view.sql
|
+++ b/src/test/regress/sql/create_view.sql
|
||||||
@@ -23,7 +23,8 @@ CREATE TABLE real_city (
|
@@ -23,7 +23,8 @@ CREATE TABLE real_city (
|
||||||
@@ -2893,11 +2901,11 @@ index aa147b14a9..370e0dd570 100644
|
|||||||
CREATE FOREIGN DATA WRAPPER dummy;
|
CREATE FOREIGN DATA WRAPPER dummy;
|
||||||
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
|
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
|
||||||
diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql
|
diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql
|
||||||
index 45c7a534cb..32dd26b8cd 100644
|
index 22e177f89b..7138d5e1d4 100644
|
||||||
--- a/src/test/regress/sql/foreign_key.sql
|
--- a/src/test/regress/sql/foreign_key.sql
|
||||||
+++ b/src/test/regress/sql/foreign_key.sql
|
+++ b/src/test/regress/sql/foreign_key.sql
|
||||||
@@ -1435,7 +1435,7 @@ ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES
|
@@ -1418,7 +1418,7 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2
|
||||||
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
|
-- leave these tables around intentionally
|
||||||
|
|
||||||
-- test the case when the referenced table is owned by a different user
|
-- test the case when the referenced table is owned by a different user
|
||||||
-create role regress_other_partitioned_fk_owner;
|
-create role regress_other_partitioned_fk_owner;
|
||||||
@@ -2955,7 +2963,7 @@ index 527024f710..de49c0b85f 100644
|
|||||||
-- the data in this file has a lot of duplicates in the index key
|
-- the data in this file has a lot of duplicates in the index key
|
||||||
-- fields, leading to long bucket chains and lots of table expansion.
|
-- fields, leading to long bucket chains and lots of table expansion.
|
||||||
diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql
|
diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql
|
||||||
index 7537258a75..9041e35e34 100644
|
index 91d2e443b4..241c93f373 100644
|
||||||
--- a/src/test/regress/sql/identity.sql
|
--- a/src/test/regress/sql/identity.sql
|
||||||
+++ b/src/test/regress/sql/identity.sql
|
+++ b/src/test/regress/sql/identity.sql
|
||||||
@@ -287,7 +287,7 @@ ALTER TABLE itest7 ALTER COLUMN a RESTART;
|
@@ -287,7 +287,7 @@ ALTER TABLE itest7 ALTER COLUMN a RESTART;
|
||||||
@@ -2968,10 +2976,10 @@ index 7537258a75..9041e35e34 100644
|
|||||||
GRANT SELECT, INSERT ON itest8 TO regress_identity_user1;
|
GRANT SELECT, INSERT ON itest8 TO regress_identity_user1;
|
||||||
SET ROLE regress_identity_user1;
|
SET ROLE regress_identity_user1;
|
||||||
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
|
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
|
||||||
index b5b554a125..109889ad24 100644
|
index fe699c54d5..bdd5993f45 100644
|
||||||
--- a/src/test/regress/sql/inherit.sql
|
--- a/src/test/regress/sql/inherit.sql
|
||||||
+++ b/src/test/regress/sql/inherit.sql
|
+++ b/src/test/regress/sql/inherit.sql
|
||||||
@@ -958,7 +958,7 @@ create index on permtest_parent (left(c, 3));
|
@@ -950,7 +950,7 @@ create index on permtest_parent (left(c, 3));
|
||||||
insert into permtest_parent
|
insert into permtest_parent
|
||||||
select 1, 'a', left(fipshash(i::text), 5) from generate_series(0, 100) i;
|
select 1, 'a', left(fipshash(i::text), 5) from generate_series(0, 100) i;
|
||||||
analyze permtest_parent;
|
analyze permtest_parent;
|
||||||
@@ -3173,7 +3181,7 @@ index 1a6c61f49d..1c31ac6a53 100644
|
|||||||
-- Test generic object addressing/identification functions
|
-- Test generic object addressing/identification functions
|
||||||
CREATE SCHEMA addr_nsp;
|
CREATE SCHEMA addr_nsp;
|
||||||
diff --git a/src/test/regress/sql/password.sql b/src/test/regress/sql/password.sql
|
diff --git a/src/test/regress/sql/password.sql b/src/test/regress/sql/password.sql
|
||||||
index 53e86b0b6c..0303fdfe96 100644
|
index 53e86b0b6c..f07cf1ec54 100644
|
||||||
--- a/src/test/regress/sql/password.sql
|
--- a/src/test/regress/sql/password.sql
|
||||||
+++ b/src/test/regress/sql/password.sql
|
+++ b/src/test/regress/sql/password.sql
|
||||||
@@ -10,11 +10,11 @@ SET password_encryption = 'scram-sha-256'; -- ok
|
@@ -10,11 +10,11 @@ SET password_encryption = 'scram-sha-256'; -- ok
|
||||||
@@ -3192,61 +3200,25 @@ index 53e86b0b6c..0303fdfe96 100644
|
|||||||
|
|
||||||
-- check list of created entries
|
-- check list of created entries
|
||||||
--
|
--
|
||||||
@@ -42,26 +42,18 @@ ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
|
@@ -42,14 +42,14 @@ ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
|
||||||
SET password_encryption = 'md5';
|
SET password_encryption = 'md5';
|
||||||
|
|
||||||
-- encrypt with MD5
|
-- encrypt with MD5
|
||||||
-ALTER ROLE regress_passwd2 PASSWORD 'foo';
|
-ALTER ROLE regress_passwd2 PASSWORD 'foo';
|
||||||
--- already encrypted, use as they are
|
|
||||||
-ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
|
|
||||||
-ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
|
|
||||||
+ALTER ROLE regress_passwd2 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
+ALTER ROLE regress_passwd2 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
||||||
|
-- already encrypted, use as they are
|
||||||
|
ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
|
||||||
|
ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
|
||||||
|
|
||||||
SET password_encryption = 'scram-sha-256';
|
SET password_encryption = 'scram-sha-256';
|
||||||
-- create SCRAM secret
|
-- create SCRAM secret
|
||||||
-ALTER ROLE regress_passwd4 PASSWORD 'foo';
|
-ALTER ROLE regress_passwd4 PASSWORD 'foo';
|
||||||
--- already encrypted with MD5, use as it is
|
|
||||||
-CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
|
|
||||||
+ALTER ROLE regress_passwd4 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
+ALTER ROLE regress_passwd4 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
||||||
+-- Neon does not support encrypted passwords, use unencrypted instead
|
-- already encrypted with MD5, use as it is
|
||||||
+CREATE ROLE regress_passwd5 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
|
||||||
|
|
||||||
--- This looks like a valid SCRAM-SHA-256 secret, but it is not
|
|
||||||
--- so it should be hashed with SCRAM-SHA-256.
|
|
||||||
-CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
|
|
||||||
--- These may look like valid MD5 secrets, but they are not, so they
|
|
||||||
--- should be hashed with SCRAM-SHA-256.
|
|
||||||
--- trailing garbage at the end
|
|
||||||
-CREATE ROLE regress_passwd7 PASSWORD 'md5012345678901234567890123456789zz';
|
|
||||||
--- invalid length
|
|
||||||
-CREATE ROLE regress_passwd8 PASSWORD 'md501234567890123456789012345678901zz';
|
|
||||||
+-- Neon does not support encrypted passwords, use unencrypted instead
|
|
||||||
+CREATE ROLE regress_passwd6 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
+CREATE ROLE regress_passwd7 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
+CREATE ROLE regress_passwd8 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
|
|
||||||
-- Changing the SCRAM iteration count
|
|
||||||
SET scram_iterations = 1024;
|
|
||||||
@@ -78,13 +70,10 @@ ALTER ROLE regress_passwd_empty PASSWORD 'md585939a5ce845f1a1b620742e3c659e0a';
|
|
||||||
ALTER ROLE regress_passwd_empty PASSWORD 'SCRAM-SHA-256$4096:hpFyHTUsSWcR7O9P$LgZFIt6Oqdo27ZFKbZ2nV+vtnYM995pDh9ca6WSi120=:qVV5NeluNfUPkwm7Vqat25RjSPLkGeoZBQs6wVv+um4=';
|
|
||||||
SELECT rolpassword FROM pg_authid WHERE rolname='regress_passwd_empty';
|
|
||||||
|
|
||||||
--- Test with invalid stored and server keys.
|
|
||||||
---
|
|
||||||
--- The first is valid, to act as a control. The others have too long
|
|
||||||
--- stored/server keys. They will be re-hashed.
|
|
||||||
-CREATE ROLE regress_passwd_sha_len0 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
|
|
||||||
-CREATE ROLE regress_passwd_sha_len1 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96RqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
|
|
||||||
-CREATE ROLE regress_passwd_sha_len2 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=';
|
|
||||||
+-- Neon does not support encrypted passwords, use unencrypted instead
|
|
||||||
+CREATE ROLE regress_passwd_sha_len0 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
+CREATE ROLE regress_passwd_sha_len1 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
+CREATE ROLE regress_passwd_sha_len2 PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
|
|
||||||
-- Check that the invalid secrets were re-hashed. A re-hashed secret
|
|
||||||
-- should not contain the original salt.
|
|
||||||
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
|
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
|
||||||
index 249df17a58..b258e7f26a 100644
|
index 3f68cafcd1..004b26831d 100644
|
||||||
--- a/src/test/regress/sql/privileges.sql
|
--- a/src/test/regress/sql/privileges.sql
|
||||||
+++ b/src/test/regress/sql/privileges.sql
|
+++ b/src/test/regress/sql/privileges.sql
|
||||||
@@ -24,18 +24,18 @@ RESET client_min_messages;
|
@@ -24,18 +24,18 @@ RESET client_min_messages;
|
||||||
@@ -3297,7 +3269,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
|
|
||||||
GRANT pg_read_all_data TO regress_priv_user6;
|
GRANT pg_read_all_data TO regress_priv_user6;
|
||||||
GRANT pg_write_all_data TO regress_priv_user7;
|
GRANT pg_write_all_data TO regress_priv_user7;
|
||||||
@@ -163,8 +163,8 @@ DROP USER regress_priv_user10;
|
@@ -130,8 +130,8 @@ DROP USER regress_priv_user10;
|
||||||
DROP USER regress_priv_user9;
|
DROP USER regress_priv_user9;
|
||||||
DROP USER regress_priv_user8;
|
DROP USER regress_priv_user8;
|
||||||
|
|
||||||
@@ -3308,7 +3280,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
|
|
||||||
ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4;
|
ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4;
|
||||||
|
|
||||||
@@ -1157,7 +1157,7 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP
|
@@ -1124,7 +1124,7 @@ SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OP
|
||||||
|
|
||||||
-- security-restricted operations
|
-- security-restricted operations
|
||||||
\c -
|
\c -
|
||||||
@@ -3317,7 +3289,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
|
|
||||||
-- Check that index expressions and predicates are run as the table's owner
|
-- Check that index expressions and predicates are run as the table's owner
|
||||||
|
|
||||||
@@ -1653,8 +1653,8 @@ DROP SCHEMA testns CASCADE;
|
@@ -1620,8 +1620,8 @@ DROP SCHEMA testns CASCADE;
|
||||||
-- Change owner of the schema & and rename of new schema owner
|
-- Change owner of the schema & and rename of new schema owner
|
||||||
\c -
|
\c -
|
||||||
|
|
||||||
@@ -3328,7 +3300,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
|
|
||||||
SET SESSION ROLE regress_schemauser1;
|
SET SESSION ROLE regress_schemauser1;
|
||||||
CREATE SCHEMA testns;
|
CREATE SCHEMA testns;
|
||||||
@@ -1748,7 +1748,7 @@ DROP USER regress_priv_user8; -- does not exist
|
@@ -1715,7 +1715,7 @@ DROP USER regress_priv_user8; -- does not exist
|
||||||
|
|
||||||
|
|
||||||
-- permissions with LOCK TABLE
|
-- permissions with LOCK TABLE
|
||||||
@@ -3337,7 +3309,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
CREATE TABLE lock_table (a int);
|
CREATE TABLE lock_table (a int);
|
||||||
|
|
||||||
-- LOCK TABLE and SELECT permission
|
-- LOCK TABLE and SELECT permission
|
||||||
@@ -1836,7 +1836,7 @@ DROP USER regress_locktable_user;
|
@@ -1803,7 +1803,7 @@ DROP USER regress_locktable_user;
|
||||||
-- switch to superuser
|
-- switch to superuser
|
||||||
\c -
|
\c -
|
||||||
|
|
||||||
@@ -3346,7 +3318,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
|
|
||||||
SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no
|
SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no
|
||||||
SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- no
|
SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- no
|
||||||
@@ -1856,10 +1856,10 @@ RESET ROLE;
|
@@ -1823,10 +1823,10 @@ RESET ROLE;
|
||||||
DROP ROLE regress_readallstats;
|
DROP ROLE regress_readallstats;
|
||||||
|
|
||||||
-- test role grantor machinery
|
-- test role grantor machinery
|
||||||
@@ -3361,7 +3333,7 @@ index 249df17a58..b258e7f26a 100644
|
|||||||
|
|
||||||
GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE;
|
GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE;
|
||||||
GRANT regress_group_direct_manager TO regress_group_indirect_manager;
|
GRANT regress_group_direct_manager TO regress_group_indirect_manager;
|
||||||
@@ -1881,9 +1881,9 @@ DROP ROLE regress_group_indirect_manager;
|
@@ -1848,9 +1848,9 @@ DROP ROLE regress_group_indirect_manager;
|
||||||
DROP ROLE regress_group_member;
|
DROP ROLE regress_group_member;
|
||||||
|
|
||||||
-- test SET and INHERIT options with object ownership changes
|
-- test SET and INHERIT options with object ownership changes
|
||||||
@@ -3653,7 +3625,7 @@ index c961b2d730..0859b89c4f 100644
|
|||||||
-- clean up roles
|
-- clean up roles
|
||||||
DROP ROLE regress_test_def_superuser;
|
DROP ROLE regress_test_def_superuser;
|
||||||
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
|
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
|
||||||
index d3bfd53e23..919ce1d0c6 100644
|
index dec7340538..cdbc03a5cc 100644
|
||||||
--- a/src/test/regress/sql/rowsecurity.sql
|
--- a/src/test/regress/sql/rowsecurity.sql
|
||||||
+++ b/src/test/regress/sql/rowsecurity.sql
|
+++ b/src/test/regress/sql/rowsecurity.sql
|
||||||
@@ -20,13 +20,13 @@ DROP SCHEMA IF EXISTS regress_rls_schema CASCADE;
|
@@ -20,13 +20,13 @@ DROP SCHEMA IF EXISTS regress_rls_schema CASCADE;
|
||||||
@@ -3729,19 +3701,6 @@ index 689c448cc2..223ceb1d75 100644
|
|||||||
ALTER DEFAULT PRIVILEGES FOR ROLE regress_selinto_user
|
ALTER DEFAULT PRIVILEGES FOR ROLE regress_selinto_user
|
||||||
REVOKE INSERT ON TABLES FROM regress_selinto_user;
|
REVOKE INSERT ON TABLES FROM regress_selinto_user;
|
||||||
GRANT ALL ON SCHEMA selinto_schema TO public;
|
GRANT ALL ON SCHEMA selinto_schema TO public;
|
||||||
diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql
|
|
||||||
index 33d78e16dc..cb193c9b27 100644
|
|
||||||
--- a/src/test/regress/sql/select_parallel.sql
|
|
||||||
+++ b/src/test/regress/sql/select_parallel.sql
|
|
||||||
@@ -464,7 +464,7 @@ SELECT 1 FROM tenk1_vw_sec
|
|
||||||
rollback;
|
|
||||||
|
|
||||||
-- test that function option SET ROLE works in parallel workers.
|
|
||||||
-create role regress_parallel_worker;
|
|
||||||
+create role regress_parallel_worker PASSWORD NEON_PASSWORD_PLACEHOLDER;
|
|
||||||
|
|
||||||
create function set_and_report_role() returns text as
|
|
||||||
$$ select current_setting('role') $$ language sql parallel safe
|
|
||||||
diff --git a/src/test/regress/sql/select_views.sql b/src/test/regress/sql/select_views.sql
|
diff --git a/src/test/regress/sql/select_views.sql b/src/test/regress/sql/select_views.sql
|
||||||
index e742f13699..7bd0255df8 100644
|
index e742f13699..7bd0255df8 100644
|
||||||
--- a/src/test/regress/sql/select_views.sql
|
--- a/src/test/regress/sql/select_views.sql
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,242 +0,0 @@
|
|||||||
diff --git a/contrib/amcheck/expected/check_heap.out b/contrib/amcheck/expected/check_heap.out
|
|
||||||
index 979e5e8..2375b45 100644
|
|
||||||
--- a/contrib/amcheck/expected/check_heap.out
|
|
||||||
+++ b/contrib/amcheck/expected/check_heap.out
|
|
||||||
@@ -80,12 +80,9 @@ INSERT INTO heaptest (a, b)
|
|
||||||
-- same transaction. The heaptest table is smaller than the default
|
|
||||||
-- wal_skip_threshold, so a wal_level=minimal commit reads the table into
|
|
||||||
-- shared_buffers. A transaction delays that and excludes any autovacuum.
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_test_stats_tblspc LOCATION '';
|
|
||||||
SELECT sum(reads) AS stats_bulkreads_before
|
|
||||||
FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
BEGIN;
|
|
||||||
-ALTER TABLE heaptest SET TABLESPACE regress_test_stats_tblspc;
|
|
||||||
-- Check that valid options are not rejected nor corruption reported
|
|
||||||
-- for a non-empty table
|
|
||||||
SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none');
|
|
||||||
@@ -118,14 +115,6 @@ SELECT pg_stat_force_next_flush();
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-SELECT sum(reads) AS stats_bulkreads_after
|
|
||||||
- FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
-SELECT :stats_bulkreads_after > :stats_bulkreads_before;
|
|
||||||
- ?column?
|
|
||||||
-----------
|
|
||||||
- t
|
|
||||||
-(1 row)
|
|
||||||
-
|
|
||||||
CREATE ROLE regress_heaptest_role;
|
|
||||||
-- verify permissions are checked (error due to function not callable)
|
|
||||||
SET ROLE regress_heaptest_role;
|
|
||||||
@@ -233,7 +222,6 @@ ERROR: cannot check relation "test_foreign_table"
|
|
||||||
DETAIL: This operation is not supported for foreign tables.
|
|
||||||
-- cleanup
|
|
||||||
DROP TABLE heaptest;
|
|
||||||
-DROP TABLESPACE regress_test_stats_tblspc;
|
|
||||||
DROP TABLE test_partition;
|
|
||||||
DROP TABLE test_partitioned;
|
|
||||||
DROP OWNED BY regress_heaptest_role; -- permissions
|
|
||||||
diff --git a/contrib/amcheck/sql/check_heap.sql b/contrib/amcheck/sql/check_heap.sql
|
|
||||||
index 1745bae..3b429c3 100644
|
|
||||||
--- a/contrib/amcheck/sql/check_heap.sql
|
|
||||||
+++ b/contrib/amcheck/sql/check_heap.sql
|
|
||||||
@@ -40,12 +40,9 @@ INSERT INTO heaptest (a, b)
|
|
||||||
-- same transaction. The heaptest table is smaller than the default
|
|
||||||
-- wal_skip_threshold, so a wal_level=minimal commit reads the table into
|
|
||||||
-- shared_buffers. A transaction delays that and excludes any autovacuum.
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_test_stats_tblspc LOCATION '';
|
|
||||||
SELECT sum(reads) AS stats_bulkreads_before
|
|
||||||
FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
BEGIN;
|
|
||||||
-ALTER TABLE heaptest SET TABLESPACE regress_test_stats_tblspc;
|
|
||||||
-- Check that valid options are not rejected nor corruption reported
|
|
||||||
-- for a non-empty table
|
|
||||||
SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none');
|
|
||||||
@@ -58,9 +55,6 @@ COMMIT;
|
|
||||||
-- ALTER TABLE ... SET TABLESPACE ...
|
|
||||||
-- causing an additional bulkread, which should be reflected in pg_stat_io.
|
|
||||||
SELECT pg_stat_force_next_flush();
|
|
||||||
-SELECT sum(reads) AS stats_bulkreads_after
|
|
||||||
- FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
-SELECT :stats_bulkreads_after > :stats_bulkreads_before;
|
|
||||||
|
|
||||||
CREATE ROLE regress_heaptest_role;
|
|
||||||
|
|
||||||
@@ -140,7 +134,6 @@ SELECT * FROM verify_heapam('test_foreign_table',
|
|
||||||
|
|
||||||
-- cleanup
|
|
||||||
DROP TABLE heaptest;
|
|
||||||
-DROP TABLESPACE regress_test_stats_tblspc;
|
|
||||||
DROP TABLE test_partition;
|
|
||||||
DROP TABLE test_partitioned;
|
|
||||||
DROP OWNED BY regress_heaptest_role; -- permissions
|
|
||||||
diff --git a/contrib/citext/expected/create_index_acl.out b/contrib/citext/expected/create_index_acl.out
|
|
||||||
index 33be13a..70a406c 100644
|
|
||||||
--- a/contrib/citext/expected/create_index_acl.out
|
|
||||||
+++ b/contrib/citext/expected/create_index_acl.out
|
|
||||||
@@ -5,9 +5,6 @@
|
|
||||||
-- owner having as few applicable privileges as possible. (The privileges.sql
|
|
||||||
-- regress_sro_user tests look for the opposite defect; they confirm that
|
|
||||||
-- DefineIndex() uses the table owner userid where necessary.)
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_create_idx_tblspace LOCATION '';
|
|
||||||
-RESET allow_in_place_tablespaces;
|
|
||||||
BEGIN;
|
|
||||||
CREATE ROLE regress_minimal;
|
|
||||||
CREATE SCHEMA s;
|
|
||||||
@@ -49,11 +46,9 @@ ALTER TABLE s.x OWNER TO regress_minimal;
|
|
||||||
-- Empty-table DefineIndex()
|
|
||||||
CREATE UNIQUE INDEX u0rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e0rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Make the table nonempty.
|
|
||||||
INSERT INTO s.x VALUES ('foo'), ('bar');
|
|
||||||
@@ -66,11 +61,9 @@ RESET search_path;
|
|
||||||
GRANT EXECUTE ON FUNCTION s.index_this_expr TO regress_minimal;
|
|
||||||
CREATE UNIQUE INDEX u2rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Shall not find s.coll via search_path, despite the s.const->public.setter
|
|
||||||
-- call having set search_path=s during expression planning. Suppress the
|
|
||||||
@@ -78,9 +71,7 @@ ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
\set VERBOSITY sqlstate
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT underqualified EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
ERROR: 42704
|
|
||||||
\set VERBOSITY default
|
|
||||||
ROLLBACK;
|
|
||||||
-DROP TABLESPACE regress_create_idx_tblspace;
|
|
||||||
diff --git a/contrib/citext/sql/create_index_acl.sql b/contrib/citext/sql/create_index_acl.sql
|
|
||||||
index 10b5225..ae442e1 100644
|
|
||||||
--- a/contrib/citext/sql/create_index_acl.sql
|
|
||||||
+++ b/contrib/citext/sql/create_index_acl.sql
|
|
||||||
@@ -6,10 +6,6 @@
|
|
||||||
-- regress_sro_user tests look for the opposite defect; they confirm that
|
|
||||||
-- DefineIndex() uses the table owner userid where necessary.)
|
|
||||||
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_create_idx_tblspace LOCATION '';
|
|
||||||
-RESET allow_in_place_tablespaces;
|
|
||||||
-
|
|
||||||
BEGIN;
|
|
||||||
CREATE ROLE regress_minimal;
|
|
||||||
CREATE SCHEMA s;
|
|
||||||
@@ -51,11 +47,9 @@ ALTER TABLE s.x OWNER TO regress_minimal;
|
|
||||||
-- Empty-table DefineIndex()
|
|
||||||
CREATE UNIQUE INDEX u0rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e0rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Make the table nonempty.
|
|
||||||
INSERT INTO s.x VALUES ('foo'), ('bar');
|
|
||||||
@@ -68,11 +62,9 @@ RESET search_path;
|
|
||||||
GRANT EXECUTE ON FUNCTION s.index_this_expr TO regress_minimal;
|
|
||||||
CREATE UNIQUE INDEX u2rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Shall not find s.coll via search_path, despite the s.const->public.setter
|
|
||||||
-- call having set search_path=s during expression planning. Suppress the
|
|
||||||
@@ -80,9 +72,7 @@ ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
\set VERBOSITY sqlstate
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT underqualified EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
\set VERBOSITY default
|
|
||||||
ROLLBACK;
|
|
||||||
|
|
||||||
-DROP TABLESPACE regress_create_idx_tblspace;
|
|
||||||
diff --git a/contrib/file_fdw/expected/file_fdw.out b/contrib/file_fdw/expected/file_fdw.out
|
|
||||||
index 72304e0..ebe131b 100644
|
|
||||||
--- a/contrib/file_fdw/expected/file_fdw.out
|
|
||||||
+++ b/contrib/file_fdw/expected/file_fdw.out
|
|
||||||
@@ -4,6 +4,7 @@
|
|
||||||
-- directory paths are passed to us in environment variables
|
|
||||||
\getenv abs_srcdir PG_ABS_SRCDIR
|
|
||||||
-- Clean up in case a prior regression run failed
|
|
||||||
+SET compute_query_id TO 'off';
|
|
||||||
SET client_min_messages TO 'warning';
|
|
||||||
DROP ROLE IF EXISTS regress_file_fdw_superuser, regress_file_fdw_user, regress_no_priv_user;
|
|
||||||
RESET client_min_messages;
|
|
||||||
diff --git a/contrib/file_fdw/sql/file_fdw.sql b/contrib/file_fdw/sql/file_fdw.sql
|
|
||||||
index f0548e1..848a08c 100644
|
|
||||||
--- a/contrib/file_fdw/sql/file_fdw.sql
|
|
||||||
+++ b/contrib/file_fdw/sql/file_fdw.sql
|
|
||||||
@@ -6,6 +6,7 @@
|
|
||||||
\getenv abs_srcdir PG_ABS_SRCDIR
|
|
||||||
|
|
||||||
-- Clean up in case a prior regression run failed
|
|
||||||
+SET compute_query_id TO 'off';
|
|
||||||
SET client_min_messages TO 'warning';
|
|
||||||
DROP ROLE IF EXISTS regress_file_fdw_superuser, regress_file_fdw_user, regress_no_priv_user;
|
|
||||||
RESET client_min_messages;
|
|
||||||
diff --git a/contrib/pageinspect/expected/gist.out b/contrib/pageinspect/expected/gist.out
|
|
||||||
index d1adbab..38b52ac 100644
|
|
||||||
--- a/contrib/pageinspect/expected/gist.out
|
|
||||||
+++ b/contrib/pageinspect/expected/gist.out
|
|
||||||
@@ -10,25 +10,6 @@ BEGIN;
|
|
||||||
CREATE TABLE test_gist AS SELECT point(i,i) p, i::text t FROM
|
|
||||||
generate_series(1,1000) i;
|
|
||||||
CREATE INDEX test_gist_idx ON test_gist USING gist (p);
|
|
||||||
--- Page 0 is the root, the rest are leaf pages
|
|
||||||
-SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 0));
|
|
||||||
- lsn | nsn | rightlink | flags
|
|
||||||
------+-----+------------+-------
|
|
||||||
- 0/1 | 0/0 | 4294967295 | {}
|
|
||||||
-(1 row)
|
|
||||||
-
|
|
||||||
-SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 1));
|
|
||||||
- lsn | nsn | rightlink | flags
|
|
||||||
------+-----+------------+--------
|
|
||||||
- 0/1 | 0/0 | 4294967295 | {leaf}
|
|
||||||
-(1 row)
|
|
||||||
-
|
|
||||||
-SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 2));
|
|
||||||
- lsn | nsn | rightlink | flags
|
|
||||||
------+-----+-----------+--------
|
|
||||||
- 0/1 | 0/0 | 1 | {leaf}
|
|
||||||
-(1 row)
|
|
||||||
-
|
|
||||||
COMMIT;
|
|
||||||
SELECT * FROM gist_page_items(get_raw_page('test_gist_idx', 0), 'test_gist_idx');
|
|
||||||
itemoffset | ctid | itemlen | dead | keys
|
|
||||||
diff --git a/contrib/pageinspect/sql/gist.sql b/contrib/pageinspect/sql/gist.sql
|
|
||||||
index d263542..607992f 100644
|
|
||||||
--- a/contrib/pageinspect/sql/gist.sql
|
|
||||||
+++ b/contrib/pageinspect/sql/gist.sql
|
|
||||||
@@ -12,11 +12,6 @@ CREATE TABLE test_gist AS SELECT point(i,i) p, i::text t FROM
|
|
||||||
generate_series(1,1000) i;
|
|
||||||
CREATE INDEX test_gist_idx ON test_gist USING gist (p);
|
|
||||||
|
|
||||||
--- Page 0 is the root, the rest are leaf pages
|
|
||||||
-SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 0));
|
|
||||||
-SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 1));
|
|
||||||
-SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 2));
|
|
||||||
-
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
SELECT * FROM gist_page_items(get_raw_page('test_gist_idx', 0), 'test_gist_idx');
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
diff --git a/contrib/amcheck/expected/check_heap.out b/contrib/amcheck/expected/check_heap.out
|
|
||||||
index 979e5e8..2375b45 100644
|
|
||||||
--- a/contrib/amcheck/expected/check_heap.out
|
|
||||||
+++ b/contrib/amcheck/expected/check_heap.out
|
|
||||||
@@ -80,12 +80,9 @@ INSERT INTO heaptest (a, b)
|
|
||||||
-- same transaction. The heaptest table is smaller than the default
|
|
||||||
-- wal_skip_threshold, so a wal_level=minimal commit reads the table into
|
|
||||||
-- shared_buffers. A transaction delays that and excludes any autovacuum.
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_test_stats_tblspc LOCATION '';
|
|
||||||
SELECT sum(reads) AS stats_bulkreads_before
|
|
||||||
FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
BEGIN;
|
|
||||||
-ALTER TABLE heaptest SET TABLESPACE regress_test_stats_tblspc;
|
|
||||||
-- Check that valid options are not rejected nor corruption reported
|
|
||||||
-- for a non-empty table
|
|
||||||
SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none');
|
|
||||||
@@ -118,14 +115,6 @@ SELECT pg_stat_force_next_flush();
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-SELECT sum(reads) AS stats_bulkreads_after
|
|
||||||
- FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
-SELECT :stats_bulkreads_after > :stats_bulkreads_before;
|
|
||||||
- ?column?
|
|
||||||
-----------
|
|
||||||
- t
|
|
||||||
-(1 row)
|
|
||||||
-
|
|
||||||
CREATE ROLE regress_heaptest_role;
|
|
||||||
-- verify permissions are checked (error due to function not callable)
|
|
||||||
SET ROLE regress_heaptest_role;
|
|
||||||
@@ -233,7 +222,6 @@ ERROR: cannot check relation "test_foreign_table"
|
|
||||||
DETAIL: This operation is not supported for foreign tables.
|
|
||||||
-- cleanup
|
|
||||||
DROP TABLE heaptest;
|
|
||||||
-DROP TABLESPACE regress_test_stats_tblspc;
|
|
||||||
DROP TABLE test_partition;
|
|
||||||
DROP TABLE test_partitioned;
|
|
||||||
DROP OWNED BY regress_heaptest_role; -- permissions
|
|
||||||
diff --git a/contrib/amcheck/sql/check_heap.sql b/contrib/amcheck/sql/check_heap.sql
|
|
||||||
index 1745bae..3b429c3 100644
|
|
||||||
--- a/contrib/amcheck/sql/check_heap.sql
|
|
||||||
+++ b/contrib/amcheck/sql/check_heap.sql
|
|
||||||
@@ -40,12 +40,9 @@ INSERT INTO heaptest (a, b)
|
|
||||||
-- same transaction. The heaptest table is smaller than the default
|
|
||||||
-- wal_skip_threshold, so a wal_level=minimal commit reads the table into
|
|
||||||
-- shared_buffers. A transaction delays that and excludes any autovacuum.
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_test_stats_tblspc LOCATION '';
|
|
||||||
SELECT sum(reads) AS stats_bulkreads_before
|
|
||||||
FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
BEGIN;
|
|
||||||
-ALTER TABLE heaptest SET TABLESPACE regress_test_stats_tblspc;
|
|
||||||
-- Check that valid options are not rejected nor corruption reported
|
|
||||||
-- for a non-empty table
|
|
||||||
SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none');
|
|
||||||
@@ -58,9 +55,6 @@ COMMIT;
|
|
||||||
-- ALTER TABLE ... SET TABLESPACE ...
|
|
||||||
-- causing an additional bulkread, which should be reflected in pg_stat_io.
|
|
||||||
SELECT pg_stat_force_next_flush();
|
|
||||||
-SELECT sum(reads) AS stats_bulkreads_after
|
|
||||||
- FROM pg_stat_io WHERE context = 'bulkread' \gset
|
|
||||||
-SELECT :stats_bulkreads_after > :stats_bulkreads_before;
|
|
||||||
|
|
||||||
CREATE ROLE regress_heaptest_role;
|
|
||||||
|
|
||||||
@@ -140,7 +134,6 @@ SELECT * FROM verify_heapam('test_foreign_table',
|
|
||||||
|
|
||||||
-- cleanup
|
|
||||||
DROP TABLE heaptest;
|
|
||||||
-DROP TABLESPACE regress_test_stats_tblspc;
|
|
||||||
DROP TABLE test_partition;
|
|
||||||
DROP TABLE test_partitioned;
|
|
||||||
DROP OWNED BY regress_heaptest_role; -- permissions
|
|
||||||
diff --git a/contrib/citext/expected/create_index_acl.out b/contrib/citext/expected/create_index_acl.out
|
|
||||||
index 33be13a..70a406c 100644
|
|
||||||
--- a/contrib/citext/expected/create_index_acl.out
|
|
||||||
+++ b/contrib/citext/expected/create_index_acl.out
|
|
||||||
@@ -5,9 +5,6 @@
|
|
||||||
-- owner having as few applicable privileges as possible. (The privileges.sql
|
|
||||||
-- regress_sro_user tests look for the opposite defect; they confirm that
|
|
||||||
-- DefineIndex() uses the table owner userid where necessary.)
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_create_idx_tblspace LOCATION '';
|
|
||||||
-RESET allow_in_place_tablespaces;
|
|
||||||
BEGIN;
|
|
||||||
CREATE ROLE regress_minimal;
|
|
||||||
CREATE SCHEMA s;
|
|
||||||
@@ -49,11 +46,9 @@ ALTER TABLE s.x OWNER TO regress_minimal;
|
|
||||||
-- Empty-table DefineIndex()
|
|
||||||
CREATE UNIQUE INDEX u0rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e0rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Make the table nonempty.
|
|
||||||
INSERT INTO s.x VALUES ('foo'), ('bar');
|
|
||||||
@@ -66,11 +61,9 @@ RESET search_path;
|
|
||||||
GRANT EXECUTE ON FUNCTION s.index_this_expr TO regress_minimal;
|
|
||||||
CREATE UNIQUE INDEX u2rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Shall not find s.coll via search_path, despite the s.const->public.setter
|
|
||||||
-- call having set search_path=s during expression planning. Suppress the
|
|
||||||
@@ -78,9 +71,7 @@ ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
\set VERBOSITY sqlstate
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT underqualified EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
ERROR: 42704
|
|
||||||
\set VERBOSITY default
|
|
||||||
ROLLBACK;
|
|
||||||
-DROP TABLESPACE regress_create_idx_tblspace;
|
|
||||||
diff --git a/contrib/citext/sql/create_index_acl.sql b/contrib/citext/sql/create_index_acl.sql
|
|
||||||
index 10b5225..ae442e1 100644
|
|
||||||
--- a/contrib/citext/sql/create_index_acl.sql
|
|
||||||
+++ b/contrib/citext/sql/create_index_acl.sql
|
|
||||||
@@ -6,10 +6,6 @@
|
|
||||||
-- regress_sro_user tests look for the opposite defect; they confirm that
|
|
||||||
-- DefineIndex() uses the table owner userid where necessary.)
|
|
||||||
|
|
||||||
-SET allow_in_place_tablespaces = true;
|
|
||||||
-CREATE TABLESPACE regress_create_idx_tblspace LOCATION '';
|
|
||||||
-RESET allow_in_place_tablespaces;
|
|
||||||
-
|
|
||||||
BEGIN;
|
|
||||||
CREATE ROLE regress_minimal;
|
|
||||||
CREATE SCHEMA s;
|
|
||||||
@@ -51,11 +47,9 @@ ALTER TABLE s.x OWNER TO regress_minimal;
|
|
||||||
-- Empty-table DefineIndex()
|
|
||||||
CREATE UNIQUE INDEX u0rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e0rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Make the table nonempty.
|
|
||||||
INSERT INTO s.x VALUES ('foo'), ('bar');
|
|
||||||
@@ -68,11 +62,9 @@ RESET search_path;
|
|
||||||
GRANT EXECUTE ON FUNCTION s.index_this_expr TO regress_minimal;
|
|
||||||
CREATE UNIQUE INDEX u2rows ON s.x USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll s.citext_pattern_ops)
|
|
||||||
- TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE s.index_row_if(y);
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE s.coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
-- Shall not find s.coll via search_path, despite the s.const->public.setter
|
|
||||||
-- call having set search_path=s during expression planning. Suppress the
|
|
||||||
@@ -80,9 +72,7 @@ ALTER TABLE s.x ADD CONSTRAINT e2rows EXCLUDE USING btree
|
|
||||||
\set VERBOSITY sqlstate
|
|
||||||
ALTER TABLE s.x ADD CONSTRAINT underqualified EXCLUDE USING btree
|
|
||||||
((s.index_this_expr(y, s.const())) COLLATE coll WITH s.=)
|
|
||||||
- USING INDEX TABLESPACE regress_create_idx_tblspace
|
|
||||||
WHERE (s.index_row_if(y));
|
|
||||||
\set VERBOSITY default
|
|
||||||
ROLLBACK;
|
|
||||||
|
|
||||||
-DROP TABLESPACE regress_create_idx_tblspace;
|
|
||||||
diff --git a/contrib/file_fdw/expected/file_fdw.out b/contrib/file_fdw/expected/file_fdw.out
|
|
||||||
index 86c148a..81bdb2c 100644
|
|
||||||
--- a/contrib/file_fdw/expected/file_fdw.out
|
|
||||||
+++ b/contrib/file_fdw/expected/file_fdw.out
|
|
||||||
@@ -4,6 +4,7 @@
|
|
||||||
-- directory paths are passed to us in environment variables
|
|
||||||
\getenv abs_srcdir PG_ABS_SRCDIR
|
|
||||||
-- Clean up in case a prior regression run failed
|
|
||||||
+SET compute_query_id TO 'off';
|
|
||||||
SET client_min_messages TO 'warning';
|
|
||||||
DROP ROLE IF EXISTS regress_file_fdw_superuser, regress_file_fdw_user, regress_no_priv_user;
|
|
||||||
RESET client_min_messages;
|
|
||||||
diff --git a/contrib/file_fdw/sql/file_fdw.sql b/contrib/file_fdw/sql/file_fdw.sql
|
|
||||||
index f0548e1..848a08c 100644
|
|
||||||
--- a/contrib/file_fdw/sql/file_fdw.sql
|
|
||||||
+++ b/contrib/file_fdw/sql/file_fdw.sql
|
|
||||||
@@ -6,6 +6,7 @@
|
|
||||||
\getenv abs_srcdir PG_ABS_SRCDIR
|
|
||||||
|
|
||||||
-- Clean up in case a prior regression run failed
|
|
||||||
+SET compute_query_id TO 'off';
|
|
||||||
SET client_min_messages TO 'warning';
|
|
||||||
DROP ROLE IF EXISTS regress_file_fdw_superuser, regress_file_fdw_user, regress_no_priv_user;
|
|
||||||
RESET client_min_messages;
|
|
||||||
@@ -1,45 +1,3 @@
|
|||||||
commit 00aa659afc9c7336ab81036edec3017168aabf40
|
|
||||||
Author: Heikki Linnakangas <heikki@neon.tech>
|
|
||||||
Date: Tue Nov 12 16:59:19 2024 +0200
|
|
||||||
|
|
||||||
Temporarily disable test that depends on timezone
|
|
||||||
|
|
||||||
diff --git a/tests/expected/generalization.out b/tests/expected/generalization.out
|
|
||||||
index 23ef5fa..9e60deb 100644
|
|
||||||
--- a/ext-src/pg_anon-src/tests/expected/generalization.out
|
|
||||||
+++ b/ext-src/pg_anon-src/tests/expected/generalization.out
|
|
||||||
@@ -284,12 +284,9 @@ SELECT anon.generalize_tstzrange('19041107','century');
|
|
||||||
["Tue Jan 01 00:00:00 1901 PST","Mon Jan 01 00:00:00 2001 PST")
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-SELECT anon.generalize_tstzrange('19041107','millennium');
|
|
||||||
- generalize_tstzrange
|
|
||||||
------------------------------------------------------------------
|
|
||||||
- ["Thu Jan 01 00:00:00 1001 PST","Mon Jan 01 00:00:00 2001 PST")
|
|
||||||
-(1 row)
|
|
||||||
-
|
|
||||||
+-- temporarily disabled, see:
|
|
||||||
+-- https://gitlab.com/dalibo/postgresql_anonymizer/-/commit/199f0a392b37c59d92ae441fb8f037e094a11a52#note_2148017485
|
|
||||||
+--SELECT anon.generalize_tstzrange('19041107','millennium');
|
|
||||||
-- generalize_daterange
|
|
||||||
SELECT anon.generalize_daterange('19041107');
|
|
||||||
generalize_daterange
|
|
||||||
diff --git a/tests/sql/generalization.sql b/tests/sql/generalization.sql
|
|
||||||
index b868344..b4fc977 100644
|
|
||||||
--- a/ext-src/pg_anon-src/tests/sql/generalization.sql
|
|
||||||
+++ b/ext-src/pg_anon-src/tests/sql/generalization.sql
|
|
||||||
@@ -61,7 +61,9 @@ SELECT anon.generalize_tstzrange('19041107','month');
|
|
||||||
SELECT anon.generalize_tstzrange('19041107','year');
|
|
||||||
SELECT anon.generalize_tstzrange('19041107','decade');
|
|
||||||
SELECT anon.generalize_tstzrange('19041107','century');
|
|
||||||
-SELECT anon.generalize_tstzrange('19041107','millennium');
|
|
||||||
+-- temporarily disabled, see:
|
|
||||||
+-- https://gitlab.com/dalibo/postgresql_anonymizer/-/commit/199f0a392b37c59d92ae441fb8f037e094a11a52#note_2148017485
|
|
||||||
+--SELECT anon.generalize_tstzrange('19041107','millennium');
|
|
||||||
|
|
||||||
-- generalize_daterange
|
|
||||||
SELECT anon.generalize_daterange('19041107');
|
|
||||||
|
|
||||||
commit 7dd414ee75f2875cffb1d6ba474df1f135a6fc6f
|
commit 7dd414ee75f2875cffb1d6ba474df1f135a6fc6f
|
||||||
Author: Alexey Masterov <alexeymasterov@neon.tech>
|
Author: Alexey Masterov <alexeymasterov@neon.tech>
|
||||||
Date: Fri May 31 06:34:26 2024 +0000
|
Date: Fri May 31 06:34:26 2024 +0000
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
commit ec6a491d126882966a696f9ad5d3698935361d55
|
|
||||||
Author: Alexey Masterov <alexeymasterov@neon.tech>
|
|
||||||
Date: Tue Dec 17 10:25:00 2024 +0100
|
|
||||||
|
|
||||||
Changes required to run tests on Neon
|
|
||||||
|
|
||||||
diff --git a/test/expected/permissions_functions.out b/test/expected/permissions_functions.out
|
|
||||||
index 1e9fbc2..94cbe25 100644
|
|
||||||
--- a/test/expected/permissions_functions.out
|
|
||||||
+++ b/test/expected/permissions_functions.out
|
|
||||||
@@ -64,7 +64,7 @@ begin;
|
|
||||||
select current_user;
|
|
||||||
current_user
|
|
||||||
--------------
|
|
||||||
- postgres
|
|
||||||
+ cloud_admin
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- revoke default access from the public role for new functions
|
|
||||||
@@ -6,16 +6,16 @@ index da723b8..5328114 100644
|
|||||||
----
|
----
|
||||||
-- No.A-1-1-3
|
-- No.A-1-1-3
|
||||||
CREATE EXTENSION pg_hint_plan;
|
CREATE EXTENSION pg_hint_plan;
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/pg_hint_plan
|
+LOG: Sending request to compute_ctl: http://localhost:3080/extension_server/pg_hint_plan
|
||||||
-- No.A-1-2-3
|
-- No.A-1-2-3
|
||||||
DROP EXTENSION pg_hint_plan;
|
DROP EXTENSION pg_hint_plan;
|
||||||
-- No.A-1-1-4
|
-- No.A-1-1-4
|
||||||
CREATE SCHEMA other_schema;
|
CREATE SCHEMA other_schema;
|
||||||
CREATE EXTENSION pg_hint_plan SCHEMA other_schema;
|
CREATE EXTENSION pg_hint_plan SCHEMA other_schema;
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/pg_hint_plan
|
+LOG: Sending request to compute_ctl: http://localhost:3080/extension_server/pg_hint_plan
|
||||||
ERROR: extension "pg_hint_plan" must be installed in schema "hint_plan"
|
ERROR: extension "pg_hint_plan" must be installed in schema "hint_plan"
|
||||||
CREATE EXTENSION pg_hint_plan;
|
CREATE EXTENSION pg_hint_plan;
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/pg_hint_plan
|
+LOG: Sending request to compute_ctl: http://localhost:3080/extension_server/pg_hint_plan
|
||||||
DROP SCHEMA other_schema;
|
DROP SCHEMA other_schema;
|
||||||
----
|
----
|
||||||
---- No. A-5-1 comment pattern
|
---- No. A-5-1 comment pattern
|
||||||
@@ -35,7 +35,7 @@ index d372459..6282afe 100644
|
|||||||
SET client_min_messages TO LOG;
|
SET client_min_messages TO LOG;
|
||||||
SET pg_hint_plan.enable_hint TO on;
|
SET pg_hint_plan.enable_hint TO on;
|
||||||
CREATE EXTENSION file_fdw;
|
CREATE EXTENSION file_fdw;
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/file_fdw
|
+LOG: Sending request to compute_ctl: http://localhost:3080/extension_server/file_fdw
|
||||||
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
|
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
|
||||||
CREATE USER MAPPING FOR PUBLIC SERVER file_server;
|
CREATE USER MAPPING FOR PUBLIC SERVER file_server;
|
||||||
CREATE FOREIGN TABLE ft1 (id int, val int) SERVER file_server OPTIONS (format 'csv', filename :'filename');
|
CREATE FOREIGN TABLE ft1 (id int, val int) SERVER file_server OPTIONS (format 'csv', filename :'filename');
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
diff --git a/expected/ut-A.out b/expected/ut-A.out
|
|
||||||
index e7d68a1..65a056c 100644
|
|
||||||
--- a/expected/ut-A.out
|
|
||||||
+++ b/expected/ut-A.out
|
|
||||||
@@ -9,13 +9,16 @@ SET search_path TO public;
|
|
||||||
----
|
|
||||||
-- No.A-1-1-3
|
|
||||||
CREATE EXTENSION pg_hint_plan;
|
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/pg_hint_plan
|
|
||||||
-- No.A-1-2-3
|
|
||||||
DROP EXTENSION pg_hint_plan;
|
|
||||||
-- No.A-1-1-4
|
|
||||||
CREATE SCHEMA other_schema;
|
|
||||||
CREATE EXTENSION pg_hint_plan SCHEMA other_schema;
|
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/pg_hint_plan
|
|
||||||
ERROR: extension "pg_hint_plan" must be installed in schema "hint_plan"
|
|
||||||
CREATE EXTENSION pg_hint_plan;
|
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/pg_hint_plan
|
|
||||||
DROP SCHEMA other_schema;
|
|
||||||
----
|
|
||||||
---- No. A-5-1 comment pattern
|
|
||||||
diff --git a/expected/ut-J.out b/expected/ut-J.out
|
|
||||||
index 2fa3c70..314e929 100644
|
|
||||||
--- a/expected/ut-J.out
|
|
||||||
+++ b/expected/ut-J.out
|
|
||||||
@@ -789,38 +789,6 @@ NestLoop(st1 st2)
|
|
||||||
MergeJoin(t1 t2)
|
|
||||||
not used hint:
|
|
||||||
duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-NestLoop(st1 st2)
|
|
||||||
-MergeJoin(t1 t2)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-NestLoop(st1 st2)
|
|
||||||
-MergeJoin(t1 t2)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-NestLoop(st1 st2)
|
|
||||||
-MergeJoin(t1 t2)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-NestLoop(st1 st2)
|
|
||||||
-MergeJoin(t1 t2)
|
|
||||||
-duplication hint:
|
|
||||||
error hint:
|
|
||||||
|
|
||||||
explain_filter
|
|
||||||
diff --git a/expected/ut-S.out b/expected/ut-S.out
|
|
||||||
index 0bfcfb8..e75f581 100644
|
|
||||||
--- a/expected/ut-S.out
|
|
||||||
+++ b/expected/ut-S.out
|
|
||||||
@@ -4415,34 +4415,6 @@ used hint:
|
|
||||||
IndexScan(ti1 ti1_pred)
|
|
||||||
not used hint:
|
|
||||||
duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(ti1 ti1_pred)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(ti1 ti1_pred)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(ti1 ti1_pred)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(ti1 ti1_pred)
|
|
||||||
-duplication hint:
|
|
||||||
error hint:
|
|
||||||
|
|
||||||
explain_filter
|
|
||||||
diff --git a/expected/ut-W.out b/expected/ut-W.out
|
|
||||||
index a09bd34..0ad227c 100644
|
|
||||||
--- a/expected/ut-W.out
|
|
||||||
+++ b/expected/ut-W.out
|
|
||||||
@@ -1341,54 +1341,6 @@ IndexScan(ft1)
|
|
||||||
IndexScan(t)
|
|
||||||
Parallel(s1 3 hard)
|
|
||||||
duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(*VALUES*)
|
|
||||||
-SeqScan(cte1)
|
|
||||||
-IndexScan(ft1)
|
|
||||||
-IndexScan(t)
|
|
||||||
-Parallel(p1 5 hard)
|
|
||||||
-Parallel(s1 3 hard)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(*VALUES*)
|
|
||||||
-SeqScan(cte1)
|
|
||||||
-IndexScan(ft1)
|
|
||||||
-IndexScan(t)
|
|
||||||
-Parallel(p1 5 hard)
|
|
||||||
-Parallel(s1 3 hard)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(*VALUES*)
|
|
||||||
-SeqScan(cte1)
|
|
||||||
-IndexScan(ft1)
|
|
||||||
-IndexScan(t)
|
|
||||||
-Parallel(p1 5 hard)
|
|
||||||
-Parallel(s1 3 hard)
|
|
||||||
-duplication hint:
|
|
||||||
-error hint:
|
|
||||||
-
|
|
||||||
-LOG: pg_hint_plan:
|
|
||||||
-used hint:
|
|
||||||
-not used hint:
|
|
||||||
-IndexScan(*VALUES*)
|
|
||||||
-SeqScan(cte1)
|
|
||||||
-IndexScan(ft1)
|
|
||||||
-IndexScan(t)
|
|
||||||
-Parallel(p1 5 hard)
|
|
||||||
-Parallel(s1 3 hard)
|
|
||||||
-duplication hint:
|
|
||||||
error hint:
|
|
||||||
|
|
||||||
explain_filter
|
|
||||||
diff --git a/expected/ut-fdw.out b/expected/ut-fdw.out
|
|
||||||
index 017fa4b..98d989b 100644
|
|
||||||
--- a/expected/ut-fdw.out
|
|
||||||
+++ b/expected/ut-fdw.out
|
|
||||||
@@ -7,6 +7,7 @@ SET pg_hint_plan.debug_print TO on;
|
|
||||||
SET client_min_messages TO LOG;
|
|
||||||
SET pg_hint_plan.enable_hint TO on;
|
|
||||||
CREATE EXTENSION file_fdw;
|
|
||||||
+LOG: Sending request to compute_ctl: http://localhost:3081/extension_server/file_fdw
|
|
||||||
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
|
|
||||||
CREATE USER MAPPING FOR PUBLIC SERVER file_server;
|
|
||||||
CREATE FOREIGN TABLE ft1 (id int, val int) SERVER file_server OPTIONS (format 'csv', filename :'filename');
|
|
||||||
@@ -1,24 +1,8 @@
|
|||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index 7a4b88c..56678af 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -3,7 +3,10 @@ EXTVERSION = 0.8.0
|
|
||||||
|
|
||||||
MODULE_big = vector
|
|
||||||
DATA = $(wildcard sql/*--*--*.sql)
|
|
||||||
-DATA_built = sql/$(EXTENSION)--$(EXTVERSION).sql
|
|
||||||
+# This change is needed to install different per-version SQL files
|
|
||||||
+# like pgvector--0.8.0.sql and pgvector--0.7.4.sql
|
|
||||||
+# The corresponding file is downloaded during the Docker image build process
|
|
||||||
+DATA_built = sql/$(EXTENSION)--$(EXTVERSION).sql sql/vector--0.7.4.sql
|
|
||||||
OBJS = src/bitutils.o src/bitvec.o src/halfutils.o src/halfvec.o src/hnsw.o src/hnswbuild.o src/hnswinsert.o src/hnswscan.o src/hnswutils.o src/hnswvacuum.o src/ivfbuild.o src/ivfflat.o src/ivfinsert.o src/ivfkmeans.o src/ivfscan.o src/ivfutils.o src/ivfvacuum.o src/sparsevec.o src/vector.o
|
|
||||||
HEADERS = src/halfvec.h src/sparsevec.h src/vector.h
|
|
||||||
|
|
||||||
diff --git a/src/hnswbuild.c b/src/hnswbuild.c
|
diff --git a/src/hnswbuild.c b/src/hnswbuild.c
|
||||||
index b667478..fc1897c 100644
|
index dcfb2bd..d5189ee 100644
|
||||||
--- a/src/hnswbuild.c
|
--- a/src/hnswbuild.c
|
||||||
+++ b/src/hnswbuild.c
|
+++ b/src/hnswbuild.c
|
||||||
@@ -843,9 +843,17 @@ HnswParallelBuildMain(dsm_segment *seg, shm_toc *toc)
|
@@ -860,9 +860,17 @@ HnswParallelBuildMain(dsm_segment *seg, shm_toc *toc)
|
||||||
|
|
||||||
hnswarea = shm_toc_lookup(toc, PARALLEL_KEY_HNSW_AREA, false);
|
hnswarea = shm_toc_lookup(toc, PARALLEL_KEY_HNSW_AREA, false);
|
||||||
|
|
||||||
@@ -36,7 +20,7 @@ index b667478..fc1897c 100644
|
|||||||
/* Close relations within worker */
|
/* Close relations within worker */
|
||||||
index_close(indexRel, indexLockmode);
|
index_close(indexRel, indexLockmode);
|
||||||
table_close(heapRel, heapLockmode);
|
table_close(heapRel, heapLockmode);
|
||||||
@@ -1100,12 +1108,38 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
|
@@ -1117,12 +1125,38 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
|
||||||
SeedRandom(42);
|
SeedRandom(42);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
commit 46b38d3e46f9cd6c70d9b189dd6ff4abaa17cf5e
|
|
||||||
Author: Alexander Bayandin <alexander@neon.tech>
|
|
||||||
Date: Sat Nov 30 18:29:32 2024 +0000
|
|
||||||
|
|
||||||
Fix v8 9.7.37 compilation on Debian 12
|
|
||||||
|
|
||||||
diff --git a/patches/code/84cf3230a9680aac3b73c410c2b758760b6d3066.patch b/patches/code/84cf3230a9680aac3b73c410c2b758760b6d3066.patch
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..f0a5dc7
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/patches/code/84cf3230a9680aac3b73c410c2b758760b6d3066.patch
|
|
||||||
@@ -0,0 +1,30 @@
|
|
||||||
+From 84cf3230a9680aac3b73c410c2b758760b6d3066 Mon Sep 17 00:00:00 2001
|
|
||||||
+From: Michael Lippautz <mlippautz@chromium.org>
|
|
||||||
+Date: Thu, 27 Jan 2022 14:14:11 +0100
|
|
||||||
+Subject: [PATCH] cppgc: Fix include
|
|
||||||
+
|
|
||||||
+Add <utility> to cover for std::exchange.
|
|
||||||
+
|
|
||||||
+Bug: v8:12585
|
|
||||||
+Change-Id: Ida65144e93e466be8914527d0e646f348c136bcb
|
|
||||||
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3420309
|
|
||||||
+Auto-Submit: Michael Lippautz <mlippautz@chromium.org>
|
|
||||||
+Reviewed-by: Omer Katz <omerkatz@chromium.org>
|
|
||||||
+Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
|
|
||||||
+Cr-Commit-Position: refs/heads/main@{#78820}
|
|
||||||
+---
|
|
||||||
+ src/heap/cppgc/prefinalizer-handler.h | 1 +
|
|
||||||
+ 1 file changed, 1 insertion(+)
|
|
||||||
+
|
|
||||||
+diff --git a/src/heap/cppgc/prefinalizer-handler.h b/src/heap/cppgc/prefinalizer-handler.h
|
|
||||||
+index bc17c99b1838..c82c91ff5a45 100644
|
|
||||||
+--- a/src/heap/cppgc/prefinalizer-handler.h
|
|
||||||
++++ b/src/heap/cppgc/prefinalizer-handler.h
|
|
||||||
+@@ -5,6 +5,7 @@
|
|
||||||
+ #ifndef V8_HEAP_CPPGC_PREFINALIZER_HANDLER_H_
|
|
||||||
+ #define V8_HEAP_CPPGC_PREFINALIZER_HANDLER_H_
|
|
||||||
+
|
|
||||||
++#include <utility>
|
|
||||||
+ #include <vector>
|
|
||||||
+
|
|
||||||
+ #include "include/cppgc/prefinalizer.h"
|
|
||||||
@@ -26,11 +26,7 @@ commands:
|
|||||||
- name: postgres-exporter
|
- name: postgres-exporter
|
||||||
user: nobody
|
user: nobody
|
||||||
sysvInitAction: respawn
|
sysvInitAction: respawn
|
||||||
shell: 'DATA_SOURCE_NAME="user=cloud_admin sslmode=disable dbname=postgres application_name=postgres-exporter" /bin/postgres_exporter --config.file=/etc/postgres_exporter.yml'
|
shell: 'DATA_SOURCE_NAME="user=cloud_admin sslmode=disable dbname=postgres application_name=postgres-exporter" /bin/postgres_exporter'
|
||||||
- name: pgbouncer-exporter
|
|
||||||
user: postgres
|
|
||||||
sysvInitAction: respawn
|
|
||||||
shell: '/bin/pgbouncer_exporter --pgBouncer.connectionString="postgres:///pgbouncer?host=/tmp&port=6432&dbname=pgbouncer&user=pgbouncer"'
|
|
||||||
- name: sql-exporter
|
- name: sql-exporter
|
||||||
user: nobody
|
user: nobody
|
||||||
sysvInitAction: respawn
|
sysvInitAction: respawn
|
||||||
@@ -47,9 +43,7 @@ files:
|
|||||||
# Allow postgres user (which is what compute_ctl runs as) to run /neonvm/bin/resize-swap
|
# Allow postgres user (which is what compute_ctl runs as) to run /neonvm/bin/resize-swap
|
||||||
# and /neonvm/bin/set-disk-quota as root without requiring entering a password (NOPASSWD),
|
# and /neonvm/bin/set-disk-quota as root without requiring entering a password (NOPASSWD),
|
||||||
# regardless of hostname (ALL)
|
# regardless of hostname (ALL)
|
||||||
#
|
postgres ALL=(root) NOPASSWD: /neonvm/bin/resize-swap, /neonvm/bin/set-disk-quota
|
||||||
# Also allow it to shut down the VM. The fast_import job does that when it's finished.
|
|
||||||
postgres ALL=(root) NOPASSWD: /neonvm/bin/resize-swap, /neonvm/bin/set-disk-quota, /neonvm/bin/poweroff
|
|
||||||
- filename: cgconfig.conf
|
- filename: cgconfig.conf
|
||||||
content: |
|
content: |
|
||||||
# Configuration for cgroups in VM compute nodes
|
# Configuration for cgroups in VM compute nodes
|
||||||
@@ -74,8 +68,8 @@ build: |
|
|||||||
# At time of migration to bookworm (2024-10-09), debian has a version of libcgroup/cgroup-tools 2.0.2,
|
# At time of migration to bookworm (2024-10-09), debian has a version of libcgroup/cgroup-tools 2.0.2,
|
||||||
# and it _probably_ can be used as-is. However, we'll build it ourselves to minimise the changeset
|
# and it _probably_ can be used as-is. However, we'll build it ourselves to minimise the changeset
|
||||||
# for debian version migration.
|
# for debian version migration.
|
||||||
ARG BOOKWORM_SLIM_SHA=sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7
|
#
|
||||||
FROM debian@$BOOKWORM_SLIM_SHA as libcgroup-builder
|
FROM debian:bookworm-slim as libcgroup-builder
|
||||||
ENV LIBCGROUP_VERSION=v2.0.3
|
ENV LIBCGROUP_VERSION=v2.0.3
|
||||||
|
|
||||||
RUN set -exu \
|
RUN set -exu \
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ commands:
|
|||||||
- name: postgres-exporter
|
- name: postgres-exporter
|
||||||
user: nobody
|
user: nobody
|
||||||
sysvInitAction: respawn
|
sysvInitAction: respawn
|
||||||
shell: 'DATA_SOURCE_NAME="user=cloud_admin sslmode=disable dbname=postgres application_name=postgres-exporter" /bin/postgres_exporter --config.file=/etc/postgres_exporter.yml'
|
shell: 'DATA_SOURCE_NAME="user=cloud_admin sslmode=disable dbname=postgres application_name=postgres-exporter" /bin/postgres_exporter'
|
||||||
- name: pgbouncer-exporter
|
|
||||||
user: postgres
|
|
||||||
sysvInitAction: respawn
|
|
||||||
shell: '/bin/pgbouncer_exporter --pgBouncer.connectionString="postgres:///pgbouncer?host=/tmp&port=6432&dbname=pgbouncer&user=pgbouncer"'
|
|
||||||
- name: sql-exporter
|
- name: sql-exporter
|
||||||
user: nobody
|
user: nobody
|
||||||
sysvInitAction: respawn
|
sysvInitAction: respawn
|
||||||
@@ -68,8 +64,7 @@ build: |
|
|||||||
# At time of writing (2023-03-14), debian bullseye has a version of cgroup-tools (technically
|
# At time of writing (2023-03-14), debian bullseye has a version of cgroup-tools (technically
|
||||||
# libcgroup) that doesn't support cgroup v2 (version 0.41-11). Unfortunately, the vm-monitor
|
# libcgroup) that doesn't support cgroup v2 (version 0.41-11). Unfortunately, the vm-monitor
|
||||||
# requires cgroup v2, so we'll build cgroup-tools ourselves.
|
# requires cgroup v2, so we'll build cgroup-tools ourselves.
|
||||||
ARG BULLSEYE_SLIM_SHA=sha256:e831d9a884d63734fe3dd9c491ed9a5a3d4c6a6d32c5b14f2067357c49b0b7e1
|
FROM debian:bullseye-slim as libcgroup-builder
|
||||||
FROM debian@$BULLSEYE_SLIM_SHA as libcgroup-builder
|
|
||||||
ENV LIBCGROUP_VERSION=v2.0.3
|
ENV LIBCGROUP_VERSION=v2.0.3
|
||||||
|
|
||||||
RUN set -exu \
|
RUN set -exu \
|
||||||
|
|||||||
@@ -7,40 +7,27 @@ license.workspace = true
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
# Enables test specific features.
|
# Enables test specific features.
|
||||||
testing = ["fail/failpoints"]
|
testing = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64.workspace = true
|
|
||||||
aws-config.workspace = true
|
|
||||||
aws-sdk-s3.workspace = true
|
|
||||||
aws-sdk-kms.workspace = true
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
axum = { workspace = true, features = [] }
|
|
||||||
camino.workspace = true
|
camino.workspace = true
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
cfg-if.workspace = true
|
cfg-if.workspace = true
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
fail.workspace = true
|
|
||||||
flate2.workspace = true
|
flate2.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
http.workspace = true
|
hyper0 = { workspace = true, features = ["full"] }
|
||||||
jsonwebtoken.workspace = true
|
|
||||||
metrics.workspace = true
|
|
||||||
nix.workspace = true
|
nix.workspace = true
|
||||||
notify.workspace = true
|
notify.workspace = true
|
||||||
num_cpus.workspace = true
|
num_cpus.workspace = true
|
||||||
once_cell.workspace = true
|
|
||||||
opentelemetry.workspace = true
|
opentelemetry.workspace = true
|
||||||
opentelemetry_sdk.workspace = true
|
opentelemetry_sdk.workspace = true
|
||||||
postgres.workspace = true
|
postgres.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
serde.workspace = true
|
|
||||||
serde_with.workspace = true
|
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
signal-hook.workspace = true
|
signal-hook.workspace = true
|
||||||
tar.workspace = true
|
tar.workspace = true
|
||||||
tower.workspace = true
|
|
||||||
tower-http.workspace = true
|
|
||||||
reqwest = { workspace = true, features = ["json"] }
|
reqwest = { workspace = true, features = ["json"] }
|
||||||
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
|
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
|
||||||
tokio-postgres.workspace = true
|
tokio-postgres.workspace = true
|
||||||
@@ -52,10 +39,7 @@ tracing-subscriber.workspace = true
|
|||||||
tracing-utils.workspace = true
|
tracing-utils.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
uuid.workspace = true
|
|
||||||
prometheus.workspace = true
|
|
||||||
|
|
||||||
postgres_initdb.workspace = true
|
|
||||||
compute_api.workspace = true
|
compute_api.workspace = true
|
||||||
utils.workspace = true
|
utils.workspace = true
|
||||||
workspace_hack.workspace = true
|
workspace_hack.workspace = true
|
||||||
|
|||||||
@@ -34,150 +34,45 @@
|
|||||||
//! -r http://pg-ext-s3-gateway \
|
//! -r http://pg-ext-s3-gateway \
|
||||||
//! ```
|
//! ```
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsString;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::{mpsc, Arc, Condvar, Mutex, RwLock};
|
use std::sync::{mpsc, Arc, Condvar, Mutex, RwLock};
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::{thread, time::Duration};
|
use std::{thread, time::Duration};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use clap::Parser;
|
use clap::Arg;
|
||||||
use compute_tools::disk_quota::set_disk_quota;
|
use compute_tools::disk_quota::set_disk_quota;
|
||||||
use compute_tools::http::server::Server;
|
|
||||||
use compute_tools::lsn_lease::launch_lsn_lease_bg_task_for_static;
|
use compute_tools::lsn_lease::launch_lsn_lease_bg_task_for_static;
|
||||||
use signal_hook::consts::{SIGQUIT, SIGTERM};
|
use signal_hook::consts::{SIGQUIT, SIGTERM};
|
||||||
use signal_hook::{consts::SIGINT, iterator::Signals};
|
use signal_hook::{consts::SIGINT, iterator::Signals};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use compute_api::responses::{ComputeCtlConfig, ComputeStatus};
|
use compute_api::responses::ComputeStatus;
|
||||||
use compute_api::spec::ComputeSpec;
|
use compute_api::spec::ComputeSpec;
|
||||||
|
|
||||||
use compute_tools::compute::{
|
use compute_tools::compute::{
|
||||||
forward_termination_signal, ComputeNode, ComputeState, ParsedSpec, PG_PID,
|
forward_termination_signal, ComputeNode, ComputeState, ParsedSpec, PG_PID,
|
||||||
};
|
};
|
||||||
use compute_tools::configurator::launch_configurator;
|
use compute_tools::configurator::launch_configurator;
|
||||||
use compute_tools::extension_server::get_pg_version_string;
|
use compute_tools::extension_server::get_pg_version;
|
||||||
|
use compute_tools::http::api::launch_http_server;
|
||||||
use compute_tools::logger::*;
|
use compute_tools::logger::*;
|
||||||
use compute_tools::monitor::launch_monitor;
|
use compute_tools::monitor::launch_monitor;
|
||||||
use compute_tools::params::*;
|
use compute_tools::params::*;
|
||||||
use compute_tools::spec::*;
|
use compute_tools::spec::*;
|
||||||
use compute_tools::swap::resize_swap;
|
use compute_tools::swap::resize_swap;
|
||||||
use rlimit::{setrlimit, Resource};
|
use rlimit::{setrlimit, Resource};
|
||||||
use utils::failpoint_support;
|
|
||||||
|
|
||||||
// this is an arbitrary build tag. Fine as a default / for testing purposes
|
// this is an arbitrary build tag. Fine as a default / for testing purposes
|
||||||
// in-case of not-set environment var
|
// in-case of not-set environment var
|
||||||
const BUILD_TAG_DEFAULT: &str = "latest";
|
const BUILD_TAG_DEFAULT: &str = "latest";
|
||||||
|
|
||||||
// Compatibility hack: if the control plane specified any remote-ext-config
|
|
||||||
// use the default value for extension storage proxy gateway.
|
|
||||||
// Remove this once the control plane is updated to pass the gateway URL
|
|
||||||
fn parse_remote_ext_config(arg: &str) -> Result<String> {
|
|
||||||
if arg.starts_with("http") {
|
|
||||||
Ok(arg.trim_end_matches('/').to_string())
|
|
||||||
} else {
|
|
||||||
Ok("http://pg-ext-s3-gateway".to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate a compute ID if one is not supplied. This exists to keep forward
|
|
||||||
/// compatibility tests working, but will be removed in a future iteration.
|
|
||||||
fn generate_compute_id() -> String {
|
|
||||||
let now = SystemTime::now();
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"compute-{}",
|
|
||||||
now.duration_since(SystemTime::UNIX_EPOCH)
|
|
||||||
.unwrap()
|
|
||||||
.as_secs()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(rename_all = "kebab-case")]
|
|
||||||
struct Cli {
|
|
||||||
#[arg(short = 'b', long, default_value = "postgres", env = "POSTGRES_PATH")]
|
|
||||||
pub pgbin: String,
|
|
||||||
|
|
||||||
#[arg(short = 'r', long, value_parser = parse_remote_ext_config)]
|
|
||||||
pub remote_ext_config: Option<String>,
|
|
||||||
|
|
||||||
/// The port to bind the external listening HTTP server to. Clients running
|
|
||||||
/// outside the compute will talk to the compute through this port. Keep
|
|
||||||
/// the previous name for this argument around for a smoother release
|
|
||||||
/// with the control plane.
|
|
||||||
///
|
|
||||||
/// TODO: Remove the alias after the control plane release which teaches the
|
|
||||||
/// control plane about the renamed argument.
|
|
||||||
#[arg(long, alias = "http-port", default_value_t = 3080)]
|
|
||||||
pub external_http_port: u16,
|
|
||||||
|
|
||||||
/// The port to bind the internal listening HTTP server to. Clients like
|
|
||||||
/// the neon extension (for installing remote extensions) and local_proxy.
|
|
||||||
#[arg(long)]
|
|
||||||
pub internal_http_port: Option<u16>,
|
|
||||||
|
|
||||||
#[arg(short = 'D', long, value_name = "DATADIR")]
|
|
||||||
pub pgdata: String,
|
|
||||||
|
|
||||||
#[arg(short = 'C', long, value_name = "DATABASE_URL")]
|
|
||||||
pub connstr: String,
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
#[arg(long, default_value = "neon-postgres")]
|
|
||||||
pub cgroup: String,
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
#[arg(
|
|
||||||
long,
|
|
||||||
default_value = "host=localhost port=5432 dbname=postgres user=cloud_admin sslmode=disable application_name=vm-monitor"
|
|
||||||
)]
|
|
||||||
pub filecache_connstr: String,
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
#[arg(long, default_value = "0.0.0.0:10301")]
|
|
||||||
pub vm_monitor_addr: String,
|
|
||||||
|
|
||||||
#[arg(long, action = clap::ArgAction::SetTrue)]
|
|
||||||
pub resize_swap_on_bind: bool,
|
|
||||||
|
|
||||||
#[arg(long)]
|
|
||||||
pub set_disk_quota_for_fs: Option<String>,
|
|
||||||
|
|
||||||
#[arg(short = 's', long = "spec", group = "spec")]
|
|
||||||
pub spec_json: Option<String>,
|
|
||||||
|
|
||||||
#[arg(short = 'S', long, group = "spec-path")]
|
|
||||||
pub spec_path: Option<OsString>,
|
|
||||||
|
|
||||||
#[arg(short = 'i', long, group = "compute-id", default_value = generate_compute_id())]
|
|
||||||
pub compute_id: String,
|
|
||||||
|
|
||||||
#[arg(short = 'p', long, conflicts_with_all = ["spec", "spec-path"], value_name = "CONTROL_PLANE_API_BASE_URL")]
|
|
||||||
pub control_plane_uri: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let cli = Cli::parse();
|
let (build_tag, clap_args) = init()?;
|
||||||
|
|
||||||
// For historical reasons, the main thread that processes the spec and launches postgres
|
|
||||||
// is synchronous, but we always have this tokio runtime available and we "enter" it so
|
|
||||||
// that you can use tokio::spawn() and tokio::runtime::Handle::current().block_on(...)
|
|
||||||
// from all parts of compute_ctl.
|
|
||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()?;
|
|
||||||
let _rt_guard = runtime.enter();
|
|
||||||
|
|
||||||
let build_tag = runtime.block_on(init())?;
|
|
||||||
|
|
||||||
let scenario = failpoint_support::init();
|
|
||||||
|
|
||||||
// enable core dumping for all child processes
|
// enable core dumping for all child processes
|
||||||
setrlimit(Resource::CORE, rlimit::INFINITY, rlimit::INFINITY)?;
|
setrlimit(Resource::CORE, rlimit::INFINITY, rlimit::INFINITY)?;
|
||||||
@@ -186,11 +81,13 @@ fn main() -> Result<()> {
|
|||||||
// Enter startup tracing context
|
// Enter startup tracing context
|
||||||
let _startup_context_guard = startup_context_from_env();
|
let _startup_context_guard = startup_context_from_env();
|
||||||
|
|
||||||
let cli_spec = try_spec_from_cli(&cli)?;
|
let cli_args = process_cli(&clap_args)?;
|
||||||
|
|
||||||
let compute = wait_spec(build_tag, &cli, cli_spec)?;
|
let cli_spec = try_spec_from_cli(&clap_args, &cli_args)?;
|
||||||
|
|
||||||
start_postgres(&cli, compute)?
|
let wait_spec_result = wait_spec(build_tag, cli_args, cli_spec)?;
|
||||||
|
|
||||||
|
start_postgres(&clap_args, wait_spec_result)?
|
||||||
|
|
||||||
// Startup is finished, exit the startup tracing span
|
// Startup is finished, exit the startup tracing span
|
||||||
};
|
};
|
||||||
@@ -202,13 +99,11 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
maybe_delay_exit(delay_exit);
|
maybe_delay_exit(delay_exit);
|
||||||
|
|
||||||
scenario.teardown();
|
|
||||||
|
|
||||||
deinit_and_exit(wait_pg_result);
|
deinit_and_exit(wait_pg_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init() -> Result<String> {
|
fn init() -> Result<(String, clap::ArgMatches)> {
|
||||||
init_tracing_and_logging(DEFAULT_LOG_LEVEL).await?;
|
init_tracing_and_logging(DEFAULT_LOG_LEVEL)?;
|
||||||
|
|
||||||
let mut signals = Signals::new([SIGINT, SIGTERM, SIGQUIT])?;
|
let mut signals = Signals::new([SIGINT, SIGTERM, SIGQUIT])?;
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
@@ -222,7 +117,66 @@ async fn init() -> Result<String> {
|
|||||||
.to_string();
|
.to_string();
|
||||||
info!("build_tag: {build_tag}");
|
info!("build_tag: {build_tag}");
|
||||||
|
|
||||||
Ok(build_tag)
|
Ok((build_tag, cli().get_matches()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_cli(matches: &clap::ArgMatches) -> Result<ProcessCliResult> {
|
||||||
|
let pgbin_default = "postgres";
|
||||||
|
let pgbin = matches
|
||||||
|
.get_one::<String>("pgbin")
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(pgbin_default);
|
||||||
|
|
||||||
|
let ext_remote_storage = matches
|
||||||
|
.get_one::<String>("remote-ext-config")
|
||||||
|
// Compatibility hack: if the control plane specified any remote-ext-config
|
||||||
|
// use the default value for extension storage proxy gateway.
|
||||||
|
// Remove this once the control plane is updated to pass the gateway URL
|
||||||
|
.map(|conf| {
|
||||||
|
if conf.starts_with("http") {
|
||||||
|
conf.trim_end_matches('/')
|
||||||
|
} else {
|
||||||
|
"http://pg-ext-s3-gateway"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let http_port = *matches
|
||||||
|
.get_one::<u16>("http-port")
|
||||||
|
.expect("http-port is required");
|
||||||
|
let pgdata = matches
|
||||||
|
.get_one::<String>("pgdata")
|
||||||
|
.expect("PGDATA path is required");
|
||||||
|
let connstr = matches
|
||||||
|
.get_one::<String>("connstr")
|
||||||
|
.expect("Postgres connection string is required");
|
||||||
|
let spec_json = matches.get_one::<String>("spec");
|
||||||
|
let spec_path = matches.get_one::<String>("spec-path");
|
||||||
|
let resize_swap_on_bind = matches.get_flag("resize-swap-on-bind");
|
||||||
|
let set_disk_quota_for_fs = matches.get_one::<String>("set-disk-quota-for-fs");
|
||||||
|
|
||||||
|
Ok(ProcessCliResult {
|
||||||
|
connstr,
|
||||||
|
pgdata,
|
||||||
|
pgbin,
|
||||||
|
ext_remote_storage,
|
||||||
|
http_port,
|
||||||
|
spec_json,
|
||||||
|
spec_path,
|
||||||
|
resize_swap_on_bind,
|
||||||
|
set_disk_quota_for_fs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProcessCliResult<'clap> {
|
||||||
|
connstr: &'clap str,
|
||||||
|
pgdata: &'clap str,
|
||||||
|
pgbin: &'clap str,
|
||||||
|
ext_remote_storage: Option<&'clap str>,
|
||||||
|
http_port: u16,
|
||||||
|
spec_json: Option<&'clap String>,
|
||||||
|
spec_path: Option<&'clap String>,
|
||||||
|
resize_swap_on_bind: bool,
|
||||||
|
set_disk_quota_for_fs: Option<&'clap String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startup_context_from_env() -> Option<opentelemetry::ContextGuard> {
|
fn startup_context_from_env() -> Option<opentelemetry::ContextGuard> {
|
||||||
@@ -275,65 +229,83 @@ fn startup_context_from_env() -> Option<opentelemetry::ContextGuard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_spec_from_cli(cli: &Cli) -> Result<CliSpecParams> {
|
fn try_spec_from_cli(
|
||||||
// First, try to get cluster spec from the cli argument
|
matches: &clap::ArgMatches,
|
||||||
if let Some(ref spec_json) = cli.spec_json {
|
ProcessCliResult {
|
||||||
info!("got spec from cli argument {}", spec_json);
|
spec_json,
|
||||||
return Ok(CliSpecParams {
|
spec_path,
|
||||||
spec: Some(serde_json::from_str(spec_json)?),
|
..
|
||||||
compute_ctl_config: ComputeCtlConfig::default(),
|
}: &ProcessCliResult,
|
||||||
live_config_allowed: false,
|
) -> Result<CliSpecParams> {
|
||||||
});
|
let compute_id = matches.get_one::<String>("compute-id");
|
||||||
}
|
let control_plane_uri = matches.get_one::<String>("control-plane-uri");
|
||||||
|
|
||||||
// Second, try to read it from the file if path is provided
|
let spec;
|
||||||
if let Some(ref spec_path) = cli.spec_path {
|
let mut live_config_allowed = false;
|
||||||
let file = File::open(Path::new(spec_path))?;
|
match spec_json {
|
||||||
return Ok(CliSpecParams {
|
// First, try to get cluster spec from the cli argument
|
||||||
spec: Some(serde_json::from_reader(file)?),
|
Some(json) => {
|
||||||
compute_ctl_config: ComputeCtlConfig::default(),
|
info!("got spec from cli argument {}", json);
|
||||||
live_config_allowed: true,
|
spec = Some(serde_json::from_str(json)?);
|
||||||
});
|
}
|
||||||
}
|
None => {
|
||||||
|
// Second, try to read it from the file if path is provided
|
||||||
if cli.control_plane_uri.is_none() {
|
if let Some(sp) = spec_path {
|
||||||
panic!("must specify --control-plane-uri");
|
let path = Path::new(sp);
|
||||||
|
let file = File::open(path)?;
|
||||||
|
spec = Some(serde_json::from_reader(file)?);
|
||||||
|
live_config_allowed = true;
|
||||||
|
} else if let Some(id) = compute_id {
|
||||||
|
if let Some(cp_base) = control_plane_uri {
|
||||||
|
live_config_allowed = true;
|
||||||
|
spec = match get_spec_from_control_plane(cp_base, id) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
error!("cannot get response from control plane: {}", e);
|
||||||
|
panic!("neither spec nor confirmation that compute is in the Empty state was received");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
panic!("must specify both --control-plane-uri and --compute-id or none");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"compute spec should be provided by one of the following ways: \
|
||||||
|
--spec OR --spec-path OR --control-plane-uri and --compute-id"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match get_spec_from_control_plane(cli.control_plane_uri.as_ref().unwrap(), &cli.compute_id) {
|
Ok(CliSpecParams {
|
||||||
Ok(resp) => Ok(CliSpecParams {
|
spec,
|
||||||
spec: resp.0,
|
live_config_allowed,
|
||||||
compute_ctl_config: resp.1,
|
})
|
||||||
live_config_allowed: true,
|
|
||||||
}),
|
|
||||||
Err(e) => {
|
|
||||||
error!(
|
|
||||||
"cannot get response from control plane: {}\n\
|
|
||||||
neither spec nor confirmation that compute is in the Empty state was received",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CliSpecParams {
|
struct CliSpecParams {
|
||||||
/// If a spec was provided via CLI or file, the [`ComputeSpec`]
|
/// If a spec was provided via CLI or file, the [`ComputeSpec`]
|
||||||
spec: Option<ComputeSpec>,
|
spec: Option<ComputeSpec>,
|
||||||
#[allow(dead_code)]
|
|
||||||
compute_ctl_config: ComputeCtlConfig,
|
|
||||||
live_config_allowed: bool,
|
live_config_allowed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_spec(
|
fn wait_spec(
|
||||||
build_tag: String,
|
build_tag: String,
|
||||||
cli: &Cli,
|
ProcessCliResult {
|
||||||
|
connstr,
|
||||||
|
pgdata,
|
||||||
|
pgbin,
|
||||||
|
ext_remote_storage,
|
||||||
|
resize_swap_on_bind,
|
||||||
|
set_disk_quota_for_fs,
|
||||||
|
http_port,
|
||||||
|
..
|
||||||
|
}: ProcessCliResult,
|
||||||
CliSpecParams {
|
CliSpecParams {
|
||||||
spec,
|
spec,
|
||||||
live_config_allowed,
|
live_config_allowed,
|
||||||
compute_ctl_config: _,
|
|
||||||
}: CliSpecParams,
|
}: CliSpecParams,
|
||||||
) -> Result<Arc<ComputeNode>> {
|
) -> Result<WaitSpecResult> {
|
||||||
let mut new_state = ComputeState::new();
|
let mut new_state = ComputeState::new();
|
||||||
let spec_set;
|
let spec_set;
|
||||||
|
|
||||||
@@ -345,25 +317,15 @@ fn wait_spec(
|
|||||||
} else {
|
} else {
|
||||||
spec_set = false;
|
spec_set = false;
|
||||||
}
|
}
|
||||||
let connstr = Url::parse(&cli.connstr).context("cannot parse connstr as a URL")?;
|
|
||||||
let conn_conf = postgres::config::Config::from_str(connstr.as_str())
|
|
||||||
.context("cannot build postgres config from connstr")?;
|
|
||||||
let tokio_conn_conf = tokio_postgres::config::Config::from_str(connstr.as_str())
|
|
||||||
.context("cannot build tokio postgres config from connstr")?;
|
|
||||||
let compute_node = ComputeNode {
|
let compute_node = ComputeNode {
|
||||||
compute_id: cli.compute_id.clone(),
|
connstr: Url::parse(connstr).context("cannot parse connstr as a URL")?,
|
||||||
connstr,
|
pgdata: pgdata.to_string(),
|
||||||
conn_conf,
|
pgbin: pgbin.to_string(),
|
||||||
tokio_conn_conf,
|
pgversion: get_pg_version(pgbin),
|
||||||
pgdata: cli.pgdata.clone(),
|
|
||||||
pgbin: cli.pgbin.clone(),
|
|
||||||
pgversion: get_pg_version_string(&cli.pgbin),
|
|
||||||
external_http_port: cli.external_http_port,
|
|
||||||
internal_http_port: cli.internal_http_port.unwrap_or(cli.external_http_port + 1),
|
|
||||||
live_config_allowed,
|
live_config_allowed,
|
||||||
state: Mutex::new(new_state),
|
state: Mutex::new(new_state),
|
||||||
state_changed: Condvar::new(),
|
state_changed: Condvar::new(),
|
||||||
ext_remote_storage: cli.remote_ext_config.clone(),
|
ext_remote_storage: ext_remote_storage.map(|s| s.to_string()),
|
||||||
ext_download_progress: RwLock::new(HashMap::new()),
|
ext_download_progress: RwLock::new(HashMap::new()),
|
||||||
build_tag,
|
build_tag,
|
||||||
};
|
};
|
||||||
@@ -377,13 +339,10 @@ fn wait_spec(
|
|||||||
compute.prewarm_postgres()?;
|
compute.prewarm_postgres()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Launch the external HTTP server first, so that we can serve control plane
|
// Launch http service first, so that we can serve control-plane requests
|
||||||
// requests while configuration is still in progress.
|
// while configuration is still in progress.
|
||||||
Server::External(cli.external_http_port).launch(&compute);
|
let _http_handle =
|
||||||
|
launch_http_server(http_port, &compute).expect("cannot launch http endpoint thread");
|
||||||
// The internal HTTP server could be launched later, but there isn't much
|
|
||||||
// sense in waiting.
|
|
||||||
Server::Internal(cli.internal_http_port.unwrap_or(cli.external_http_port + 1)).launch(&compute);
|
|
||||||
|
|
||||||
if !spec_set {
|
if !spec_set {
|
||||||
// No spec provided, hang waiting for it.
|
// No spec provided, hang waiting for it.
|
||||||
@@ -415,12 +374,31 @@ fn wait_spec(
|
|||||||
|
|
||||||
launch_lsn_lease_bg_task_for_static(&compute);
|
launch_lsn_lease_bg_task_for_static(&compute);
|
||||||
|
|
||||||
Ok(compute)
|
Ok(WaitSpecResult {
|
||||||
|
compute,
|
||||||
|
http_port,
|
||||||
|
resize_swap_on_bind,
|
||||||
|
set_disk_quota_for_fs: set_disk_quota_for_fs.cloned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WaitSpecResult {
|
||||||
|
compute: Arc<ComputeNode>,
|
||||||
|
// passed through from ProcessCliResult
|
||||||
|
http_port: u16,
|
||||||
|
resize_swap_on_bind: bool,
|
||||||
|
set_disk_quota_for_fs: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_postgres(
|
fn start_postgres(
|
||||||
cli: &Cli,
|
// need to allow unused because `matches` is only used if target_os = "linux"
|
||||||
compute: Arc<ComputeNode>,
|
#[allow(unused_variables)] matches: &clap::ArgMatches,
|
||||||
|
WaitSpecResult {
|
||||||
|
compute,
|
||||||
|
http_port,
|
||||||
|
resize_swap_on_bind,
|
||||||
|
set_disk_quota_for_fs,
|
||||||
|
}: WaitSpecResult,
|
||||||
) -> Result<(Option<PostgresHandle>, StartPostgresResult)> {
|
) -> Result<(Option<PostgresHandle>, StartPostgresResult)> {
|
||||||
// We got all we need, update the state.
|
// We got all we need, update the state.
|
||||||
let mut state = compute.state.lock().unwrap();
|
let mut state = compute.state.lock().unwrap();
|
||||||
@@ -430,14 +408,9 @@ fn start_postgres(
|
|||||||
"running compute with features: {:?}",
|
"running compute with features: {:?}",
|
||||||
state.pspec.as_ref().unwrap().spec.features
|
state.pspec.as_ref().unwrap().spec.features
|
||||||
);
|
);
|
||||||
// before we release the mutex, fetch some parameters for later.
|
// before we release the mutex, fetch the swap size (if any) for later.
|
||||||
let &ComputeSpec {
|
let swap_size_bytes = state.pspec.as_ref().unwrap().spec.swap_size_bytes;
|
||||||
swap_size_bytes,
|
let disk_quota_bytes = state.pspec.as_ref().unwrap().spec.disk_quota_bytes;
|
||||||
disk_quota_bytes,
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
disable_lfc_resizing,
|
|
||||||
..
|
|
||||||
} = &state.pspec.as_ref().unwrap().spec;
|
|
||||||
drop(state);
|
drop(state);
|
||||||
|
|
||||||
// Launch remaining service threads
|
// Launch remaining service threads
|
||||||
@@ -448,7 +421,7 @@ fn start_postgres(
|
|||||||
let mut delay_exit = false;
|
let mut delay_exit = false;
|
||||||
|
|
||||||
// Resize swap to the desired size if the compute spec says so
|
// Resize swap to the desired size if the compute spec says so
|
||||||
if let (Some(size_bytes), true) = (swap_size_bytes, cli.resize_swap_on_bind) {
|
if let (Some(size_bytes), true) = (swap_size_bytes, resize_swap_on_bind) {
|
||||||
// To avoid 'swapoff' hitting postgres startup, we need to run resize-swap to completion
|
// To avoid 'swapoff' hitting postgres startup, we need to run resize-swap to completion
|
||||||
// *before* starting postgres.
|
// *before* starting postgres.
|
||||||
//
|
//
|
||||||
@@ -475,9 +448,9 @@ fn start_postgres(
|
|||||||
|
|
||||||
// Set disk quota if the compute spec says so
|
// Set disk quota if the compute spec says so
|
||||||
if let (Some(disk_quota_bytes), Some(disk_quota_fs_mountpoint)) =
|
if let (Some(disk_quota_bytes), Some(disk_quota_fs_mountpoint)) =
|
||||||
(disk_quota_bytes, cli.set_disk_quota_for_fs.as_ref())
|
(disk_quota_bytes, set_disk_quota_for_fs)
|
||||||
{
|
{
|
||||||
match set_disk_quota(disk_quota_bytes, disk_quota_fs_mountpoint) {
|
match set_disk_quota(disk_quota_bytes, &disk_quota_fs_mountpoint) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
let size_mib = disk_quota_bytes as f32 / (1 << 20) as f32; // just for more coherent display.
|
let size_mib = disk_quota_bytes as f32 / (1 << 20) as f32; // just for more coherent display.
|
||||||
info!(%disk_quota_bytes, %size_mib, "set disk quota");
|
info!(%disk_quota_bytes, %size_mib, "set disk quota");
|
||||||
@@ -495,14 +468,13 @@ fn start_postgres(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let extension_server_port: u16 = http_port;
|
||||||
|
|
||||||
// Start Postgres
|
// Start Postgres
|
||||||
let mut pg = None;
|
let mut pg = None;
|
||||||
if !prestartup_failed {
|
if !prestartup_failed {
|
||||||
pg = match compute.start_compute() {
|
pg = match compute.start_compute(extension_server_port) {
|
||||||
Ok(pg) => {
|
Ok(pg) => Some(pg),
|
||||||
info!(postmaster_pid = %pg.0.id(), "Postgres was started");
|
|
||||||
Some(pg)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("could not start the compute node: {:#}", err);
|
error!("could not start the compute node: {:#}", err);
|
||||||
compute.set_failed_status(err);
|
compute.set_failed_status(err);
|
||||||
@@ -520,30 +492,41 @@ fn start_postgres(
|
|||||||
if #[cfg(target_os = "linux")] {
|
if #[cfg(target_os = "linux")] {
|
||||||
use std::env;
|
use std::env;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
let vm_monitor_addr = matches
|
||||||
|
.get_one::<String>("vm-monitor-addr")
|
||||||
|
.expect("--vm-monitor-addr should always be set because it has a default arg");
|
||||||
|
let file_cache_connstr = matches.get_one::<String>("filecache-connstr");
|
||||||
|
let cgroup = matches.get_one::<String>("cgroup");
|
||||||
|
|
||||||
|
// Only make a runtime if we need to.
|
||||||
|
// Note: it seems like you can make a runtime in an inner scope and
|
||||||
|
// if you start a task in it it won't be dropped. However, make it
|
||||||
|
// in the outermost scope just to be safe.
|
||||||
|
let rt = if env::var_os("AUTOSCALING").is_some() {
|
||||||
|
Some(
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.worker_threads(4)
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("failed to create tokio runtime for monitor")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// This token is used internally by the monitor to clean up all threads
|
// This token is used internally by the monitor to clean up all threads
|
||||||
let token = CancellationToken::new();
|
let token = CancellationToken::new();
|
||||||
|
|
||||||
// don't pass postgres connection string to vm-monitor if we don't want it to resize LFC
|
let vm_monitor = rt.as_ref().map(|rt| {
|
||||||
let pgconnstr = if disable_lfc_resizing.unwrap_or(false) {
|
rt.spawn(vm_monitor::start(
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(cli.filecache_connstr.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
let vm_monitor = if env::var_os("AUTOSCALING").is_some() {
|
|
||||||
let vm_monitor = tokio::spawn(vm_monitor::start(
|
|
||||||
Box::leak(Box::new(vm_monitor::Args {
|
Box::leak(Box::new(vm_monitor::Args {
|
||||||
cgroup: Some(cli.cgroup.clone()),
|
cgroup: cgroup.cloned(),
|
||||||
pgconnstr,
|
pgconnstr: file_cache_connstr.cloned(),
|
||||||
addr: cli.vm_monitor_addr.clone(),
|
addr: vm_monitor_addr.clone(),
|
||||||
})),
|
})),
|
||||||
token.clone(),
|
token.clone(),
|
||||||
));
|
))
|
||||||
Some(vm_monitor)
|
});
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,6 +536,8 @@ fn start_postgres(
|
|||||||
delay_exit,
|
delay_exit,
|
||||||
compute,
|
compute,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
rt,
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
token,
|
token,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
vm_monitor,
|
vm_monitor,
|
||||||
@@ -560,13 +545,15 @@ fn start_postgres(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostgresHandle = (std::process::Child, tokio::task::JoinHandle<Result<()>>);
|
type PostgresHandle = (std::process::Child, std::thread::JoinHandle<()>);
|
||||||
|
|
||||||
struct StartPostgresResult {
|
struct StartPostgresResult {
|
||||||
delay_exit: bool,
|
delay_exit: bool,
|
||||||
// passed through from WaitSpecResult
|
// passed through from WaitSpecResult
|
||||||
compute: Arc<ComputeNode>,
|
compute: Arc<ComputeNode>,
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
rt: Option<tokio::runtime::Runtime>,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
token: tokio_util::sync::CancellationToken,
|
token: tokio_util::sync::CancellationToken,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@@ -578,17 +565,15 @@ fn wait_postgres(pg: Option<PostgresHandle>) -> Result<WaitPostgresResult> {
|
|||||||
// propagate to Postgres and it will be shut down as well.
|
// propagate to Postgres and it will be shut down as well.
|
||||||
let mut exit_code = None;
|
let mut exit_code = None;
|
||||||
if let Some((mut pg, logs_handle)) = pg {
|
if let Some((mut pg, logs_handle)) = pg {
|
||||||
info!(postmaster_pid = %pg.id(), "Waiting for Postgres to exit");
|
|
||||||
|
|
||||||
let ecode = pg
|
let ecode = pg
|
||||||
.wait()
|
.wait()
|
||||||
.expect("failed to start waiting on Postgres process");
|
.expect("failed to start waiting on Postgres process");
|
||||||
PG_PID.store(0, Ordering::SeqCst);
|
PG_PID.store(0, Ordering::SeqCst);
|
||||||
|
|
||||||
// Process has exited. Wait for the log collecting task to finish.
|
// Process has exited, so we can join the logs thread.
|
||||||
let _ = tokio::runtime::Handle::current()
|
let _ = logs_handle
|
||||||
.block_on(logs_handle)
|
.join()
|
||||||
.map_err(|e| tracing::error!("log task panicked: {:?}", e));
|
.map_err(|e| tracing::error!("log thread panicked: {:?}", e));
|
||||||
|
|
||||||
info!("Postgres exited with code {}, shutting down", ecode);
|
info!("Postgres exited with code {}, shutting down", ecode);
|
||||||
exit_code = ecode.code()
|
exit_code = ecode.code()
|
||||||
@@ -609,6 +594,8 @@ fn cleanup_after_postgres_exit(
|
|||||||
vm_monitor,
|
vm_monitor,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
token,
|
token,
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
rt,
|
||||||
}: StartPostgresResult,
|
}: StartPostgresResult,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
// Terminate the vm_monitor so it releases the file watcher on
|
// Terminate the vm_monitor so it releases the file watcher on
|
||||||
@@ -621,6 +608,10 @@ fn cleanup_after_postgres_exit(
|
|||||||
token.cancel();
|
token.cancel();
|
||||||
// Kills the actual task running the monitor
|
// Kills the actual task running the monitor
|
||||||
handle.abort();
|
handle.abort();
|
||||||
|
|
||||||
|
// If handle is some, rt must have been used to produce it, and
|
||||||
|
// hence is also some
|
||||||
|
rt.unwrap().shutdown_timeout(Duration::from_secs(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -685,6 +676,105 @@ fn deinit_and_exit(WaitPostgresResult { exit_code }: WaitPostgresResult) -> ! {
|
|||||||
exit(exit_code.unwrap_or(1))
|
exit(exit_code.unwrap_or(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cli() -> clap::Command {
|
||||||
|
// Env variable is set by `cargo`
|
||||||
|
let version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
|
||||||
|
clap::Command::new("compute_ctl")
|
||||||
|
.version(version)
|
||||||
|
.arg(
|
||||||
|
Arg::new("http-port")
|
||||||
|
.long("http-port")
|
||||||
|
.value_name("HTTP_PORT")
|
||||||
|
.default_value("3080")
|
||||||
|
.value_parser(clap::value_parser!(u16))
|
||||||
|
.required(false),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("connstr")
|
||||||
|
.short('C')
|
||||||
|
.long("connstr")
|
||||||
|
.value_name("DATABASE_URL")
|
||||||
|
.required(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("pgdata")
|
||||||
|
.short('D')
|
||||||
|
.long("pgdata")
|
||||||
|
.value_name("DATADIR")
|
||||||
|
.required(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("pgbin")
|
||||||
|
.short('b')
|
||||||
|
.long("pgbin")
|
||||||
|
.default_value("postgres")
|
||||||
|
.value_name("POSTGRES_PATH"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("spec")
|
||||||
|
.short('s')
|
||||||
|
.long("spec")
|
||||||
|
.value_name("SPEC_JSON"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("spec-path")
|
||||||
|
.short('S')
|
||||||
|
.long("spec-path")
|
||||||
|
.value_name("SPEC_PATH"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("compute-id")
|
||||||
|
.short('i')
|
||||||
|
.long("compute-id")
|
||||||
|
.value_name("COMPUTE_ID"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("control-plane-uri")
|
||||||
|
.short('p')
|
||||||
|
.long("control-plane-uri")
|
||||||
|
.value_name("CONTROL_PLANE_API_BASE_URI"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("remote-ext-config")
|
||||||
|
.short('r')
|
||||||
|
.long("remote-ext-config")
|
||||||
|
.value_name("REMOTE_EXT_CONFIG"),
|
||||||
|
)
|
||||||
|
// TODO(fprasx): we currently have default arguments because the cloud PR
|
||||||
|
// to pass them in hasn't been merged yet. We should get rid of them once
|
||||||
|
// the PR is merged.
|
||||||
|
.arg(
|
||||||
|
Arg::new("vm-monitor-addr")
|
||||||
|
.long("vm-monitor-addr")
|
||||||
|
.default_value("0.0.0.0:10301")
|
||||||
|
.value_name("VM_MONITOR_ADDR"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("cgroup")
|
||||||
|
.long("cgroup")
|
||||||
|
.default_value("neon-postgres")
|
||||||
|
.value_name("CGROUP"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("filecache-connstr")
|
||||||
|
.long("filecache-connstr")
|
||||||
|
.default_value(
|
||||||
|
"host=localhost port=5432 dbname=postgres user=cloud_admin sslmode=disable application_name=vm-monitor",
|
||||||
|
)
|
||||||
|
.value_name("FILECACHE_CONNSTR"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("resize-swap-on-bind")
|
||||||
|
.long("resize-swap-on-bind")
|
||||||
|
.action(clap::ArgAction::SetTrue),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("set-disk-quota-for-fs")
|
||||||
|
.long("set-disk-quota-for-fs")
|
||||||
|
.value_name("SET_DISK_QUOTA_FOR_FS")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// When compute_ctl is killed, send also termination signal to sync-safekeepers
|
/// When compute_ctl is killed, send also termination signal to sync-safekeepers
|
||||||
/// to prevent leakage. TODO: it is better to convert compute_ctl to async and
|
/// to prevent leakage. TODO: it is better to convert compute_ctl to async and
|
||||||
/// wait for termination which would be easy then.
|
/// wait for termination which would be easy then.
|
||||||
@@ -694,14 +784,7 @@ fn handle_exit_signal(sig: i32) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[test]
|
||||||
mod test {
|
fn verify_cli() {
|
||||||
use clap::CommandFactory;
|
cli().debug_assert()
|
||||||
|
|
||||||
use super::Cli;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn verify_cli() {
|
|
||||||
Cli::command().debug_assert()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,460 +0,0 @@
|
|||||||
//! This program dumps a remote Postgres database into a local Postgres database
|
|
||||||
//! and uploads the resulting PGDATA into object storage for import into a Timeline.
|
|
||||||
//!
|
|
||||||
//! # Context, Architecture, Design
|
|
||||||
//!
|
|
||||||
//! See cloud.git Fast Imports RFC (<https://github.com/neondatabase/cloud/pull/19799>)
|
|
||||||
//! for the full picture.
|
|
||||||
//! The RFC describing the storage pieces of importing the PGDATA dump into a Timeline
|
|
||||||
//! is publicly accessible at <https://github.com/neondatabase/neon/pull/9538>.
|
|
||||||
//!
|
|
||||||
//! # This is a Prototype!
|
|
||||||
//!
|
|
||||||
//! This program is part of a prototype feature and not yet used in production.
|
|
||||||
//!
|
|
||||||
//! The cloud.git RFC contains lots of suggestions for improving e2e throughput
|
|
||||||
//! of this step of the timeline import process.
|
|
||||||
//!
|
|
||||||
//! # Local Testing
|
|
||||||
//!
|
|
||||||
//! - Comment out most of the pgxns in compute-node.Dockerfile to speed up the build.
|
|
||||||
//! - Build the image with the following command:
|
|
||||||
//!
|
|
||||||
//! ```bash
|
|
||||||
//! docker buildx build --platform linux/amd64 --build-arg DEBIAN_VERSION=bullseye --build-arg GIT_VERSION=local --build-arg PG_VERSION=v14 --build-arg BUILD_TAG="$(date --iso-8601=s -u)" -t localhost:3030/localregistry/compute-node-v14:latest -f compute/compute-node.Dockerfile .
|
|
||||||
//! docker push localhost:3030/localregistry/compute-node-v14:latest
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use aws_config::BehaviorVersion;
|
|
||||||
use camino::{Utf8Path, Utf8PathBuf};
|
|
||||||
use clap::Parser;
|
|
||||||
use compute_tools::extension_server::{get_pg_version, PostgresMajorVersion};
|
|
||||||
use nix::unistd::Pid;
|
|
||||||
use tracing::{error, info, info_span, warn, Instrument};
|
|
||||||
use utils::fs_ext::is_directory_empty;
|
|
||||||
|
|
||||||
#[path = "fast_import/aws_s3_sync.rs"]
|
|
||||||
mod aws_s3_sync;
|
|
||||||
#[path = "fast_import/child_stdio_to_log.rs"]
|
|
||||||
mod child_stdio_to_log;
|
|
||||||
#[path = "fast_import/s3_uri.rs"]
|
|
||||||
mod s3_uri;
|
|
||||||
|
|
||||||
const PG_WAIT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(600);
|
|
||||||
const PG_WAIT_RETRY_INTERVAL: std::time::Duration = std::time::Duration::from_millis(300);
|
|
||||||
|
|
||||||
#[derive(clap::Parser)]
|
|
||||||
struct Args {
|
|
||||||
#[clap(long)]
|
|
||||||
working_directory: Utf8PathBuf,
|
|
||||||
#[clap(long, env = "NEON_IMPORTER_S3_PREFIX")]
|
|
||||||
s3_prefix: Option<s3_uri::S3Uri>,
|
|
||||||
#[clap(long)]
|
|
||||||
source_connection_string: Option<String>,
|
|
||||||
#[clap(short, long)]
|
|
||||||
interactive: bool,
|
|
||||||
#[clap(long)]
|
|
||||||
pg_bin_dir: Utf8PathBuf,
|
|
||||||
#[clap(long)]
|
|
||||||
pg_lib_dir: Utf8PathBuf,
|
|
||||||
#[clap(long)]
|
|
||||||
pg_port: Option<u16>, // port to run postgres on, 5432 is default
|
|
||||||
|
|
||||||
/// Number of CPUs in the system. This is used to configure # of
|
|
||||||
/// parallel worker processes, for index creation.
|
|
||||||
#[clap(long, env = "NEON_IMPORTER_NUM_CPUS")]
|
|
||||||
num_cpus: Option<usize>,
|
|
||||||
|
|
||||||
/// Amount of RAM in the system. This is used to configure shared_buffers
|
|
||||||
/// and maintenance_work_mem.
|
|
||||||
#[clap(long, env = "NEON_IMPORTER_MEMORY_MB")]
|
|
||||||
memory_mb: Option<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde_with::serde_as]
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
struct Spec {
|
|
||||||
encryption_secret: EncryptionSecret,
|
|
||||||
#[serde_as(as = "serde_with::base64::Base64")]
|
|
||||||
source_connstring_ciphertext_base64: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
enum EncryptionSecret {
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
|
||||||
KMS { key_id: String },
|
|
||||||
}
|
|
||||||
|
|
||||||
// copied from pageserver_api::config::defaults::DEFAULT_LOCALE to avoid dependency just for a constant
|
|
||||||
const DEFAULT_LOCALE: &str = if cfg!(target_os = "macos") {
|
|
||||||
"C"
|
|
||||||
} else {
|
|
||||||
"C.UTF-8"
|
|
||||||
};
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
pub(crate) async fn main() -> anyhow::Result<()> {
|
|
||||||
utils::logging::init(
|
|
||||||
utils::logging::LogFormat::Plain,
|
|
||||||
utils::logging::TracingErrorLayerEnablement::EnableWithRustLogFilter,
|
|
||||||
utils::logging::Output::Stdout,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
info!("starting");
|
|
||||||
|
|
||||||
let args = Args::parse();
|
|
||||||
|
|
||||||
// Validate arguments
|
|
||||||
if args.s3_prefix.is_none() && args.source_connection_string.is_none() {
|
|
||||||
anyhow::bail!("either s3_prefix or source_connection_string must be specified");
|
|
||||||
}
|
|
||||||
if args.s3_prefix.is_some() && args.source_connection_string.is_some() {
|
|
||||||
anyhow::bail!("only one of s3_prefix or source_connection_string can be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
let working_directory = args.working_directory;
|
|
||||||
let pg_bin_dir = args.pg_bin_dir;
|
|
||||||
let pg_lib_dir = args.pg_lib_dir;
|
|
||||||
let pg_port = args.pg_port.unwrap_or_else(|| {
|
|
||||||
info!("pg_port not specified, using default 5432");
|
|
||||||
5432
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize AWS clients only if s3_prefix is specified
|
|
||||||
let (aws_config, kms_client) = if args.s3_prefix.is_some() {
|
|
||||||
let config = aws_config::load_defaults(BehaviorVersion::v2024_03_28()).await;
|
|
||||||
let kms = aws_sdk_kms::Client::new(&config);
|
|
||||||
(Some(config), Some(kms))
|
|
||||||
} else {
|
|
||||||
(None, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get source connection string either from S3 spec or direct argument
|
|
||||||
let source_connection_string = if let Some(s3_prefix) = &args.s3_prefix {
|
|
||||||
let spec: Spec = {
|
|
||||||
let spec_key = s3_prefix.append("/spec.json");
|
|
||||||
let s3_client = aws_sdk_s3::Client::new(aws_config.as_ref().unwrap());
|
|
||||||
let object = s3_client
|
|
||||||
.get_object()
|
|
||||||
.bucket(&spec_key.bucket)
|
|
||||||
.key(spec_key.key)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.context("get spec from s3")?
|
|
||||||
.body
|
|
||||||
.collect()
|
|
||||||
.await
|
|
||||||
.context("download spec body")?;
|
|
||||||
serde_json::from_slice(&object.into_bytes()).context("parse spec as json")?
|
|
||||||
};
|
|
||||||
|
|
||||||
match spec.encryption_secret {
|
|
||||||
EncryptionSecret::KMS { key_id } => {
|
|
||||||
let mut output = kms_client
|
|
||||||
.unwrap()
|
|
||||||
.decrypt()
|
|
||||||
.key_id(key_id)
|
|
||||||
.ciphertext_blob(aws_sdk_s3::primitives::Blob::new(
|
|
||||||
spec.source_connstring_ciphertext_base64,
|
|
||||||
))
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.context("decrypt source connection string")?;
|
|
||||||
let plaintext = output
|
|
||||||
.plaintext
|
|
||||||
.take()
|
|
||||||
.context("get plaintext source connection string")?;
|
|
||||||
String::from_utf8(plaintext.into_inner())
|
|
||||||
.context("parse source connection string as utf8")?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
args.source_connection_string.unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
match tokio::fs::create_dir(&working_directory).await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
|
|
||||||
if !is_directory_empty(&working_directory)
|
|
||||||
.await
|
|
||||||
.context("check if working directory is empty")?
|
|
||||||
{
|
|
||||||
anyhow::bail!("working directory is not empty");
|
|
||||||
} else {
|
|
||||||
// ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => return Err(anyhow::Error::new(e).context("create working directory")),
|
|
||||||
}
|
|
||||||
|
|
||||||
let pgdata_dir = working_directory.join("pgdata");
|
|
||||||
tokio::fs::create_dir(&pgdata_dir)
|
|
||||||
.await
|
|
||||||
.context("create pgdata directory")?;
|
|
||||||
|
|
||||||
let pgbin = pg_bin_dir.join("postgres");
|
|
||||||
let pg_version = match get_pg_version(pgbin.as_ref()) {
|
|
||||||
PostgresMajorVersion::V14 => 14,
|
|
||||||
PostgresMajorVersion::V15 => 15,
|
|
||||||
PostgresMajorVersion::V16 => 16,
|
|
||||||
PostgresMajorVersion::V17 => 17,
|
|
||||||
};
|
|
||||||
let superuser = "cloud_admin"; // XXX: this shouldn't be hard-coded
|
|
||||||
postgres_initdb::do_run_initdb(postgres_initdb::RunInitdbArgs {
|
|
||||||
superuser,
|
|
||||||
locale: DEFAULT_LOCALE, // XXX: this shouldn't be hard-coded,
|
|
||||||
pg_version,
|
|
||||||
initdb_bin: pg_bin_dir.join("initdb").as_ref(),
|
|
||||||
library_search_path: &pg_lib_dir, // TODO: is this right? Prob works in compute image, not sure about neon_local.
|
|
||||||
pgdata: &pgdata_dir,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.context("initdb")?;
|
|
||||||
|
|
||||||
// If the caller didn't specify CPU / RAM to use for sizing, default to
|
|
||||||
// number of CPUs in the system, and pretty arbitrarily, 256 MB of RAM.
|
|
||||||
let nproc = args.num_cpus.unwrap_or_else(num_cpus::get);
|
|
||||||
let memory_mb = args.memory_mb.unwrap_or(256);
|
|
||||||
|
|
||||||
// Somewhat arbitrarily, use 10 % of memory for shared buffer cache, 70% for
|
|
||||||
// maintenance_work_mem (i.e. for sorting during index creation), and leave the rest
|
|
||||||
// available for misc other stuff that PostgreSQL uses memory for.
|
|
||||||
let shared_buffers_mb = ((memory_mb as f32) * 0.10) as usize;
|
|
||||||
let maintenance_work_mem_mb = ((memory_mb as f32) * 0.70) as usize;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Launch postgres process
|
|
||||||
//
|
|
||||||
let mut postgres_proc = tokio::process::Command::new(pgbin)
|
|
||||||
.arg("-D")
|
|
||||||
.arg(&pgdata_dir)
|
|
||||||
.args(["-p", &format!("{pg_port}")])
|
|
||||||
.args(["-c", "wal_level=minimal"])
|
|
||||||
.args(["-c", &format!("shared_buffers={shared_buffers_mb}MB")])
|
|
||||||
.args(["-c", "max_wal_senders=0"])
|
|
||||||
.args(["-c", "fsync=off"])
|
|
||||||
.args(["-c", "full_page_writes=off"])
|
|
||||||
.args(["-c", "synchronous_commit=off"])
|
|
||||||
.args([
|
|
||||||
"-c",
|
|
||||||
&format!("maintenance_work_mem={maintenance_work_mem_mb}MB"),
|
|
||||||
])
|
|
||||||
.args(["-c", &format!("max_parallel_maintenance_workers={nproc}")])
|
|
||||||
.args(["-c", &format!("max_parallel_workers={nproc}")])
|
|
||||||
.args(["-c", &format!("max_parallel_workers_per_gather={nproc}")])
|
|
||||||
.args(["-c", &format!("max_worker_processes={nproc}")])
|
|
||||||
.args([
|
|
||||||
"-c",
|
|
||||||
&format!(
|
|
||||||
"effective_io_concurrency={}",
|
|
||||||
if cfg!(target_os = "macos") { 0 } else { 100 }
|
|
||||||
),
|
|
||||||
])
|
|
||||||
.env_clear()
|
|
||||||
.env("LD_LIBRARY_PATH", &pg_lib_dir)
|
|
||||||
.env(
|
|
||||||
"ASAN_OPTIONS",
|
|
||||||
std::env::var("ASAN_OPTIONS").unwrap_or_default(),
|
|
||||||
)
|
|
||||||
.env(
|
|
||||||
"UBSAN_OPTIONS",
|
|
||||||
std::env::var("UBSAN_OPTIONS").unwrap_or_default(),
|
|
||||||
)
|
|
||||||
.stdout(std::process::Stdio::piped())
|
|
||||||
.stderr(std::process::Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.context("spawn postgres")?;
|
|
||||||
|
|
||||||
info!("spawned postgres, waiting for it to become ready");
|
|
||||||
tokio::spawn(
|
|
||||||
child_stdio_to_log::relay_process_output(
|
|
||||||
postgres_proc.stdout.take(),
|
|
||||||
postgres_proc.stderr.take(),
|
|
||||||
)
|
|
||||||
.instrument(info_span!("postgres")),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create neondb database in the running postgres
|
|
||||||
let restore_pg_connstring =
|
|
||||||
format!("host=localhost port={pg_port} user={superuser} dbname=postgres");
|
|
||||||
|
|
||||||
let start_time = std::time::Instant::now();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if start_time.elapsed() > PG_WAIT_TIMEOUT {
|
|
||||||
error!(
|
|
||||||
"timeout exceeded: failed to poll postgres and create database within 10 minutes"
|
|
||||||
);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
match tokio_postgres::connect(&restore_pg_connstring, tokio_postgres::NoTls).await {
|
|
||||||
Ok((client, connection)) => {
|
|
||||||
// Spawn the connection handling task to maintain the connection
|
|
||||||
tokio::spawn(async move {
|
|
||||||
if let Err(e) = connection.await {
|
|
||||||
warn!("connection error: {}", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match client.simple_query("CREATE DATABASE neondb;").await {
|
|
||||||
Ok(_) => {
|
|
||||||
info!("created neondb database");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
warn!(
|
|
||||||
"failed to create database: {}, retying in {}s",
|
|
||||||
e,
|
|
||||||
PG_WAIT_RETRY_INTERVAL.as_secs_f32()
|
|
||||||
);
|
|
||||||
tokio::time::sleep(PG_WAIT_RETRY_INTERVAL).await;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
info!(
|
|
||||||
"postgres not ready yet, retrying in {}s",
|
|
||||||
PG_WAIT_RETRY_INTERVAL.as_secs_f32()
|
|
||||||
);
|
|
||||||
tokio::time::sleep(PG_WAIT_RETRY_INTERVAL).await;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let restore_pg_connstring = restore_pg_connstring.replace("dbname=postgres", "dbname=neondb");
|
|
||||||
|
|
||||||
let dumpdir = working_directory.join("dumpdir");
|
|
||||||
|
|
||||||
let common_args = [
|
|
||||||
// schema mapping (prob suffices to specify them on one side)
|
|
||||||
"--no-owner".to_string(),
|
|
||||||
"--no-privileges".to_string(),
|
|
||||||
"--no-publications".to_string(),
|
|
||||||
"--no-security-labels".to_string(),
|
|
||||||
"--no-subscriptions".to_string(),
|
|
||||||
"--no-tablespaces".to_string(),
|
|
||||||
// format
|
|
||||||
"--format".to_string(),
|
|
||||||
"directory".to_string(),
|
|
||||||
// concurrency
|
|
||||||
"--jobs".to_string(),
|
|
||||||
num_cpus::get().to_string(),
|
|
||||||
// progress updates
|
|
||||||
"--verbose".to_string(),
|
|
||||||
];
|
|
||||||
|
|
||||||
info!("dump into the working directory");
|
|
||||||
{
|
|
||||||
let mut pg_dump = tokio::process::Command::new(pg_bin_dir.join("pg_dump"))
|
|
||||||
.args(&common_args)
|
|
||||||
.arg("-f")
|
|
||||||
.arg(&dumpdir)
|
|
||||||
.arg("--no-sync")
|
|
||||||
// POSITIONAL args
|
|
||||||
// source db (db name included in connection string)
|
|
||||||
.arg(&source_connection_string)
|
|
||||||
// how we run it
|
|
||||||
.env_clear()
|
|
||||||
.env("LD_LIBRARY_PATH", &pg_lib_dir)
|
|
||||||
.kill_on_drop(true)
|
|
||||||
.stdout(std::process::Stdio::piped())
|
|
||||||
.stderr(std::process::Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.context("spawn pg_dump")?;
|
|
||||||
|
|
||||||
info!(pid=%pg_dump.id().unwrap(), "spawned pg_dump");
|
|
||||||
|
|
||||||
tokio::spawn(
|
|
||||||
child_stdio_to_log::relay_process_output(pg_dump.stdout.take(), pg_dump.stderr.take())
|
|
||||||
.instrument(info_span!("pg_dump")),
|
|
||||||
);
|
|
||||||
|
|
||||||
let st = pg_dump.wait().await.context("wait for pg_dump")?;
|
|
||||||
info!(status=?st, "pg_dump exited");
|
|
||||||
if !st.success() {
|
|
||||||
warn!(status=%st, "pg_dump failed, restore will likely fail as well");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: do it in a streaming way, plenty of internal research done on this already
|
|
||||||
// TODO: do the unlogged table trick
|
|
||||||
|
|
||||||
info!("restore from working directory into vanilla postgres");
|
|
||||||
{
|
|
||||||
let mut pg_restore = tokio::process::Command::new(pg_bin_dir.join("pg_restore"))
|
|
||||||
.args(&common_args)
|
|
||||||
.arg("-d")
|
|
||||||
.arg(&restore_pg_connstring)
|
|
||||||
// POSITIONAL args
|
|
||||||
.arg(&dumpdir)
|
|
||||||
// how we run it
|
|
||||||
.env_clear()
|
|
||||||
.env("LD_LIBRARY_PATH", &pg_lib_dir)
|
|
||||||
.kill_on_drop(true)
|
|
||||||
.stdout(std::process::Stdio::piped())
|
|
||||||
.stderr(std::process::Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.context("spawn pg_restore")?;
|
|
||||||
|
|
||||||
info!(pid=%pg_restore.id().unwrap(), "spawned pg_restore");
|
|
||||||
tokio::spawn(
|
|
||||||
child_stdio_to_log::relay_process_output(
|
|
||||||
pg_restore.stdout.take(),
|
|
||||||
pg_restore.stderr.take(),
|
|
||||||
)
|
|
||||||
.instrument(info_span!("pg_restore")),
|
|
||||||
);
|
|
||||||
let st = pg_restore.wait().await.context("wait for pg_restore")?;
|
|
||||||
info!(status=?st, "pg_restore exited");
|
|
||||||
if !st.success() {
|
|
||||||
warn!(status=%st, "pg_restore failed, restore will likely fail as well");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If interactive mode, wait for Ctrl+C
|
|
||||||
if args.interactive {
|
|
||||||
info!("Running in interactive mode. Press Ctrl+C to shut down.");
|
|
||||||
tokio::signal::ctrl_c().await.context("wait for ctrl-c")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("shutdown postgres");
|
|
||||||
{
|
|
||||||
nix::sys::signal::kill(
|
|
||||||
Pid::from_raw(
|
|
||||||
i32::try_from(postgres_proc.id().unwrap()).expect("convert child pid to i32"),
|
|
||||||
),
|
|
||||||
nix::sys::signal::SIGTERM,
|
|
||||||
)
|
|
||||||
.context("signal postgres to shut down")?;
|
|
||||||
postgres_proc
|
|
||||||
.wait()
|
|
||||||
.await
|
|
||||||
.context("wait for postgres to shut down")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only sync if s3_prefix was specified
|
|
||||||
if let Some(s3_prefix) = args.s3_prefix {
|
|
||||||
info!("upload pgdata");
|
|
||||||
aws_s3_sync::sync(Utf8Path::new(&pgdata_dir), &s3_prefix.append("/pgdata/"))
|
|
||||||
.await
|
|
||||||
.context("sync dump directory to destination")?;
|
|
||||||
|
|
||||||
info!("write status");
|
|
||||||
{
|
|
||||||
let status_dir = working_directory.join("status");
|
|
||||||
std::fs::create_dir(&status_dir).context("create status directory")?;
|
|
||||||
let status_file = status_dir.join("pgdata");
|
|
||||||
std::fs::write(&status_file, serde_json::json!({"done": true}).to_string())
|
|
||||||
.context("write status file")?;
|
|
||||||
aws_s3_sync::sync(&status_dir, &s3_prefix.append("/status/"))
|
|
||||||
.await
|
|
||||||
.context("sync status directory to destination")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
use anyhow::Context;
|
|
||||||
use camino::Utf8Path;
|
|
||||||
|
|
||||||
use super::s3_uri::S3Uri;
|
|
||||||
|
|
||||||
pub(crate) async fn sync(local: &Utf8Path, remote: &S3Uri) -> anyhow::Result<()> {
|
|
||||||
let mut builder = tokio::process::Command::new("aws");
|
|
||||||
builder
|
|
||||||
.arg("s3")
|
|
||||||
.arg("sync")
|
|
||||||
.arg(local.as_str())
|
|
||||||
.arg(remote.to_string());
|
|
||||||
let st = builder
|
|
||||||
.spawn()
|
|
||||||
.context("spawn aws s3 sync")?
|
|
||||||
.wait()
|
|
||||||
.await
|
|
||||||
.context("wait for aws s3 sync")?;
|
|
||||||
if st.success() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(anyhow::anyhow!("aws s3 sync failed"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
|
||||||
use tokio::process::{ChildStderr, ChildStdout};
|
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
/// Asynchronously relays the output from a child process's `stdout` and `stderr` to the tracing log.
|
|
||||||
/// Each line is read and logged individually, with lossy UTF-8 conversion.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `stdout`: An `Option<ChildStdout>` from the child process.
|
|
||||||
/// * `stderr`: An `Option<ChildStderr>` from the child process.
|
|
||||||
///
|
|
||||||
pub(crate) async fn relay_process_output(stdout: Option<ChildStdout>, stderr: Option<ChildStderr>) {
|
|
||||||
let stdout_fut = async {
|
|
||||||
if let Some(stdout) = stdout {
|
|
||||||
let reader = BufReader::new(stdout);
|
|
||||||
let mut lines = reader.lines();
|
|
||||||
while let Ok(Some(line)) = lines.next_line().await {
|
|
||||||
info!(fd = "stdout", "{}", line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let stderr_fut = async {
|
|
||||||
if let Some(stderr) = stderr {
|
|
||||||
let reader = BufReader::new(stderr);
|
|
||||||
let mut lines = reader.lines();
|
|
||||||
while let Ok(Some(line)) = lines.next_line().await {
|
|
||||||
info!(fd = "stderr", "{}", line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tokio::join!(stdout_fut, stderr_fut);
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
/// Struct to hold parsed S3 components
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct S3Uri {
|
|
||||||
pub bucket: String,
|
|
||||||
pub key: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for S3Uri {
|
|
||||||
type Err = anyhow::Error;
|
|
||||||
|
|
||||||
/// Parse an S3 URI into a bucket and key
|
|
||||||
fn from_str(uri: &str) -> Result<Self> {
|
|
||||||
// Ensure the URI starts with "s3://"
|
|
||||||
if !uri.starts_with("s3://") {
|
|
||||||
return Err(anyhow::anyhow!("Invalid S3 URI scheme"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the "s3://" prefix
|
|
||||||
let stripped_uri = &uri[5..];
|
|
||||||
|
|
||||||
// Split the remaining string into bucket and key parts
|
|
||||||
if let Some((bucket, key)) = stripped_uri.split_once('/') {
|
|
||||||
Ok(S3Uri {
|
|
||||||
bucket: bucket.to_string(),
|
|
||||||
key: key.to_string(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(anyhow::anyhow!(
|
|
||||||
"Invalid S3 URI format, missing bucket or key"
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl S3Uri {
|
|
||||||
pub fn append(&self, suffix: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
bucket: self.bucket.clone(),
|
|
||||||
key: format!("{}{}", self.key, suffix),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for S3Uri {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(f, "s3://{}/{}", self.bucket, self.key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl clap::builder::TypedValueParser for S3Uri {
|
|
||||||
type Value = Self;
|
|
||||||
|
|
||||||
fn parse_ref(
|
|
||||||
&self,
|
|
||||||
_cmd: &clap::Command,
|
|
||||||
_arg: Option<&clap::Arg>,
|
|
||||||
value: &std::ffi::OsStr,
|
|
||||||
) -> Result<Self::Value, clap::Error> {
|
|
||||||
let value_str = value.to_str().ok_or_else(|| {
|
|
||||||
clap::Error::raw(
|
|
||||||
clap::error::ErrorKind::InvalidUtf8,
|
|
||||||
"Invalid UTF-8 sequence",
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
S3Uri::from_str(value_str).map_err(|e| {
|
|
||||||
clap::Error::raw(
|
|
||||||
clap::error::ErrorKind::InvalidValue,
|
|
||||||
format!("Failed to parse S3 URI: {}", e),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +1,46 @@
|
|||||||
|
use compute_api::{
|
||||||
|
responses::CatalogObjects,
|
||||||
|
spec::{Database, Role},
|
||||||
|
};
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use postgres::NoTls;
|
use postgres::{Client, NoTls};
|
||||||
use std::{path::Path, process::Stdio, result::Result, sync::Arc};
|
use std::{path::Path, process::Stdio, result::Result, sync::Arc};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncBufReadExt, BufReader},
|
io::{AsyncBufReadExt, BufReader},
|
||||||
process::Command,
|
process::Command,
|
||||||
spawn,
|
task,
|
||||||
};
|
};
|
||||||
use tokio_stream::{self as stream, StreamExt};
|
use tokio_stream::{self as stream, StreamExt};
|
||||||
use tokio_util::codec::{BytesCodec, FramedRead};
|
use tokio_util::codec::{BytesCodec, FramedRead};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
use crate::compute::ComputeNode;
|
use crate::{
|
||||||
use crate::pg_helpers::{get_existing_dbs_async, get_existing_roles_async, postgres_conf_for_db};
|
compute::ComputeNode,
|
||||||
use compute_api::responses::CatalogObjects;
|
pg_helpers::{get_existing_dbs, get_existing_roles},
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn get_dbs_and_roles(compute: &Arc<ComputeNode>) -> anyhow::Result<CatalogObjects> {
|
pub async fn get_dbs_and_roles(compute: &Arc<ComputeNode>) -> anyhow::Result<CatalogObjects> {
|
||||||
let conf = compute.get_tokio_conn_conf(Some("compute_ctl:get_dbs_and_roles"));
|
let connstr = compute.connstr.clone();
|
||||||
let (client, connection): (tokio_postgres::Client, _) = conf.connect(NoTls).await?;
|
task::spawn_blocking(move || {
|
||||||
|
let mut client = Client::connect(connstr.as_str(), NoTls)?;
|
||||||
spawn(async move {
|
let roles: Vec<Role>;
|
||||||
if let Err(e) = connection.await {
|
{
|
||||||
eprintln!("connection error: {}", e);
|
let mut xact = client.transaction()?;
|
||||||
|
roles = get_existing_roles(&mut xact)?;
|
||||||
}
|
}
|
||||||
});
|
let databases: Vec<Database> = get_existing_dbs(&mut client)?.values().cloned().collect();
|
||||||
|
|
||||||
let roles = get_existing_roles_async(&client).await?;
|
Ok(CatalogObjects { roles, databases })
|
||||||
|
})
|
||||||
let databases = get_existing_dbs_async(&client)
|
.await?
|
||||||
.await?
|
|
||||||
.into_values()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(CatalogObjects { roles, databases })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum SchemaDumpError {
|
pub enum SchemaDumpError {
|
||||||
#[error("database does not exist")]
|
#[error("Database does not exist.")]
|
||||||
DatabaseDoesNotExist,
|
DatabaseDoesNotExist,
|
||||||
#[error("failed to execute pg_dump")]
|
#[error("Failed to execute pg_dump.")]
|
||||||
IO(#[from] std::io::Error),
|
IO(#[from] std::io::Error),
|
||||||
#[error("unexpected I/O error")]
|
|
||||||
Unexpected,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// It uses the pg_dump utility to dump the schema of the specified database.
|
// It uses the pg_dump utility to dump the schema of the specified database.
|
||||||
@@ -59,38 +58,11 @@ pub async fn get_database_schema(
|
|||||||
let pgbin = &compute.pgbin;
|
let pgbin = &compute.pgbin;
|
||||||
let basepath = Path::new(pgbin).parent().unwrap();
|
let basepath = Path::new(pgbin).parent().unwrap();
|
||||||
let pgdump = basepath.join("pg_dump");
|
let pgdump = basepath.join("pg_dump");
|
||||||
|
let mut connstr = compute.connstr.clone();
|
||||||
// Replace the DB in the connection string and disable it to parts.
|
connstr.set_path(dbname);
|
||||||
// This is the only option to handle DBs with special characters.
|
|
||||||
let conf =
|
|
||||||
postgres_conf_for_db(&compute.connstr, dbname).map_err(|_| SchemaDumpError::Unexpected)?;
|
|
||||||
let host = conf
|
|
||||||
.get_hosts()
|
|
||||||
.first()
|
|
||||||
.ok_or(SchemaDumpError::Unexpected)?;
|
|
||||||
let host = match host {
|
|
||||||
tokio_postgres::config::Host::Tcp(ip) => ip.to_string(),
|
|
||||||
#[cfg(unix)]
|
|
||||||
tokio_postgres::config::Host::Unix(path) => path.to_string_lossy().to_string(),
|
|
||||||
};
|
|
||||||
let port = conf
|
|
||||||
.get_ports()
|
|
||||||
.first()
|
|
||||||
.ok_or(SchemaDumpError::Unexpected)?;
|
|
||||||
let user = conf.get_user().ok_or(SchemaDumpError::Unexpected)?;
|
|
||||||
let dbname = conf.get_dbname().ok_or(SchemaDumpError::Unexpected)?;
|
|
||||||
|
|
||||||
let mut cmd = Command::new(pgdump)
|
let mut cmd = Command::new(pgdump)
|
||||||
// XXX: this seems to be the only option to deal with DBs with `=` in the name
|
|
||||||
// See <https://www.postgresql.org/message-id/flat/20151023003445.931.91267%40wrigleys.postgresql.org>
|
|
||||||
.env("PGDATABASE", dbname)
|
|
||||||
.arg("--host")
|
|
||||||
.arg(host)
|
|
||||||
.arg("--port")
|
|
||||||
.arg(port.to_string())
|
|
||||||
.arg("--username")
|
|
||||||
.arg(user)
|
|
||||||
.arg("--schema-only")
|
.arg("--schema-only")
|
||||||
|
.arg(connstr.as_str())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.kill_on_drop(true)
|
.kill_on_drop(true)
|
||||||
@@ -140,34 +112,5 @@ pub async fn get_database_schema(
|
|||||||
warn!("pg_dump stderr: {}", line)
|
warn!("pg_dump stderr: {}", line)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Ok(initial_stream.chain(stdout_reader.map(|res| res.map(|b| b.freeze()))))
|
||||||
#[allow(dead_code)]
|
|
||||||
struct SchemaStream<S> {
|
|
||||||
// We keep a reference to the child process to ensure it stays alive
|
|
||||||
// while the stream is being consumed. When SchemaStream is dropped,
|
|
||||||
// cmd will be dropped, which triggers kill_on_drop and terminates pg_dump
|
|
||||||
cmd: tokio::process::Child,
|
|
||||||
stream: S,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> Stream for SchemaStream<S>
|
|
||||||
where
|
|
||||||
S: Stream<Item = Result<bytes::Bytes, std::io::Error>> + Unpin,
|
|
||||||
{
|
|
||||||
type Item = Result<bytes::Bytes, std::io::Error>;
|
|
||||||
|
|
||||||
fn poll_next(
|
|
||||||
mut self: std::pin::Pin<&mut Self>,
|
|
||||||
cx: &mut std::task::Context<'_>,
|
|
||||||
) -> std::task::Poll<Option<Self::Item>> {
|
|
||||||
Stream::poll_next(std::pin::Pin::new(&mut self.stream), cx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let schema_stream = SchemaStream {
|
|
||||||
cmd,
|
|
||||||
stream: initial_stream.chain(stdout_reader.map(|res| res.map(|b| b.freeze()))),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(schema_stream)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,43 @@
|
|||||||
use anyhow::{anyhow, Ok, Result};
|
use anyhow::{anyhow, Ok, Result};
|
||||||
|
use postgres::Client;
|
||||||
use tokio_postgres::NoTls;
|
use tokio_postgres::NoTls;
|
||||||
use tracing::{error, instrument, warn};
|
use tracing::{error, instrument, warn};
|
||||||
|
|
||||||
use crate::compute::ComputeNode;
|
use crate::compute::ComputeNode;
|
||||||
|
|
||||||
|
/// Create a special service table for availability checks
|
||||||
|
/// only if it does not exist already.
|
||||||
|
pub fn create_availability_check_data(client: &mut Client) -> Result<()> {
|
||||||
|
let query = "
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS(
|
||||||
|
SELECT 1
|
||||||
|
FROM pg_catalog.pg_tables
|
||||||
|
WHERE tablename = 'health_check'
|
||||||
|
)
|
||||||
|
THEN
|
||||||
|
CREATE TABLE health_check (
|
||||||
|
id serial primary key,
|
||||||
|
updated_at timestamptz default now()
|
||||||
|
);
|
||||||
|
INSERT INTO health_check VALUES (1, now())
|
||||||
|
ON CONFLICT (id) DO UPDATE
|
||||||
|
SET updated_at = now();
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;";
|
||||||
|
client.execute(query, &[])?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Update timestamp in a row in a special service table to check
|
/// Update timestamp in a row in a special service table to check
|
||||||
/// that we can actually write some data in this particular timeline.
|
/// that we can actually write some data in this particular timeline.
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn check_writability(compute: &ComputeNode) -> Result<()> {
|
pub async fn check_writability(compute: &ComputeNode) -> Result<()> {
|
||||||
// Connect to the database.
|
// Connect to the database.
|
||||||
let conf = compute.get_tokio_conn_conf(Some("compute_ctl:availability_checker"));
|
let (client, connection) = tokio_postgres::connect(compute.connstr.as_str(), NoTls).await?;
|
||||||
let (client, connection) = conf.connect(NoTls).await?;
|
|
||||||
if client.is_closed() {
|
if client.is_closed() {
|
||||||
return Err(anyhow!("connection to postgres closed"));
|
return Err(anyhow!("connection to postgres closed"));
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@ pub fn line_in_file(path: &Path, line: &str) -> Result<bool> {
|
|||||||
pub fn write_postgres_conf(
|
pub fn write_postgres_conf(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
spec: &ComputeSpec,
|
spec: &ComputeSpec,
|
||||||
extension_server_port: u16,
|
extension_server_port: Option<u16>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// File::create() destroys the file content if it exists.
|
// File::create() destroys the file content if it exists.
|
||||||
let mut file = File::create(path)?;
|
let mut file = File::create(path)?;
|
||||||
@@ -73,19 +73,6 @@ pub fn write_postgres_conf(
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locales
|
|
||||||
if cfg!(target_os = "macos") {
|
|
||||||
writeln!(file, "lc_messages='C'")?;
|
|
||||||
writeln!(file, "lc_monetary='C'")?;
|
|
||||||
writeln!(file, "lc_time='C'")?;
|
|
||||||
writeln!(file, "lc_numeric='C'")?;
|
|
||||||
} else {
|
|
||||||
writeln!(file, "lc_messages='C.UTF-8'")?;
|
|
||||||
writeln!(file, "lc_monetary='C.UTF-8'")?;
|
|
||||||
writeln!(file, "lc_time='C.UTF-8'")?;
|
|
||||||
writeln!(file, "lc_numeric='C.UTF-8'")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match spec.mode {
|
match spec.mode {
|
||||||
ComputeMode::Primary => {}
|
ComputeMode::Primary => {}
|
||||||
ComputeMode::Static(lsn) => {
|
ComputeMode::Static(lsn) => {
|
||||||
@@ -116,7 +103,7 @@ pub fn write_postgres_conf(
|
|||||||
vartype: "enum".to_owned(),
|
vartype: "enum".to_owned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
writeln!(file, "{}", opt.to_pg_setting())?;
|
write!(file, "{}", opt.to_pg_setting())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,13 +114,8 @@ pub fn write_postgres_conf(
|
|||||||
writeln!(file, "# Managed by compute_ctl: end")?;
|
writeln!(file, "# Managed by compute_ctl: end")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(file, "neon.extension_server_port={}", extension_server_port)?;
|
if let Some(port) = extension_server_port {
|
||||||
|
writeln!(file, "neon.extension_server_port={}", port)?;
|
||||||
if spec.drop_subscriptions_before_start {
|
|
||||||
writeln!(file, "neon.disable_logical_replication_subscribers=true")?;
|
|
||||||
} else {
|
|
||||||
// be explicit about the default value
|
|
||||||
writeln!(file, "neon.disable_logical_replication_subscribers=false")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is essential to keep this line at the end of the file,
|
// This is essential to keep this line at the end of the file,
|
||||||
|
|||||||
@@ -51,12 +51,9 @@ fn configurator_main_loop(compute: &Arc<ComputeNode>) {
|
|||||||
pub fn launch_configurator(compute: &Arc<ComputeNode>) -> thread::JoinHandle<()> {
|
pub fn launch_configurator(compute: &Arc<ComputeNode>) -> thread::JoinHandle<()> {
|
||||||
let compute = Arc::clone(compute);
|
let compute = Arc::clone(compute);
|
||||||
|
|
||||||
let runtime = tokio::runtime::Handle::current();
|
|
||||||
|
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("compute-configurator".into())
|
.name("compute-configurator".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
let _rt_guard = runtime.enter();
|
|
||||||
configurator_main_loop(&compute);
|
configurator_main_loop(&compute);
|
||||||
info!("configurator thread is exited");
|
info!("configurator thread is exited");
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ use tracing::info;
|
|||||||
use tracing::log::warn;
|
use tracing::log::warn;
|
||||||
use zstd::stream::read::Decoder;
|
use zstd::stream::read::Decoder;
|
||||||
|
|
||||||
use crate::metrics::{REMOTE_EXT_REQUESTS_TOTAL, UNKNOWN_HTTP_STATUS};
|
|
||||||
|
|
||||||
fn get_pg_config(argument: &str, pgbin: &str) -> String {
|
fn get_pg_config(argument: &str, pgbin: &str) -> String {
|
||||||
// gives the result of `pg_config [argument]`
|
// gives the result of `pg_config [argument]`
|
||||||
// where argument is a flag like `--version` or `--sharedir`
|
// where argument is a flag like `--version` or `--sharedir`
|
||||||
@@ -105,33 +103,14 @@ fn get_pg_config(argument: &str, pgbin: &str) -> String {
|
|||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pg_version(pgbin: &str) -> PostgresMajorVersion {
|
pub fn get_pg_version(pgbin: &str) -> String {
|
||||||
// pg_config --version returns a (platform specific) human readable string
|
// pg_config --version returns a (platform specific) human readable string
|
||||||
// such as "PostgreSQL 15.4". We parse this to v14/v15/v16 etc.
|
// such as "PostgreSQL 15.4". We parse this to v14/v15/v16 etc.
|
||||||
let human_version = get_pg_config("--version", pgbin);
|
let human_version = get_pg_config("--version", pgbin);
|
||||||
parse_pg_version(&human_version)
|
parse_pg_version(&human_version).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pg_version_string(pgbin: &str) -> String {
|
fn parse_pg_version(human_version: &str) -> &str {
|
||||||
match get_pg_version(pgbin) {
|
|
||||||
PostgresMajorVersion::V14 => "v14",
|
|
||||||
PostgresMajorVersion::V15 => "v15",
|
|
||||||
PostgresMajorVersion::V16 => "v16",
|
|
||||||
PostgresMajorVersion::V17 => "v17",
|
|
||||||
}
|
|
||||||
.to_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub enum PostgresMajorVersion {
|
|
||||||
V14,
|
|
||||||
V15,
|
|
||||||
V16,
|
|
||||||
V17,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_pg_version(human_version: &str) -> PostgresMajorVersion {
|
|
||||||
use PostgresMajorVersion::*;
|
|
||||||
// Normal releases have version strings like "PostgreSQL 15.4". But there
|
// Normal releases have version strings like "PostgreSQL 15.4". But there
|
||||||
// are also pre-release versions like "PostgreSQL 17devel" or "PostgreSQL
|
// are also pre-release versions like "PostgreSQL 17devel" or "PostgreSQL
|
||||||
// 16beta2" or "PostgreSQL 17rc1". And with the --with-extra-version
|
// 16beta2" or "PostgreSQL 17rc1". And with the --with-extra-version
|
||||||
@@ -142,10 +121,10 @@ fn parse_pg_version(human_version: &str) -> PostgresMajorVersion {
|
|||||||
.captures(human_version)
|
.captures(human_version)
|
||||||
{
|
{
|
||||||
Some(captures) if captures.len() == 2 => match &captures["major"] {
|
Some(captures) if captures.len() == 2 => match &captures["major"] {
|
||||||
"14" => return V14,
|
"14" => return "v14",
|
||||||
"15" => return V15,
|
"15" => return "v15",
|
||||||
"16" => return V16,
|
"16" => return "v16",
|
||||||
"17" => return V17,
|
"17" => return "v17",
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -258,60 +237,23 @@ pub fn create_control_files(remote_extensions: &RemoteExtSpec, pgbin: &str) {
|
|||||||
async fn download_extension_tar(ext_remote_storage: &str, ext_path: &str) -> Result<Bytes> {
|
async fn download_extension_tar(ext_remote_storage: &str, ext_path: &str) -> Result<Bytes> {
|
||||||
let uri = format!("{}/{}", ext_remote_storage, ext_path);
|
let uri = format!("{}/{}", ext_remote_storage, ext_path);
|
||||||
|
|
||||||
info!("Download extension {} from uri {}", ext_path, uri);
|
info!("Download extension {:?} from uri {:?}", ext_path, uri);
|
||||||
|
|
||||||
match do_extension_server_request(&uri).await {
|
let resp = reqwest::get(uri).await?;
|
||||||
Ok(resp) => {
|
|
||||||
info!("Successfully downloaded remote extension data {}", ext_path);
|
|
||||||
REMOTE_EXT_REQUESTS_TOTAL
|
|
||||||
.with_label_values(&[&StatusCode::OK.to_string()])
|
|
||||||
.inc();
|
|
||||||
Ok(resp)
|
|
||||||
}
|
|
||||||
Err((msg, status)) => {
|
|
||||||
REMOTE_EXT_REQUESTS_TOTAL
|
|
||||||
.with_label_values(&[&status])
|
|
||||||
.inc();
|
|
||||||
bail!(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a single remote extensions server request.
|
match resp.status() {
|
||||||
// Return result or (error message + stringified status code) in case of any failures.
|
|
||||||
async fn do_extension_server_request(uri: &str) -> Result<Bytes, (String, String)> {
|
|
||||||
let resp = reqwest::get(uri).await.map_err(|e| {
|
|
||||||
(
|
|
||||||
format!(
|
|
||||||
"could not perform remote extensions server request: {:?}",
|
|
||||||
e
|
|
||||||
),
|
|
||||||
UNKNOWN_HTTP_STATUS.to_string(),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
let status = resp.status();
|
|
||||||
|
|
||||||
match status {
|
|
||||||
StatusCode::OK => match resp.bytes().await {
|
StatusCode::OK => match resp.bytes().await {
|
||||||
Ok(resp) => Ok(resp),
|
Ok(resp) => {
|
||||||
Err(e) => Err((
|
info!("Download extension {:?} completed successfully", ext_path);
|
||||||
format!("could not read remote extensions server response: {:?}", e),
|
Ok(resp)
|
||||||
// It's fine to return and report error with status as 200 OK,
|
}
|
||||||
// because we still failed to read the response.
|
Err(e) => bail!("could not deserialize remote extension response: {}", e),
|
||||||
status.to_string(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
StatusCode::SERVICE_UNAVAILABLE => Err((
|
StatusCode::SERVICE_UNAVAILABLE => bail!("remote extension is temporarily unavailable"),
|
||||||
"remote extensions server is temporarily unavailable".to_string(),
|
_ => bail!(
|
||||||
status.to_string(),
|
"unexpected remote extension response status code: {}",
|
||||||
)),
|
resp.status()
|
||||||
_ => Err((
|
),
|
||||||
format!(
|
|
||||||
"unexpected remote extensions server response status code: {}",
|
|
||||||
status
|
|
||||||
),
|
|
||||||
status.to_string(),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,25 +263,24 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_pg_version() {
|
fn test_parse_pg_version() {
|
||||||
use super::PostgresMajorVersion::*;
|
assert_eq!(parse_pg_version("PostgreSQL 15.4"), "v15");
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 15.4"), V15);
|
assert_eq!(parse_pg_version("PostgreSQL 15.14"), "v15");
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 15.14"), V15);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_pg_version("PostgreSQL 15.4 (Ubuntu 15.4-0ubuntu0.23.04.1)"),
|
parse_pg_version("PostgreSQL 15.4 (Ubuntu 15.4-0ubuntu0.23.04.1)"),
|
||||||
V15
|
"v15"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 14.15"), V14);
|
assert_eq!(parse_pg_version("PostgreSQL 14.15"), "v14");
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 14.0"), V14);
|
assert_eq!(parse_pg_version("PostgreSQL 14.0"), "v14");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_pg_version("PostgreSQL 14.9 (Debian 14.9-1.pgdg120+1"),
|
parse_pg_version("PostgreSQL 14.9 (Debian 14.9-1.pgdg120+1"),
|
||||||
V14
|
"v14"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 16devel"), V16);
|
assert_eq!(parse_pg_version("PostgreSQL 16devel"), "v16");
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 16beta1"), V16);
|
assert_eq!(parse_pg_version("PostgreSQL 16beta1"), "v16");
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 16rc2"), V16);
|
assert_eq!(parse_pg_version("PostgreSQL 16rc2"), "v16");
|
||||||
assert_eq!(parse_pg_version("PostgreSQL 16extra"), V16);
|
assert_eq!(parse_pg_version("PostgreSQL 16extra"), "v16");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
549
compute_tools/src/http/api.rs
Normal file
549
compute_tools/src/http/api.rs
Normal file
@@ -0,0 +1,549 @@
|
|||||||
|
use std::convert::Infallible;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::net::Ipv6Addr;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
use crate::catalog::SchemaDumpError;
|
||||||
|
use crate::catalog::{get_database_schema, get_dbs_and_roles};
|
||||||
|
use crate::compute::forward_termination_signal;
|
||||||
|
use crate::compute::{ComputeNode, ComputeState, ParsedSpec};
|
||||||
|
use compute_api::requests::{ConfigurationRequest, ExtensionInstallRequest, SetRoleGrantsRequest};
|
||||||
|
use compute_api::responses::{
|
||||||
|
ComputeStatus, ComputeStatusResponse, ExtensionInstallResult, GenericAPIError,
|
||||||
|
SetRoleGrantsResponse,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use hyper::header::CONTENT_TYPE;
|
||||||
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
|
use hyper::{Body, Method, Request, Response, Server, StatusCode};
|
||||||
|
use tokio::task;
|
||||||
|
use tracing::{debug, error, info, warn};
|
||||||
|
use tracing_utils::http::OtelName;
|
||||||
|
use utils::http::request::must_get_query_param;
|
||||||
|
|
||||||
|
fn status_response_from_state(state: &ComputeState) -> ComputeStatusResponse {
|
||||||
|
ComputeStatusResponse {
|
||||||
|
start_time: state.start_time,
|
||||||
|
tenant: state
|
||||||
|
.pspec
|
||||||
|
.as_ref()
|
||||||
|
.map(|pspec| pspec.tenant_id.to_string()),
|
||||||
|
timeline: state
|
||||||
|
.pspec
|
||||||
|
.as_ref()
|
||||||
|
.map(|pspec| pspec.timeline_id.to_string()),
|
||||||
|
status: state.status,
|
||||||
|
last_active: state.last_active,
|
||||||
|
error: state.error.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service function to handle all available routes.
|
||||||
|
async fn routes(req: Request<Body>, compute: &Arc<ComputeNode>) -> Response<Body> {
|
||||||
|
//
|
||||||
|
// NOTE: The URI path is currently included in traces. That's OK because
|
||||||
|
// it doesn't contain any variable parts or sensitive information. But
|
||||||
|
// please keep that in mind if you change the routing here.
|
||||||
|
//
|
||||||
|
match (req.method(), req.uri().path()) {
|
||||||
|
// Serialized compute state.
|
||||||
|
(&Method::GET, "/status") => {
|
||||||
|
debug!("serving /status GET request");
|
||||||
|
let state = compute.state.lock().unwrap();
|
||||||
|
let status_response = status_response_from_state(&state);
|
||||||
|
Response::new(Body::from(serde_json::to_string(&status_response).unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Startup metrics in JSON format. Keep /metrics reserved for a possible
|
||||||
|
// future use for Prometheus metrics format.
|
||||||
|
(&Method::GET, "/metrics.json") => {
|
||||||
|
info!("serving /metrics.json GET request");
|
||||||
|
let metrics = compute.state.lock().unwrap().metrics.clone();
|
||||||
|
Response::new(Body::from(serde_json::to_string(&metrics).unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect Postgres current usage insights
|
||||||
|
(&Method::GET, "/insights") => {
|
||||||
|
info!("serving /insights GET request");
|
||||||
|
let status = compute.get_status();
|
||||||
|
if status != ComputeStatus::Running {
|
||||||
|
let msg = format!("compute is not running, current status: {:?}", status);
|
||||||
|
error!(msg);
|
||||||
|
return Response::new(Body::from(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let insights = compute.collect_insights().await;
|
||||||
|
Response::new(Body::from(insights))
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::POST, "/check_writability") => {
|
||||||
|
info!("serving /check_writability POST request");
|
||||||
|
let status = compute.get_status();
|
||||||
|
if status != ComputeStatus::Running {
|
||||||
|
let msg = format!(
|
||||||
|
"invalid compute status for check_writability request: {:?}",
|
||||||
|
status
|
||||||
|
);
|
||||||
|
error!(msg);
|
||||||
|
return Response::new(Body::from(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = crate::checker::check_writability(compute).await;
|
||||||
|
match res {
|
||||||
|
Ok(_) => Response::new(Body::from("true")),
|
||||||
|
Err(e) => {
|
||||||
|
error!("check_writability failed: {}", e);
|
||||||
|
Response::new(Body::from(e.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::POST, "/extensions") => {
|
||||||
|
info!("serving /extensions POST request");
|
||||||
|
let status = compute.get_status();
|
||||||
|
if status != ComputeStatus::Running {
|
||||||
|
let msg = format!(
|
||||||
|
"invalid compute status for extensions request: {:?}",
|
||||||
|
status
|
||||||
|
);
|
||||||
|
error!(msg);
|
||||||
|
return render_json_error(&msg, StatusCode::PRECONDITION_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = hyper::body::to_bytes(req.into_body()).await.unwrap();
|
||||||
|
let request = serde_json::from_slice::<ExtensionInstallRequest>(&request).unwrap();
|
||||||
|
let res = compute
|
||||||
|
.install_extension(&request.extension, &request.database, request.version)
|
||||||
|
.await;
|
||||||
|
match res {
|
||||||
|
Ok(version) => render_json(Body::from(
|
||||||
|
serde_json::to_string(&ExtensionInstallResult {
|
||||||
|
extension: request.extension,
|
||||||
|
version,
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
)),
|
||||||
|
Err(e) => {
|
||||||
|
error!("install_extension failed: {}", e);
|
||||||
|
render_json_error(&e.to_string(), StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::GET, "/info") => {
|
||||||
|
let num_cpus = num_cpus::get_physical();
|
||||||
|
info!("serving /info GET request. num_cpus: {}", num_cpus);
|
||||||
|
Response::new(Body::from(
|
||||||
|
serde_json::json!({
|
||||||
|
"num_cpus": num_cpus,
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept spec in JSON format and request compute configuration. If
|
||||||
|
// anything goes wrong after we set the compute status to `ConfigurationPending`
|
||||||
|
// and update compute state with new spec, we basically leave compute
|
||||||
|
// in the potentially wrong state. That said, it's control-plane's
|
||||||
|
// responsibility to watch compute state after reconfiguration request
|
||||||
|
// and to clean restart in case of errors.
|
||||||
|
(&Method::POST, "/configure") => {
|
||||||
|
info!("serving /configure POST request");
|
||||||
|
match handle_configure_request(req, compute).await {
|
||||||
|
Ok(msg) => Response::new(Body::from(msg)),
|
||||||
|
Err((msg, code)) => {
|
||||||
|
error!("error handling /configure request: {msg}");
|
||||||
|
render_json_error(&msg, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::POST, "/terminate") => {
|
||||||
|
info!("serving /terminate POST request");
|
||||||
|
match handle_terminate_request(compute).await {
|
||||||
|
Ok(()) => Response::new(Body::empty()),
|
||||||
|
Err((msg, code)) => {
|
||||||
|
error!("error handling /terminate request: {msg}");
|
||||||
|
render_json_error(&msg, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::GET, "/dbs_and_roles") => {
|
||||||
|
info!("serving /dbs_and_roles GET request",);
|
||||||
|
match get_dbs_and_roles(compute).await {
|
||||||
|
Ok(res) => render_json(Body::from(serde_json::to_string(&res).unwrap())),
|
||||||
|
Err(_) => {
|
||||||
|
render_json_error("can't get dbs and roles", StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::GET, "/database_schema") => {
|
||||||
|
let database = match must_get_query_param(&req, "database") {
|
||||||
|
Err(e) => return e.into_response(),
|
||||||
|
Ok(database) => database,
|
||||||
|
};
|
||||||
|
info!("serving /database_schema GET request with database: {database}",);
|
||||||
|
match get_database_schema(compute, &database).await {
|
||||||
|
Ok(res) => render_plain(Body::wrap_stream(res)),
|
||||||
|
Err(SchemaDumpError::DatabaseDoesNotExist) => {
|
||||||
|
render_json_error("database does not exist", StatusCode::NOT_FOUND)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("can't get schema dump: {}", e);
|
||||||
|
render_json_error("can't get schema dump", StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(&Method::POST, "/grants") => {
|
||||||
|
info!("serving /grants POST request");
|
||||||
|
let status = compute.get_status();
|
||||||
|
if status != ComputeStatus::Running {
|
||||||
|
let msg = format!(
|
||||||
|
"invalid compute status for set_role_grants request: {:?}",
|
||||||
|
status
|
||||||
|
);
|
||||||
|
error!(msg);
|
||||||
|
return render_json_error(&msg, StatusCode::PRECONDITION_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = hyper::body::to_bytes(req.into_body()).await.unwrap();
|
||||||
|
let request = serde_json::from_slice::<SetRoleGrantsRequest>(&request).unwrap();
|
||||||
|
|
||||||
|
let res = compute
|
||||||
|
.set_role_grants(
|
||||||
|
&request.database,
|
||||||
|
&request.schema,
|
||||||
|
&request.privileges,
|
||||||
|
&request.role,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
match res {
|
||||||
|
Ok(()) => render_json(Body::from(
|
||||||
|
serde_json::to_string(&SetRoleGrantsResponse {
|
||||||
|
database: request.database,
|
||||||
|
schema: request.schema,
|
||||||
|
role: request.role,
|
||||||
|
privileges: request.privileges,
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
)),
|
||||||
|
Err(e) => render_json_error(
|
||||||
|
&format!("could not grant role privileges to the schema: {e}"),
|
||||||
|
// TODO: can we filter on role/schema not found errors
|
||||||
|
// and return appropriate error code?
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the list of installed extensions
|
||||||
|
// currently only used in python tests
|
||||||
|
// TODO: call it from cplane
|
||||||
|
(&Method::GET, "/installed_extensions") => {
|
||||||
|
info!("serving /installed_extensions GET request");
|
||||||
|
let status = compute.get_status();
|
||||||
|
if status != ComputeStatus::Running {
|
||||||
|
let msg = format!(
|
||||||
|
"invalid compute status for extensions request: {:?}",
|
||||||
|
status
|
||||||
|
);
|
||||||
|
error!(msg);
|
||||||
|
return Response::new(Body::from(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let connstr = compute.connstr.clone();
|
||||||
|
let res = crate::installed_extensions::get_installed_extensions(connstr).await;
|
||||||
|
match res {
|
||||||
|
Ok(res) => render_json(Body::from(serde_json::to_string(&res).unwrap())),
|
||||||
|
Err(e) => render_json_error(
|
||||||
|
&format!("could not get list of installed extensions: {}", e),
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// download extension files from remote extension storage on demand
|
||||||
|
(&Method::POST, route) if route.starts_with("/extension_server/") => {
|
||||||
|
info!("serving {:?} POST request", route);
|
||||||
|
info!("req.uri {:?}", req.uri());
|
||||||
|
|
||||||
|
// don't even try to download extensions
|
||||||
|
// if no remote storage is configured
|
||||||
|
if compute.ext_remote_storage.is_none() {
|
||||||
|
info!("no extensions remote storage configured");
|
||||||
|
let mut resp = Response::new(Body::from("no remote storage configured"));
|
||||||
|
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut is_library = false;
|
||||||
|
if let Some(params) = req.uri().query() {
|
||||||
|
info!("serving {:?} POST request with params: {}", route, params);
|
||||||
|
if params == "is_library=true" {
|
||||||
|
is_library = true;
|
||||||
|
} else {
|
||||||
|
let mut resp = Response::new(Body::from("Wrong request parameters"));
|
||||||
|
*resp.status_mut() = StatusCode::BAD_REQUEST;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let filename = route.split('/').last().unwrap().to_string();
|
||||||
|
info!("serving /extension_server POST request, filename: {filename:?} is_library: {is_library}");
|
||||||
|
|
||||||
|
// get ext_name and path from spec
|
||||||
|
// don't lock compute_state for too long
|
||||||
|
let ext = {
|
||||||
|
let compute_state = compute.state.lock().unwrap();
|
||||||
|
let pspec = compute_state.pspec.as_ref().expect("spec must be set");
|
||||||
|
let spec = &pspec.spec;
|
||||||
|
|
||||||
|
// debug only
|
||||||
|
info!("spec: {:?}", spec);
|
||||||
|
|
||||||
|
let remote_extensions = match spec.remote_extensions.as_ref() {
|
||||||
|
Some(r) => r,
|
||||||
|
None => {
|
||||||
|
info!("no remote extensions spec was provided");
|
||||||
|
let mut resp = Response::new(Body::from("no remote storage configured"));
|
||||||
|
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
remote_extensions.get_ext(
|
||||||
|
&filename,
|
||||||
|
is_library,
|
||||||
|
&compute.build_tag,
|
||||||
|
&compute.pgversion,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
match ext {
|
||||||
|
Ok((ext_name, ext_path)) => {
|
||||||
|
match compute.download_extension(ext_name, ext_path).await {
|
||||||
|
Ok(_) => Response::new(Body::from("OK")),
|
||||||
|
Err(e) => {
|
||||||
|
error!("extension download failed: {}", e);
|
||||||
|
let mut resp = Response::new(Body::from(e.to_string()));
|
||||||
|
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
|
resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("extension download failed to find extension: {}", e);
|
||||||
|
let mut resp = Response::new(Body::from("failed to find file"));
|
||||||
|
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
|
resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the `404 Not Found` for any other routes.
|
||||||
|
_ => {
|
||||||
|
let mut not_found = Response::new(Body::from("404 Not Found"));
|
||||||
|
*not_found.status_mut() = StatusCode::NOT_FOUND;
|
||||||
|
not_found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_configure_request(
|
||||||
|
req: Request<Body>,
|
||||||
|
compute: &Arc<ComputeNode>,
|
||||||
|
) -> Result<String, (String, StatusCode)> {
|
||||||
|
if !compute.live_config_allowed {
|
||||||
|
return Err((
|
||||||
|
"live configuration is not allowed for this compute node".to_string(),
|
||||||
|
StatusCode::PRECONDITION_FAILED,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap();
|
||||||
|
let spec_raw = String::from_utf8(body_bytes.to_vec()).unwrap();
|
||||||
|
if let Ok(request) = serde_json::from_str::<ConfigurationRequest>(&spec_raw) {
|
||||||
|
let spec = request.spec;
|
||||||
|
|
||||||
|
let parsed_spec = match ParsedSpec::try_from(spec) {
|
||||||
|
Ok(ps) => ps,
|
||||||
|
Err(msg) => return Err((msg, StatusCode::BAD_REQUEST)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX: wrap state update under lock in code blocks. Otherwise,
|
||||||
|
// we will try to `Send` `mut state` into the spawned thread
|
||||||
|
// bellow, which will cause error:
|
||||||
|
// ```
|
||||||
|
// error: future cannot be sent between threads safely
|
||||||
|
// ```
|
||||||
|
{
|
||||||
|
let mut state = compute.state.lock().unwrap();
|
||||||
|
if state.status != ComputeStatus::Empty && state.status != ComputeStatus::Running {
|
||||||
|
let msg = format!(
|
||||||
|
"invalid compute status for configuration request: {:?}",
|
||||||
|
state.status.clone()
|
||||||
|
);
|
||||||
|
return Err((msg, StatusCode::PRECONDITION_FAILED));
|
||||||
|
}
|
||||||
|
state.pspec = Some(parsed_spec);
|
||||||
|
state.set_status(ComputeStatus::ConfigurationPending, &compute.state_changed);
|
||||||
|
drop(state);
|
||||||
|
info!("set new spec and notified waiters");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn a blocking thread to wait for compute to become Running.
|
||||||
|
// This is needed to do not block the main pool of workers and
|
||||||
|
// be able to serve other requests while some particular request
|
||||||
|
// is waiting for compute to finish configuration.
|
||||||
|
let c = compute.clone();
|
||||||
|
task::spawn_blocking(move || {
|
||||||
|
let mut state = c.state.lock().unwrap();
|
||||||
|
while state.status != ComputeStatus::Running {
|
||||||
|
state = c.state_changed.wait(state).unwrap();
|
||||||
|
info!(
|
||||||
|
"waiting for compute to become Running, current status: {:?}",
|
||||||
|
state.status
|
||||||
|
);
|
||||||
|
|
||||||
|
if state.status == ComputeStatus::Failed {
|
||||||
|
let err = state.error.as_ref().map_or("unknown error", |x| x);
|
||||||
|
let msg = format!("compute configuration failed: {:?}", err);
|
||||||
|
return Err((msg, StatusCode::INTERNAL_SERVER_ERROR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
|
||||||
|
// Return current compute state if everything went well.
|
||||||
|
let state = compute.state.lock().unwrap().clone();
|
||||||
|
let status_response = status_response_from_state(&state);
|
||||||
|
Ok(serde_json::to_string(&status_response).unwrap())
|
||||||
|
} else {
|
||||||
|
Err(("invalid spec".to_string(), StatusCode::BAD_REQUEST))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_json_error(e: &str, status: StatusCode) -> Response<Body> {
|
||||||
|
let error = GenericAPIError {
|
||||||
|
error: e.to_string(),
|
||||||
|
};
|
||||||
|
Response::builder()
|
||||||
|
.status(status)
|
||||||
|
.header(CONTENT_TYPE, "application/json")
|
||||||
|
.body(Body::from(serde_json::to_string(&error).unwrap()))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_json(body: Body) -> Response<Body> {
|
||||||
|
Response::builder()
|
||||||
|
.header(CONTENT_TYPE, "application/json")
|
||||||
|
.body(body)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_plain(body: Body) -> Response<Body> {
|
||||||
|
Response::builder()
|
||||||
|
.header(CONTENT_TYPE, "text/plain")
|
||||||
|
.body(body)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_terminate_request(compute: &Arc<ComputeNode>) -> Result<(), (String, StatusCode)> {
|
||||||
|
{
|
||||||
|
let mut state = compute.state.lock().unwrap();
|
||||||
|
if state.status == ComputeStatus::Terminated {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if state.status != ComputeStatus::Empty && state.status != ComputeStatus::Running {
|
||||||
|
let msg = format!(
|
||||||
|
"invalid compute status for termination request: {}",
|
||||||
|
state.status
|
||||||
|
);
|
||||||
|
return Err((msg, StatusCode::PRECONDITION_FAILED));
|
||||||
|
}
|
||||||
|
state.set_status(ComputeStatus::TerminationPending, &compute.state_changed);
|
||||||
|
drop(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_termination_signal();
|
||||||
|
info!("sent signal and notified waiters");
|
||||||
|
|
||||||
|
// Spawn a blocking thread to wait for compute to become Terminated.
|
||||||
|
// This is needed to do not block the main pool of workers and
|
||||||
|
// be able to serve other requests while some particular request
|
||||||
|
// is waiting for compute to finish configuration.
|
||||||
|
let c = compute.clone();
|
||||||
|
task::spawn_blocking(move || {
|
||||||
|
let mut state = c.state.lock().unwrap();
|
||||||
|
while state.status != ComputeStatus::Terminated {
|
||||||
|
state = c.state_changed.wait(state).unwrap();
|
||||||
|
info!(
|
||||||
|
"waiting for compute to become {}, current status: {:?}",
|
||||||
|
ComputeStatus::Terminated,
|
||||||
|
state.status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
info!("terminated Postgres");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main Hyper HTTP server function that runs it and blocks waiting on it forever.
|
||||||
|
#[tokio::main]
|
||||||
|
async fn serve(port: u16, state: Arc<ComputeNode>) {
|
||||||
|
// this usually binds to both IPv4 and IPv6 on linux
|
||||||
|
// see e.g. https://github.com/rust-lang/rust/pull/34440
|
||||||
|
let addr = SocketAddr::new(IpAddr::from(Ipv6Addr::UNSPECIFIED), port);
|
||||||
|
|
||||||
|
let make_service = make_service_fn(move |_conn| {
|
||||||
|
let state = state.clone();
|
||||||
|
async move {
|
||||||
|
Ok::<_, Infallible>(service_fn(move |req: Request<Body>| {
|
||||||
|
let state = state.clone();
|
||||||
|
async move {
|
||||||
|
Ok::<_, Infallible>(
|
||||||
|
// NOTE: We include the URI path in the string. It
|
||||||
|
// doesn't contain any variable parts or sensitive
|
||||||
|
// information in this API.
|
||||||
|
tracing_utils::http::tracing_handler(
|
||||||
|
req,
|
||||||
|
|req| routes(req, &state),
|
||||||
|
OtelName::UriPath,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
info!("starting HTTP server on {}", addr);
|
||||||
|
|
||||||
|
let server = Server::bind(&addr).serve(make_service);
|
||||||
|
|
||||||
|
// Run this server forever
|
||||||
|
if let Err(e) = server.await {
|
||||||
|
error!("server error: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Launch a separate Hyper HTTP API server thread and return its `JoinHandle`.
|
||||||
|
pub fn launch_http_server(port: u16, state: &Arc<ComputeNode>) -> Result<thread::JoinHandle<()>> {
|
||||||
|
let state = Arc::clone(state);
|
||||||
|
|
||||||
|
Ok(thread::Builder::new()
|
||||||
|
.name("http-endpoint".into())
|
||||||
|
.spawn(move || serve(port, state))?)
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
use axum::extract::{rejection::JsonRejection, FromRequest, Request};
|
|
||||||
use compute_api::responses::GenericAPIError;
|
|
||||||
use http::StatusCode;
|
|
||||||
|
|
||||||
/// Custom `Json` extractor, so that we can format errors into
|
|
||||||
/// `JsonResponse<GenericAPIError>`.
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
|
||||||
pub(crate) struct Json<T>(pub T);
|
|
||||||
|
|
||||||
impl<S, T> FromRequest<S> for Json<T>
|
|
||||||
where
|
|
||||||
axum::Json<T>: FromRequest<S, Rejection = JsonRejection>,
|
|
||||||
S: Send + Sync,
|
|
||||||
{
|
|
||||||
type Rejection = (StatusCode, axum::Json<GenericAPIError>);
|
|
||||||
|
|
||||||
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
|
||||||
match axum::Json::<T>::from_request(req, state).await {
|
|
||||||
Ok(value) => Ok(Self(value.0)),
|
|
||||||
Err(rejection) => Err((
|
|
||||||
rejection.status(),
|
|
||||||
axum::Json(GenericAPIError {
|
|
||||||
error: rejection.body_text().to_lowercase(),
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for Json<T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DerefMut for Json<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
pub(crate) mod json;
|
|
||||||
pub(crate) mod path;
|
|
||||||
pub(crate) mod query;
|
|
||||||
|
|
||||||
pub(crate) use json::Json;
|
|
||||||
pub(crate) use path::Path;
|
|
||||||
pub(crate) use query::Query;
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
use axum::extract::{rejection::PathRejection, FromRequestParts};
|
|
||||||
use compute_api::responses::GenericAPIError;
|
|
||||||
use http::{request::Parts, StatusCode};
|
|
||||||
|
|
||||||
/// Custom `Path` extractor, so that we can format errors into
|
|
||||||
/// `JsonResponse<GenericAPIError>`.
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
|
||||||
pub(crate) struct Path<T>(pub T);
|
|
||||||
|
|
||||||
impl<S, T> FromRequestParts<S> for Path<T>
|
|
||||||
where
|
|
||||||
axum::extract::Path<T>: FromRequestParts<S, Rejection = PathRejection>,
|
|
||||||
S: Send + Sync,
|
|
||||||
{
|
|
||||||
type Rejection = (StatusCode, axum::Json<GenericAPIError>);
|
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
|
||||||
match axum::extract::Path::<T>::from_request_parts(parts, state).await {
|
|
||||||
Ok(value) => Ok(Self(value.0)),
|
|
||||||
Err(rejection) => Err((
|
|
||||||
rejection.status(),
|
|
||||||
axum::Json(GenericAPIError {
|
|
||||||
error: rejection.body_text().to_ascii_lowercase(),
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for Path<T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DerefMut for Path<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
use axum::extract::{rejection::QueryRejection, FromRequestParts};
|
|
||||||
use compute_api::responses::GenericAPIError;
|
|
||||||
use http::{request::Parts, StatusCode};
|
|
||||||
|
|
||||||
/// Custom `Query` extractor, so that we can format errors into
|
|
||||||
/// `JsonResponse<GenericAPIError>`.
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
|
||||||
pub(crate) struct Query<T>(pub T);
|
|
||||||
|
|
||||||
impl<S, T> FromRequestParts<S> for Query<T>
|
|
||||||
where
|
|
||||||
axum::extract::Query<T>: FromRequestParts<S, Rejection = QueryRejection>,
|
|
||||||
S: Send + Sync,
|
|
||||||
{
|
|
||||||
type Rejection = (StatusCode, axum::Json<GenericAPIError>);
|
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
|
||||||
match axum::extract::Query::<T>::from_request_parts(parts, state).await {
|
|
||||||
Ok(value) => Ok(Self(value.0)),
|
|
||||||
Err(rejection) => Err((
|
|
||||||
rejection.status(),
|
|
||||||
axum::Json(GenericAPIError {
|
|
||||||
error: rejection.body_text().to_ascii_lowercase(),
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for Query<T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DerefMut for Query<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +1 @@
|
|||||||
use axum::{body::Body, response::Response};
|
pub mod api;
|
||||||
use compute_api::responses::{ComputeStatus, GenericAPIError};
|
|
||||||
use http::{header::CONTENT_TYPE, StatusCode};
|
|
||||||
use serde::Serialize;
|
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
mod extract;
|
|
||||||
mod routes;
|
|
||||||
pub mod server;
|
|
||||||
|
|
||||||
/// Convenience response builder for JSON responses
|
|
||||||
struct JsonResponse;
|
|
||||||
|
|
||||||
impl JsonResponse {
|
|
||||||
/// Helper for actually creating a response
|
|
||||||
fn create_response(code: StatusCode, body: impl Serialize) -> Response {
|
|
||||||
Response::builder()
|
|
||||||
.status(code)
|
|
||||||
.header(CONTENT_TYPE.as_str(), "application/json")
|
|
||||||
.body(Body::from(serde_json::to_string(&body).unwrap()))
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a successful error response
|
|
||||||
pub(self) fn success(code: StatusCode, body: impl Serialize) -> Response {
|
|
||||||
assert!({
|
|
||||||
let code = code.as_u16();
|
|
||||||
|
|
||||||
(200..300).contains(&code)
|
|
||||||
});
|
|
||||||
|
|
||||||
Self::create_response(code, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an error response
|
|
||||||
pub(self) fn error(code: StatusCode, error: impl ToString) -> Response {
|
|
||||||
assert!(code.as_u16() >= 400);
|
|
||||||
|
|
||||||
let message = error.to_string();
|
|
||||||
error!(message);
|
|
||||||
|
|
||||||
Self::create_response(code, &GenericAPIError { error: message })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an error response related to the compute being in an invalid state
|
|
||||||
pub(self) fn invalid_status(status: ComputeStatus) -> Response {
|
|
||||||
Self::create_response(
|
|
||||||
StatusCode::PRECONDITION_FAILED,
|
|
||||||
&GenericAPIError {
|
|
||||||
error: format!("invalid compute status: {status}"),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -37,21 +37,6 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/ComputeMetrics"
|
$ref: "#/components/schemas/ComputeMetrics"
|
||||||
|
|
||||||
/metrics:
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- Info
|
|
||||||
summary: Get compute node metrics in text format.
|
|
||||||
description: ""
|
|
||||||
operationId: getComputeMetrics
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: ComputeMetrics
|
|
||||||
content:
|
|
||||||
text/plain:
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
description: Metrics in text format.
|
|
||||||
/insights:
|
/insights:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -68,6 +53,35 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/ComputeInsights"
|
$ref: "#/components/schemas/ComputeInsights"
|
||||||
|
|
||||||
|
/installed_extensions:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Info
|
||||||
|
summary: Get installed extensions.
|
||||||
|
description: ""
|
||||||
|
operationId: getInstalledExtensions
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: List of installed extensions
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/InstalledExtensions"
|
||||||
|
/info:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Info
|
||||||
|
summary: Get info about the compute pod / VM.
|
||||||
|
description: ""
|
||||||
|
operationId: getInfo
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Info
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Info"
|
||||||
|
|
||||||
/dbs_and_roles:
|
/dbs_and_roles:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -508,14 +522,12 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
extname:
|
extname:
|
||||||
type: string
|
type: string
|
||||||
version:
|
versions:
|
||||||
type: string
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
n_databases:
|
n_databases:
|
||||||
type: integer
|
type: integer
|
||||||
owned_by_superuser:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
SetRoleGrantsRequest:
|
SetRoleGrantsRequest:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use axum::{extract::State, response::Response};
|
|
||||||
use compute_api::responses::ComputeStatus;
|
|
||||||
use http::StatusCode;
|
|
||||||
|
|
||||||
use crate::{checker::check_writability, compute::ComputeNode, http::JsonResponse};
|
|
||||||
|
|
||||||
/// Check that the compute is currently running.
|
|
||||||
pub(in crate::http) async fn is_writable(State(compute): State<Arc<ComputeNode>>) -> Response {
|
|
||||||
let status = compute.get_status();
|
|
||||||
if status != ComputeStatus::Running {
|
|
||||||
return JsonResponse::invalid_status(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
match check_writability(&compute).await {
|
|
||||||
Ok(_) => JsonResponse::success(StatusCode::OK, true),
|
|
||||||
Err(e) => JsonResponse::error(StatusCode::INTERNAL_SERVER_ERROR, e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use axum::{extract::State, response::Response};
|
|
||||||
use compute_api::{
|
|
||||||
requests::ConfigurationRequest,
|
|
||||||
responses::{ComputeStatus, ComputeStatusResponse},
|
|
||||||
};
|
|
||||||
use http::StatusCode;
|
|
||||||
use tokio::task;
|
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
compute::{ComputeNode, ParsedSpec},
|
|
||||||
http::{extract::Json, JsonResponse},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Accept spec in JSON format and request compute configuration. If anything
|
|
||||||
// goes wrong after we set the compute status to `ConfigurationPending` and
|
|
||||||
// update compute state with new spec, we basically leave compute in the
|
|
||||||
// potentially wrong state. That said, it's control-plane's responsibility to
|
|
||||||
// watch compute state after reconfiguration request and to clean restart in
|
|
||||||
// case of errors.
|
|
||||||
pub(in crate::http) async fn configure(
|
|
||||||
State(compute): State<Arc<ComputeNode>>,
|
|
||||||
request: Json<ConfigurationRequest>,
|
|
||||||
) -> Response {
|
|
||||||
if !compute.live_config_allowed {
|
|
||||||
return JsonResponse::error(
|
|
||||||
StatusCode::PRECONDITION_FAILED,
|
|
||||||
"live configuration is not allowed for this compute node".to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let pspec = match ParsedSpec::try_from(request.spec.clone()) {
|
|
||||||
Ok(p) => p,
|
|
||||||
Err(e) => return JsonResponse::error(StatusCode::BAD_REQUEST, e),
|
|
||||||
};
|
|
||||||
|
|
||||||
// XXX: wrap state update under lock in a code block. Otherwise, we will try
|
|
||||||
// to `Send` `mut state` into the spawned thread bellow, which will cause
|
|
||||||
// the following rustc error:
|
|
||||||
//
|
|
||||||
// error: future cannot be sent between threads safely
|
|
||||||
{
|
|
||||||
let mut state = compute.state.lock().unwrap();
|
|
||||||
if !matches!(state.status, ComputeStatus::Empty | ComputeStatus::Running) {
|
|
||||||
return JsonResponse::invalid_status(state.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.pspec = Some(pspec);
|
|
||||||
state.set_status(ComputeStatus::ConfigurationPending, &compute.state_changed);
|
|
||||||
drop(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn a blocking thread to wait for compute to become Running. This is
|
|
||||||
// needed to do not block the main pool of workers and be able to serve
|
|
||||||
// other requests while some particular request is waiting for compute to
|
|
||||||
// finish configuration.
|
|
||||||
let c = compute.clone();
|
|
||||||
let completed = task::spawn_blocking(move || {
|
|
||||||
let mut state = c.state.lock().unwrap();
|
|
||||||
while state.status != ComputeStatus::Running {
|
|
||||||
state = c.state_changed.wait(state).unwrap();
|
|
||||||
info!(
|
|
||||||
"waiting for compute to become {}, current status: {}",
|
|
||||||
ComputeStatus::Running,
|
|
||||||
state.status
|
|
||||||
);
|
|
||||||
|
|
||||||
if state.status == ComputeStatus::Failed {
|
|
||||||
let err = state.error.as_ref().map_or("unknown error", |x| x);
|
|
||||||
let msg = format!("compute configuration failed: {:?}", err);
|
|
||||||
return Err(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Err(e) = completed {
|
|
||||||
return JsonResponse::error(StatusCode::INTERNAL_SERVER_ERROR, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return current compute state if everything went well.
|
|
||||||
let state = compute.state.lock().unwrap().clone();
|
|
||||||
let body = ComputeStatusResponse::from(&state);
|
|
||||||
|
|
||||||
JsonResponse::success(StatusCode::OK, body)
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use axum::{body::Body, extract::State, response::Response};
|
|
||||||
use http::{header::CONTENT_TYPE, StatusCode};
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
catalog::{get_database_schema, SchemaDumpError},
|
|
||||||
compute::ComputeNode,
|
|
||||||
http::{extract::Query, JsonResponse},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub(in crate::http) struct DatabaseSchemaParams {
|
|
||||||
database: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a schema dump of the requested database.
|
|
||||||
pub(in crate::http) async fn get_schema_dump(
|
|
||||||
params: Query<DatabaseSchemaParams>,
|
|
||||||
State(compute): State<Arc<ComputeNode>>,
|
|
||||||
) -> Response {
|
|
||||||
match get_database_schema(&compute, ¶ms.database).await {
|
|
||||||
Ok(schema) => Response::builder()
|
|
||||||
.status(StatusCode::OK)
|
|
||||||
.header(CONTENT_TYPE.as_str(), "application/json")
|
|
||||||
.body(Body::from_stream(schema))
|
|
||||||
.unwrap(),
|
|
||||||
Err(SchemaDumpError::DatabaseDoesNotExist) => {
|
|
||||||
JsonResponse::error(StatusCode::NOT_FOUND, SchemaDumpError::DatabaseDoesNotExist)
|
|
||||||
}
|
|
||||||
Err(e) => JsonResponse::error(StatusCode::INTERNAL_SERVER_ERROR, e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use axum::{extract::State, response::Response};
|
|
||||||
use http::StatusCode;
|
|
||||||
|
|
||||||
use crate::{catalog::get_dbs_and_roles, compute::ComputeNode, http::JsonResponse};
|
|
||||||
|
|
||||||
/// Get the databases and roles from the compute.
|
|
||||||
pub(in crate::http) async fn get_catalog_objects(
|
|
||||||
State(compute): State<Arc<ComputeNode>>,
|
|
||||||
) -> Response {
|
|
||||||
match get_dbs_and_roles(&compute).await {
|
|
||||||
Ok(catalog_objects) => JsonResponse::success(StatusCode::OK, catalog_objects),
|
|
||||||
Err(e) => JsonResponse::error(StatusCode::INTERNAL_SERVER_ERROR, e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user