This is an automated email from the ASF dual-hosted git repository.
baoyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 31148aa65 fix(docker): support valid YAML variations in standalone
mode (#12949)
31148aa65 is described below
commit 31148aa6590ea0f047123acb0a6007aa3fc744d0
Author: Mohammad Izzraff Janius
<[email protected]>
AuthorDate: Wed Feb 4 13:52:02 2026 +0800
fix(docker): support valid YAML variations in standalone mode (#12949)
---
.github/workflows/docker-standalone.yml | 63 +++++++++
Makefile | 1 -
apisix/cli/ops.lua | 22 +++
ci/linux_apisix_current_luarocks_runner.sh | 2 +
docker/debian-dev/Dockerfile | 4 +-
docker/debian-dev/docker-entrypoint.sh | 3 -
docker/utils/check_standalone_config.sh | 35 -----
t/cli/test_standalone_docker.sh | 214 +++++++++++++++++++++++++++++
t/cli/test_standalone_yaml_format.sh | 169 +++++++++++++++++++++++
9 files changed, 471 insertions(+), 42 deletions(-)
diff --git a/.github/workflows/docker-standalone.yml
b/.github/workflows/docker-standalone.yml
new file mode 100644
index 000000000..a048ee36e
--- /dev/null
+++ b/.github/workflows/docker-standalone.yml
@@ -0,0 +1,63 @@
+name: Docker Standalone Test
+
+on:
+ push:
+ branches: [master, 'release/**']
+ paths:
+ - 'apisix/cli/ops.lua'
+ - 'docker/debian-dev/**'
+ - 't/cli/test_standalone_docker.sh'
+ - 'Makefile'
+ - '.github/workflows/docker-standalone.yml'
+ pull_request:
+ branches: [master, 'release/**']
+ paths:
+ - 'apisix/cli/ops.lua'
+ - 'docker/debian-dev/**'
+ - 't/cli/test_standalone_docker.sh'
+ - 'Makefile'
+ - '.github/workflows/docker-standalone.yml'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/master' &&
github.run_number || github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+
+jobs:
+ docker-test:
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v5
+
+ - name: Build APISIX Dashboard
+ run: |
+ # install node.js and pnpm
+ sudo n lts
+ corepack enable pnpm
+
+ # prepare apisix-dashboard source code
+ source .requirements
+ git clone --revision=${APISIX_DASHBOARD_COMMIT} --depth 1
https://github.com/apache/apisix-dashboard.git
+ pushd apisix-dashboard
+
+ # compile
+ pnpm install --frozen-lockfile
+ pnpm run build
+ popd
+
+ # copy the dist files to the ui directory
+ mkdir ui
+ cp -r apisix-dashboard/dist/* ui/
+ rm -r apisix-dashboard
+
+ # build Docker image
+ make build-on-debian-dev
+
+ - name: Run Docker standalone test
+ run: |
+ ./t/cli/test_standalone_docker.sh
diff --git a/Makefile b/Makefile
index 423b24056..b54d7eefc 100644
--- a/Makefile
+++ b/Makefile
@@ -501,7 +501,6 @@ build-on-debian-dev:
--build-arg CODE_PATH=. \
--build-arg
ENTRYPOINT_PATH=./docker/debian-dev/docker-entrypoint.sh \
--build-arg
INSTALL_BROTLI=./docker/debian-dev/install-brotli.sh \
- --build-arg
CHECK_STANDALONE_CONFIG=./docker/utils/check_standalone_config.sh \
-f ./docker/debian-dev/Dockerfile .
@$(call func_echo_success_status, "$@ -> [ Done ]")
diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua
index 0bb64b689..f5e9beb17 100644
--- a/apisix/cli/ops.lua
+++ b/apisix/cli/ops.lua
@@ -181,6 +181,28 @@ local function init(env)
util.die(err, "\n")
end
+ -- validate standalone mode config
+ local standalone_env = getenv("APISIX_STAND_ALONE")
+ if standalone_env == "true" then
+ local role = yaml_conf.deployment.role
+ local config_provider
+
+ if role == "data_plane" then
+ config_provider =
yaml_conf.deployment.role_data_plane.config_provider
+ elseif role == "traditional" then
+ config_provider = yaml_conf.deployment.role_traditional and
+ yaml_conf.deployment.role_traditional.config_provider
+ end
+
+ if config_provider ~= "yaml" and config_provider ~= "json" then
+ util.die("APISIX_STAND_ALONE is set to 'true' but config_provider
is '"
+ .. tostring(config_provider) .. "'\n"
+ .. "For standalone mode, config_provider must be 'yaml' or
'json'\n"
+ .. "Current role: " .. tostring(role) .. "\n"
+ .. "See:
https://apisix.apache.org/docs/apisix/deployment-modes/\n")
+ end
+ end
+
-- check the Admin API token
local checked_admin_key = false
local allow_admin = yaml_conf.deployment.admin and
diff --git a/ci/linux_apisix_current_luarocks_runner.sh
b/ci/linux_apisix_current_luarocks_runner.sh
index 39b9df8d0..a77f8878b 100755
--- a/ci/linux_apisix_current_luarocks_runner.sh
+++ b/ci/linux_apisix_current_luarocks_runner.sh
@@ -72,6 +72,8 @@ script() {
ulimit -n -H
for f in ./t/cli/test_*.sh; do
+ # skip docker test - runs in separate container
+ [[ "$f" == "./t/cli/test_standalone_docker.sh" ]] && continue
PATH="$PATH" "$f"
done
}
diff --git a/docker/debian-dev/Dockerfile b/docker/debian-dev/Dockerfile
index ae971dff2..ff906d551 100644
--- a/docker/debian-dev/Dockerfile
+++ b/docker/debian-dev/Dockerfile
@@ -43,7 +43,6 @@ FROM debian:bullseye-slim
ARG ENTRYPOINT_PATH=./docker-entrypoint.sh
ARG INSTALL_BROTLI=./install-brotli.sh
-ARG CHECK_STANDALONE_CONFIG=./check_standalone_config.sh
# Install the runtime libyaml package
RUN apt-get -y update --fix-missing \
@@ -72,8 +71,7 @@ RUN ln -sf /dev/stdout /usr/local/apisix/logs/access.log \
EXPOSE 9080 9443
COPY ${ENTRYPOINT_PATH} /docker-entrypoint.sh
-COPY ${CHECK_STANDALONE_CONFIG} /check_standalone_config.sh
-RUN chmod +x /docker-entrypoint.sh /check_standalone_config.sh
+RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
diff --git a/docker/debian-dev/docker-entrypoint.sh
b/docker/debian-dev/docker-entrypoint.sh
index 7ca7b8a91..41fab0905 100644
--- a/docker/debian-dev/docker-entrypoint.sh
+++ b/docker/debian-dev/docker-entrypoint.sh
@@ -30,9 +30,6 @@ deployment:
role_data_plane:
config_provider: yaml
_EOC_
- else
- # Check if the deployment role is set to data_plane and config
provider is set to yaml for standalone mode
- source /check_standalone_config.sh
fi
if [ ! -f "${PREFIX}/conf/apisix.yaml" ]; then
diff --git a/docker/utils/check_standalone_config.sh
b/docker/utils/check_standalone_config.sh
deleted file mode 100644
index 22792c54f..000000000
--- a/docker/utils/check_standalone_config.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-if ! grep -q 'role: data_plane' "${PREFIX}/conf/config.yaml"; then
- echo "Error: ${PREFIX}/conf/config.yaml does not contain 'role:
data_plane'. Deployment role must be set to 'data_plane' for standalone mode."
- echo "Please refer to the APISIX documentation for deployment modes:
https://apisix.apache.org/docs/apisix/deployment-modes/"
- exit 1
-fi
-
-if ! grep -q 'role_data_plane:' "${PREFIX}/conf/config.yaml"; then
- echo "Error: ${PREFIX}/conf/config.yaml does not contain
'role_data_plane:'."
- echo "Please refer to the APISIX documentation for deployment modes:
https://apisix.apache.org/docs/apisix/deployment-modes/"
- exit 1
-fi
-
-if ! grep -q 'config_provider: yaml' "${PREFIX}/conf/config.yaml"; then
- echo "Error: ${PREFIX}/conf/config.yaml does not contain 'config_provider:
yaml'. Config provider must be set to 'yaml' for standalone mode."
- echo "Please refer to the APISIX documentation for deployment modes:
https://apisix.apache.org/docs/apisix/deployment-modes/"
- exit 1
-fi
diff --git a/t/cli/test_standalone_docker.sh b/t/cli/test_standalone_docker.sh
new file mode 100755
index 000000000..7fce58364
--- /dev/null
+++ b/t/cli/test_standalone_docker.sh
@@ -0,0 +1,214 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+. ./t/cli/common.sh
+
+standalone() {
+ clean_up
+ docker rm -f apisix-test-standalone 2>/dev/null || true
+ git checkout conf/apisix.yaml
+}
+
+DOCKER_IMAGE="${DOCKER_IMAGE:-apache/apisix:master-debian-dev}"
+trap standalone EXIT
+
+echo 'routes: []
+#END' > conf/apisix.yaml
+
+run_docker_test() {
+ local standalone_flag=$1
+ local config_mode=${2:-ro}
+
+ if [ "$standalone_flag" = "true" ]; then
+ docker run -d --name apisix-test-standalone \
+ -e APISIX_STAND_ALONE=true \
+ -v
$(pwd)/conf/config.yaml:/usr/local/apisix/conf/config.yaml:${config_mode} \
+ -v $(pwd)/conf/apisix.yaml:/usr/local/apisix/conf/apisix.yaml:ro \
+ ${DOCKER_IMAGE} > /dev/null 2>&1
+ else
+ docker run -d --name apisix-test-standalone \
+ -v
$(pwd)/conf/config.yaml:/usr/local/apisix/conf/config.yaml:${config_mode} \
+ -v $(pwd)/conf/apisix.yaml:/usr/local/apisix/conf/apisix.yaml:ro \
+ ${DOCKER_IMAGE} > /dev/null 2>&1
+ fi
+
+ sleep 5
+
+ if ! docker ps | grep -q apisix-test-standalone; then
+ echo "Container failed to start. Logs:"
+ docker logs apisix-test-standalone
+ docker rm -f apisix-test-standalone > /dev/null 2>&1
+ return 1
+ fi
+
+ docker rm -f apisix-test-standalone > /dev/null 2>&1
+ return 0
+}
+
+# normal YAML format
+echo '
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+if ! run_docker_test "true"; then
+ echo "failed: normal YAML format 'role: data_plane' was rejected"
+ exit 1
+fi
+
+echo "passed: normal YAML format accepted"
+
+# double-quoted format
+echo '
+deployment:
+ role: "data_plane"
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+if ! run_docker_test "true"; then
+ echo "failed: double-quoted 'role: \"data_plane\"' was rejected"
+ exit 1
+fi
+
+echo "passed: double-quoted format accepted"
+
+# single-quoted format
+echo "
+deployment:
+ role: 'data_plane'
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+" > conf/config.yaml
+
+if ! run_docker_test "true"; then
+ echo "failed: single quoted \"role: 'data_plane'\" was rejected"
+ exit 1
+fi
+
+echo "passed: single-quoted format accepted"
+
+# flow syntax
+echo '
+deployment: {"role": "data_plane", "role_data_plane": {"config_provider":
"yaml"}}
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+if ! run_docker_test "true"; then
+ echo "failed: flow syntax 'role: {\"data_plane\"}' was rejected"
+ exit 1
+fi
+
+echo "passed: flow syntax format accepted"
+
+# mixed quotes
+echo "
+deployment:
+ role: \"data_plane\"
+ role_data_plane:
+ config_provider: 'yaml'
+apisix:
+ node_listen: 9080
+" > conf/config.yaml
+
+if ! run_docker_test "true"; then
+ echo "failed: mixed quotes format was rejected"
+ exit 1
+fi
+
+echo "passed: mixed quotes format accepted"
+
+# etcd config_provider should fail in standalone mode
+echo '
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: etcd
+ etcd:
+ host:
+ - "http://127.0.0.1:2379"
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+if run_docker_test "true"; then
+ echo "failed: 'config_provider: etcd' should be rejected in standalone
mode"
+ exit 1
+fi
+
+echo "passed: 'config_provider: etcd' was correctly rejected in standalone
mode"
+
+# traditional role with yaml config_provider should work
+echo '
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: yaml
+ admin:
+ admin_key_required: false
+apisix:
+ node_listen: 9080
+ enable_admin: true
+' > conf/config.yaml
+
+if ! run_docker_test "true" "rw"; then
+ echo "failed: traditional role with 'config_provider: yaml' was rejected"
+ exit 1
+fi
+
+echo "passed: traditional role with 'config_provider: yaml' accepted"
+
+# check is APISIX_PROFILE is respected in standalone mode
+echo '
+ deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: yaml
+ apisix:
+ node_listen: 9080
+ ' > conf/config-prod.yaml
+
+ docker run -d --name apisix-test-standalone \
+ -e APISIX_STAND_ALONE=true \
+ -e APISIX_PROFILE=prod \
+ -v
$(pwd)/conf/config-prod.yaml:/usr/local/apisix/conf/config-prod.yaml:ro \
+ -v $(pwd)/conf/apisix.yaml:/usr/local/apisix/conf/apisix.yaml:ro \
+ ${DOCKER_IMAGE} > /dev/null 2>&1
+
+ sleep 5
+
+ if ! docker ps | grep -q apisix-test-standalone; then
+ echo "failed: APISIX_PROFILE=prod in standalone mode was rejected"
+ docker logs apisix-test-standalone
+ docker rm -f apisix-test-standalone > /dev/null 2>&1
+ exit 1
+ fi
+
+ docker rm -f apisix-test-standalone > /dev/null 2>&1
+
+ echo "passed: APISIX_PROFILE=prod in standalone mode accepted"
diff --git a/t/cli/test_standalone_yaml_format.sh
b/t/cli/test_standalone_yaml_format.sh
new file mode 100755
index 000000000..d44eb430a
--- /dev/null
+++ b/t/cli/test_standalone_yaml_format.sh
@@ -0,0 +1,169 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+. ./t/cli/common.sh
+
+standalone() {
+ clean_up
+ git checkout conf/apisix.yaml
+ rm -f conf/config-prod.yaml
+ unset APISIX_STAND_ALONE
+ unset APISIX_PROFILE
+}
+
+trap standalone EXIT
+
+# normal YAML format
+echo '
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+export APISIX_STAND_ALONE=true
+
+if ! make init > /dev/null 2>&1; then
+ echo "failed: normal YAML format 'role: data_plane' was rejected"
+ exit 1
+fi
+
+echo "passed: normal YAML format accepted"
+
+# double-quoted format
+echo '
+deployment:
+ role: "data_plane"
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+make clean > /dev/null 2>&1
+
+if ! make init > /dev/null 2>&1; then
+ echo "failed: double-quoted 'role: \"data_plane\"' was rejected"
+ exit 1
+fi
+
+echo "passed: double-quoted format accepted"
+
+# single-quoted format
+echo "
+deployment:
+ role: 'data_plane'
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+" > conf/config.yaml
+
+make clean > /dev/null 2>&1
+
+if ! make init > /dev/null 2>&1; then
+ echo "failed: single quoted "role: 'data_plane'" was rejected"
+ exit 1
+fi
+
+echo "passed: single-quoted format accepted"
+
+# flow syntax
+echo '
+deployment: {"role": "data_plane", "role_data_plane": {"config_provider":
"yaml"}}
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+make clean > /dev/null 2>&1
+
+if ! make init > /dev/null 2>&1; then
+ echo "failed: flow syntax was rejected"
+ exit 1
+fi
+
+# should fail - etcd config_provider in standalone mode
+echo '
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: etcd
+ etcd:
+ host:
+ - "http://127.0.0.1:2379"
+apisix:
+ node_listen: 9080
+' > conf/config.yaml
+
+make clean > /dev/null 2>&1
+
+if make init > /dev/null 2>&1; then
+ echo "failed: 'config_provider: etcd' should be rejected in standalone
mode"
+ exit 1
+fi
+
+echo "passed: 'config_provider: etcd' was correctly rejected in standalone
mode"
+
+# traditional role with yaml config_provider
+echo '
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: yaml
+ admin:
+ admin_key_required: false
+apisix:
+ node_listen: 9080
+ enable_admin: true
+' > conf/config.yaml
+
+make clean > /dev/null 2>&1
+
+if ! make init > /dev/null 2>&1; then
+ echo "failed: 'role: traditional' with 'config_provider: yaml' was
rejected"
+ exit 1
+fi
+
+echo "passed: 'role: traditional' with 'config_provider: yaml' accepted"
+
+# check APISIX_PROFILE is respected
+echo '
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: yaml
+apisix:
+ node_listen: 9080
+' > conf/config-prod.yaml
+
+echo 'routes: []
+#END' > conf/apisix.yaml
+
+export APISIX_PROFILE=prod
+
+make clean > /dev/null 2>&1
+
+if ! make init > /dev/null 2>&1; then
+ echo "failed: APISIX_PROFILE=prod is not respected in standalone mode"
+ exit 1
+fi
+
+echo "passed: APISIX_PROFILE=prod is respected in standalone mode"