mirror of
https://github.com/alibaba/higress.git
synced 2026-02-25 21:21:01 +08:00
Compare commits
342 Commits
v2.0.1
...
v2.1.2-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07154d1f49 | ||
|
|
db30c0962a | ||
|
|
731fe43d14 | ||
|
|
5bd20aa559 | ||
|
|
a2e4f944e9 | ||
|
|
7955aec639 | ||
|
|
e12feb9f57 | ||
|
|
03b4144cff | ||
|
|
c382635e7f | ||
|
|
e381806ba0 | ||
|
|
52114b37f8 | ||
|
|
b4e68c02f9 | ||
|
|
c241ccf19d | ||
|
|
e4fa1e6390 | ||
|
|
b103b9d7cb | ||
|
|
90b02a90e0 | ||
|
|
38f718b965 | ||
|
|
8752a763c2 | ||
|
|
a57173ce28 | ||
|
|
3a8d8f5b94 | ||
|
|
1c37c361e1 | ||
|
|
b8133a95b2 | ||
|
|
36d5d391b8 | ||
|
|
1da9a07866 | ||
|
|
8620838f8b | ||
|
|
e7d2005382 | ||
|
|
4f47d3fc12 | ||
|
|
6773482300 | ||
|
|
b6d61f9568 | ||
|
|
1834d4acef | ||
|
|
7f9ae38e51 | ||
|
|
b13bce6a36 | ||
|
|
275cac9dbb | ||
|
|
8cce7f5d50 | ||
|
|
4f0834d817 | ||
|
|
7cf0dae824 | ||
|
|
707061fb68 | ||
|
|
3255925bf0 | ||
|
|
a44f7ef76e | ||
|
|
c7abfb8aff | ||
|
|
ed925ddf84 | ||
|
|
1301af4638 | ||
|
|
de6144439f | ||
|
|
e37c4dc286 | ||
|
|
b8e0baa5ab | ||
|
|
4a157e98e9 | ||
|
|
6af8b17216 | ||
|
|
4500b10a42 | ||
|
|
c5a86b5298 | ||
|
|
36806d9e5c | ||
|
|
d1700009e8 | ||
|
|
2c3188dad7 | ||
|
|
7d423cddbd | ||
|
|
0e94e1a58a | ||
|
|
b1307ba97e | ||
|
|
8ae810b01a | ||
|
|
83b38b896c | ||
|
|
1385028f01 | ||
|
|
af663b701a | ||
|
|
e5c24a10fb | ||
|
|
ea85ccb694 | ||
|
|
2467004dc9 | ||
|
|
5af818a94e | ||
|
|
728a9de165 | ||
|
|
823527ab94 | ||
|
|
cb7f6ccd0f | ||
|
|
5107ce5137 | ||
|
|
e6d32aa1cf | ||
|
|
3c73976130 | ||
|
|
639956c0b8 | ||
|
|
a602f7a725 | ||
|
|
7b6e4154f4 | ||
|
|
12e3f34c0b | ||
|
|
bdd802f44f | ||
|
|
d58b66df8f | ||
|
|
5d99c7d80a | ||
|
|
3428932aca | ||
|
|
7ba3f75d41 | ||
|
|
ae9a06b05c | ||
|
|
9ebe968921 | ||
|
|
93e3b086ce | ||
|
|
20dfc3d64f | ||
|
|
492c5d350a | ||
|
|
037c71a320 | ||
|
|
9a07c50f44 | ||
|
|
b86e9fc938 | ||
|
|
2014234356 | ||
|
|
83f69a0186 | ||
|
|
8495d17070 | ||
|
|
6f762b5e4c | ||
|
|
96e4713703 | ||
|
|
d3887835a3 | ||
|
|
1965d107d0 | ||
|
|
b2f9bf94fa | ||
|
|
9257077fa3 | ||
|
|
7e310a3520 | ||
|
|
663b28fa9b | ||
|
|
9fbe331f5f | ||
|
|
dd50ac09dc | ||
|
|
8450a0869b | ||
|
|
bd6708552d | ||
|
|
50cfa0bb4b | ||
|
|
ea0143829d | ||
|
|
f83e66c23b | ||
|
|
87fe1aeeb5 | ||
|
|
386a208b14 | ||
|
|
ee77ffb753 | ||
|
|
6eeef07621 | ||
|
|
8978a4e0e0 | ||
|
|
71029d791d | ||
|
|
d9f16f7d5e | ||
|
|
f5d20b72e0 | ||
|
|
9bde0dfb46 | ||
|
|
f5c1e7f2ec | ||
|
|
45fbc8b084 | ||
|
|
1812a6b0a9 | ||
|
|
2640c76760 | ||
|
|
4223b2d666 | ||
|
|
dee4786c1c | ||
|
|
e549c79ae4 | ||
|
|
6742df57df | ||
|
|
eef8adf42f | ||
|
|
029c3e75fc | ||
|
|
9fa3a730d5 | ||
|
|
9acaed0b43 | ||
|
|
f95264448c | ||
|
|
e0dc9672ac | ||
|
|
5de7c2a5ea | ||
|
|
9a89665b22 | ||
|
|
4a82d50d80 | ||
|
|
34b3fc3114 | ||
|
|
f09e029a6b | ||
|
|
5e7e20ff7e | ||
|
|
26bfdd45ff | ||
|
|
61defc13c6 | ||
|
|
19496e5759 | ||
|
|
beb60fcacd | ||
|
|
01cc7939ae | ||
|
|
5a5af4ecbf | ||
|
|
d172cf4d19 | ||
|
|
58c4ba2021 | ||
|
|
9e2df8f7c7 | ||
|
|
b897825069 | ||
|
|
f45bc9008a | ||
|
|
5536502c15 | ||
|
|
a0c334a7cb | ||
|
|
9e6bd6d2cc | ||
|
|
ab419efda4 | ||
|
|
d4155411ee | ||
|
|
d721c235cb | ||
|
|
0905cd0fc0 | ||
|
|
188914a16b | ||
|
|
988e2c1fa7 | ||
|
|
4f1901586a | ||
|
|
80b58e86e1 | ||
|
|
ca32e587d3 | ||
|
|
6d2d98f653 | ||
|
|
2d1d8ac2b1 | ||
|
|
a2b8f9a646 | ||
|
|
5bece9c8ef | ||
|
|
45fdd95a9c | ||
|
|
d3afe345ad | ||
|
|
90ca903d2e | ||
|
|
2d8a8f26da | ||
|
|
9ea2410388 | ||
|
|
9e1792c245 | ||
|
|
3eda7def89 | ||
|
|
1787553294 | ||
|
|
f6c48415d1 | ||
|
|
e27d3d0971 | ||
|
|
49617c7a98 | ||
|
|
53a015d8fe | ||
|
|
e711e9f997 | ||
|
|
8530742472 | ||
|
|
c0c1f5113a | ||
|
|
2e6ddd7e35 | ||
|
|
2328e19c9d | ||
|
|
fabc22f218 | ||
|
|
2986e1911d | ||
|
|
a566f7257d | ||
|
|
3dbd1b2731 | ||
|
|
7f23980bf5 | ||
|
|
6fb0684c39 | ||
|
|
dfac9fa5e6 | ||
|
|
bfd9e3026d | ||
|
|
49aad4152c | ||
|
|
94aacf5153 | ||
|
|
efcfdbf36e | ||
|
|
2dbde1833f | ||
|
|
7272eff8b6 | ||
|
|
a84a382f1d | ||
|
|
477e44b9f1 | ||
|
|
512385d225 | ||
|
|
b997e6fd26 | ||
|
|
fab3ebb35a | ||
|
|
1431ff9cfe | ||
|
|
fac2c3e7a3 | ||
|
|
574d1aa36a | ||
|
|
7840167c4a | ||
|
|
9d8e78dae3 | ||
|
|
133a30b8d5 | ||
|
|
ce94c6e62d | ||
|
|
05f251e627 | ||
|
|
0259eaddbb | ||
|
|
cfa3baddf8 | ||
|
|
b1f625a652 | ||
|
|
fd1eb54f25 | ||
|
|
c7550e2d49 | ||
|
|
ba74f4bbb9 | ||
|
|
9e418dafd9 | ||
|
|
95523a1bc7 | ||
|
|
dcd8466127 | ||
|
|
cceae6ad2a | ||
|
|
32f9a5ff32 | ||
|
|
6f95297b80 | ||
|
|
95426d5ccf | ||
|
|
a05b6b1e9d | ||
|
|
d0628344da | ||
|
|
a1bf315b13 | ||
|
|
b3d9123d59 | ||
|
|
817061c6cc | ||
|
|
ea0d5e7564 | ||
|
|
2a89c3bb70 | ||
|
|
a570c72504 | ||
|
|
ab1316dfe1 | ||
|
|
e97448b71b | ||
|
|
6820a06a99 | ||
|
|
4733af849d | ||
|
|
1c2330e33b | ||
|
|
61fef0ecf8 | ||
|
|
d29b8d7ca8 | ||
|
|
2501895b66 | ||
|
|
187a7b5408 | ||
|
|
00be491d02 | ||
|
|
2d74c48e8a | ||
|
|
6dc4d43df5 | ||
|
|
2a4e55d46f | ||
|
|
579c986915 | ||
|
|
380717ae3d | ||
|
|
8f3723f554 | ||
|
|
909cc0f088 | ||
|
|
4eaf204737 | ||
|
|
748bcb083a | ||
|
|
39c007d045 | ||
|
|
d74d327b68 | ||
|
|
be27726721 | ||
|
|
34cc1c0632 | ||
|
|
5694475872 | ||
|
|
2f5709a93e | ||
|
|
2a200cdd42 | ||
|
|
ec39d56731 | ||
|
|
8544fa604d | ||
|
|
0ba63e5dd4 | ||
|
|
441408c593 | ||
|
|
be57960c22 | ||
|
|
f32020068a | ||
|
|
1a8fce48f0 | ||
|
|
85c7b1f501 | ||
|
|
8f660211e3 | ||
|
|
433227323d | ||
|
|
b36e5ea26b | ||
|
|
ce66ff68ce | ||
|
|
d026f0fca5 | ||
|
|
22790aa149 | ||
|
|
7ce6d7aba1 | ||
|
|
e705a0344f | ||
|
|
d6094974c2 | ||
|
|
6187be97e5 | ||
|
|
bb64b43f23 | ||
|
|
ca7458cf1c | ||
|
|
ee2dd76ae1 | ||
|
|
8154cf95f1 | ||
|
|
a7593381e1 | ||
|
|
e68a8ac25f | ||
|
|
96575b982e | ||
|
|
c2d405b2a7 | ||
|
|
6efb3109f2 | ||
|
|
1b1c08afb7 | ||
|
|
d24123a55f | ||
|
|
f2a5df3949 | ||
|
|
ebc5b2987e | ||
|
|
ca97cbd75a | ||
|
|
a787e237ce | ||
|
|
6a1bf90d42 | ||
|
|
60e476da87 | ||
|
|
2cb8558cda | ||
|
|
4d1a037942 | ||
|
|
39b6eac9d0 | ||
|
|
7697af9d2b | ||
|
|
3660715506 | ||
|
|
7bd438877b | ||
|
|
0fbeb39cac | ||
|
|
d02c974af4 | ||
|
|
8ad4970231 | ||
|
|
aee37c5e22 | ||
|
|
73cf32aadd | ||
|
|
1ab69fcf82 | ||
|
|
9b995321bb | ||
|
|
00cac813e3 | ||
|
|
548cf2f081 | ||
|
|
c1f2504e87 | ||
|
|
7e8b0445ad | ||
|
|
63d5422da6 | ||
|
|
035e81a5ca | ||
|
|
9a1edcd4c8 | ||
|
|
2219a17898 | ||
|
|
93c1e5c2bb | ||
|
|
7c2d2b2855 | ||
|
|
b1550e91ab | ||
|
|
0b42836e85 | ||
|
|
7c33ebf6ea | ||
|
|
acec48ed8b | ||
|
|
d309bf2e25 | ||
|
|
496d365a95 | ||
|
|
d952fa562b | ||
|
|
e7561c30e5 | ||
|
|
cdd71155a9 | ||
|
|
a5ccb90b28 | ||
|
|
d76f574ab3 | ||
|
|
bb6c43c767 | ||
|
|
b8f5826a32 | ||
|
|
0d79386ce2 | ||
|
|
871ae179c3 | ||
|
|
f8d62a8ac3 | ||
|
|
badf4b7101 | ||
|
|
fc6902ded2 | ||
|
|
d96994767c | ||
|
|
32e5a59ae0 | ||
|
|
49bb5ec2b9 | ||
|
|
11ff2d1d31 | ||
|
|
c67f494b49 | ||
|
|
299621476f | ||
|
|
7e6168a644 | ||
|
|
e923cbaecc | ||
|
|
6f86c31bac | ||
|
|
51c956f0b3 | ||
|
|
d0693d8c4b | ||
|
|
e298078065 | ||
|
|
85f8eb5166 | ||
|
|
0a112d1a1e | ||
|
|
04ce776f14 | ||
|
|
952c9ec5dc |
@@ -3,9 +3,16 @@ name: Build and Push Wasm Plugin Image
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "wasm-go-*-v*.*.*" # 匹配 wasm-go-{pluginName}-vX.Y.Z 格式的标签
|
||||
- "wasm-*-*-v*.*.*" # 匹配 wasm-{go|rust}-{pluginName}-vX.Y.Z 格式的标签
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
plugin_type:
|
||||
description: 'Type of the plugin'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- go
|
||||
- rust
|
||||
plugin_name:
|
||||
description: 'Name of the plugin'
|
||||
required: true
|
||||
@@ -23,32 +30,42 @@ jobs:
|
||||
env:
|
||||
IMAGE_REGISTRY_SERVICE: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
IMAGE_REPOSITORY: ${{ vars.PLUGIN_IMAGE_REPOSITORY || 'plugins' }}
|
||||
RUST_VERSION: 1.82
|
||||
GO_VERSION: 1.19
|
||||
TINYGO_VERSION: 0.28.1
|
||||
ORAS_VERSION: 1.0.0
|
||||
steps:
|
||||
- name: Set plugin_name and version from inputs or ref_name
|
||||
- name: Set plugin_type, plugin_name and version from inputs or ref_name
|
||||
id: set_vars
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
plugin_type="${{ github.event.inputs.plugin_type }}"
|
||||
plugin_name="${{ github.event.inputs.plugin_name }}"
|
||||
version="${{ github.event.inputs.version }}"
|
||||
else
|
||||
ref_name=${{ github.ref_name }}
|
||||
plugin_type=${ref_name#*-} # 删除插件类型前面的字段(wasm-)
|
||||
plugin_type=${plugin_type%%-*} # 删除插件类型后面的字段(-{plugin_name}-vX.Y.Z)
|
||||
plugin_name=${ref_name#*-*-} # 删除插件名前面的字段(wasm-go-)
|
||||
plugin_name=${plugin_name%-*} # 删除插件名后面的字段(-vX.Y.Z)
|
||||
version=$(echo "$ref_name" | awk -F'v' '{print $2}')
|
||||
fi
|
||||
|
||||
if [[ "$plugin_type" == "rust" ]]; then
|
||||
builder_image="higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-rust-builder:rust${{ env.RUST_VERSION }}-oras${{ env.ORAS_VERSION }}"
|
||||
else
|
||||
builder_image="higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go${{ env.GO_VERSION }}-tinygo${{ env.TINYGO_VERSION }}-oras${{ env.ORAS_VERSION }}"
|
||||
fi
|
||||
echo "PLUGIN_TYPE=$plugin_type" >> $GITHUB_ENV
|
||||
echo "PLUGIN_NAME=$plugin_name" >> $GITHUB_ENV
|
||||
echo "VERSION=$version" >> $GITHUB_ENV
|
||||
echo "BUILDER_IMAGE=$builder_image" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: File Check
|
||||
run: |
|
||||
workspace=${{ github.workspace }}/plugins/wasm-go/extensions/${PLUGIN_NAME}
|
||||
workspace=${{ github.workspace }}/plugins/wasm-${PLUGIN_TYPE}/extensions/${PLUGIN_NAME}
|
||||
push_command="./plugin.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip"
|
||||
|
||||
# 查找spec.yaml
|
||||
@@ -75,10 +92,10 @@ jobs:
|
||||
|
||||
echo "PUSH_COMMAND=\"$push_command\"" >> $GITHUB_ENV
|
||||
|
||||
- name: Run a wasm-go-builder
|
||||
- name: Run a wasm-builder
|
||||
env:
|
||||
PLUGIN_NAME: ${{ env.PLUGIN_NAME }}
|
||||
BUILDER_IMAGE: higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go${{ env.GO_VERSION }}-tinygo${{ env.TINYGO_VERSION }}-oras${{ env.ORAS_VERSION }}
|
||||
BUILDER_IMAGE: ${{ env.BUILDER_IMAGE }}
|
||||
run: |
|
||||
docker run -itd --name builder -v ${{ github.workspace }}:/workspace -e PLUGIN_NAME=${{ env.PLUGIN_NAME }} --rm ${{ env.BUILDER_IMAGE }} /bin/bash
|
||||
|
||||
@@ -93,7 +110,7 @@ jobs:
|
||||
echo "TargetImage=${target_image}"
|
||||
echo "TargetImageLatest=${target_image_latest}"
|
||||
|
||||
cd ${{ github.workspace }}/plugins/wasm-go/extensions/${PLUGIN_NAME}
|
||||
cd ${{ github.workspace }}/plugins/wasm-${PLUGIN_TYPE}/extensions/${PLUGIN_NAME}
|
||||
if [ -f ./.buildrc ]; then
|
||||
echo 'Found .buildrc file, sourcing it...'
|
||||
. ./.buildrc
|
||||
@@ -101,7 +118,7 @@ jobs:
|
||||
echo '.buildrc file not found'
|
||||
fi
|
||||
echo "EXTRA_TAGS=${EXTRA_TAGS}"
|
||||
|
||||
if [ "${PLUGIN_TYPE}" == "go" ]; then
|
||||
command="
|
||||
set -e
|
||||
cd /workspace/plugins/wasm-go/extensions/${PLUGIN_NAME}
|
||||
@@ -112,4 +129,26 @@ jobs:
|
||||
oras push ${target_image} ${push_command}
|
||||
oras push ${target_image_latest} ${push_command}
|
||||
"
|
||||
elif [ "${PLUGIN_TYPE}" == "rust" ]; then
|
||||
command="
|
||||
set -e
|
||||
cd /workspace/plugins/wasm-rust/extensions/${PLUGIN_NAME}
|
||||
if [ -f ./.prebuild ]; then
|
||||
echo 'Found .prebuild file, sourcing it...'
|
||||
. ./.prebuild
|
||||
fi
|
||||
rustup target add wasm32-wasip1
|
||||
cargo build --target wasm32-wasip1 --release
|
||||
cp target/wasm32-wasip1/release/*.wasm plugin.wasm
|
||||
tar czvf plugin.tar.gz plugin.wasm
|
||||
echo ${{ secrets.REGISTRY_PASSWORD }} | oras login -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin ${{ env.IMAGE_REGISTRY_SERVICE }}
|
||||
oras push ${target_image} ${push_command}
|
||||
oras push ${target_image_latest} ${push_command}
|
||||
"
|
||||
else
|
||||
|
||||
command="
|
||||
echo "unkown type ${PLUGIN_TYPE}"
|
||||
"
|
||||
fi
|
||||
docker exec builder bash -c "$command"
|
||||
|
||||
8
.github/workflows/build-and-test-plugin.yaml
vendored
8
.github/workflows/build-and-test-plugin.yaml
vendored
@@ -6,11 +6,15 @@ on:
|
||||
paths:
|
||||
- 'plugins/**'
|
||||
- 'test/**'
|
||||
- 'helm/**'
|
||||
- 'Makefile.core.mk'
|
||||
pull_request:
|
||||
branches: [ "*" ]
|
||||
paths:
|
||||
- 'plugins/**'
|
||||
- 'test/**'
|
||||
- 'helm/**'
|
||||
- 'Makefile.core.mk'
|
||||
workflow_dispatch: ~
|
||||
|
||||
jobs:
|
||||
@@ -20,7 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
# There are too many lint errors in current code bases
|
||||
# uncomment when we decide what lint should be addressed or ignored.
|
||||
# - run: make lint
|
||||
@@ -47,7 +51,7 @@ jobs:
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
||||
8
.github/workflows/build-and-test.yaml
vendored
8
.github/workflows/build-and-test.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
# There are too many lint errors in current code bases
|
||||
# uncomment when we decide what lint should be addressed or ignored.
|
||||
# - run: make lint
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
|
||||
487
.github/workflows/build-image-and-push.yaml
vendored
487
.github/workflows/build-image-and-push.yaml
vendored
@@ -1,229 +1,258 @@
|
||||
name: Build Docker Images and Push to Image Registry
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
workflow_dispatch: ~
|
||||
|
||||
jobs:
|
||||
build-controller-image:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: image-registry-controller
|
||||
env:
|
||||
CONTROLLER_IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
CONTROLLER_IMAGE_NAME: ${{ vars.CONTROLLER_IMAGE_NAME || 'higress/higress' }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }}"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |-
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-go
|
||||
|
||||
- name: Calculate Docker metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.CONTROLLER_IMAGE_REGISTRY }}/${{ env.CONTROLLER_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.CONTROLLER_IMAGE_REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Docker Image and Push
|
||||
run: |
|
||||
GOPROXY="https://proxy.golang.org,direct" make docker-buildx-push
|
||||
BUILT_IMAGE="higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/higress"
|
||||
readarray -t IMAGES <<< "${{ steps.docker-meta.outputs.tags }}"
|
||||
for image in ${IMAGES[@]}; do
|
||||
echo "Image: $image"
|
||||
docker buildx imagetools create $BUILT_IMAGE:$GITHUB_SHA --tag $image
|
||||
done
|
||||
|
||||
build-pilot-image:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: image-registry-pilot
|
||||
env:
|
||||
PILOT_IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
PILOT_IMAGE_NAME: ${{ vars.PILOT_IMAGE_NAME || 'higress/pilot' }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }}"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |-
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-go
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Calculate Docker metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.PILOT_IMAGE_REGISTRY }}/${{ env.PILOT_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.PILOT_IMAGE_REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Pilot-Discovery Image and Push
|
||||
run: |
|
||||
GOPROXY="https://proxy.golang.org,direct" make build-istio
|
||||
BUILT_IMAGE="higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/pilot"
|
||||
readarray -t IMAGES <<< "${{ steps.docker-meta.outputs.tags }}"
|
||||
for image in ${IMAGES[@]}; do
|
||||
echo "Image: $image"
|
||||
docker buildx imagetools create $BUILT_IMAGE:$GITHUB_SHA --tag $image
|
||||
done
|
||||
|
||||
|
||||
build-gateway-image:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: image-registry-pilot
|
||||
env:
|
||||
GATEWAY_IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
GATEWAY_IMAGE_NAME: ${{ vars.GATEWAY_IMAGE_NAME || 'higress/gateway' }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }}"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |-
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-go
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Calculate Docker metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.GATEWAY_IMAGE_REGISTRY }}/${{ env.GATEWAY_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.GATEWAY_IMAGE_REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Gateway Image and Push
|
||||
run: |
|
||||
GOPROXY="https://proxy.golang.org,direct" make build-gateway
|
||||
BUILT_IMAGE="higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/proxyv2"
|
||||
readarray -t IMAGES <<< "${{ steps.docker-meta.outputs.tags }}"
|
||||
for image in ${IMAGES[@]}; do
|
||||
echo "Image: $image"
|
||||
docker buildx imagetools create $BUILT_IMAGE:$GITHUB_SHA --tag $image
|
||||
done
|
||||
name: Build Docker Images and Push to Image Registry
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
workflow_dispatch: ~
|
||||
|
||||
jobs:
|
||||
build-controller-image:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: image-registry-controller
|
||||
env:
|
||||
CONTROLLER_IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
CONTROLLER_IMAGE_NAME: ${{ vars.CONTROLLER_IMAGE_NAME || 'higress/higress' }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }}"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |-
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-go
|
||||
|
||||
- name: Calculate Docker metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.CONTROLLER_IMAGE_REGISTRY }}/${{ env.CONTROLLER_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.CONTROLLER_IMAGE_REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Docker Image and Push
|
||||
run: |
|
||||
BUILT_IMAGE=""
|
||||
readarray -t IMAGES <<< "${{ steps.docker-meta.outputs.tags }}"
|
||||
for image in ${IMAGES[@]}; do
|
||||
echo "Image: $image"
|
||||
if [ "$BUILT_IMAGE" == "" ]; then
|
||||
GOPROXY="https://proxy.golang.org,direct" IMG_URL="$image" make docker-buildx-push
|
||||
BUILT_IMAGE="$image"
|
||||
else
|
||||
docker buildx imagetools create $BUILT_IMAGE --tag $image
|
||||
fi
|
||||
done
|
||||
|
||||
build-pilot-image:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: image-registry-pilot
|
||||
env:
|
||||
PILOT_IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
PILOT_IMAGE_NAME: ${{ vars.PILOT_IMAGE_NAME || 'higress/pilot' }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }}"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |-
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-go
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
image: tonistiigi/binfmt:qemu-v7.0.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Calculate Docker metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.PILOT_IMAGE_REGISTRY }}/${{ env.PILOT_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.PILOT_IMAGE_REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Pilot-Discovery Image and Push
|
||||
run: |
|
||||
BUILT_IMAGE=""
|
||||
readarray -t IMAGES <<< "${{ steps.docker-meta.outputs.tags }}"
|
||||
for image in ${IMAGES[@]}; do
|
||||
echo "Image: $image"
|
||||
if [ "$BUILT_IMAGE" == "" ]; then
|
||||
TAG=${image#*:}
|
||||
HUB=${image%:*}
|
||||
HUB=${HUB%/*}
|
||||
BUILT_IMAGE="$HUB/pilot:$TAG"
|
||||
GOPROXY="https://proxy.golang.org,direct" IMG_URL="$BUILT_IMAGE" make build-istio
|
||||
fi
|
||||
if [ "$BUILT_IMAGE" != "$image" ]; then
|
||||
docker buildx imagetools create $BUILT_IMAGE --tag $image
|
||||
fi
|
||||
done
|
||||
|
||||
build-gateway-image:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: image-registry-gateway
|
||||
env:
|
||||
GATEWAY_IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'higress-registry.cn-hangzhou.cr.aliyuncs.com' }}
|
||||
GATEWAY_IMAGE_NAME: ${{ vars.GATEWAY_IMAGE_NAME || 'higress/gateway' }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }}"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Free Up GitHub Actions Ubuntu Runner Disk Space 🔧
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
|
||||
- name: "Setup Go"
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22
|
||||
|
||||
- name: Setup Golang Caches
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |-
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-go
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
image: tonistiigi/binfmt:qemu-v7.0.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Calculate Docker metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.GATEWAY_IMAGE_REGISTRY }}/${{ env.GATEWAY_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.GATEWAY_IMAGE_REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Build Gateway Image and Push
|
||||
run: |
|
||||
BUILT_IMAGE=""
|
||||
readarray -t IMAGES <<< "${{ steps.docker-meta.outputs.tags }}"
|
||||
for image in ${IMAGES[@]}; do
|
||||
echo "Image: $image"
|
||||
if [ "$BUILT_IMAGE" == "" ]; then
|
||||
TAG=${image#*:}
|
||||
HUB=${image%:*}
|
||||
HUB=${HUB%/*}
|
||||
BUILT_IMAGE="$HUB/proxyv2:$TAG"
|
||||
GOPROXY="https://proxy.golang.org,direct" IMG_URL="$BUILT_IMAGE" make build-gateway
|
||||
fi
|
||||
if [ "$BUILT_IMAGE" != "$image" ]; then
|
||||
docker buildx imagetools create $BUILT_IMAGE --tag $image
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -20,11 +20,11 @@ jobs:
|
||||
name: Prepare Standalone Package
|
||||
run: |
|
||||
mkdir ./artifact
|
||||
cp ./tools/get-higress.sh ./artifact
|
||||
LOCAL_RELEASE_URL="https://github.com/higress-group/higress-standalone/releases"
|
||||
VERSION=$(curl -Ls $LOCAL_RELEASE_URL | grep 'href="/higress-group/higress-standalone/releases/tag/v[0-9]*.[0-9]*.[0-9]*\"' | sed -E 's/.*\/higress-group\/higress-standalone\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1)
|
||||
DOWNLOAD_URL="https://github.com/higress-group/higress-standalone/archive/refs/tags/${VERSION}.tar.gz"
|
||||
curl -SsL "$DOWNLOAD_URL" -o "./artifact/higress-${VERSION}.tar.gz"
|
||||
curl -SsL "https://raw.githubusercontent.com/higress-group/higress-standalone/refs/heads/main/src/get-higress.sh" -o "./artifact/get-higress.sh"
|
||||
echo -n "$VERSION" > ./artifact/VERSION
|
||||
echo "Version=$VERSION"
|
||||
# Step 3
|
||||
|
||||
2
.github/workflows/deploy-to-oss.yaml
vendored
2
.github/workflows/deploy-to-oss.yaml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Download Helm Charts Index
|
||||
uses: doggycool/ossutil-github-action@master
|
||||
with:
|
||||
ossArgs: 'cp -r -u oss://higress-website-cn-hongkong/helm-charts/index.yaml ./artifact/'
|
||||
ossArgs: 'cp oss://higress-website-cn-hongkong/helm-charts/index.yaml ./artifact/'
|
||||
accessKey: ${{ secrets.ACCESS_KEYID }}
|
||||
accessSecret: ${{ secrets.ACCESS_KEYSECRET }}
|
||||
endpoint: oss-cn-hongkong.aliyuncs.com
|
||||
|
||||
126
.github/workflows/helm-docs.yaml
vendored
Normal file
126
.github/workflows/helm-docs.yaml
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
name: "Helm Docs"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
paths:
|
||||
- 'helm/**'
|
||||
workflow_dispatch: ~
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'helm/**'
|
||||
|
||||
jobs:
|
||||
helm:
|
||||
name: Helm Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22.9'
|
||||
|
||||
- name: Run helm-docs
|
||||
run: |
|
||||
GOBIN=$PWD GO111MODULE=on go install github.com/norwoodj/helm-docs/cmd/helm-docs@v1.14.2
|
||||
./helm-docs -c ${GITHUB_WORKSPACE}/helm/higress -f ../core/values.yaml
|
||||
DIFF=$(git diff ${GITHUB_WORKSPACE}/helm/higress/*md)
|
||||
if [ ! -z "$DIFF" ]; then
|
||||
echo "Please use helm-docs in your clone, of your fork, of the project, and commit a updated README.md for the chart."
|
||||
fi
|
||||
git diff --exit-code
|
||||
rm -f ./helm-docs
|
||||
|
||||
translate-readme:
|
||||
needs: helm
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y jq
|
||||
|
||||
- name: Compare README.md
|
||||
id: compare_readme
|
||||
run: |
|
||||
cd ./helm/higress
|
||||
BASE_BRANCH=main
|
||||
UPSTREAM_REPO=https://github.com/alibaba/higress.git
|
||||
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
git clone --depth 1 --branch $BASE_BRANCH $UPSTREAM_REPO $TEMP_DIR
|
||||
|
||||
if diff -q "$TEMP_DIR/README.md" README.md > /dev/null; then
|
||||
echo "README.md has no changes in comparison to base branch. Skipping translation."
|
||||
echo "skip_translation=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "README.md has changed in comparison to base branch. Proceeding with translation."
|
||||
echo "skip_translation=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Translate README.md to Chinese
|
||||
if: env.skip_translation == 'false'
|
||||
env:
|
||||
API_URL: ${{ secrets.HIGRESS_OPENAI_API_URL }}
|
||||
API_KEY: ${{ secrets.HIGRESS_OPENAI_API_KEY }}
|
||||
API_MODEL: ${{ secrets.HIGRESS_OPENAI_API_MODEL }}
|
||||
run: |
|
||||
cd ./helm/higress
|
||||
FILE_CONTENT=$(cat README.md)
|
||||
|
||||
PAYLOAD=$(jq -n \
|
||||
--arg model "$API_MODEL" \
|
||||
--arg content "$FILE_CONTENT" \
|
||||
'{
|
||||
model: $model,
|
||||
messages: [
|
||||
{"role": "system", "content": "You are a translation assistant that translates English Markdown text to Chinese."},
|
||||
{"role": "user", "content": $content}
|
||||
],
|
||||
temperature: 1.1,
|
||||
stream: false
|
||||
}')
|
||||
|
||||
RESPONSE=$(curl -s -X POST "$API_URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-d "$PAYLOAD")
|
||||
|
||||
echo "Response: $RESPONSE"
|
||||
|
||||
echo "$RESPONSE" | jq -c -r '.choices[] | .message.content' > README.zh.new.md
|
||||
|
||||
if [ -f "README.zh.new.md" ]; then
|
||||
echo "Translation completed and saved to README.zh.new.md."
|
||||
else
|
||||
echo "Translation failed or no content returned!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mv README.zh.new.md README.zh.md
|
||||
|
||||
- name: Create Pull Request
|
||||
if: env.skip_translation == 'false'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: "Update helm translated README.zh.md"
|
||||
branch: update-helm-readme-zh
|
||||
title: "Update helm translated README.zh.md"
|
||||
body: |
|
||||
This PR updates the translated README.zh.md file.
|
||||
|
||||
- Automatically generated by GitHub Actions
|
||||
labels: translation, automated
|
||||
base: main
|
||||
24
.github/workflows/release-crd.yaml
vendored
Normal file
24
.github/workflows/release-crd.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Release CRD to GitHub
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
workflow_dispatch: ~
|
||||
|
||||
jobs:
|
||||
release-crd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: generate crds
|
||||
run: |
|
||||
cat helm/core/crds/customresourcedefinitions.gen.yaml helm/core/crds/istio-envoyfilter.yaml > crd.yaml
|
||||
|
||||
- name: Upload hgctl packages to the GitHub release
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
crd.yaml
|
||||
8
.github/workflows/release-hgctl.yaml
vendored
8
.github/workflows/release-hgctl.yaml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Build hgctl latest multiarch binaries
|
||||
run: |
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Build hgctl latest macos binaries
|
||||
run: |
|
||||
@@ -58,14 +58,14 @@ jobs:
|
||||
hgctl_${{ env.HGCTL_VERSION }}_darwin_arm64.tar.gz
|
||||
|
||||
release-hgctl-macos-amd64:
|
||||
runs-on: macos-12
|
||||
runs-on: macos-14
|
||||
env:
|
||||
HGCTL_VERSION: ${{github.ref_name}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21.5
|
||||
go-version: 1.22
|
||||
|
||||
- name: Build hgctl latest macos binaries
|
||||
run: |
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -16,4 +16,4 @@ helm/**/charts/**.tgz
|
||||
target/
|
||||
tools/hack/cluster.conf
|
||||
envoy/1.20
|
||||
istio/1.12
|
||||
istio/1.12
|
||||
|
||||
@@ -12,6 +12,7 @@ header:
|
||||
- 'LICENSE'
|
||||
- 'api/**'
|
||||
- 'samples/**'
|
||||
- 'docs/**'
|
||||
- '.github/**'
|
||||
- '.licenserc.yaml'
|
||||
- 'helm/**'
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
/envoy @gengleilei @johnlanni
|
||||
/istio @SpecialYang @johnlanni
|
||||
/pkg @SpecialYang @johnlanni @CH3CHO
|
||||
/plugins @johnlanni @WeixinX @CH3CHO
|
||||
/plugins/wasm-rust @007gzs
|
||||
/plugins @johnlanni @CH3CHO @rinfx
|
||||
/plugins/wasm-go/extensions/ai-proxy @cr7258 @CH3CHO @rinfx
|
||||
/plugins/wasm-rust @007gzs @jizhuozhi
|
||||
/registry @NameHaibinZhang @2456868764 @johnlanni
|
||||
/test @Xunzhuo @2456868764 @CH3CHO
|
||||
/tools @johnlanni @Xunzhuo @2456868764
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to Higress
|
||||
|
||||
It is warmly welcomed if you have interest to hack on Higress. First, we encourage this kind of willing very much. And here is a list of contributing guide for you.
|
||||
Your interest in contributing to Higress is warmly welcomed. First, we encourage this kind of willing very much. And here is a list of contributing guide for you.
|
||||
|
||||
[[中文贡献文档](./CONTRIBUTING_CN.md)]
|
||||
|
||||
|
||||
195
CONTRIBUTING_JP.md
Normal file
195
CONTRIBUTING_JP.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# Higress への貢献
|
||||
|
||||
Higress のハッキングに興味がある場合は、温かく歓迎します。まず、このような意欲を非常に奨励します。そして、以下は貢献ガイドのリストです。
|
||||
|
||||
[[中文](./CONTRIBUTING.md)] | [[English Contributing Document](./CONTRIBUTING_EN.md)]
|
||||
|
||||
## トピック
|
||||
|
||||
- [Higress への貢献](#higress-への貢献)
|
||||
- [トピック](#トピック)
|
||||
- [セキュリティ問題の報告](#セキュリティ問題の報告)
|
||||
- [一般的な問題の報告](#一般的な問題の報告)
|
||||
- [コードとドキュメントの貢献](#コードとドキュメントの貢献)
|
||||
- [ワークスペースの準備](#ワークスペースの準備)
|
||||
- [ブランチの定義](#ブランチの定義)
|
||||
- [コミットルール](#コミットルール)
|
||||
- [コミットメッセージ](#コミットメッセージ)
|
||||
- [コミット内容](#コミット内容)
|
||||
- [PR 説明](#pr-説明)
|
||||
- [テストケースの貢献](#テストケースの貢献)
|
||||
- [何かを手伝うための参加](#何かを手伝うための参加)
|
||||
- [コードスタイル](#コードスタイル)
|
||||
|
||||
## セキュリティ問題の報告
|
||||
|
||||
セキュリティ問題は常に真剣に扱われます。通常の原則として、セキュリティ問題を広めることは推奨しません。Higress のセキュリティ問題を発見した場合は、公開で議論せず、公開の問題を開かないでください。代わりに、[higress@googlegroups.com](mailto:higress@googlegroups.com) にプライベートなメールを送信して報告することをお勧めします。
|
||||
|
||||
## 一般的な問題の報告
|
||||
|
||||
正直なところ、Higress のすべてのユーザーを非常に親切な貢献者と見なしています。Higress を体験した後、プロジェクトに対するフィードバックがあるかもしれません。その場合は、[NEW ISSUE](https://github.com/alibaba/higress/issues/new/choose) を通じて問題を開くことを自由に行ってください。
|
||||
|
||||
Higress プロジェクトを分散型で協力しているため、**よく書かれた**、**詳細な**、**明確な**問題報告を高く評価します。コミュニケーションをより効率的にするために、問題が検索リストに存在するかどうかを検索することを希望します。存在する場合は、新しい問題を開くのではなく、既存の問題のコメントに詳細を追加してください。
|
||||
|
||||
問題の詳細をできるだけ標準化するために、問題報告者のために [ISSUE TEMPLATE](./.github/ISSUE_TEMPLATE) を設定しました。テンプレートのフィールドに従って指示に従って記入してください。
|
||||
|
||||
問題を開く場合は多くのケースがあります:
|
||||
|
||||
* バグ報告
|
||||
* 機能要求
|
||||
* パフォーマンス問題
|
||||
* 機能提案
|
||||
* 機能設計
|
||||
* 助けが必要
|
||||
* ドキュメントが不完全
|
||||
* テストの改善
|
||||
* プロジェクトに関する質問
|
||||
* その他
|
||||
|
||||
また、新しい問題を記入する際には、投稿から機密データを削除することを忘れないでください。機密データには、パスワード、秘密鍵、ネットワークの場所、プライベートなビジネスデータなどが含まれる可能性があります。
|
||||
|
||||
## コードとドキュメントの貢献
|
||||
|
||||
Higress プロジェクトをより良くするためのすべての行動が奨励されます。GitHub では、Higress のすべての改善は PR(プルリクエストの略)を通じて行うことができます。
|
||||
|
||||
* タイプミスを見つけた場合は、修正してみてください!
|
||||
* バグを見つけた場合は、修正してみてください!
|
||||
* 冗長なコードを見つけた場合は、削除してみてください!
|
||||
* 欠落しているテストケースを見つけた場合は、追加してみてください!
|
||||
* 機能を強化できる場合は、**ためらわないでください**!
|
||||
* コードが不明瞭な場合は、コメントを追加して明確にしてください!
|
||||
* コードが醜い場合は、リファクタリングしてみてください!
|
||||
* ドキュメントの改善に役立つ場合は、さらに良いです!
|
||||
* ドキュメントが不正確な場合は、修正してください!
|
||||
* ...
|
||||
|
||||
実際には、それらを完全にリストすることは不可能です。1つの原則を覚えておいてください:
|
||||
|
||||
> あなたからの PR を楽しみにしています。
|
||||
|
||||
Higress を PR で改善する準備ができたら、ここで PR ルールを確認することをお勧めします。
|
||||
|
||||
* [ワークスペースの準備](#ワークスペースの準備)
|
||||
* [ブランチの定義](#ブランチの定義)
|
||||
* [コミットルール](#コミットルール)
|
||||
* [PR 説明](#pr-説明)
|
||||
|
||||
### ワークスペースの準備
|
||||
|
||||
PR を提出するために、GitHub ID に登録していることを前提とします。その後、以下の手順で準備を完了できます:
|
||||
|
||||
1. Higress を自分のリポジトリに **FORK** します。この作業を行うには、[alibaba/higress](https://github.com/alibaba/higress) のメインページの右上にある Fork ボタンをクリックするだけです。その後、`https://github.com/<your-username>/higress` に自分のリポジトリが作成されます。ここで、`your-username` はあなたの GitHub ユーザー名です。
|
||||
|
||||
2. 自分のリポジトリをローカルに **CLONE** します。`git clone git@github.com:<your-username>/higress.git` を使用してリポジトリをローカルマシンにクローンします。その後、新しいブランチを作成して、行いたい変更を完了できます。
|
||||
|
||||
3. リモートを `git@github.com:alibaba/higress.git` に設定します。以下の2つのコマンドを使用します:
|
||||
|
||||
```bash
|
||||
git remote add upstream git@github.com:alibaba/higress.git
|
||||
git remote set-url --push upstream no-pushing
|
||||
```
|
||||
|
||||
このリモート設定を使用すると、git リモート設定を次のように確認できます:
|
||||
|
||||
```shell
|
||||
$ git remote -v
|
||||
origin git@github.com:<your-username>/higress.git (fetch)
|
||||
origin git@github.com:<your-username>/higress.git (push)
|
||||
upstream git@github.com:alibaba/higress.git (fetch)
|
||||
upstream no-pushing (push)
|
||||
```
|
||||
|
||||
これを追加すると、ローカルブランチを上流ブランチと簡単に同期できます。
|
||||
|
||||
### ブランチの定義
|
||||
|
||||
現在、プルリクエストを通じたすべての貢献は Higress の [main ブランチ](https://github.com/alibaba/higress/tree/main) に対するものであると仮定します。貢献する前に、ブランチの定義を理解することは非常に役立ちます。
|
||||
|
||||
貢献者として、プルリクエストを通じたすべての貢献は main ブランチに対するものであることを再度覚えておいてください。Higress プロジェクトには、リリースブランチ(例:0.6.0、0.6.1)、機能ブランチ、ホットフィックスブランチなど、いくつかの他のブランチがあります。
|
||||
|
||||
正式にバージョンをリリースする際には、リリースブランチが作成され、バージョン番号で命名されます。
|
||||
|
||||
リリース後、リリースブランチのコミットを main ブランチにマージします。
|
||||
|
||||
特定のバージョンにバグがある場合、後のバージョンで修正するか、特定のホットフィックスバージョンで修正するかを決定します。ホットフィックスバージョンで修正することを決定した場合、対応するリリースブランチに基づいてホットフィックスブランチをチェックアウトし、コード修正と検証を行い、main ブランチにマージします。
|
||||
|
||||
大きな機能については、開発と検証のために機能ブランチを引き出します。
|
||||
|
||||
### コミットルール
|
||||
|
||||
実際には、Higress ではコミット時に2つのルールを真剣に考えています:
|
||||
|
||||
* [コミットメッセージ](#コミットメッセージ)
|
||||
* [コミット内容](#コミット内容)
|
||||
|
||||
#### コミットメッセージ
|
||||
|
||||
コミットメッセージは、提出された PR の目的をレビュアーがよりよく理解するのに役立ちます。また、コードレビューの手続きを加速するのにも役立ちます。貢献者には、曖昧なメッセージではなく、**明確な**コミットメッセージを使用することを奨励します。一般的に、以下のコミットメッセージタイプを推奨します:
|
||||
|
||||
* docs: xxxx. 例:"docs: add docs about Higress cluster installation".
|
||||
* feature: xxxx. 例:"feature: use higress config instead of istio config".
|
||||
* bugfix: xxxx. 例:"bugfix: fix panic when input nil parameter".
|
||||
* refactor: xxxx. 例:"refactor: simplify to make codes more readable".
|
||||
* test: xxx. 例:"test: add unit test case for func InsertIntoArray".
|
||||
* その他の読みやすく明確な表現方法。
|
||||
|
||||
一方で、以下のような方法でのコミットメッセージは推奨しません:
|
||||
|
||||
* ~~バグ修正~~
|
||||
* ~~更新~~
|
||||
* ~~ドキュメント追加~~
|
||||
|
||||
迷った場合は、[Git コミットメッセージの書き方](http://chris.beams.io/posts/git-commit/) を参照してください。
|
||||
|
||||
#### コミット内容
|
||||
|
||||
コミット内容は、1つのコミットに含まれるすべての内容の変更を表します。1つのコミットに、他のコミットの助けを借りずにレビュアーが完全にレビューできる内容を含めるのが最善です。言い換えれば、1つのコミットの内容は CI を通過でき、コードの混乱を避けることができます。簡単に言えば、次の3つの小さなルールを覚えておく必要があります:
|
||||
|
||||
* コミットで非常に大きな変更を避ける;
|
||||
* 各コミットが完全でレビュー可能であること。
|
||||
* コミット時に git config(`user.name`、`user.email`)を確認して、それが GitHub ID に関連付けられていることを確認します。
|
||||
|
||||
```bash
|
||||
git config --get user.name
|
||||
git config --get user.email
|
||||
```
|
||||
|
||||
* pr を提出する際には、'changes/' フォルダーの下の XXX.md ファイルに現在の変更の簡単な説明を追加してください。
|
||||
|
||||
さらに、コード変更部分では、すべての貢献者が Higress の [コードスタイル](#コードスタイル) を読むことをお勧めします。
|
||||
|
||||
コミットメッセージやコミット内容に関係なく、コードレビューに重点を置いています。
|
||||
|
||||
### PR 説明
|
||||
|
||||
PR は Higress プロジェクトファイルを変更する唯一の方法です。レビュアーが目的をよりよく理解できるようにするために、PR 説明は詳細すぎることはありません。貢献者には、[PR テンプレート](./.github/PULL_REQUEST_TEMPLATE.md) に従ってプルリクエストを完了することを奨励します。
|
||||
|
||||
### 開発前の準備
|
||||
|
||||
```shell
|
||||
make prebuild && go mod tidy
|
||||
```
|
||||
|
||||
## テストケースの貢献
|
||||
|
||||
テストケースは歓迎されます。現在、Higress の機能テストケースが高優先度です。
|
||||
|
||||
* 単体テストの場合、同じモジュールの test ディレクトリに xxxTest.go という名前のテストファイルを作成する必要があります。
|
||||
* 統合テストの場合、統合テストを test ディレクトリに配置できます。
|
||||
//TBD
|
||||
|
||||
## 何かを手伝うための参加
|
||||
|
||||
GitHub を Higress の協力の主要な場所として選択しました。したがって、Higress の最新の更新は常にここにあります。PR を通じた貢献は明確な助けの方法ですが、他の方法も呼びかけています。
|
||||
|
||||
* 可能であれば、他の人の質問に返信する;
|
||||
* 他のユーザーの問題を解決するのを手伝う;
|
||||
* 他の人の PR 設計をレビューするのを手伝う;
|
||||
* 他の人の PR のコードをレビューするのを手伝う;
|
||||
* Higress について議論して、物事を明確にする;
|
||||
* GitHub 以外で Higress 技術を宣伝する;
|
||||
* Higress に関するブログを書くなど。
|
||||
|
||||
## コードスタイル
|
||||
//TBD
|
||||
要するに、**どんな助けも貢献です。**
|
||||
@@ -72,17 +72,17 @@ go.test.coverage: prebuild
|
||||
|
||||
.PHONY: build
|
||||
build: prebuild $(OUT)
|
||||
GOPROXY=$(GOPROXY) GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT)/ $(HIGRESS_BINARIES)
|
||||
GOPROXY="$(GOPROXY)" GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT)/ $(HIGRESS_BINARIES)
|
||||
|
||||
.PHONY: build-linux
|
||||
build-linux: prebuild $(OUT)
|
||||
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ $(HIGRESS_BINARIES)
|
||||
GOPROXY="$(GOPROXY)" GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ $(HIGRESS_BINARIES)
|
||||
|
||||
$(AMD64_OUT_LINUX)/higress:
|
||||
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=amd64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/linux_amd64/ $(HIGRESS_BINARIES)
|
||||
GOPROXY="$(GOPROXY)" GOOS=linux GOARCH=amd64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/linux_amd64/ $(HIGRESS_BINARIES)
|
||||
|
||||
$(ARM64_OUT_LINUX)/higress:
|
||||
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=arm64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/linux_arm64/ $(HIGRESS_BINARIES)
|
||||
GOPROXY="$(GOPROXY)" GOOS=linux GOARCH=arm64 LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh ./out/linux_arm64/ $(HIGRESS_BINARIES)
|
||||
|
||||
.PHONY: build-hgctl
|
||||
build-hgctl: prebuild $(OUT)
|
||||
@@ -144,7 +144,7 @@ docker-buildx-push: clean-env docker.higress-buildx
|
||||
export PARENT_GIT_TAG:=$(shell cat VERSION)
|
||||
export PARENT_GIT_REVISION:=$(TAG)
|
||||
|
||||
export ENVOY_PACKAGE_URL_PATTERN?=https://github.com/higress-group/proxy/releases/download/v2.0.0/envoy-symbol-ARCH.tar.gz
|
||||
export ENVOY_PACKAGE_URL_PATTERN?=https://github.com/higress-group/proxy/releases/download/v2.1.5/envoy-symbol-ARCH.tar.gz
|
||||
|
||||
build-envoy: prebuild
|
||||
./tools/hack/build-envoy.sh
|
||||
@@ -159,16 +159,20 @@ build-pilot-local: prebuild
|
||||
buildx-prepare:
|
||||
docker buildx inspect multi-arch >/dev/null 2>&1 || docker buildx create --name multi-arch --platform linux/amd64,linux/arm64 --use
|
||||
|
||||
build-gateway: prebuild buildx-prepare
|
||||
build-gateway: prebuild buildx-prepare build-golang-filter
|
||||
USE_REAL_USER=1 TARGET_ARCH=amd64 DOCKER_TARGETS="docker.proxyv2" ./tools/hack/build-istio-image.sh init
|
||||
USE_REAL_USER=1 TARGET_ARCH=arm64 DOCKER_TARGETS="docker.proxyv2" ./tools/hack/build-istio-image.sh init
|
||||
DOCKER_TARGETS="docker.proxyv2" ./tools/hack/build-istio-image.sh docker.buildx
|
||||
DOCKER_TARGETS="docker.proxyv2" IMG_URL="${IMG_URL}" ./tools/hack/build-istio-image.sh docker.buildx
|
||||
|
||||
build-gateway-local: prebuild
|
||||
build-gateway-local: prebuild build-golang-filter
|
||||
TARGET_ARCH=${TARGET_ARCH} DOCKER_TARGETS="docker.proxyv2" ./tools/hack/build-istio-image.sh docker
|
||||
|
||||
build-golang-filter:
|
||||
TARGET_ARCH=amd64 ./tools/hack/build-golang-filters.sh
|
||||
TARGET_ARCH=arm64 ./tools/hack/build-golang-filters.sh
|
||||
|
||||
build-istio: prebuild buildx-prepare
|
||||
DOCKER_TARGETS="docker.pilot" ./tools/hack/build-istio-image.sh docker.buildx
|
||||
DOCKER_TARGETS="docker.pilot" IMG_URL="${IMG_URL}" ./tools/hack/build-istio-image.sh docker.buildx
|
||||
|
||||
build-istio-local: prebuild
|
||||
TARGET_ARCH=${TARGET_ARCH} DOCKER_TARGETS="docker.pilot" ./tools/hack/build-istio-image.sh docker
|
||||
@@ -187,8 +191,8 @@ install: pre-install
|
||||
cd helm/higress; helm dependency build
|
||||
helm install higress helm/higress -n higress-system --create-namespace --set 'global.local=true'
|
||||
|
||||
ENVOY_LATEST_IMAGE_TAG ?= 2.0.1
|
||||
ISTIO_LATEST_IMAGE_TAG ?= 2.0.1
|
||||
ENVOY_LATEST_IMAGE_TAG ?= 958467a353d411ae3f06e03b096bfd342cddb2c6
|
||||
ISTIO_LATEST_IMAGE_TAG ?= d9c728d3b01f64855e012b08d136e306f1160397
|
||||
|
||||
install-dev: pre-install
|
||||
helm install higress helm/core -n higress-system --create-namespace --set 'controller.tag=$(TAG)' --set 'gateway.replicas=1' --set 'pilot.tag=$(ISTIO_LATEST_IMAGE_TAG)' --set 'gateway.tag=$(ENVOY_LATEST_IMAGE_TAG)' --set 'global.local=true'
|
||||
@@ -221,12 +225,17 @@ clean-higress: ## Cleans all the intermediate files and folders previously gener
|
||||
rm -rf $(DIRS_TO_CLEAN)
|
||||
|
||||
clean-istio:
|
||||
rm -rf external/api
|
||||
rm -rf external/client-go
|
||||
rm -rf external/istio
|
||||
rm -rf external/pkg
|
||||
|
||||
clean-gateway: clean-istio
|
||||
rm -rf external/envoy
|
||||
rm -rf external/proxy
|
||||
rm -rf external/go-control-plane
|
||||
rm -rf external/package/envoy.tar.gz
|
||||
rm -rf external/package/*.so
|
||||
|
||||
clean-env:
|
||||
rm -rf out/
|
||||
@@ -284,6 +293,8 @@ delete-cluster: $(tools/kind) ## Delete kind cluster.
|
||||
.PHONY: kube-load-image
|
||||
kube-load-image: $(tools/kind) ## Install the Higress image to a kind cluster using the provided $IMAGE and $TAG.
|
||||
tools/hack/kind-load-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/higress $(TAG)
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/pilot $(ISTIO_LATEST_IMAGE_TAG)
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/gateway $(ENVOY_LATEST_IMAGE_TAG)
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/dubbo-provider-demo 0.0.3-x86
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/nacos-standlone-rc3 1.0.0-RC3
|
||||
tools/hack/docker-pull-image.sh docker.io/hashicorp/consul 1.16.0
|
||||
@@ -293,7 +304,8 @@ kube-load-image: $(tools/kind) ## Install the Higress image to a kind cluster us
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/echo-server 1.3.0
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/echo-server v1.0
|
||||
tools/hack/docker-pull-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/echo-body 1.0.0
|
||||
tools/hack/docker-pull-image.sh openpolicyagent/opa latest
|
||||
tools/hack/docker-pull-image.sh openpolicyagent/opa 0.61.0
|
||||
tools/hack/docker-pull-image.sh curlimages/curl latest
|
||||
tools/hack/docker-pull-image.sh registry.cn-hangzhou.aliyuncs.com/2456868764/httpbin 1.0.2
|
||||
tools/hack/docker-pull-image.sh registry.cn-hangzhou.aliyuncs.com/hinsteny/nacos-standlone-rc3 1.0.0-RC3
|
||||
tools/hack/kind-load-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/dubbo-provider-demo 0.0.3-x86
|
||||
@@ -305,7 +317,8 @@ kube-load-image: $(tools/kind) ## Install the Higress image to a kind cluster us
|
||||
tools/hack/kind-load-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/echo-server 1.3.0
|
||||
tools/hack/kind-load-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/echo-server v1.0
|
||||
tools/hack/kind-load-image.sh higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/echo-body 1.0.0
|
||||
tools/hack/kind-load-image.sh openpolicyagent/opa latest
|
||||
tools/hack/kind-load-image.sh openpolicyagent/opa 0.61.0
|
||||
tools/hack/kind-load-image.sh curlimages/curl latest
|
||||
tools/hack/kind-load-image.sh registry.cn-hangzhou.aliyuncs.com/2456868764/httpbin 1.0.2
|
||||
tools/hack/kind-load-image.sh registry.cn-hangzhou.aliyuncs.com/hinsteny/nacos-standlone-rc3 1.0.0-RC3
|
||||
|
||||
|
||||
201
README.md
201
README.md
@@ -1,3 +1,4 @@
|
||||
<a name="readme-top"></a>
|
||||
<h1 align="center">
|
||||
<img src="https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!!6000000006895-2-tps-960-290.png" alt="Higress" width="240" height="72.5">
|
||||
<br>
|
||||
@@ -5,175 +6,163 @@
|
||||
</h1>
|
||||
<h4 align="center"> AI Native API Gateway </h4>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/alibaba/higress/actions)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
[**官网**](https://higress.cn/) |
|
||||
[**文档**](https://higress.cn/docs/latest/user/quickstart/) |
|
||||
[**博客**](https://higress.cn/blog/) |
|
||||
[**电子书**](https://higress.cn/docs/ebook/wasm14/) |
|
||||
[**开发指引**](https://higress.cn/docs/latest/dev/architecture/) |
|
||||
[**AI插件**](https://higress.cn/plugin/)
|
||||
<a href="https://trendshift.io/repositories/10918" target="_blank"><img src="https://trendshift.io/api/badge/repositories/10918" alt="alibaba%2Fhigress | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a> <a href="https://www.producthunt.com/posts/higress?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-higress" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=951287&theme=light&t=1745492822283" alt="Higress - Global APIs as MCP powered by AI Gateway | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
|
||||
</div>
|
||||
|
||||
[**Official Site**](https://higress.ai/en/) |
|
||||
[**MCP Server QuickStart**](https://higress.cn/en/ai/mcp-quick-start/) |
|
||||
[**Wasm Plugin Hub**](https://higress.cn/en/plugin/) |
|
||||
|
||||
<p>
|
||||
<a href="README_EN.md"> English <a/> | 中文
|
||||
English | <a href="README_ZH.md">中文<a/> | <a href="README_JP.md">日本語<a/>
|
||||
</p>
|
||||
|
||||
## What is Higress?
|
||||
|
||||
Higress 是基于阿里内部多年的 Envoy Gateway 实践沉淀,以开源 [Istio](https://github.com/istio/istio) 与 [Envoy](https://github.com/envoyproxy/envoy) 为核心构建的云原生 API 网关。
|
||||
Higress is a cloud-native API gateway based on Istio and Envoy, which can be extended with Wasm plugins written in Go/Rust/JS. It provides dozens of ready-to-use general-purpose plugins and an out-of-the-box console (try the [demo here](http://demo.higress.io/)).
|
||||
|
||||
Higress 在阿里内部作为 AI 网关,承载了通义千问 APP、百炼大模型 API、机器学习 PAI 平台等 AI 业务的流量。
|
||||
### Core Use Cases
|
||||
|
||||
Higress 能够用统一的协议对接国内外所有 LLM 模型厂商,同时具备丰富的 AI 可观测、多模型负载均衡/fallback、AI token 流控、AI 缓存等能力:
|
||||
Higress's AI gateway capabilities support all [mainstream model providers](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/ai-proxy/provider) both domestic and international. It also supports hosting MCP (Model Context Protocol) Servers through its plugin mechanism, enabling AI Agents to easily call various tools and services. With the [openapi-to-mcp tool](https://github.com/higress-group/openapi-to-mcpserver), you can quickly convert OpenAPI specifications into remote MCP servers for hosting. Higress provides unified management for both LLM API and MCP API.
|
||||
|
||||

|
||||
**🌟 Try it now at [https://mcp.higress.ai/](https://mcp.higress.ai/)** to experience Higress-hosted Remote MCP Servers firsthand:
|
||||
|
||||

|
||||
|
||||
### Enterprise Adoption
|
||||
|
||||
Higress was born within Alibaba to solve the issues of Tengine reload affecting long-connection services and insufficient load balancing capabilities for gRPC/Dubbo. Within Alibaba Cloud, Higress's AI gateway capabilities support core AI applications such as Tongyi Bailian model studio, machine learning PAI platform, and other critical AI services. Alibaba Cloud has built its cloud-native API gateway product based on Higress, providing 99.99% gateway high availability guarantee service capabilities for a large number of enterprise customers.
|
||||
|
||||
## Summary
|
||||
|
||||
- [**快速开始**](#快速开始)
|
||||
- [**功能展示**](#功能展示)
|
||||
- [**使用场景**](#使用场景)
|
||||
- [**核心优势**](#核心优势)
|
||||
- [**社区**](#社区)
|
||||
- [**Quick Start**](#quick-start)
|
||||
- [**Feature Showcase**](#feature-showcase)
|
||||
- [**Use Cases**](#use-cases)
|
||||
- [**Core Advantages**](#core-advantages)
|
||||
- [**Community**](#community)
|
||||
|
||||
## 快速开始
|
||||
## Quick Start
|
||||
|
||||
Higress 只需 Docker 即可启动,方便个人开发者在本地搭建学习,或者用于搭建简易站点:
|
||||
Higress can be started with just Docker, making it convenient for individual developers to set up locally for learning or for building simple sites:
|
||||
|
||||
```bash
|
||||
# 创建一个工作目录
|
||||
# Create a working directory
|
||||
mkdir higress; cd higress
|
||||
# 启动 higress,配置文件会写到工作目录下
|
||||
# Start higress, configuration files will be written to the working directory
|
||||
docker run -d --rm --name higress-ai -v ${PWD}:/data \
|
||||
-p 8001:8001 -p 8080:8080 -p 8443:8443 \
|
||||
higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/all-in-one:latest
|
||||
```
|
||||
|
||||
监听端口说明如下:
|
||||
Port descriptions:
|
||||
|
||||
- 8001 端口:Higress UI 控制台入口
|
||||
- 8080 端口:网关 HTTP 协议入口
|
||||
- 8443 端口:网关 HTTPS 协议入口
|
||||
- Port 8001: Higress UI console entry
|
||||
- Port 8080: Gateway HTTP protocol entry
|
||||
- Port 8443: Gateway HTTPS protocol entry
|
||||
|
||||
**Higress 的所有 Docker 镜像都一直使用自己独享的仓库,不受 Docker Hub 境内不可访问的影响**
|
||||
> All Higress Docker images use Higress's own image repository and are not affected by Docker Hub rate limits.
|
||||
> In addition, the submission and updates of the images are protected by a security scanning mechanism (powered by Alibaba Cloud ACR), making them very secure for use in production environments.
|
||||
|
||||
K8s 下使用 Helm 部署等其他安装方式可以参考官网 [Quick Start 文档](https://higress.cn/docs/latest/user/quickstart/)。
|
||||
For other installation methods such as Helm deployment under K8s, please refer to the official [Quick Start documentation](https://higress.io/en-us/docs/user/quickstart).
|
||||
|
||||
## Use Cases
|
||||
|
||||
## 使用场景
|
||||
- **MCP Server Hosting**:
|
||||
|
||||
- **AI 网关**:
|
||||
Higress hosts MCP Servers through its plugin mechanism, enabling AI Agents to easily call various tools and services. With the [openapi-to-mcp tool](https://github.com/higress-group/openapi-to-mcpserver), you can quickly convert OpenAPI specifications into remote MCP servers.
|
||||
|
||||
Higress 提供了一站式的 AI 插件集,可以增强依赖 AI 能力业务的稳定性、灵活性、可观测性,使得业务与 AI 的集成更加便捷和高效。
|
||||

|
||||
|
||||
- **Kubernetes Ingress 网关**:
|
||||
Key benefits of hosting MCP Servers with Higress:
|
||||
- Unified authentication and authorization mechanisms
|
||||
- Fine-grained rate limiting to prevent abuse
|
||||
- Comprehensive audit logs for all tool calls
|
||||
- Rich observability for monitoring performance
|
||||
- Simplified deployment through Higress's plugin mechanism
|
||||
- Dynamic updates without disruption or connection drops
|
||||
|
||||
Higress 可以作为 K8s 集群的 Ingress 入口网关, 并且兼容了大量 K8s Nginx Ingress 的注解,可以从 K8s Nginx Ingress 快速平滑迁移到 Higress。
|
||||
[Learn more...](https://higress.cn/en/ai/mcp-quick-start/?spm=36971b57.7beea2de.0.0.d85f20a94jsWGm)
|
||||
|
||||
- **AI Gateway**:
|
||||
|
||||
Higress connects to all LLM model providers using a unified protocol, with AI observability, multi-model load balancing, token rate limiting, and caching capabilities:
|
||||
|
||||

|
||||
|
||||
- **Kubernetes ingress controller**:
|
||||
|
||||
Higress can function as a feature-rich ingress controller, which is compatible with many annotations of K8s' nginx ingress controller.
|
||||
|
||||
支持 [Gateway API](https://gateway-api.sigs.k8s.io/) 标准,支持用户从 Ingress API 平滑迁移到 Gateway API。
|
||||
[Gateway API](https://gateway-api.sigs.k8s.io/) support is coming soon and will support smooth migration from Ingress API to Gateway API.
|
||||
|
||||
- **微服务网关**:
|
||||
- **Microservice gateway**:
|
||||
|
||||
Higress 可以作为微服务网关, 能够对接多种类型的注册中心发现服务配置路由,例如 Nacos, ZooKeeper, Consul, Eureka 等。
|
||||
Higress can function as a microservice gateway, which can discovery microservices from various service registries, such as Nacos, ZooKeeper, Consul, Eureka, etc.
|
||||
|
||||
并且深度集成了 [Dubbo](https://github.com/apache/dubbo), [Nacos](https://github.com/alibaba/nacos), [Sentinel](https://github.com/alibaba/Sentinel) 等微服务技术栈,基于 Envoy C++ 网关内核的出色性能,相比传统 Java 类微服务网关,可以显著降低资源使用率,减少成本。
|
||||
It deeply integrates with [Dubbo](https://github.com/apache/dubbo), [Nacos](https://github.com/alibaba/nacos), [Sentinel](https://github.com/alibaba/Sentinel) and other microservice technology stacks.
|
||||
|
||||
- **安全防护网关**:
|
||||
- **Security gateway**:
|
||||
|
||||
Higress 可以作为安全防护网关, 提供 WAF 的能力,并且支持多种认证鉴权策略,例如 key-auth, hmac-auth, jwt-auth, basic-auth, oidc 等。
|
||||
Higress can be used as a security gateway, supporting WAF and various authentication strategies, such as key-auth, hmac-auth, jwt-auth, basic-auth, oidc, etc.
|
||||
|
||||
## 核心优势
|
||||
|
||||
- **生产等级**
|
||||
## Core Advantages
|
||||
|
||||
脱胎于阿里巴巴2年多生产验证的内部产品,支持每秒请求量达数十万级的大规模场景。
|
||||
- **Production Grade**
|
||||
|
||||
彻底摆脱 Nginx reload 引起的流量抖动,配置变更毫秒级生效且业务无感。对 AI 业务等长连接场景特别友好。
|
||||
Born from Alibaba's internal product with over 2 years of production validation, supporting large-scale scenarios with hundreds of thousands of requests per second.
|
||||
|
||||
- **流式处理**
|
||||
Completely eliminates traffic jitter caused by Nginx reload, configuration changes take effect in milliseconds and are transparent to business. Especially friendly to long-connection scenarios such as AI businesses.
|
||||
|
||||
支持真正的完全流式处理请求/响应 Body,Wasm 插件很方便地自定义处理 SSE (Server-Sent Events)等流式协议的报文。
|
||||
- **Streaming Processing**
|
||||
|
||||
在 AI 业务等大带宽场景下,可以显著降低内存开销。
|
||||
Supports true complete streaming processing of request/response bodies, Wasm plugins can easily customize the handling of streaming protocols such as SSE (Server-Sent Events).
|
||||
|
||||
In high-bandwidth scenarios such as AI businesses, it can significantly reduce memory overhead.
|
||||
|
||||
- **便于扩展**
|
||||
- **Easy to Extend**
|
||||
|
||||
提供丰富的官方插件库,涵盖 AI、流量管理、安全防护等常用功能,满足90%以上的业务场景需求。
|
||||
Provides a rich official plugin library covering AI, traffic management, security protection and other common functions, meeting more than 90% of business scenario requirements.
|
||||
|
||||
主打 Wasm 插件扩展,通过沙箱隔离确保内存安全,支持多种编程语言,允许插件版本独立升级,实现流量无损热更新网关逻辑。
|
||||
Focuses on Wasm plugin extensions, ensuring memory safety through sandbox isolation, supporting multiple programming languages, allowing plugin versions to be upgraded independently, and achieving traffic-lossless hot updates of gateway logic.
|
||||
|
||||
- **安全易用**
|
||||
- **Secure and Easy to Use**
|
||||
|
||||
基于 Ingress API 和 Gateway API 标准,提供开箱即用的 UI 控制台,WAF 防护插件、IP/Cookie CC 防护插件开箱即用。
|
||||
Based on Ingress API and Gateway API standards, provides out-of-the-box UI console, WAF protection plugin, IP/Cookie CC protection plugin ready to use.
|
||||
|
||||
支持对接 Let's Encrypt 自动签发和续签免费证书,并且可以脱离 K8s 部署,一行 Docker 命令即可启动,方便个人开发者使用。
|
||||
Supports connecting to Let's Encrypt for automatic issuance and renewal of free certificates, and can be deployed outside of K8s, started with a single Docker command, convenient for individual developers to use.
|
||||
|
||||
## Community
|
||||
|
||||
## 功能展示
|
||||
[Slack](https://w1689142780-euk177225.slack.com/archives/C05GEL4TGTG): to get invited go [here](https://communityinviter.com/apps/w1689142780-euk177225/higress).
|
||||
|
||||
### AI 网关 Demo 展示
|
||||
### Thanks
|
||||
|
||||
[从 OpenAI 到其他大模型,30 秒完成迁移
|
||||
](https://www.bilibili.com/video/BV1dT421a7w7/?spm_id_from=333.788.recommend_more_video.14)
|
||||
Higress would not be possible without the valuable open-source work of projects in the community. We would like to extend a special thank you to Envoy and Istio.
|
||||
|
||||
### Related Repositories
|
||||
|
||||
### Higress UI 控制台
|
||||
|
||||
- **丰富的可观测**
|
||||
- Higress Console: https://github.com/higress-group/higress-console
|
||||
- Higress Standalone: https://github.com/higress-group/higress-standalone
|
||||
|
||||
提供开箱即用的可观测,Grafana&Prometheus 可以使用内置的也可对接自建的
|
||||
### Contributors
|
||||
|
||||

|
||||
|
||||
<a href="https://github.com/alibaba/higress/graphs/contributors">
|
||||
<img alt="contributors" src="https://contrib.rocks/image?repo=alibaba/higress"/>
|
||||
</a>
|
||||
|
||||
- **插件扩展机制**
|
||||
### Star History
|
||||
|
||||
官方提供了多种插件,用户也可以[开发](./plugins/wasm-go)自己的插件,构建成 docker/oci 镜像后在控制台配置,可以实时变更插件逻辑,对流量完全无损。
|
||||
[](https://star-history.com/#alibaba/higress&Date)
|
||||
|
||||

|
||||
|
||||
|
||||
- **多种服务发现**
|
||||
|
||||
默认提供 K8s Service 服务发现,通过配置可以对接 Nacos/ZooKeeper 等注册中心实现服务发现,也可以基于静态 IP 或者 DNS 来发现
|
||||
|
||||

|
||||
|
||||
|
||||
- **域名和证书**
|
||||
|
||||
可以创建管理 TLS 证书,并配置域名的 HTTP/HTTPS 行为,域名策略里支持对特定域名生效插件
|
||||
|
||||

|
||||
|
||||
|
||||
- **丰富的路由能力**
|
||||
|
||||
通过上面定义的服务发现机制,发现的服务会出现在服务列表中;创建路由时,选择域名,定义路由匹配机制,再选择目标服务进行路由;路由策略里支持对特定路由生效插件
|
||||
|
||||

|
||||
|
||||
|
||||
## 社区
|
||||
|
||||
### 感谢
|
||||
|
||||
如果没有 Envoy 和 Istio 的开源工作,Higress 就不可能实现,在这里向这两个项目献上最诚挚的敬意。
|
||||
|
||||
### 交流群
|
||||
|
||||

|
||||
|
||||
### 技术分享
|
||||
|
||||
微信公众号:
|
||||
|
||||

|
||||
|
||||
### 关联仓库
|
||||
|
||||
- Higress 控制台:https://github.com/higress-group/higress-console
|
||||
- Higress(独立运行版):https://github.com/higress-group/higress-standalone
|
||||
<p align="right" style="font-size: 14px; color: #555; margin-top: 20px;">
|
||||
<a href="#readme-top" style="text-decoration: none; color: #007bff; font-weight: bold;">
|
||||
↑ Back to Top ↑
|
||||
</a>
|
||||
</p>
|
||||
|
||||
89
README_EN.md
89
README_EN.md
@@ -1,89 +0,0 @@
|
||||
<h1 align="center">
|
||||
<img src="https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!!6000000006895-2-tps-960-290.png" alt="Higress" width="240" height="72.5">
|
||||
<br>
|
||||
Cloud Native API Gateway
|
||||
</h1>
|
||||
|
||||
[](https://github.com/alibaba/higress/actions)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
[**Official Site**](https://higress.io/en-us/) |
|
||||
[**Docs**](https://higress.io/en-us/docs/overview/what-is-higress) |
|
||||
[**Blog**](https://higress.io/en-us/blog) |
|
||||
[**Developer**](https://higress.io/en-us/docs/developers/developers_dev) |
|
||||
[**Higress in Cloud**](https://www.alibabacloud.com/product/microservices-engine?spm=higress-website.topbar.0.0.0)
|
||||
|
||||
|
||||
<p>
|
||||
English | <a href="README.md">中文<a/>
|
||||
</p>
|
||||
|
||||
Higress is a cloud-native api gateway based on Alibaba's internal gateway practices.
|
||||
|
||||
Powered by [Istio](https://github.com/istio/istio) and [Envoy](https://github.com/envoyproxy/envoy), Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway and security gateway, thereby greatly reducing the costs of deployment, operation and maintenance.
|
||||
|
||||
<h1 align="center">
|
||||
<img src="https://img.alicdn.com/imgextra/i1/O1CN01iO9ph825juHbOIg75_!!6000000007563-2-tps-2483-2024.png" alt="Higress Architecture">
|
||||
</h1>
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
- [**Use Cases**](#use-cases)
|
||||
- [**Higress Features**](#higress-features)
|
||||
- [**Quick Start**](https://higress.io/en-us/docs/user/quickstart)
|
||||
- [**Community**](#community)
|
||||
- [**Thanks**](#thanks)
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Kubernetes ingress controller**:
|
||||
|
||||
Higress can function as a feature-rich ingress controller, which is compatible with many annotations of K8s' nginx ingress controller.
|
||||
|
||||
[Gateway API](https://gateway-api.sigs.k8s.io/) support is coming soon and will support smooth migration from Ingress API to Gateway API.
|
||||
|
||||
- **Microservice gateway**:
|
||||
|
||||
Higress can function as a microservice gateway, which can discovery microservices from various service registries, such as Nacos, ZooKeeper, Consul, Eureka, etc.
|
||||
|
||||
It deeply integrates of [Dubbo](https://github.com/apache/dubbo), [Nacos](https://github.com/alibaba/nacos), [Sentinel](https://github.com/alibaba/Sentinel) and other microservice technology stacks.
|
||||
|
||||
- **Security gateway**:
|
||||
|
||||
Higress can be used as a security gateway, supporting WAF and various authentication strategies, such as key-auth, hmac-auth, jwt-auth, basic-auth, oidc, etc.
|
||||
|
||||
## Higress Features
|
||||
|
||||
- **Easy to use**
|
||||
|
||||
Provide one-stop gateway solutions for traffic scheduling, service management, and security protection, support Console, K8s Ingress, and Gateway API configuration methods, and also support HTTP to Dubbo protocol conversion, and easily complete protocol mapping configuration.
|
||||
|
||||
- **Easy to expand**
|
||||
|
||||
Provides Wasm, Lua, and out-of-process plug-in extension mechanisms, so that multi-language plug-in writing is no longer an obstacle. The granularity of plug-in effectiveness supports not only the global level, domain name level, but also fine-grained routing level
|
||||
|
||||
- **Dynamic hot update**
|
||||
|
||||
Get rid of the traffic jitter caused by reload at the bottom, the configuration change takes effect in milliseconds and the business is not affected, the Wasm plug-in is hot updated and the traffic is not damaged
|
||||
|
||||
- **Smooth upgrade**
|
||||
|
||||
Compatible with 80%+ usage scenarios of Nginx Ingress Annotation, and provides more feature-rich annotations, easy to handle Nginx Ingress migration in one step
|
||||
|
||||
- **Security**
|
||||
|
||||
Provides JWT, OIDC, custom authentication and authentication, deeply integrates open source web application firewall.
|
||||
|
||||
## Community
|
||||
|
||||
[Slack](https://w1689142780-euk177225.slack.com/archives/C05GEL4TGTG): to get invited go [here](https://communityinviter.com/apps/w1689142780-euk177225/higress).
|
||||
|
||||
### Thanks
|
||||
|
||||
Higress would not be possible without the valuable open-source work of projects in the community. We would like to extend a special thank-you to Envoy and Istio.
|
||||
|
||||
### Related Repositories
|
||||
|
||||
- Higress Console: https://github.com/higress-group/higress-console
|
||||
- Higress Standalone: https://github.com/higress-group/higress-standalone
|
||||
226
README_JP.md
Normal file
226
README_JP.md
Normal file
@@ -0,0 +1,226 @@
|
||||
<a name="readme-top"></a>
|
||||
<h1 align="center">
|
||||
<img src="https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!!6000000006895-2-tps-960-290.png" alt="Higress" width="240" height="72.5">
|
||||
<br>
|
||||
AIゲートウェイ
|
||||
</h1>
|
||||
<h4 align="center"> AIネイティブAPIゲートウェイ </h4>
|
||||
|
||||
[](https://github.com/alibaba/higress/actions)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
[**公式サイト**](https://higress.cn/) |
|
||||
[**ドキュメント**](https://higress.cn/docs/latest/overview/what-is-higress/) |
|
||||
[**ブログ**](https://higress.cn/blog/) |
|
||||
[**電子書籍**](https://higress.cn/docs/ebook/wasm14/) |
|
||||
[**開発ガイド**](https://higress.cn/docs/latest/dev/architecture/) |
|
||||
[**AIプラグイン**](https://higress.cn/plugin/)
|
||||
|
||||
|
||||
<p>
|
||||
<a href="README_EN.md"> English <a/> | <a href="README.md">中文<a/> | 日本語
|
||||
</p>
|
||||
|
||||
|
||||
## Higressとは?
|
||||
|
||||
Higressは、IstioとEnvoyをベースにしたクラウドネイティブAPIゲートウェイで、Go/Rust/JSなどを使用してWasmプラグインを作成できます。数十の既製の汎用プラグインと、すぐに使用できるコンソールを提供しています(デモは[こちら](http://demo.higress.io/))。
|
||||
|
||||
### 主な使用シナリオ
|
||||
|
||||
HigressのAIゲートウェイ機能は、国内外のすべての[主要モデルプロバイダー](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/ai-proxy/provider)をサポートし、vllm/ollamaなどに基づく自己構築DeepSeekモデルにも対応しています。また、プラグインメカニズムを通じてMCP(Model Context Protocol)サーバーをホストすることもでき、AI Agentが様々なツールやサービスを簡単に呼び出せるようにします。[openapi-to-mcpツール](https://github.com/higress-group/openapi-to-mcpserver)を使用すると、OpenAPI仕様を迅速にリモートMCPサーバーに変換してホスティングできます。HigressはLLM APIとMCP APIの統一管理を提供します。
|
||||
|
||||
**🌟 今すぐ[https://mcp.higress.ai/](https://mcp.higress.ai/)で体験**してください。HigressがホストするリモートMCPサーバーを直接体験できます:
|
||||
|
||||

|
||||
|
||||
### 企業での採用
|
||||
|
||||
Higressは、Tengineのリロードが長時間接続のビジネスに影響を与える問題や、gRPC/Dubboの負荷分散能力の不足を解決するために、Alibaba内部で誕生しました。Alibaba Cloud内では、HigressのAIゲートウェイ機能がTongyi Qianwen APP、Tongyi Bailian Model Studio、機械学習PAIプラットフォームなどの中核的なAIアプリケーションをサポートしています。また、国内の主要なAIGC企業(例:ZeroOne)やAI製品(例:FastGPT)にもサービスを提供しています。Alibaba Cloudは、Higressを基盤にクラウドネイティブAPIゲートウェイ製品を構築し、多くの企業顧客に99.99%のゲートウェイ高可用性保証サービスを提供しています。
|
||||
|
||||
|
||||
## 目次
|
||||
|
||||
- [**クイックスタート**](#クイックスタート)
|
||||
- [**機能紹介**](#機能紹介)
|
||||
- [**使用シナリオ**](#使用シナリオ)
|
||||
- [**主な利点**](#主な利点)
|
||||
- [**コミュニティ**](#コミュニティ)
|
||||
|
||||
## クイックスタート
|
||||
|
||||
HigressはDockerだけで起動でき、個人開発者がローカルで学習用にセットアップしたり、簡易サイトを構築するのに便利です。
|
||||
|
||||
```bash
|
||||
# 作業ディレクトリを作成
|
||||
mkdir higress; cd higress
|
||||
# Higressを起動し、設定ファイルを作業ディレクトリに書き込みます
|
||||
docker run -d --rm --name higress-ai -v ${PWD}:/data \
|
||||
-p 8001:8001 -p 8080:8080 -p 8443:8443 \
|
||||
higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/all-in-one:latest
|
||||
```
|
||||
|
||||
リスンポートの説明は以下の通りです:
|
||||
|
||||
- 8001ポート:Higress UIコンソールのエントリーポイント
|
||||
- 8080ポート:ゲートウェイのHTTPプロトコルエントリーポイント
|
||||
- 8443ポート:ゲートウェイのHTTPSプロトコルエントリーポイント
|
||||
|
||||
**HigressのすべてのDockerイメージは専用のリポジトリを使用しており、Docker Hubの国内アクセス不可の影響を受けません**
|
||||
|
||||
K8sでのHelmデプロイなどの他のインストール方法については、公式サイトの[クイックスタートドキュメント](https://higress.cn/docs/latest/user/quickstart/)を参照してください。
|
||||
|
||||
|
||||
## 使用シナリオ
|
||||
|
||||
- **AIゲートウェイ**:
|
||||
|
||||
Higressは、国内外のすべてのLLMモデルプロバイダーと統一されたプロトコルで接続でき、豊富なAI可観測性、多モデル負荷分散/フォールバック、AIトークンフロー制御、AIキャッシュなどの機能を備えています。
|
||||
|
||||

|
||||
|
||||
- **MCP Server ホスティング**:
|
||||
|
||||
Higressは、EnvoyベースのAPIゲートウェイとして、プラグインメカニズムを通じてMCP Serverをホストすることができます。MCP(Model Context Protocol)は本質的にAIにより親和性の高いAPIであり、AI Agentが様々なツールやサービスを簡単に呼び出せるようにします。Higressはツール呼び出しの認証、認可、レート制限、可観測性などの統一機能を提供し、AIアプリケーションの開発とデプロイを簡素化します。
|
||||
|
||||

|
||||
|
||||
Higressを使用してMCP Serverをホストすることで、以下のことが実現できます:
|
||||
- 統一された認証と認可メカニズム、AIツール呼び出しのセキュリティを確保
|
||||
- きめ細かいレート制限、乱用やリソース枯渇を防止
|
||||
- 包括的な監査ログ、すべてのツール呼び出し行動を記録
|
||||
- 豊富な可観測性、ツール呼び出しのパフォーマンスと健全性を監視
|
||||
- 簡素化されたデプロイと管理、Higressのプラグインメカニズムを通じて新しいMCP Serverを迅速に追加
|
||||
- 動的更新による無停止:Envoyの長時間接続に対する友好的なサポートとWasmプラグインの動的更新メカニズムにより、MCP Serverのロジックをリアルタイムで更新でき、トラフィックに完全に影響を与えず、接続が切断されることはありません
|
||||
|
||||
- **Kubernetes Ingressゲートウェイ**:
|
||||
|
||||
HigressはK8sクラスターのIngressエントリーポイントゲートウェイとして機能し、多くのK8s Nginx Ingressの注釈に対応しています。K8s Nginx IngressからHigressへのスムーズな移行が可能です。
|
||||
|
||||
[Gateway API](https://gateway-api.sigs.k8s.io/)標準をサポートし、ユーザーがIngress APIからGateway APIにスムーズに移行できるようにします。
|
||||
|
||||
ingress-nginxと比較して、リソースの消費が大幅に減少し、ルーティングの変更が10倍速く反映されます。
|
||||
|
||||

|
||||

|
||||
|
||||
- **マイクロサービスゲートウェイ**:
|
||||
|
||||
Higressはマイクロサービスゲートウェイとして機能し、Nacos、ZooKeeper、Consul、Eurekaなどのさまざまなサービスレジストリからサービスを発見し、ルーティングを構成できます。
|
||||
|
||||
また、[Dubbo](https://github.com/apache/dubbo)、[Nacos](https://github.com/alibaba/nacos)、[Sentinel](https://github.com/alibaba/Sentinel)などのマイクロサービス技術スタックと深く統合されています。Envoy C++ゲートウェイコアの優れたパフォーマンスに基づいて、従来のJavaベースのマイクロサービスゲートウェイと比較して、リソース使用率を大幅に削減し、コストを削減できます。
|
||||
|
||||

|
||||
|
||||
- **セキュリティゲートウェイ**:
|
||||
|
||||
Higressはセキュリティゲートウェイとして機能し、WAF機能を提供し、key-auth、hmac-auth、jwt-auth、basic-auth、oidcなどのさまざまな認証戦略をサポートします。
|
||||
|
||||
## 主な利点
|
||||
|
||||
- **プロダクションレベル**
|
||||
|
||||
Alibabaで2年以上のプロダクション検証を経た内部製品から派生し、毎秒数十万のリクエストを処理する大規模なシナリオをサポートします。
|
||||
|
||||
Nginxのリロードによるトラフィックの揺れを完全に排除し、構成変更がミリ秒単位で反映され、ビジネスに影響を与えません。AIビジネスなどの長時間接続シナリオに特に適しています。
|
||||
|
||||
- **ストリーム処理**
|
||||
|
||||
リクエスト/レスポンスボディの完全なストリーム処理をサポートし、Wasmプラグインを使用してSSE(Server-Sent Events)などのストリームプロトコルのメッセージをカスタマイズして処理できます。
|
||||
|
||||
AIビジネスなどの大帯域幅シナリオで、メモリ使用量を大幅に削減できます。
|
||||
|
||||
- **拡張性**
|
||||
|
||||
AI、トラフィック管理、セキュリティ保護などの一般的な機能をカバーする豊富な公式プラグインライブラリを提供し、90%以上のビジネスシナリオのニーズを満たします。
|
||||
|
||||
Wasmプラグイン拡張を主力とし、サンドボックス隔離を通じてメモリの安全性を確保し、複数のプログラミング言語をサポートし、プラグインバージョンの独立したアップグレードを許可し、トラフィックに影響を与えずにゲートウェイロジックをホットアップデートできます。
|
||||
|
||||
- **安全で使いやすい**
|
||||
|
||||
Ingress APIおよびGateway API標準に基づき、すぐに使用できるUIコンソールを提供し、WAF保護プラグイン、IP/Cookie CC保護プラグインをすぐに使用できます。
|
||||
|
||||
Let's Encryptの自動証明書発行および更新をサポートし、K8sを使用せずにデプロイでき、1行のDockerコマンドで起動でき、個人開発者にとって便利です。
|
||||
|
||||
|
||||
## 機能紹介
|
||||
|
||||
### AIゲートウェイデモ展示
|
||||
|
||||
[OpenAIから他の大規模モデルへの移行を30秒で完了
|
||||
](https://www.bilibili.com/video/BV1dT421a7w7/?spm_id_from=333.788.recommend_more_video.14)
|
||||
|
||||
|
||||
### Higress UIコンソール
|
||||
|
||||
- **豊富な可観測性**
|
||||
|
||||
すぐに使用できる可観測性を提供し、Grafana&Prometheusは組み込みのものを使用することも、自分で構築したものを接続することもできます。
|
||||
|
||||

|
||||
|
||||
|
||||
- **プラグイン拡張メカニズム**
|
||||
|
||||
公式にはさまざまなプラグインが提供されており、ユーザーは[独自のプラグインを開発](./plugins/wasm-go)し、Docker/OCIイメージとして構築し、コンソールで構成して、プラグインロジックをリアルタイムで変更できます。トラフィックに影響を与えずにプラグインロジックをホットアップデートできます。
|
||||
|
||||

|
||||
|
||||
|
||||
- **さまざまなサービス発見**
|
||||
|
||||
デフォルトでK8s Serviceサービス発見を提供し、構成を通じてNacos/ZooKeeperなどのレジストリに接続してサービスを発見することも、静的IPまたはDNSに基づいて発見することもできます。
|
||||
|
||||

|
||||
|
||||
|
||||
- **ドメインと証明書**
|
||||
|
||||
TLS証明書を作成および管理し、ドメインのHTTP/HTTPS動作を構成できます。ドメインポリシーでは、特定のドメインに対してプラグインを適用することができます。
|
||||
|
||||

|
||||
|
||||
|
||||
- **豊富なルーティング機能**
|
||||
|
||||
上記で定義されたサービス発見メカニズムを通じて、発見されたサービスはサービスリストに表示されます。ルーティングを作成する際に、ドメインを選択し、ルーティングマッチングメカニズムを定義し、ターゲットサービスを選択してルーティングを行います。ルーティングポリシーでは、特定のルーティングに対してプラグインを適用することができます。
|
||||
|
||||

|
||||
|
||||
|
||||
## コミュニティ
|
||||
|
||||
### 感謝
|
||||
|
||||
EnvoyとIstioのオープンソースの取り組みがなければ、Higressは実現できませんでした。これらのプロジェクトに最も誠実な敬意を表します。
|
||||
|
||||
### 交流グループ
|
||||
|
||||

|
||||
|
||||
### 技術共有
|
||||
|
||||
WeChat公式アカウント:
|
||||
|
||||

|
||||
|
||||
### 関連リポジトリ
|
||||
|
||||
- Higressコンソール:https://github.com/higress-group/higress-console
|
||||
- Higress(スタンドアロン版):https://github.com/higress-group/higress-standalone
|
||||
|
||||
### 貢献者
|
||||
|
||||
<a href="https://github.com/alibaba/higress/graphs/contributors">
|
||||
<img alt="contributors" src="https://contrib.rocks/image?repo=alibaba/higress"/>
|
||||
</a>
|
||||
|
||||
### スターの歴史
|
||||
|
||||
[](https://star-history.com/#alibaba/higress&Date)
|
||||
|
||||
<p align="right" style="font-size: 14px; color: #555; margin-top: 20px;">
|
||||
<a href="#readme-top" style="text-decoration: none; color: #007bff; font-weight: bold;">
|
||||
↑ トップに戻る ↑
|
||||
</a>
|
||||
</p>
|
||||
236
README_ZH.md
Normal file
236
README_ZH.md
Normal file
@@ -0,0 +1,236 @@
|
||||
<a name="readme-top"></a>
|
||||
<h1 align="center">
|
||||
<img src="https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!!6000000006895-2-tps-960-290.png" alt="Higress" width="240" height="72.5">
|
||||
<br>
|
||||
AI Gateway
|
||||
</h1>
|
||||
<h4 align="center"> AI Native API Gateway </h4>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/alibaba/higress/actions)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
<a href="https://trendshift.io/repositories/10918" target="_blank"><img src="https://trendshift.io/api/badge/repositories/10918" alt="alibaba%2Fhigress | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a> <a href="https://www.producthunt.com/posts/higress?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-higress" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=951287&theme=light&t=1745492822283" alt="Higress - Global APIs as MCP powered by AI Gateway | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
</div>
|
||||
|
||||
[**官网**](https://higress.cn/) |
|
||||
[**文档**](https://higress.cn/docs/latest/overview/what-is-higress/) |
|
||||
[**博客**](https://higress.cn/blog/) |
|
||||
[**电子书**](https://higress.cn/docs/ebook/wasm14/) |
|
||||
[**开发指引**](https://higress.cn/docs/latest/dev/architecture/) |
|
||||
[**AI插件**](https://higress.cn/plugin/)
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
<a href="README.md"> English <a/>| 中文 | <a href="README_JP.md"> 日本語 <a/>
|
||||
</p>
|
||||
|
||||
|
||||
## Higress 是什么?
|
||||
|
||||
Higress 是一款云原生 API 网关,内核基于 Istio 和 Envoy,可以用 Go/Rust/JS 等编写 Wasm 插件,提供了数十个现成的通用插件,以及开箱即用的控制台(demo 点[这里](http://demo.higress.io/))
|
||||
|
||||
### 核心使用场景
|
||||
|
||||
Higress 的 AI 网关能力支持国内外所有[主流模型供应商](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/ai-proxy/provider)和基于 vllm/ollama 等自建的 DeepSeek 模型。同时,Higress 支持通过插件方式托管 MCP (Model Context Protocol) 服务器,使 AI Agent 能够更容易地调用各种工具和服务。借助 [openapi-to-mcp 工具](https://github.com/higress-group/openapi-to-mcpserver),您可以快速将 OpenAPI 规范转换为远程 MCP 服务器进行托管。Higress 提供了对 LLM API 和 MCP API 的统一管理。
|
||||
|
||||
**🌟 立即体验 [https://mcp.higress.ai/](https://mcp.higress.ai/)** 基于 Higress 托管的远程 MCP 服务器:
|
||||
|
||||

|
||||
|
||||
### 生产环境采用
|
||||
|
||||
Higress 在阿里内部为解决 Tengine reload 对长连接业务有损,以及 gRPC/Dubbo 负载均衡能力不足而诞生。在阿里云内部,Higress 的 AI 网关能力支撑了通义千问 APP、通义百炼模型工作室、机器学习 PAI 平台等核心 AI 应用。同时服务国内头部的 AIGC 企业(如零一万物),以及 AI 产品(如 FastGPT)。阿里云基于 Higress 构建了云原生 API 网关产品,为大量企业客户提供 99.99% 的网关高可用保障服务能力。
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
- [**快速开始**](#快速开始)
|
||||
- [**功能展示**](#功能展示)
|
||||
- [**使用场景**](#使用场景)
|
||||
- [**核心优势**](#核心优势)
|
||||
- [**社区**](#社区)
|
||||
|
||||
## 快速开始
|
||||
|
||||
Higress 只需 Docker 即可启动,方便个人开发者在本地搭建学习,或者用于搭建简易站点:
|
||||
|
||||
```bash
|
||||
# 创建一个工作目录
|
||||
mkdir higress; cd higress
|
||||
# 启动 higress,配置文件会写到工作目录下
|
||||
docker run -d --rm --name higress-ai -v ${PWD}:/data \
|
||||
-p 8001:8001 -p 8080:8080 -p 8443:8443 \
|
||||
higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/all-in-one:latest
|
||||
```
|
||||
|
||||
监听端口说明如下:
|
||||
|
||||
- 8001 端口:Higress UI 控制台入口
|
||||
- 8080 端口:网关 HTTP 协议入口
|
||||
- 8443 端口:网关 HTTPS 协议入口
|
||||
|
||||
**Higress 的所有 Docker 镜像都一直使用自己独享的仓库,不受 Docker Hub 境内访问受限的影响**
|
||||
|
||||
K8s 下使用 Helm 部署等其他安装方式可以参考官网 [Quick Start 文档](https://higress.cn/docs/latest/user/quickstart/)。
|
||||
|
||||
如果您是在云上部署,生产环境推荐使用[企业版](https://higress.io/cloud/),开发测试可以使用下面一键部署社区版:
|
||||
|
||||
[](https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=Higress社区版)
|
||||
|
||||
|
||||
## 使用场景
|
||||
|
||||
- **AI 网关**:
|
||||
|
||||
Higress 能够用统一的协议对接国内外所有 LLM 模型厂商,同时具备丰富的 AI 可观测、多模型负载均衡/fallback、AI token 流控、AI 缓存等能力:
|
||||
|
||||

|
||||
|
||||
- **MCP Server 托管**:
|
||||
|
||||
Higress 作为基于 Envoy 的 API 网关,支持通过插件方式托管 MCP Server。MCP(Model Context Protocol)本质是面向 AI 更友好的 API,使 AI Agent 能够更容易地调用各种工具和服务。Higress 可以统一处理工具调用的认证/鉴权/限流/观测等能力,简化 AI 应用的开发和部署。
|
||||
|
||||

|
||||
|
||||
通过 Higress 托管 MCP Server,可以实现:
|
||||
- 统一的认证和鉴权机制,确保 AI 工具调用的安全性
|
||||
- 精细化的速率限制,防止滥用和资源耗尽
|
||||
- 完整的审计日志,记录所有工具调用行为
|
||||
- 丰富的可观测性,监控工具调用的性能和健康状况
|
||||
- 简化的部署和管理,通过 Higress 插件机制快速添加新的 MCP Server
|
||||
- 动态更新无损:得益于 Envoy 对长连接保持的友好支持,以及 Wasm 插件的动态更新机制,MCP Server 逻辑可以实时更新,且对流量完全无损,不会导致任何连接断开
|
||||
|
||||
- **Kubernetes Ingress 网关**:
|
||||
|
||||
Higress 可以作为 K8s 集群的 Ingress 入口网关, 并且兼容了大量 K8s Nginx Ingress 的注解,可以从 K8s Nginx Ingress 快速平滑迁移到 Higress。
|
||||
|
||||
支持 [Gateway API](https://gateway-api.sigs.k8s.io/) 标准,支持用户从 Ingress API 平滑迁移到 Gateway API。
|
||||
|
||||
相比 ingress-nginx,资源开销大幅下降,路由变更生效速度有十倍提升:
|
||||
|
||||

|
||||

|
||||
|
||||
- **微服务网关**:
|
||||
|
||||
Higress 可以作为微服务网关, 能够对接多种类型的注册中心发现服务配置路由,例如 Nacos, ZooKeeper, Consul, Eureka 等。
|
||||
|
||||
并且深度集成了 [Dubbo](https://github.com/apache/dubbo), [Nacos](https://github.com/alibaba/nacos), [Sentinel](https://github.com/alibaba/Sentinel) 等微服务技术栈,基于 Envoy C++ 网关内核的出色性能,相比传统 Java 类微服务网关,可以显著降低资源使用率,减少成本。
|
||||
|
||||

|
||||
|
||||
- **安全防护网关**:
|
||||
|
||||
Higress 可以作为安全防护网关, 提供 WAF 的能力,并且支持多种认证鉴权策略,例如 key-auth, hmac-auth, jwt-auth, basic-auth, oidc 等。
|
||||
|
||||
## 核心优势
|
||||
|
||||
- **生产等级**
|
||||
|
||||
脱胎于阿里巴巴2年多生产验证的内部产品,支持每秒请求量达数十万级的大规模场景。
|
||||
|
||||
彻底摆脱 Nginx reload 引起的流量抖动,配置变更毫秒级生效且业务无感。对 AI 业务等长连接场景特别友好。
|
||||
|
||||
- **流式处理**
|
||||
|
||||
支持真正的完全流式处理请求/响应 Body,Wasm 插件很方便地自定义处理 SSE (Server-Sent Events)等流式协议的报文。
|
||||
|
||||
在 AI 业务等大带宽场景下,可以显著降低内存开销。
|
||||
|
||||
- **便于扩展**
|
||||
|
||||
提供丰富的官方插件库,涵盖 AI、流量管理、安全防护等常用功能,满足90%以上的业务场景需求。
|
||||
|
||||
主打 Wasm 插件扩展,通过沙箱隔离确保内存安全,支持多种编程语言,允许插件版本独立升级,实现流量无损热更新网关逻辑。
|
||||
|
||||
- **安全易用**
|
||||
|
||||
基于 Ingress API 和 Gateway API 标准,提供开箱即用的 UI 控制台,WAF 防护插件、IP/Cookie CC 防护插件开箱即用。
|
||||
|
||||
支持对接 Let's Encrypt 自动签发和续签免费证书,并且可以脱离 K8s 部署,一行 Docker 命令即可启动,方便个人开发者使用。
|
||||
|
||||
|
||||
## 功能展示
|
||||
|
||||
### AI 网关 Demo 展示
|
||||
|
||||
[从 OpenAI 到其他大模型,30 秒完成迁移
|
||||
](https://www.bilibili.com/video/BV1dT421a7w7/?spm_id_from=333.788.recommend_more_video.14)
|
||||
|
||||
|
||||
### Higress UI 控制台
|
||||
|
||||
- **丰富的可观测**
|
||||
|
||||
提供开箱即用的可观测,Grafana&Prometheus 可以使用内置的也可对接自建的
|
||||
|
||||

|
||||
|
||||
|
||||
- **插件扩展机制**
|
||||
|
||||
官方提供了多种插件,用户也可以[开发](./plugins/wasm-go)自己的插件,构建成 docker/oci 镜像后在控制台配置,可以实时变更插件逻辑,对流量完全无损。
|
||||
|
||||

|
||||
|
||||
|
||||
- **多种服务发现**
|
||||
|
||||
默认提供 K8s Service 服务发现,通过配置可以对接 Nacos/ZooKeeper 等注册中心实现服务发现,也可以基于静态 IP 或者 DNS 来发现
|
||||
|
||||

|
||||
|
||||
|
||||
- **域名和证书**
|
||||
|
||||
可以创建管理 TLS 证书,并配置域名的 HTTP/HTTPS 行为,域名策略里支持对特定域名生效插件
|
||||
|
||||

|
||||
|
||||
|
||||
- **丰富的路由能力**
|
||||
|
||||
通过上面定义的服务发现机制,发现的服务会出现在服务列表中;创建路由时,选择域名,定义路由匹配机制,再选择目标服务进行路由;路由策略里支持对特定路由生效插件
|
||||
|
||||

|
||||
|
||||
|
||||
## 社区
|
||||
|
||||
### 感谢
|
||||
|
||||
如果没有 Envoy 和 Istio 的开源工作,Higress 就不可能实现,在这里向这两个项目献上最诚挚的敬意。
|
||||
|
||||
### 交流群
|
||||
|
||||

|
||||
|
||||
### 技术分享
|
||||
|
||||
微信公众号:
|
||||
|
||||

|
||||
|
||||
### 关联仓库
|
||||
|
||||
- Higress 控制台:https://github.com/higress-group/higress-console
|
||||
- Higress(独立运行版):https://github.com/higress-group/higress-standalone
|
||||
|
||||
### 贡献者
|
||||
|
||||
<a href="https://github.com/alibaba/higress/graphs/contributors">
|
||||
<img alt="contributors" src="https://contrib.rocks/image?repo=alibaba/higress"/>
|
||||
</a>
|
||||
|
||||
### Star History
|
||||
|
||||
[](https://star-history.com/#alibaba/higress&Date)
|
||||
|
||||
<p align="right" style="font-size: 14px; color: #555; margin-top: 20px;">
|
||||
<a href="#readme-top" style="text-decoration: none; color: #007bff; font-weight: bold;">
|
||||
↑ 返回顶部 ↑
|
||||
</a>
|
||||
</p>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 2.x.x | :white_check_mark: |
|
||||
| 1.x.x | :white_check_mark: |
|
||||
| < 1.0.0 | :x: |
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ type WasmPlugin struct {
|
||||
// Extended by Higress, matching rules take effect
|
||||
MatchRules []*MatchRule `protobuf:"bytes,102,rep,name=match_rules,json=matchRules,proto3" json:"match_rules,omitempty"`
|
||||
// disable the default config
|
||||
DefaultConfigDisable bool `protobuf:"varint,103,opt,name=default_config_disable,json=defaultConfigDisable,proto3" json:"default_config_disable,omitempty"`
|
||||
DefaultConfigDisable *wrappers.BoolValue `protobuf:"bytes,103,opt,name=default_config_disable,json=defaultConfigDisable,proto3" json:"default_config_disable,omitempty"`
|
||||
}
|
||||
|
||||
func (x *WasmPlugin) Reset() {
|
||||
@@ -467,11 +467,11 @@ func (x *WasmPlugin) GetMatchRules() []*MatchRule {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *WasmPlugin) GetDefaultConfigDisable() bool {
|
||||
func (x *WasmPlugin) GetDefaultConfigDisable() *wrappers.BoolValue {
|
||||
if x != nil {
|
||||
return x.DefaultConfigDisable
|
||||
}
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
// Extended by Higress
|
||||
@@ -480,11 +480,11 @@ type MatchRule struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Ingress []string `protobuf:"bytes,1,rep,name=ingress,proto3" json:"ingress,omitempty"`
|
||||
Domain []string `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
||||
Config *_struct.Struct `protobuf:"bytes,3,opt,name=config,proto3" json:"config,omitempty"`
|
||||
ConfigDisable bool `protobuf:"varint,4,opt,name=config_disable,json=configDisable,proto3" json:"config_disable,omitempty"`
|
||||
Service []string `protobuf:"bytes,5,rep,name=service,proto3" json:"service,omitempty"`
|
||||
Ingress []string `protobuf:"bytes,1,rep,name=ingress,proto3" json:"ingress,omitempty"`
|
||||
Domain []string `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
||||
Config *_struct.Struct `protobuf:"bytes,3,opt,name=config,proto3" json:"config,omitempty"`
|
||||
ConfigDisable *wrappers.BoolValue `protobuf:"bytes,4,opt,name=config_disable,json=configDisable,proto3" json:"config_disable,omitempty"`
|
||||
Service []string `protobuf:"bytes,5,rep,name=service,proto3" json:"service,omitempty"`
|
||||
}
|
||||
|
||||
func (x *MatchRule) Reset() {
|
||||
@@ -540,11 +540,11 @@ func (x *MatchRule) GetConfig() *_struct.Struct {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *MatchRule) GetConfigDisable() bool {
|
||||
func (x *MatchRule) GetConfigDisable() *wrappers.BoolValue {
|
||||
if x != nil {
|
||||
return x.ConfigDisable
|
||||
}
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *MatchRule) GetService() []string {
|
||||
@@ -686,7 +686,7 @@ var file_extensions_v1alpha1_wasmplugin_proto_rawDesc = []byte{
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x22, 0x8d, 0x06, 0x0a, 0x0a, 0x57, 0x61, 0x73, 0x6d, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
|
||||
0x6f, 0x22, 0xa9, 0x06, 0x0a, 0x0a, 0x57, 0x61, 0x73, 0x6d, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,
|
||||
0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x53, 0x0a, 0x11, 0x69, 0x6d,
|
||||
@@ -731,52 +731,55 @@ var file_extensions_v1alpha1_wasmplugin_proto_rawDesc = []byte{
|
||||
0x73, 0x18, 0x66, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73,
|
||||
0x73, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x61,
|
||||
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x75, 0x6c, 0x65, 0x52,
|
||||
0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x64,
|
||||
0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x16, 0x64,
|
||||
0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69,
|
||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x67, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x65, 0x66,
|
||||
0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x22, 0xaf, 0x01, 0x0a, 0x09, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x75, 0x6c, 0x65, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
|
||||
0x52, 0x07, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d,
|
||||
0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x73,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x22, 0x41, 0x0a, 0x08, 0x56, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||
0x35, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68,
|
||||
0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61,
|
||||
0x72, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x22, 0x7e, 0x0a, 0x06, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72,
|
||||
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x72,
|
||||
0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x68, 0x69, 0x67, 0x72, 0x65,
|
||||
0x73, 0x73, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x72, 0x6f, 0x6d,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x45, 0x0a, 0x0b, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
|
||||
0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
|
||||
0x46, 0x49, 0x45, 0x44, 0x5f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05,
|
||||
0x41, 0x55, 0x54, 0x48, 0x4e, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x55, 0x54, 0x48, 0x5a,
|
||||
0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x54, 0x53, 0x10, 0x03, 0x2a, 0x42, 0x0a,
|
||||
0x0a, 0x50, 0x75, 0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x12, 0x55,
|
||||
0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43,
|
||||
0x59, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x66, 0x4e, 0x6f, 0x74, 0x50, 0x72, 0x65, 0x73,
|
||||
0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10,
|
||||
0x02, 0x2a, 0x26, 0x0a, 0x0e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x00, 0x12,
|
||||
0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x2a, 0x2d, 0x0a, 0x0c, 0x46, 0x61, 0x69,
|
||||
0x6c, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x41, 0x49,
|
||||
0x4c, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x41, 0x49,
|
||||
0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x6c, 0x69, 0x62, 0x61, 0x62, 0x61, 0x2f, 0x68,
|
||||
0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x67, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f,
|
||||
0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xcb, 0x01,
|
||||
0x0a, 0x09, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x69,
|
||||
0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e,
|
||||
0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
|
||||
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2f, 0x0a,
|
||||
0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41,
|
||||
0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03,
|
||||
0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x41, 0x0a, 0x08, 0x56,
|
||||
0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x65,
|
||||
0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
|
||||
0x61, 0x31, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x22, 0x7e,
|
||||
0x0a, 0x06, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4a, 0x0a, 0x0a,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e,
|
||||
0x32, 0x2b, 0x2e, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45,
|
||||
0x6e, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x45,
|
||||
0x0a, 0x0b, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x15, 0x0a,
|
||||
0x11, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x50, 0x48, 0x41,
|
||||
0x53, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x55, 0x54, 0x48, 0x4e, 0x10, 0x01, 0x12,
|
||||
0x09, 0x0a, 0x05, 0x41, 0x55, 0x54, 0x48, 0x5a, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54,
|
||||
0x41, 0x54, 0x53, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0a, 0x50, 0x75, 0x6c, 0x6c, 0x50, 0x6f, 0x6c,
|
||||
0x69, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
|
||||
0x45, 0x44, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x49,
|
||||
0x66, 0x4e, 0x6f, 0x74, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x0a, 0x0a,
|
||||
0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x02, 0x2a, 0x26, 0x0a, 0x0e, 0x45, 0x6e, 0x76,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x49,
|
||||
0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10,
|
||||
0x01, 0x2a, 0x2d, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||
0x79, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x41, 0x49, 0x4c, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10,
|
||||
0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x41, 0x49, 0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x01,
|
||||
0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61,
|
||||
0x6c, 0x69, 0x62, 0x61, 0x62, 0x61, 0x2f, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2f, 0x61,
|
||||
0x70, 0x69, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31,
|
||||
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -804,6 +807,7 @@ var file_extensions_v1alpha1_wasmplugin_proto_goTypes = []interface{}{
|
||||
(*EnvVar)(nil), // 7: higress.extensions.v1alpha1.EnvVar
|
||||
(*_struct.Struct)(nil), // 8: google.protobuf.Struct
|
||||
(*wrappers.Int32Value)(nil), // 9: google.protobuf.Int32Value
|
||||
(*wrappers.BoolValue)(nil), // 10: google.protobuf.BoolValue
|
||||
}
|
||||
var file_extensions_v1alpha1_wasmplugin_proto_depIdxs = []int32{
|
||||
1, // 0: higress.extensions.v1alpha1.WasmPlugin.image_pull_policy:type_name -> higress.extensions.v1alpha1.PullPolicy
|
||||
@@ -814,14 +818,16 @@ var file_extensions_v1alpha1_wasmplugin_proto_depIdxs = []int32{
|
||||
6, // 5: higress.extensions.v1alpha1.WasmPlugin.vm_config:type_name -> higress.extensions.v1alpha1.VmConfig
|
||||
8, // 6: higress.extensions.v1alpha1.WasmPlugin.default_config:type_name -> google.protobuf.Struct
|
||||
5, // 7: higress.extensions.v1alpha1.WasmPlugin.match_rules:type_name -> higress.extensions.v1alpha1.MatchRule
|
||||
8, // 8: higress.extensions.v1alpha1.MatchRule.config:type_name -> google.protobuf.Struct
|
||||
7, // 9: higress.extensions.v1alpha1.VmConfig.env:type_name -> higress.extensions.v1alpha1.EnvVar
|
||||
2, // 10: higress.extensions.v1alpha1.EnvVar.value_from:type_name -> higress.extensions.v1alpha1.EnvValueSource
|
||||
11, // [11:11] is the sub-list for method output_type
|
||||
11, // [11:11] is the sub-list for method input_type
|
||||
11, // [11:11] is the sub-list for extension type_name
|
||||
11, // [11:11] is the sub-list for extension extendee
|
||||
0, // [0:11] is the sub-list for field type_name
|
||||
10, // 8: higress.extensions.v1alpha1.WasmPlugin.default_config_disable:type_name -> google.protobuf.BoolValue
|
||||
8, // 9: higress.extensions.v1alpha1.MatchRule.config:type_name -> google.protobuf.Struct
|
||||
10, // 10: higress.extensions.v1alpha1.MatchRule.config_disable:type_name -> google.protobuf.BoolValue
|
||||
7, // 11: higress.extensions.v1alpha1.VmConfig.env:type_name -> higress.extensions.v1alpha1.EnvVar
|
||||
2, // 12: higress.extensions.v1alpha1.EnvVar.value_from:type_name -> higress.extensions.v1alpha1.EnvValueSource
|
||||
13, // [13:13] is the sub-list for method output_type
|
||||
13, // [13:13] is the sub-list for method input_type
|
||||
13, // [13:13] is the sub-list for extension type_name
|
||||
13, // [13:13] is the sub-list for extension extendee
|
||||
0, // [0:13] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_extensions_v1alpha1_wasmplugin_proto_init() }
|
||||
|
||||
@@ -112,7 +112,7 @@ message WasmPlugin {
|
||||
// Extended by Higress, matching rules take effect
|
||||
repeated MatchRule match_rules = 102;
|
||||
// disable the default config
|
||||
bool default_config_disable = 103;
|
||||
google.protobuf.BoolValue default_config_disable = 103;
|
||||
}
|
||||
|
||||
// Extended by Higress
|
||||
@@ -120,7 +120,7 @@ message MatchRule {
|
||||
repeated string ingress = 1;
|
||||
repeated string domain = 2;
|
||||
google.protobuf.Struct config = 3;
|
||||
bool config_disable = 4;
|
||||
google.protobuf.BoolValue config_disable = 4;
|
||||
repeated string service = 5;
|
||||
}
|
||||
|
||||
|
||||
@@ -263,6 +263,14 @@ spec:
|
||||
type: string
|
||||
domain:
|
||||
type: string
|
||||
enableMCPServer:
|
||||
type: boolean
|
||||
mcpServerBaseUrl:
|
||||
type: string
|
||||
mcpServerExportDomains:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
nacosAccessKey:
|
||||
type: string
|
||||
nacosAddressServer:
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
_ "github.com/golang/protobuf/ptypes/struct"
|
||||
wrappers "github.com/golang/protobuf/ptypes/wrappers"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
@@ -109,25 +111,28 @@ type RegistryConfig struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||
Port uint32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"`
|
||||
NacosAddressServer string `protobuf:"bytes,5,opt,name=nacosAddressServer,proto3" json:"nacosAddressServer,omitempty"`
|
||||
NacosAccessKey string `protobuf:"bytes,6,opt,name=nacosAccessKey,proto3" json:"nacosAccessKey,omitempty"`
|
||||
NacosSecretKey string `protobuf:"bytes,7,opt,name=nacosSecretKey,proto3" json:"nacosSecretKey,omitempty"`
|
||||
NacosNamespaceId string `protobuf:"bytes,8,opt,name=nacosNamespaceId,proto3" json:"nacosNamespaceId,omitempty"`
|
||||
NacosNamespace string `protobuf:"bytes,9,opt,name=nacosNamespace,proto3" json:"nacosNamespace,omitempty"`
|
||||
NacosGroups []string `protobuf:"bytes,10,rep,name=nacosGroups,proto3" json:"nacosGroups,omitempty"`
|
||||
NacosRefreshInterval int64 `protobuf:"varint,11,opt,name=nacosRefreshInterval,proto3" json:"nacosRefreshInterval,omitempty"`
|
||||
ConsulNamespace string `protobuf:"bytes,12,opt,name=consulNamespace,proto3" json:"consulNamespace,omitempty"`
|
||||
ZkServicesPath []string `protobuf:"bytes,13,rep,name=zkServicesPath,proto3" json:"zkServicesPath,omitempty"`
|
||||
ConsulDatacenter string `protobuf:"bytes,14,opt,name=consulDatacenter,proto3" json:"consulDatacenter,omitempty"`
|
||||
ConsulServiceTag string `protobuf:"bytes,15,opt,name=consulServiceTag,proto3" json:"consulServiceTag,omitempty"`
|
||||
ConsulRefreshInterval int64 `protobuf:"varint,16,opt,name=consulRefreshInterval,proto3" json:"consulRefreshInterval,omitempty"`
|
||||
AuthSecretName string `protobuf:"bytes,17,opt,name=authSecretName,proto3" json:"authSecretName,omitempty"`
|
||||
Protocol string `protobuf:"bytes,18,opt,name=protocol,proto3" json:"protocol,omitempty"`
|
||||
Sni string `protobuf:"bytes,19,opt,name=sni,proto3" json:"sni,omitempty"`
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||
Port uint32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"`
|
||||
NacosAddressServer string `protobuf:"bytes,5,opt,name=nacosAddressServer,proto3" json:"nacosAddressServer,omitempty"`
|
||||
NacosAccessKey string `protobuf:"bytes,6,opt,name=nacosAccessKey,proto3" json:"nacosAccessKey,omitempty"`
|
||||
NacosSecretKey string `protobuf:"bytes,7,opt,name=nacosSecretKey,proto3" json:"nacosSecretKey,omitempty"`
|
||||
NacosNamespaceId string `protobuf:"bytes,8,opt,name=nacosNamespaceId,proto3" json:"nacosNamespaceId,omitempty"`
|
||||
NacosNamespace string `protobuf:"bytes,9,opt,name=nacosNamespace,proto3" json:"nacosNamespace,omitempty"`
|
||||
NacosGroups []string `protobuf:"bytes,10,rep,name=nacosGroups,proto3" json:"nacosGroups,omitempty"`
|
||||
NacosRefreshInterval int64 `protobuf:"varint,11,opt,name=nacosRefreshInterval,proto3" json:"nacosRefreshInterval,omitempty"`
|
||||
ConsulNamespace string `protobuf:"bytes,12,opt,name=consulNamespace,proto3" json:"consulNamespace,omitempty"`
|
||||
ZkServicesPath []string `protobuf:"bytes,13,rep,name=zkServicesPath,proto3" json:"zkServicesPath,omitempty"`
|
||||
ConsulDatacenter string `protobuf:"bytes,14,opt,name=consulDatacenter,proto3" json:"consulDatacenter,omitempty"`
|
||||
ConsulServiceTag string `protobuf:"bytes,15,opt,name=consulServiceTag,proto3" json:"consulServiceTag,omitempty"`
|
||||
ConsulRefreshInterval int64 `protobuf:"varint,16,opt,name=consulRefreshInterval,proto3" json:"consulRefreshInterval,omitempty"`
|
||||
AuthSecretName string `protobuf:"bytes,17,opt,name=authSecretName,proto3" json:"authSecretName,omitempty"`
|
||||
Protocol string `protobuf:"bytes,18,opt,name=protocol,proto3" json:"protocol,omitempty"`
|
||||
Sni string `protobuf:"bytes,19,opt,name=sni,proto3" json:"sni,omitempty"`
|
||||
McpServerExportDomains []string `protobuf:"bytes,20,rep,name=mcpServerExportDomains,proto3" json:"mcpServerExportDomains,omitempty"`
|
||||
McpServerBaseUrl string `protobuf:"bytes,21,opt,name=mcpServerBaseUrl,proto3" json:"mcpServerBaseUrl,omitempty"`
|
||||
EnableMCPServer *wrappers.BoolValue `protobuf:"bytes,22,opt,name=enableMCPServer,proto3" json:"enableMCPServer,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegistryConfig) Reset() {
|
||||
@@ -295,6 +300,27 @@ func (x *RegistryConfig) GetSni() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RegistryConfig) GetMcpServerExportDomains() []string {
|
||||
if x != nil {
|
||||
return x.McpServerExportDomains
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RegistryConfig) GetMcpServerBaseUrl() string {
|
||||
if x != nil {
|
||||
return x.McpServerBaseUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RegistryConfig) GetEnableMCPServer() *wrappers.BoolValue {
|
||||
if x != nil {
|
||||
return x.EnableMCPServer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_networking_v1_mcp_bridge_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_networking_v1_mcp_bridge_proto_rawDesc = []byte{
|
||||
@@ -303,61 +329,76 @@ var file_networking_v1_mcp_bridge_proto_rawDesc = []byte{
|
||||
0x12, 0x15, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
||||
0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
|
||||
0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69,
|
||||
0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x52, 0x0a, 0x09, 0x4d, 0x63, 0x70, 0x42,
|
||||
0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
|
||||
0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x69, 0x67, 0x72,
|
||||
0x65, 0x73, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x52, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xd3, 0x05, 0x0a,
|
||||
0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||
0x17, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0,
|
||||
0x41, 0x02, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x06,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41,
|
||||
0x02, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12,
|
||||
0x6e, 0x61, 0x63, 0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x4b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x61, 0x63, 0x6f,
|
||||
0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x61,
|
||||
0x63, 0x6f, 0x73, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b,
|
||||
0x65, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x61,
|
||||
0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x26,
|
||||
0x0a, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x47,
|
||||
0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x61, 0x63,
|
||||
0x6f, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x6e, 0x61, 0x63, 0x6f,
|
||||
0x73, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
|
||||
0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x52, 0x65, 0x66,
|
||||
0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x28, 0x0a, 0x0f,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18,
|
||||
0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x7a, 0x6b, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e,
|
||||
0x7a, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a,
|
||||
0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x75, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x61, 0x67, 0x18, 0x0f,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x54, 0x61, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18,
|
||||
0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x52, 0x65, 0x66,
|
||||
0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x0e,
|
||||
0x61, 0x75, 0x74, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x11,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73,
|
||||
0x6e, 0x69, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x61, 0x6c, 0x69, 0x62, 0x61, 0x62, 0x61, 0x2f, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73, 0x73,
|
||||
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2f,
|
||||
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65,
|
||||
0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x52, 0x0a, 0x09, 0x4d, 0x63, 0x70, 0x42, 0x72, 0x69,
|
||||
0x64, 0x67, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x69, 0x65,
|
||||
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73,
|
||||
0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a,
|
||||
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xfd, 0x06, 0x0a, 0x0e, 0x52,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x17, 0x0a,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02,
|
||||
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x64, 0x6f,
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52,
|
||||
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x12, 0x2e, 0x0a, 0x12, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6e, 0x61,
|
||||
0x63, 0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b,
|
||||
0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x41,
|
||||
0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x61, 0x63, 0x6f,
|
||||
0x73, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79,
|
||||
0x12, 0x2a, 0x0a, 0x10, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x49, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x61, 0x63, 0x6f,
|
||||
0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e,
|
||||
0x6e, 0x61, 0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x09,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x47, 0x72, 0x6f,
|
||||
0x75, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x61, 0x63, 0x6f, 0x73,
|
||||
0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x52,
|
||||
0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0b,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x61, 0x63, 0x6f, 0x73, 0x52, 0x65, 0x66, 0x72, 0x65,
|
||||
0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x75, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0c, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x7a, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x7a, 0x6b,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x10,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x44, 0x61,
|
||||
0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x75, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x61, 0x67, 0x18, 0x0f, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x54, 0x61, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x52, 0x65,
|
||||
0x66, 0x72, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x10, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x52, 0x65, 0x66, 0x72, 0x65,
|
||||
0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x0e, 0x61, 0x75,
|
||||
0x74, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x11, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x12,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x6e, 0x69,
|
||||
0x12, 0x36, 0x0a, 0x16, 0x6d, 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x78, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09,
|
||||
0x52, 0x16, 0x6d, 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x78, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x63, 0x70, 0x53,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x61, 0x73, 0x65, 0x55, 0x72, 0x6c, 0x18, 0x15, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x10, 0x6d, 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x61, 0x73,
|
||||
0x65, 0x55, 0x72, 0x6c, 0x12, 0x44, 0x0a, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x43,
|
||||
0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x6c, 0x69, 0x62, 0x61, 0x62, 0x61,
|
||||
0x2f, 0x68, 0x69, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6e, 0x65, 0x74,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -374,16 +415,18 @@ func file_networking_v1_mcp_bridge_proto_rawDescGZIP() []byte {
|
||||
|
||||
var file_networking_v1_mcp_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_networking_v1_mcp_bridge_proto_goTypes = []interface{}{
|
||||
(*McpBridge)(nil), // 0: higress.networking.v1.McpBridge
|
||||
(*RegistryConfig)(nil), // 1: higress.networking.v1.RegistryConfig
|
||||
(*McpBridge)(nil), // 0: higress.networking.v1.McpBridge
|
||||
(*RegistryConfig)(nil), // 1: higress.networking.v1.RegistryConfig
|
||||
(*wrappers.BoolValue)(nil), // 2: google.protobuf.BoolValue
|
||||
}
|
||||
var file_networking_v1_mcp_bridge_proto_depIdxs = []int32{
|
||||
1, // 0: higress.networking.v1.McpBridge.registries:type_name -> higress.networking.v1.RegistryConfig
|
||||
1, // [1:1] is the sub-list for method output_type
|
||||
1, // [1:1] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
2, // 1: higress.networking.v1.RegistryConfig.enableMCPServer:type_name -> google.protobuf.BoolValue
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_networking_v1_mcp_bridge_proto_init() }
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/api/field_behavior.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
// $schema: higress.networking.v1.McpBridge
|
||||
// $title: McpBridge
|
||||
@@ -66,4 +68,7 @@ message RegistryConfig {
|
||||
string authSecretName = 17;
|
||||
string protocol = 18;
|
||||
string sni = 19;
|
||||
repeated string mcpServerExportDomains = 20;
|
||||
string mcpServerBaseUrl = 21;
|
||||
google.protobuf.BoolValue enableMCPServer = 22;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ DOCKER_ALL_VARIANTS ?= debug distroless
|
||||
INCLUDE_UNTAGGED_DEFAULT ?= false
|
||||
DEFAULT_DISTRIBUTION=debug
|
||||
|
||||
HIGRESS_DOCKER_BUILDX_RULE ?= $(foreach VARIANT,$(DOCKER_BUILD_VARIANTS), time (mkdir -p $(HIGRESS_DOCKER_BUILD_TOP)/$@ && TARGET_ARCH=$(TARGET_ARCH) ./docker/docker-copy.sh $^ $(HIGRESS_DOCKER_BUILD_TOP)/$@ && cd $(HIGRESS_DOCKER_BUILD_TOP)/$@ $(BUILD_PRE) && docker buildx create --name higress --node higress0 --platform linux/amd64,linux/arm64 --use && docker buildx build --no-cache --platform linux/amd64,linux/arm64 $(BUILD_ARGS) --build-arg BASE_DISTRIBUTION=$(call normalize-tag,$(VARIANT)) -t $(HUB)/higress:$(TAG)$(call variant-tag,$(VARIANT)) -f Dockerfile.higress . --push ); )
|
||||
HIGRESS_DOCKER_RULE ?= $(foreach VARIANT,$(DOCKER_BUILD_VARIANTS), time (mkdir -p $(HIGRESS_DOCKER_BUILD_TOP)/$@ && TARGET_ARCH=$(TARGET_ARCH) ./docker/docker-copy.sh $^ $(HIGRESS_DOCKER_BUILD_TOP)/$@ && cd $(HIGRESS_DOCKER_BUILD_TOP)/$@ $(BUILD_PRE) && docker build $(BUILD_ARGS) --build-arg BASE_DISTRIBUTION=$(call normalize-tag,$(VARIANT)) -t $(HUB)/higress:$(TAG)$(call variant-tag,$(VARIANT)) -f Dockerfile.higress . ); )
|
||||
IMG ?= higress
|
||||
IMG_URL ?= $(HUB)/$(IMG):$(TAG)
|
||||
|
||||
HIGRESS_DOCKER_BUILDX_RULE ?= $(foreach VARIANT,$(DOCKER_BUILD_VARIANTS), time (mkdir -p $(HIGRESS_DOCKER_BUILD_TOP)/$@ && TARGET_ARCH=$(TARGET_ARCH) ./docker/docker-copy.sh $^ $(HIGRESS_DOCKER_BUILD_TOP)/$@ && cd $(HIGRESS_DOCKER_BUILD_TOP)/$@ $(BUILD_PRE) && docker buildx create --name higress --node higress0 --platform linux/amd64,linux/arm64 --use && docker buildx build --no-cache --platform linux/amd64,linux/arm64 $(BUILD_ARGS) --build-arg BASE_DISTRIBUTION=$(call normalize-tag,$(VARIANT)) -t $(IMG_URL)$(call variant-tag,$(VARIANT)) -f Dockerfile.higress . --push ); )
|
||||
HIGRESS_DOCKER_RULE ?= $(foreach VARIANT,$(DOCKER_BUILD_VARIANTS), time (mkdir -p $(HIGRESS_DOCKER_BUILD_TOP)/$@ && TARGET_ARCH=$(TARGET_ARCH) ./docker/docker-copy.sh $^ $(HIGRESS_DOCKER_BUILD_TOP)/$@ && cd $(HIGRESS_DOCKER_BUILD_TOP)/$@ $(BUILD_PRE) && docker build $(BUILD_ARGS) --build-arg BASE_DISTRIBUTION=$(call normalize-tag,$(VARIANT)) -t $(IMG_URL)$(call variant-tag,$(VARIANT)) -f Dockerfile.higress . ); )
|
||||
|
||||
143
docs/architecture.md
Normal file
143
docs/architecture.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Higress 核心组件和原理
|
||||
|
||||
Higress 是基于 Envoy 和 Istio 进行二次定制化开发构建和功能增强,同时利用 Envoy 和 Istio 一些插件机制,实现了一个轻量级的网关服务。其包括 3 个核心组件:Higress Controller(控制器)、Higress Gateway(网关)和 Higress Console(控制台)。
|
||||
下图概况了其核心工作流程:
|
||||
|
||||

|
||||
|
||||
本章将重点介绍 Higress 的两个核心组件:Higress Controller 和 Higress Gateway。
|
||||
|
||||
## 1 Higress Console
|
||||
|
||||
Higress Console 是 Higress 网关的管理控制台,主要功能是管理 Higress 网关的路由配置、插件配置等。
|
||||
|
||||
### 1.1 Higress Admin SDK
|
||||
|
||||
Higress Admin SDK 脱胎于 Higress Console。起初,它作为 Higress Console 的一部分,为前端界面提供实际的功能支持。后来考虑到对接外部系统等需求,将配置管理的部分剥离出来,形成一个独立的逻辑组件,便于和各个系统进行对接。目前支持服务来源管理、服务管理、路由管理、域名管理、证书管理、插件管理等功能。
|
||||
Higress Admin SDK 现在只提供 Java 版本,且要求 JDK 版本不低于 17。具体如何集成请参考 Higress 官方 BLOG [如何使用 Higress Admin SDK 进行配置管理](https://higress.io/zh-cn/blog/admin-sdk-intro)。
|
||||
|
||||
## 2 Higress Controller
|
||||
|
||||
Higress Controller(控制器) 是 Higress 的核心组件,其功能主要是实现 Higress 网关的服务发现、动态配置管理,以及动态下发配置给数据面。Higress Controller 内部包含两个子组件:Discovery 和 Higress Core。
|
||||
|
||||
### 2.1 Discovery 组件
|
||||
|
||||
Discovery 组件(Istio Pilot-Discovery)是 Istio 的核心组件,负责服务发现、配置管理、证书签发、控制面和数据面之间的通讯和配置下发等。Discovery 内部结构比较复杂,本文只介绍 Discovery 配置管理和服务发现的基本原理,其核心功能的详细介绍可以参考赵化冰老师的 BLOG [Istio Pilot 组件介绍](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)。
|
||||
Discovery 将 Kubernetes Service、Gateway API 配置等转换成 Istio 配置,然后将所有 Istio 配置合并转成符合 xDS 接口规范的数据结构,通过 GRPC 下发到数据面的 Envoy。其工作原理如下图:
|
||||
|
||||

|
||||
|
||||
#### 2.1.1 Config Controller
|
||||
|
||||
Discovery 为了更好管理 Istio 配置来源,提供 `Config Controller` 用于管理各种配置来源,目前支持 4 种类型的 `Config Controller`:
|
||||
|
||||
- Kubernetes:使用 Kubernetes 作为配置信息来源,该方式的直接依赖 Kubernetes 强大的 CRD 机制来存储配置信息,简单方便,是 Istio 最开始使用的配置信息存储方案, 其中包括 `Kubernetes Controller` 和 `Gateway API Controller` 两个实现。
|
||||
- MCP(Mesh Configuration Protocol):使用 Kubernetes 存储配置数据导致了 Istio 和 Kubernetes 的耦合,限制了 Istio 在非 Kubernetes 环境下的运用。为了解决该耦合,Istio 社区提出了 MCP。
|
||||
- Memory:一个基于内存的 Config Controller 实现,主要用于测试。
|
||||
- File:一个基于文件的 Config Controller 实现,主要用于测试。
|
||||
|
||||
1. Istio 配置
|
||||
|
||||
Istio 配置包括:`Gateway`、`VirtualService`、`DestinationRule`、`ServiceEntry`、`EnvoyFilter`、`WasmPlugin`、`WorkloadEntry`、`WorkloadGroup` 等,可以参考 Istio 官方文档[流量管理](https://istio.io/latest/zh/docs/reference/config/networking/)了解更多配置信息。
|
||||
|
||||
2. Gateway API 配置
|
||||
|
||||
Gateway API 配置包括:`GatewayClass`、`Gateway`、`HttpRoute`、`TCPRoute`、`GRPCRoute` 等, 可以参考 Gateway API 官方文档 [Gateway API](https://gateway-api.sigs.k8s.io/api-types/gateway/) 了解更多配置信息。
|
||||
|
||||
3. MCP over xDS
|
||||
|
||||
Discovery 作为 MCP Client,任何实现了 MCP 协议的 Server 都可以通过 MCP 协议向 Discovery 下发配置信息,从而消除了 Istio 和 Kubernetes 之间的耦合, 同时使 Istio 的配置信息处理更加灵活和可扩展。
|
||||
同时 MCP 是一种基于 xDS 协议的配置管理协议,Higress Core 通过实现 MCP 协议,使 Higress Core 成为 Discovery 的 Istio 配置来源。
|
||||
|
||||
4. Config Controller 来源配置
|
||||
|
||||
在 `higress-system` 命名空间中,名为 `higress-config` 的 Configmap 中,`mesh` 配置项包含一个 `configSources` 属性用于配置来源。其 Configmap 部分配置项如下:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: higress-config
|
||||
namespace: higress-system
|
||||
data:
|
||||
mesh: |-
|
||||
accessLogEncoding: TEXT
|
||||
...
|
||||
configSources:
|
||||
- address: xds://127.0.0.1:15051
|
||||
- address: k8s://
|
||||
...
|
||||
meshNetworks: "networks: {}"
|
||||
```
|
||||
|
||||
#### 2.1.2 Service Controller
|
||||
|
||||
`Service Controller` 用于管理各种 `Service Registry`,提供服务发现数据,目前 Istio 支持的 `Service Registry` 主要包括:
|
||||
|
||||
- Kubernetes:对接 Kubernetes Registry,可以将 Kubernetes 中定义的 Service 和 Endpoint 采集到 Istio 中。
|
||||
- Memory:一个基于内存的 Service Controller 实现,主要用于测试。
|
||||
|
||||
### 2.2 Higress Core 组件
|
||||
|
||||
Higress Core 核心逻辑如下图:
|
||||
|
||||

|
||||
|
||||
|
||||
Higress Core 内部包含两个核心子组件: Ingress Config 和 Cert Server。
|
||||
|
||||
#### 2.2.1 Ingress Config
|
||||
|
||||
Ingress Config 包含 6 个控制器,各自负责不同的功能:
|
||||
|
||||
- Ingress Controller:监听 Ingress 资源,将 Ingress 转换为 Istio 的 Gateway、VirtualService、DestinationRule 等资源。
|
||||
- Gateway Controller:监听 Gateway、VirtualService、DestinationRule 等资源。
|
||||
- McpBridge Controller:根据 McpBridge 的配置,将来自 Nacos、Eureka、Consul、Zookeeper 等外部注册中心或 DNS 的服务信息转换成 Istio ServiceEntry 资源。
|
||||
- Http2Rpc Controller:监听 Http2Rpc 资源,实现 HTTP 协议到 RPC 协议的转换。用户可以通过配置协议转换,将 RPC 服务以 HTTP 接口的形式暴露,从而使用 HTTP 请求调用 RPC 接口。
|
||||
- WasmPlugin Controller:监听 WasmPlugin 资源,将 Higress WasmPlugin 转化为 Istio WasmPlugin。Higress WasmPlugin 在 Istio WasmPlugin 的基础上进行了扩展,支持全局、路由、域名、服务级别的配置。
|
||||
- ConfigmapMgr:监听 Higress 的全局配置 `higress-config` ConfigMap,可以根据 tracing、gzip 等配置构造 EnvoyFilter。
|
||||
|
||||
#### 2.2.2 Cert Server
|
||||
|
||||
Cert Server 管理 Secret 资源和证书自动签发。
|
||||
|
||||
## 3 Higress Gateway
|
||||
|
||||
Higress Gateway 内部包含两个子组件:Pilot Agent 和 Envoy。Pilot Agent 主要负责 Envoy 的启动和配置,同时代理 Envoy xDS 请求到 Discovery。 Envoy 作为数据面,负责接收控制面的配置下发,并代理请求到业务服务。 Pilot Agent 和 Envoy 之间通讯协议是使用 xDS 协议, 通过 Unix Domain Socket(UDS)进行通信。
|
||||
Envoy 核心架构如下图:
|
||||
|
||||

|
||||
|
||||
### 1 Envoy 核心组件
|
||||
|
||||
- 下游(Downstream):
|
||||
下游是 Envoy 的客户端,它们负责发起请求并接收 Envoy 的响应。下游通常是最终用户的设备或服务,它们通过 Envoy 代理与后端服务进行通信。
|
||||
|
||||
- 上游(Upstream):
|
||||
上游是 Envoy 的后端服务器,它们接收 Envoy 代理的连接和请求。上游提供服务或数据,对来自下游客户端的请求进行处理并返回响应。
|
||||
|
||||
- 监听器(Listener):
|
||||
监听器是可以接受来自下游客户端连接的网络地址(如 IP 地址和端口,Unix Domain Socket 等)。Envoy 支持在单个进程中配置任意数量的监听器。监听器可以通过 `Listener Discovery Service(LDS)`来动态发现和更新。
|
||||
|
||||
- 路由(Router):
|
||||
路由器是 Envoy 中连接下游和上游的桥梁。它负责决定如何将监听器接收到的请求路由到适当的集群。路由器根据配置的路由规则,如路径、HTTP 标头 等,来确定请求的目标集群,从而实现精确的流量控制和路由。路由器可以通过 `Route Discovery Service(RDS)`来动态发现和更新。
|
||||
|
||||
- 集群(Cluster):
|
||||
集群是一组逻辑上相似的服务提供者的集合。集群成员的选择由负载均衡策略决定,确保请求能够均匀或按需分配到不同的服务实例。集群可以通过 `Cluster Discovery Service(CDS)`来动态发现和更新。
|
||||
|
||||
- 端点(Endpoint):
|
||||
端点是上游集群中的具体服务实例,可以是 IP 地址和端口号的组合。端点可以通过 `Endpoint Discovery Service(EDS)`来动态发现和更新。
|
||||
|
||||
- SSL/TLS:
|
||||
Envoy 可以通过 `Secret Discovery Service (SDS)` 动态获取监听器和集群所需的 TLS 证书、私钥以及信任的根证书和撤销机制等配置信息。
|
||||
|
||||
通过这些组件的协同工作,Envoy 能够高效地处理网络请求,提供流量管理、负载均衡、服务发现和动态路由等关键功能。
|
||||
要详细了解 Envoy 的工作原理,可以参考[Envoy 官方文档](https://www.envoyproxy.io/docs/envoy/latest/intro/intro),最佳的方式可以通过一个请求通过 [Envoy 代理的生命周期](https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request)事件的过程来理解 Envoy 的工作原理。
|
||||
|
||||
|
||||
## 参考
|
||||
|
||||
- [1] [Istio Pilot 组件介绍](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)
|
||||
- [2] [Istio 服务注册插件机制代码解析](https://www.zhaohuabing.com/post/2019-02-18-pilot-service-registry-code-analysis/)
|
||||
- [3] [Istio Pilot代码深度解析](https://www.zhaohuabing.com/post/2019-10-21-pilot-discovery-code-analysis/)
|
||||
- [4] [Envoy 官方文档](https://www.envoyproxy.io/docs/envoy/latest/intro/intro)
|
||||
BIN
docs/images/img_02_01.png
Normal file
BIN
docs/images/img_02_01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
BIN
docs/images/img_02_02.png
Normal file
BIN
docs/images/img_02_02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
BIN
docs/images/img_02_03.png
Normal file
BIN
docs/images/img_02_03.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
BIN
docs/images/img_02_04.png
Normal file
BIN
docs/images/img_02_04.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
Submodule envoy/envoy updated: b3541845c1...17cf01d9f6
45
go.mod
45
go.mod
@@ -1,8 +1,6 @@
|
||||
module github.com/alibaba/higress
|
||||
|
||||
go 1.21.0
|
||||
|
||||
toolchain go1.22.2
|
||||
go 1.22.2
|
||||
|
||||
replace github.com/spf13/viper => github.com/istio/viper v1.3.3-0.20190515210538-2789fed3109c
|
||||
|
||||
@@ -23,6 +21,7 @@ require (
|
||||
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5
|
||||
github.com/dubbogo/gost v1.13.1
|
||||
github.com/envoyproxy/go-control-plane v0.11.2-0.20230725211550-11bfe846bcd4
|
||||
github.com/go-errors/errors v1.4.2
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/google/go-cmp v0.6.0
|
||||
@@ -40,7 +39,7 @@ require (
|
||||
github.com/tidwall/gjson v1.17.0
|
||||
go.uber.org/atomic v1.11.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/net v0.33.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.33.0
|
||||
@@ -72,7 +71,27 @@ require (
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/alecholmes/xfccparser v0.1.0 // indirect
|
||||
github.com/alecthomas/participle v0.4.1 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 // indirect
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2 // indirect
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 // indirect
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 // indirect
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2 // indirect
|
||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
||||
github.com/alibabacloud-go/kms-20160120/v3 v3.2.3 // indirect
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
|
||||
github.com/alibabacloud-go/tea v1.2.2 // indirect
|
||||
github.com/alibabacloud-go/tea-utils v1.4.4 // indirect
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800 // indirect
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 // indirect
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8 // indirect
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5 // indirect
|
||||
github.com/aliyun/credentials-go v1.4.3 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
@@ -83,10 +102,12 @@ require (
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/clbanning/mxj v1.8.4 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.5.5 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.6.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/docker/cli v24.0.7+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
@@ -99,7 +120,6 @@ require (
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
@@ -167,6 +187,7 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/openshift/api v0.0.0-20230720094506-afcbe27aec7c // indirect
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
@@ -184,6 +205,7 @@ require (
|
||||
github.com/tetratelabs/wazero v1.7.3 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
@@ -199,14 +221,14 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.25.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.13.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/term v0.27.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
@@ -252,5 +274,6 @@ replace github.com/caddyserver/certmagic => github.com/2456868764/certmagic v1.0
|
||||
|
||||
replace (
|
||||
github.com/dubbogo/gost => github.com/johnlanni/gost v1.11.23-0.20220713132522-0967a24036c6
|
||||
github.com/nacos-group/nacos-sdk-go/v2 => github.com/luoxiner/nacos-sdk-go/v2 v2.2.9-60
|
||||
golang.org/x/exp => golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
|
||||
)
|
||||
|
||||
144
go.sum
144
go.sum
@@ -683,9 +683,68 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.9/go.mod h1:bb+Io8Sn2RuM3/Rpme6ll86jMyFSrD1bxeV/+v61KeU=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE=
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
|
||||
github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
|
||||
github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
|
||||
github.com/alibabacloud-go/kms-20160120/v3 v3.2.3 h1:vamGcYQFwXVqR6RWcrVTTqlIXZVsYjaA7pZbx+Xw6zw=
|
||||
github.com/alibabacloud-go/kms-20160120/v3 v3.2.3/go.mod h1:3rIyughsFDLie1ut9gQJXkWkMg/NfXBCk+OtXnPu3lw=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
|
||||
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
|
||||
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA=
|
||||
github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU=
|
||||
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.4 h1:lxCDvNCdTo9FaXKKq45+4vGETQUKNOW/qKTcX9Sk53o=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.4/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.3/go.mod h1:sj1PbjPodAVTqGTA3olprfeeqqmwD0A5OQz94o9EuXQ=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 h1:PpfENOj/vPfhhy9N2OFRjpue0hjM5XqAp2thFmkXXIk=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800 h1:ie/8RxBOfKZWcrbYSJi2Z8uX8TcOlSMwPlEJh83OeOw=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 h1:nJYyoFP+aqGKgPs9JeZgS1rWQ4NndNR0Zfhh161ZltU=
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1/go.mod h1:WzGOmFFTlUzXM03CJnHWMQ85UN6QGpOXZocCjwkiyOg=
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8 h1:QeUdR7JF7iNCvO/81EhxEr3wDwxk4YBoYZOq6E0AjHI=
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8/go.mod h1:xP0KIZry6i7oGPF24vhAPr1Q8vLZRcMcxtft5xDKwCU=
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5 h1:8S0mtD101RDYa0LXwdoqgN0RxdMmmJYjq8g2mk7/lQ4=
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5/go.mod h1:M19fxYz3gpm0ETnoKweYyYtqrtnVtrpKFpwsghbw+cQ=
|
||||
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
|
||||
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
|
||||
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
|
||||
github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/aliyun/credentials-go v1.4.3 h1:N3iHyvHRMyOwY1+0qBLSf3hb5JFiOujVSVuEpgeGttY=
|
||||
github.com/aliyun/credentials-go v1.4.3/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
@@ -755,7 +814,6 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.11-0.20170329064859-445be9e134b2/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@@ -765,6 +823,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
|
||||
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
||||
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
|
||||
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
@@ -813,6 +873,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
@@ -1162,8 +1224,9 @@ github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97Dwqy
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
@@ -1371,6 +1434,8 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhn
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/luoxiner/nacos-sdk-go/v2 v2.2.9-60 h1:FA/azfz2nSkMc1XR8LeqhcAiA/2/sOMcyBGYCTUc+Cs=
|
||||
github.com/luoxiner/nacos-sdk-go/v2 v2.2.9-60/go.mod h1:9FKXl6FqOiVmm72i8kADtbeK71egyG9y3uRDBg41tpQ=
|
||||
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
|
||||
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
|
||||
github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
|
||||
@@ -1460,8 +1525,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/nacos-group/nacos-sdk-go v1.0.8 h1:8pEm05Cdav9sQgJSv5kyvlgfz0SzFUUGI3pWX6SiSnM=
|
||||
github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA=
|
||||
github.com/nacos-group/nacos-sdk-go/v2 v2.1.2 h1:A8GV6j0rw80I6tTKSav/pTpEgNECYXeFvZCsiLBWGnQ=
|
||||
github.com/nacos-group/nacos-sdk-go/v2 v2.1.2/go.mod h1:ys/1adWeKXXzbNWfRNbaFlX/t6HVLWdpsNDvmoWTw0g=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
@@ -1517,6 +1580,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.3.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc h1:Ak86L+yDSOzKFa7WM5bf5itSOo1e3Xh8bm5YCMUXIjQ=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
@@ -1560,7 +1625,6 @@ github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
@@ -1593,7 +1657,6 @@ github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/prometheus/prometheus v0.45.0 h1:O/uG+Nw4kNxx/jDPxmjsSDd+9Ohql6E7ZSY1x5x/0KI=
|
||||
@@ -1643,8 +1706,9 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0=
|
||||
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
@@ -1713,6 +1777,9 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
@@ -1746,6 +1813,7 @@ github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+Seva
|
||||
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
@@ -1832,7 +1900,6 @@ go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0
|
||||
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
@@ -1849,7 +1916,6 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -1868,9 +1934,12 @@ golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
@@ -1882,8 +1951,13 @@ golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
|
||||
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
@@ -1970,6 +2044,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
@@ -2008,8 +2083,13 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -2059,8 +2139,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -2107,6 +2187,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -2156,7 +2237,6 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -2181,8 +2261,13 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -2195,8 +2280,13 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -2214,8 +2304,11 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -2225,7 +2318,6 @@ golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
@@ -2279,6 +2371,7 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
@@ -2646,6 +2739,7 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
apiVersion: v2
|
||||
appVersion: 2.0.1
|
||||
appVersion: 2.1.2-rc.1
|
||||
description: Helm chart for deploying higress gateways
|
||||
icon: https://higress.io/img/higress_logo_small.png
|
||||
home: http://higress.io/
|
||||
keywords:
|
||||
- higress
|
||||
- gateways
|
||||
- higress
|
||||
- gateways
|
||||
name: higress-core
|
||||
sources:
|
||||
- http://github.com/alibaba/higress
|
||||
- http://github.com/alibaba/higress
|
||||
dependencies:
|
||||
- condition: global.enableRedis
|
||||
name: redis
|
||||
repository: "file://../redis"
|
||||
version: 0.0.1
|
||||
type: application
|
||||
version: 2.0.1
|
||||
version: 2.1.2-rc.1
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
Installs the core components of cloud-native gateway [Higress](http://higress.io/)
|
||||
|
||||
**Note:** It is highly recommended to install the whole package of Higress. Please visit https://higress.io/docs/user/quickstart/ for details.
|
||||
**Note:** It is highly recommended to install the whole package of Higress. Please visit https://higress.io/docs/user/quickstart/ for details.
|
||||
|
||||
23
helm/core/charts/redis/.helmignore
Normal file
23
helm/core/charts/redis/.helmignore
Normal file
@@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
24
helm/core/charts/redis/Chart.yaml
Normal file
24
helm/core/charts/redis/Chart.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
name: redis
|
||||
description: A Helm chart for Kubernetes
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.0.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "7.4.0-v3"
|
||||
34
helm/core/charts/redis/templates/_helpers.tpl
Normal file
34
helm/core/charts/redis/templates/_helpers.tpl
Normal file
@@ -0,0 +1,34 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
|
||||
{{- define "redis.name" -}}
|
||||
{{- .Values.redis.name | default "redis-stack-server" -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "redis.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "redis.labels" -}}
|
||||
helm.sh/chart: {{ include "redis.chart" . }}
|
||||
{{ include "redis.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "redis.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "redis.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
10
helm/core/charts/redis/templates/configmap.yaml
Normal file
10
helm/core/charts/redis/templates/configmap.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "redis.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
redis-stack.conf: |
|
||||
{{- if .Values.redis.password }}
|
||||
requirepass {{ .Values.redis.password }}
|
||||
{{- end }}
|
||||
16
helm/core/charts/redis/templates/pvc.yaml
Normal file
16
helm/core/charts/redis/templates/pvc.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.redis.persistence.enabled }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "redis.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{- range .Values.redis.persistence.accessModes }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
storageClassName: {{ .Values.redis.persistence.storageClass }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.redis.persistence.size | quote }}
|
||||
{{- end }}
|
||||
15
helm/core/charts/redis/templates/service.yaml
Normal file
15
helm/core/charts/redis/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "redis.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "redis.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.redis.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.redis.service.port }}
|
||||
targetPort: 6379
|
||||
protocol: TCP
|
||||
selector:
|
||||
{{- include "redis.selectorLabels" . | nindent 4 }}
|
||||
74
helm/core/charts/redis/templates/statefulset.yaml
Normal file
74
helm/core/charts/redis/templates/statefulset.yaml
Normal file
@@ -0,0 +1,74 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "redis.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "redis.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.redis.replicas }}
|
||||
serviceName: {{ include "redis.name" . }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "redis.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "redis.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
{{- with .Values.global.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.global.hub }}/{{ .Values.redis.image | default "redis-stack-server" }}:{{ .Values.redis.tag | default .Chart.AppVersion }}"
|
||||
{{- if .Values.global.imagePullPolicy }}
|
||||
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 6379
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 6379
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 6379
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
{{- toYaml .Values.redis.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /redis-stack.conf
|
||||
subPath: redis-stack.conf
|
||||
{{- if .Values.redis.persistence.enabled }}
|
||||
- name: db
|
||||
mountPath: /data
|
||||
{{- end }}
|
||||
{{- with .Values.redis.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.redis.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.redis.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ include "redis.name" . }}
|
||||
{{- if .Values.redis.persistence.enabled }}
|
||||
- name: db
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ include "redis.name" . }}
|
||||
{{- end }}
|
||||
48
helm/core/charts/redis/values.yaml
Normal file
48
helm/core/charts/redis/values.yaml
Normal file
@@ -0,0 +1,48 @@
|
||||
# Default values for redis.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
global:
|
||||
# -- Specify the image registry and pull policy
|
||||
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
|
||||
# -- Specify image pull policy if default behavior isn't desired.
|
||||
# Default behavior: latest images will be Always else IfNotPresent.
|
||||
imagePullPolicy: ""
|
||||
# -- Specify the image pull secrets
|
||||
imagePullSecrets: []
|
||||
|
||||
redis:
|
||||
# -- Specify the name
|
||||
name: redis-stack-server
|
||||
# -- Specify the image
|
||||
image: "redis-stack-server"
|
||||
# -- Specify the tag
|
||||
tag: "7.4.0-v3"
|
||||
# -- Specify the number of replicas
|
||||
replicas: 1
|
||||
# -- Specify the password, if not set, no password is used
|
||||
password: ""
|
||||
# -- Service parameters
|
||||
service:
|
||||
# -- Exporter service type
|
||||
type: ClusterIP
|
||||
# -- Exporter service port
|
||||
port: 6379
|
||||
# -- Specify the resources
|
||||
resources: {}
|
||||
# -- NodeSelector Node labels for Redis
|
||||
nodeSelector: {}
|
||||
# -- Tolerations for Redis
|
||||
tolerations: []
|
||||
# -- Affinity for Redis
|
||||
affinity: {}
|
||||
persistence:
|
||||
# -- Enable persistence on Redis
|
||||
enabled: false
|
||||
# -- If defined, storageClassName: <storageClass>
|
||||
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner
|
||||
storageClass: ""
|
||||
# -- Persistent Volume access modes
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
# -- Persistent Volume size
|
||||
size: 1Gi
|
||||
@@ -1,3 +1,4 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
|
||||
@@ -7,9 +7,6 @@ Rendering the pod template of gateway component.
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- if .Values.global.enableHigressIstio }}
|
||||
"enableHigressIstio": "true"
|
||||
{{- end }}
|
||||
{{- if .Values.gateway.podAnnotations }}
|
||||
{{- toYaml .Values.gateway.podAnnotations | nindent 6 }}
|
||||
{{- end }}
|
||||
@@ -18,6 +15,9 @@ template:
|
||||
{{- with .Values.gateway.revision }}
|
||||
istio.io/rev: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.gateway.podLabels }}
|
||||
{{- toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- include "gateway.selectorLabels" . | nindent 6 }}
|
||||
spec:
|
||||
{{- with .Values.gateway.imagePullSecrets }}
|
||||
@@ -45,9 +45,9 @@ template:
|
||||
- router
|
||||
- --domain
|
||||
- $(POD_NAMESPACE).svc.cluster.local
|
||||
- --proxyLogLevel=warning
|
||||
- --proxyComponentLogLevel=misc:error
|
||||
- --log_output_level=all:info
|
||||
- --proxyLogLevel={{- default "warning" .Values.global.proxy.logLevel }}
|
||||
- --proxyComponentLogLevel={{- default "misc:error" .Values.global.proxy.componentLogLevel }}
|
||||
- --log_output_level={{- default "default:info" .Values.global.logging.level }}
|
||||
- --serviceCluster=higress-gateway
|
||||
securityContext:
|
||||
{{- if .Values.gateway.containerSecurityContext }}
|
||||
@@ -131,7 +131,7 @@ template:
|
||||
- name: ISTIO_META_REQUESTED_NETWORK_VIEW
|
||||
value: "{{.}}"
|
||||
{{- end }}
|
||||
{{- range $key, $val := .Values.env }}
|
||||
{{- range $key, $val := .Values.gateway.env }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $val | quote }}
|
||||
{{- end }}
|
||||
@@ -268,11 +268,7 @@ template:
|
||||
{{- end }}
|
||||
- name: higress-ca-root-cert
|
||||
configMap:
|
||||
{{- if .Values.global.enableHigressIstio }}
|
||||
name: istio-ca-root-cert
|
||||
{{- else }}
|
||||
name: higress-ca-root-cert
|
||||
{{- end }}
|
||||
- name: config
|
||||
configMap:
|
||||
name: higress-config
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
accessLogFile: "/dev/stdout"
|
||||
{{- end }}
|
||||
ingressControllerMode: "OFF"
|
||||
accessLogFormat: '{"authority":"%REQ(X-ENVOY-ORIGINAL-HOST?:AUTHORITY)%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","duration":"%DURATION%","istio_policy_status":"%DYNAMIC_METADATA(istio.mixer:status)%","method":"%REQ(:METHOD)%","path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","request_id":"%REQ(X-REQUEST-ID)%","requested_server_name":"%REQUESTED_SERVER_NAME%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","route_name":"%ROUTE_NAME%","start_time":"%START_TIME%","trace_id":"%REQ(X-B3-TRACEID)%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_host":"%UPSTREAM_HOST%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","upstream_service_time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","user_agent":"%REQ(USER-AGENT)%","x_forwarded_for":"%REQ(X-FORWARDED-FOR)%","response_code_details":"%RESPONSE_CODE_DETAILS%"}
|
||||
accessLogFormat: '{"ai_log":"%FILTER_STATE(wasm.ai_log:PLAIN)%","authority":"%REQ(X-ENVOY-ORIGINAL-HOST?:AUTHORITY)%","bytes_received":"%BYTES_RECEIVED%","bytes_sent":"%BYTES_SENT%","downstream_local_address":"%DOWNSTREAM_LOCAL_ADDRESS%","downstream_remote_address":"%DOWNSTREAM_REMOTE_ADDRESS%","duration":"%DURATION%","istio_policy_status":"%DYNAMIC_METADATA(istio.mixer:status)%","method":"%REQ(:METHOD)%","path":"%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%","protocol":"%PROTOCOL%","request_id":"%REQ(X-REQUEST-ID)%","requested_server_name":"%REQUESTED_SERVER_NAME%","response_code":"%RESPONSE_CODE%","response_flags":"%RESPONSE_FLAGS%","route_name":"%ROUTE_NAME%","start_time":"%START_TIME%","trace_id":"%REQ(X-B3-TRACEID)%","upstream_cluster":"%UPSTREAM_CLUSTER%","upstream_host":"%UPSTREAM_HOST%","upstream_local_address":"%UPSTREAM_LOCAL_ADDRESS%","upstream_service_time":"%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%","upstream_transport_failure_reason":"%UPSTREAM_TRANSPORT_FAILURE_REASON%","user_agent":"%REQ(USER-AGENT)%","x_forwarded_for":"%REQ(X-FORWARDED-FOR)%","response_code_details":"%RESPONSE_CODE_DETAILS%"}
|
||||
|
||||
'
|
||||
dnsRefreshRate: 200s
|
||||
@@ -20,11 +20,7 @@
|
||||
# When processing a leaf namespace Istio will search for declarations in that namespace first
|
||||
# and if none are found it will search in the root namespace. Any matching declaration found in the root namespace
|
||||
# is processed as if it were declared in the leaf namespace.
|
||||
{{- if .Values.global.enableHigressIstio }}
|
||||
rootNamespace: {{ .Values.meshConfig.rootNamespace | default .Values.global.istioNamespace }}
|
||||
{{- else }}
|
||||
rootNamespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
|
||||
configSources:
|
||||
- address: "xds://127.0.0.1:15051"
|
||||
@@ -85,15 +81,11 @@
|
||||
discoveryAddress: {{ printf "istiod.%s.svc" .Release.Namespace }}:15012
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if .Values.global.enableHigressIstio }}
|
||||
discoveryAddress: {{ printf "istiod.%s.svc" .Values.global.istioNamespace }}:15012
|
||||
{{- else }}
|
||||
discoveryAddress: {{ include "controller.name" . }}.{{.Release.Namespace}}.svc:15012
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
proxyStatsMatcher:
|
||||
inclusionRegexps:
|
||||
- ".*"
|
||||
{{ toYaml .Values.global.proxy.proxyStatsMatcher.inclusionRegexps | indent 8 }}
|
||||
{{- end }}
|
||||
|
||||
{{/* We take the mesh config above, defined with individual values.yaml, and merge with .Values.meshConfig */}}
|
||||
@@ -116,6 +108,12 @@ data:
|
||||
{{- $existingData = index $existingConfig.data "higress" | default "{}" | fromYaml }}
|
||||
{{- end }}
|
||||
{{- $newData := dict }}
|
||||
{{- if hasKey .Values "upstream" }}
|
||||
{{- $_ := set $newData "upstream" .Values.upstream }}
|
||||
{{- end }}
|
||||
{{- if hasKey .Values "downstream" }}
|
||||
{{- $_ := set $newData "downstream" .Values.downstream }}
|
||||
{{- end }}
|
||||
{{- if and (hasKey .Values "tracing") .Values.tracing.enable }}
|
||||
{{- $_ := set $newData "tracing" .Values.tracing }}
|
||||
{{- end }}
|
||||
|
||||
@@ -129,3 +129,10 @@ rules:
|
||||
- apiGroups: ["networking.internal.knative.dev"]
|
||||
resources: ["ingresses/status"]
|
||||
verbs: ["get","patch","update"]
|
||||
# gateway api need
|
||||
- apiGroups: ["apps"]
|
||||
verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ]
|
||||
resources: [ "deployments" ]
|
||||
- apiGroups: [""]
|
||||
verbs: [ "get", "watch", "list", "update", "patch", "create", "delete" ]
|
||||
resources: [ "serviceaccounts"]
|
||||
|
||||
@@ -19,6 +19,9 @@ spec:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- with .Values.controller.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- include "controller.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.controller.imagePullSecrets }}
|
||||
@@ -69,6 +72,12 @@ spec:
|
||||
fieldPath: spec.serviceAccountName
|
||||
- name: DOMAIN_SUFFIX
|
||||
value: {{ .Values.global.proxy.clusterDomain }}
|
||||
- name: GATEWAY_NAME
|
||||
value: {{ include "gateway.name" . }}
|
||||
- name: PILOT_ENABLE_GATEWAY_API
|
||||
value: "{{ .Values.global.enableGatewayAPI }}"
|
||||
- name: PILOT_ENABLE_ALPHA_GATEWAY_API
|
||||
value: "{{ .Values.global.enableGatewayAPI }}"
|
||||
{{- if .Values.controller.env }}
|
||||
{{- range $key, $val := .Values.controller.env }}
|
||||
- name: {{ $key }}
|
||||
@@ -90,7 +99,6 @@ spec:
|
||||
volumeMounts:
|
||||
- name: log
|
||||
mountPath: /var/log
|
||||
{{- if not .Values.global.enableHigressIstio }}
|
||||
- name: discovery
|
||||
image: "{{ .Values.pilot.hub | default .Values.global.hub }}/{{ .Values.pilot.image | default "pilot" }}:{{ .Values.pilot.tag | default .Chart.AppVersion }}"
|
||||
{{- if .Values.global.imagePullPolicy }}
|
||||
@@ -131,6 +139,14 @@ spec:
|
||||
periodSeconds: 3
|
||||
timeoutSeconds: 5
|
||||
env:
|
||||
{{- if .Values.global.watchNamespace }}
|
||||
- name: ISTIO_WATCH_NAMESPACE
|
||||
value: "{{ .Values.global.watchNamespace }}"
|
||||
{{- end }}
|
||||
- name: ENABLE_PUSH_ALL_MCP_CLUSTERS
|
||||
value: "{{ .Values.global.enablePushAllMCPClusters }}"
|
||||
- name: PILOT_ENABLE_LDS_CACHE
|
||||
value: "{{ .Values.global.enableLDSCache }}"
|
||||
- name: PILOT_ENABLE_QUIC_LISTENERS
|
||||
value: "true"
|
||||
- name: VALIDATION_WEBHOOK_CONFIG_NAME
|
||||
@@ -215,18 +231,16 @@ spec:
|
||||
- name: HIGRESS_ENABLE_ISTIO_API
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- if .Values.global.enableGatewayAPI }}
|
||||
- name: PILOT_ENABLE_GATEWAY_API
|
||||
value: "true"
|
||||
value: "false"
|
||||
- name: PILOT_ENABLE_ALPHA_GATEWAY_API
|
||||
value: "false"
|
||||
- name: PILOT_ENABLE_GATEWAY_API_STATUS
|
||||
value: "true"
|
||||
value: "false"
|
||||
- name: PILOT_ENABLE_GATEWAY_API_DEPLOYMENT_CONTROLLER
|
||||
value: "false"
|
||||
{{- end }}
|
||||
{{- if not .Values.global.enableHigressIstio }}
|
||||
- name: CUSTOM_CA_CERT_NAME
|
||||
value: "higress-ca-root-cert"
|
||||
{{- end }}
|
||||
{{- if not (or .Values.global.local .Values.global.kind) }}
|
||||
resources:
|
||||
{{- if .Values.pilot.resources }}
|
||||
@@ -263,7 +277,6 @@ spec:
|
||||
- name: extracacerts
|
||||
mountPath: /cacerts
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.controller.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
@@ -279,7 +292,6 @@ spec:
|
||||
volumes:
|
||||
- name: log
|
||||
emptyDir: {}
|
||||
{{- if not .Values.global.enableHigressIstio }}
|
||||
- name: config
|
||||
configMap:
|
||||
name: higress-config
|
||||
@@ -311,4 +323,3 @@ spec:
|
||||
configMap:
|
||||
name: pilot-jwks-extra-cacerts{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -9,7 +9,6 @@ spec:
|
||||
type: {{ .Values.controller.service.type }}
|
||||
ports:
|
||||
{{- toYaml .Values.controller.ports | nindent 4 }}
|
||||
{{- if not .Values.global.enableHigressIstio }}
|
||||
- port: 15010
|
||||
name: grpc-xds # plaintext
|
||||
protocol: TCP
|
||||
@@ -23,6 +22,5 @@ spec:
|
||||
- port: 15014
|
||||
name: http-monitoring # prometheus stats
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "controller.selectorLabels" . | nindent 4 }}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{{- if eq .Values.gateway.kind "DaemonSet" -}}
|
||||
{{- $o11y := .Values.global.o11y }}
|
||||
{{- $unprivilegedPortSupported := true }}
|
||||
{{- range $index, $node := (lookup "v1" "Node" "default" "").items }}
|
||||
{{- if eq .Values.gateway.unprivilegedPortSupported nil -}}
|
||||
{{- $unprivilegedPortSupported := true }}
|
||||
{{- range $index, $node := (lookup "v1" "Node" "default" "").items }}
|
||||
{{- $kernelVersion := $node.status.nodeInfo.kernelVersion }}
|
||||
{{- if $kernelVersion }}
|
||||
{{- $kernelVersion = regexFind "^(\\d+\\.\\d+\\.\\d+)" $kernelVersion }}
|
||||
@@ -9,8 +10,9 @@
|
||||
{{- $unprivilegedPortSupported = false }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- $_ := set .Values.gateway "unprivilegedPortSupported" $unprivilegedPortSupported -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set .Values.gateway "unprivilegedPortSupported" $unprivilegedPortSupported -}}
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{{- if eq .Values.gateway.kind "Deployment" -}}
|
||||
{{- $unprivilegedPortSupported := true }}
|
||||
{{- range $index, $node := (lookup "v1" "Node" "default" "").items }}
|
||||
{{- if eq .Values.gateway.unprivilegedPortSupported nil -}}
|
||||
{{- $unprivilegedPortSupported := true }}
|
||||
{{- range $index, $node := (lookup "v1" "Node" "default" "").items }}
|
||||
{{- $kernelVersion := $node.status.nodeInfo.kernelVersion }}
|
||||
{{- if $kernelVersion }}
|
||||
{{- $kernelVersion = regexFind "^(\\d+\\.\\d+\\.\\d+)" $kernelVersion }}
|
||||
@@ -8,8 +9,9 @@
|
||||
{{- $unprivilegedPortSupported = false }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- $_ := set .Values.gateway "unprivilegedPortSupported" $unprivilegedPortSupported -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set .Values.gateway "unprivilegedPortSupported" $unprivilegedPortSupported -}}
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
||||
22
helm/core/templates/fallback-envoyfilter.yaml
Normal file
22
helm/core/templates/fallback-envoyfilter.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: EnvoyFilter
|
||||
metadata:
|
||||
name: {{ include "gateway.name" . }}-global-custom-response
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "gateway.labels" . | nindent 4}}
|
||||
spec:
|
||||
configPatches:
|
||||
- applyTo: HTTP_FILTER
|
||||
match:
|
||||
context: GATEWAY
|
||||
listener:
|
||||
filterChain:
|
||||
filter:
|
||||
name: envoy.filters.network.http_connection_manager
|
||||
patch:
|
||||
operation: INSERT_FIRST
|
||||
value:
|
||||
name: envoy.filters.http.custom_response
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.custom_response.v3.CustomResponse
|
||||
@@ -1,6 +1,8 @@
|
||||
{{- if .Values.global.ingressClass }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: IngressClass
|
||||
metadata:
|
||||
name: {{ .Values.global.ingressClass }}
|
||||
spec:
|
||||
controller: higress.io/higress-controller
|
||||
controller: higress.io/higress-controller
|
||||
{{- end }}
|
||||
|
||||
@@ -3,14 +3,18 @@ global:
|
||||
enableH3: false
|
||||
enableIPv6: false
|
||||
enableProxyProtocol: false
|
||||
liteMetrics: true
|
||||
enableLDSCache: false
|
||||
enablePushAllMCPClusters: true
|
||||
liteMetrics: false
|
||||
xdsMaxRecvMsgSize: "104857600"
|
||||
defaultUpstreamConcurrencyThreshold: 10000
|
||||
enableSRDS: true
|
||||
# -- Whether to enable Redis(redis-stack-server) for Higress, default is false.
|
||||
enableRedis: false
|
||||
onDemandRDS: false
|
||||
hostRDSMergeSubset: false
|
||||
onlyPushRouteCluster: true
|
||||
# IngressClass filters which ingress resources the higress controller watches.
|
||||
# -- IngressClass filters which ingress resources the higress controller watches.
|
||||
# The default ingress class is higress.
|
||||
# There are some special cases for special ingress class.
|
||||
# 1. When the ingress class is set as nginx, the higress controller will watch ingress
|
||||
@@ -18,28 +22,38 @@ global:
|
||||
# 2. When the ingress class is set empty, the higress controller will watch all ingress
|
||||
# resources in the k8s cluster.
|
||||
ingressClass: "higress"
|
||||
# -- If not empty, Higress Controller will only watch resources in the specified namespace.
|
||||
# When isolating different business systems using K8s namespace,
|
||||
# if each namespace requires a standalone gateway instance,
|
||||
# this parameter can be used to confine the Ingress watching of Higress within the given namespace.
|
||||
watchNamespace: ""
|
||||
# -- Whether to disable HTTP/2 in ALPN
|
||||
disableAlpnH2: false
|
||||
# -- If true, Higress Controller will update the status field of Ingress resources.
|
||||
# When migrating from Nginx Ingress, in order to avoid status field of Ingress objects being overwritten,
|
||||
# this parameter needs to be set to false,
|
||||
# so Higress won't write the entry IP to the status field of the corresponding Ingress object.
|
||||
enableStatus: true
|
||||
# whether to use autoscaling/v2 template for HPA settings
|
||||
# -- whether to use autoscaling/v2 template for HPA settings
|
||||
# for internal usage only, not to be configured by users.
|
||||
autoscalingv2API: true
|
||||
local: false # When deploying to a local cluster (e.g.: kind cluster), set this to true.
|
||||
# -- When deploying to a local cluster (e.g.: kind cluster), set this to true.
|
||||
local: false
|
||||
kind: false # Deprecated. Please use "global.local" instead. Will be removed later.
|
||||
enableIstioAPI: false
|
||||
# -- If true, Higress Controller will monitor istio resources as well
|
||||
enableIstioAPI: true
|
||||
# -- If true, Higress Controller will monitor Gateway API resources as well
|
||||
enableGatewayAPI: false
|
||||
# Deprecated
|
||||
enableHigressIstio: false
|
||||
# Used to locate istiod.
|
||||
# -- Used to locate istiod.
|
||||
istioNamespace: istio-system
|
||||
# enable pod disruption budget for the control plane, which is used to
|
||||
# -- enable pod disruption budget for the control plane, which is used to
|
||||
# ensure Istio control plane components are gradually upgraded or recovered.
|
||||
defaultPodDisruptionBudget:
|
||||
enabled: false
|
||||
# The values aren't mutable due to a current PodDisruptionBudget limitation
|
||||
# minAvailable: 1
|
||||
|
||||
# A minimal set of requested resources to applied to all deployments so that
|
||||
# -- A minimal set of requested resources to applied to all deployments so that
|
||||
# Horizontal Pod Autoscaler will be able to function (if set).
|
||||
# Each component can overwrite these default values by adding its own resources
|
||||
# block in the relevant section below and setting the desired resources values.
|
||||
@@ -51,16 +65,16 @@ global:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
# Default hub for Istio images.
|
||||
# -- Default hub for Istio images.
|
||||
# Releases are published to docker hub under 'istio' project.
|
||||
# Dev builds from prow are on gcr.io
|
||||
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
|
||||
|
||||
# Specify image pull policy if default behavior isn't desired.
|
||||
# -- Specify image pull policy if default behavior isn't desired.
|
||||
# Default behavior: latest images will be Always else IfNotPresent.
|
||||
imagePullPolicy: ""
|
||||
|
||||
# ImagePullSecrets for all ServiceAccount, list of secrets in the same namespace
|
||||
# -- ImagePullSecrets for all ServiceAccount, list of secrets in the same namespace
|
||||
# to use for pulling any images in pods that reference this ServiceAccount.
|
||||
# For components that don't use ServiceAccounts (i.e. grafana, servicegraph, tracing)
|
||||
# ImagePullSecrets will be added to the corresponding Deployment(StatefulSet) objects.
|
||||
@@ -68,14 +82,14 @@ global:
|
||||
imagePullSecrets: []
|
||||
# - private-registry-key
|
||||
|
||||
# Enabled by default in master for maximising testing.
|
||||
# -- Enabled by default in master for maximising testing.
|
||||
istiod:
|
||||
enableAnalysis: false
|
||||
|
||||
# To output all istio components logs in json format by adding --log_as_json argument to each container argument
|
||||
# -- To output all istio components logs in json format by adding --log_as_json argument to each container argument
|
||||
logAsJson: false
|
||||
|
||||
# Comma-separated minimum per-scope logging level of messages to output, in the form of <scope>:<level>,<scope>:<level>
|
||||
# -- Comma-separated minimum per-scope logging level of messages to output, in the form of <scope>:<level>,<scope>:<level>
|
||||
# The control plane has different scopes depending on component, but can configure default log level across all components
|
||||
# If empty, default scope and level will be used as configured in code
|
||||
logging:
|
||||
@@ -83,11 +97,11 @@ global:
|
||||
|
||||
omitSidecarInjectorConfigMap: false
|
||||
|
||||
# Whether to restrict the applications namespace the controller manages;
|
||||
# -- Whether to restrict the applications namespace the controller manages;
|
||||
# If not set, controller watches all namespaces
|
||||
oneNamespace: false
|
||||
|
||||
# Configure whether Operator manages webhook configurations. The current behavior
|
||||
# -- Configure whether Operator manages webhook configurations. The current behavior
|
||||
# of Istiod is to manage its own webhook configurations.
|
||||
# When this option is set as true, Istio Operator, instead of webhooks, manages the
|
||||
# webhook configurations. When this option is set as false, webhooks manage their
|
||||
@@ -106,7 +120,7 @@ global:
|
||||
#- global
|
||||
#- "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global"
|
||||
|
||||
# Kubernetes >=v1.11.0 will create two PriorityClass, including system-cluster-critical and
|
||||
# -- Kubernetes >=v1.11.0 will create two PriorityClass, including system-cluster-critical and
|
||||
# system-node-critical, it is better to configure this in order to make sure your Istio pods
|
||||
# will not be killed because of low priority class.
|
||||
# Refer to https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
|
||||
@@ -116,18 +130,18 @@ global:
|
||||
proxy:
|
||||
image: proxyv2
|
||||
|
||||
# This controls the 'policy' in the sidecar injector.
|
||||
# -- This controls the 'policy' in the sidecar injector.
|
||||
autoInject: enabled
|
||||
|
||||
# CAUTION: It is important to ensure that all Istio helm charts specify the same clusterDomain value
|
||||
# -- CAUTION: It is important to ensure that all Istio helm charts specify the same clusterDomain value
|
||||
# cluster domain. Default value is "cluster.local".
|
||||
clusterDomain: "cluster.local"
|
||||
|
||||
# Per Component log level for proxy, applies to gateways and sidecars. If a component level is
|
||||
# -- Per Component log level for proxy, applies to gateways and sidecars. If a component level is
|
||||
# not set, then the global "logLevel" will be used.
|
||||
componentLogLevel: "misc:error"
|
||||
|
||||
# If set, newly injected sidecars will have core dumps enabled.
|
||||
# -- If set, newly injected sidecars will have core dumps enabled.
|
||||
enableCoreDump: false
|
||||
|
||||
# istio ingress capture allowlist
|
||||
@@ -136,7 +150,7 @@ global:
|
||||
excludeInboundPorts: ""
|
||||
includeInboundPorts: "*"
|
||||
|
||||
# istio egress capture allowlist
|
||||
# -- istio egress capture allowlist
|
||||
# https://istio.io/docs/tasks/traffic-management/egress.html#calling-external-services-directly
|
||||
# example: includeIPRanges: "172.30.0.0/16,172.20.0.0/16"
|
||||
# would only capture egress traffic on those two IP Ranges, all other outbound traffic would
|
||||
@@ -146,29 +160,29 @@ global:
|
||||
includeOutboundPorts: ""
|
||||
excludeOutboundPorts: ""
|
||||
|
||||
# Log level for proxy, applies to gateways and sidecars.
|
||||
# -- Log level for proxy, applies to gateways and sidecars.
|
||||
# Expected values are: trace|debug|info|warning|error|critical|off
|
||||
logLevel: warning
|
||||
|
||||
#If set to true, istio-proxy container will have privileged securityContext
|
||||
# -- If set to true, istio-proxy container will have privileged securityContext
|
||||
privileged: false
|
||||
|
||||
# The number of successive failed probes before indicating readiness failure.
|
||||
# -- The number of successive failed probes before indicating readiness failure.
|
||||
readinessFailureThreshold: 30
|
||||
|
||||
# The number of successive successed probes before indicating readiness success.
|
||||
# -- The number of successive successed probes before indicating readiness success.
|
||||
readinessSuccessThreshold: 30
|
||||
|
||||
# The initial delay for readiness probes in seconds.
|
||||
# -- The initial delay for readiness probes in seconds.
|
||||
readinessInitialDelaySeconds: 1
|
||||
|
||||
# The period between readiness probes.
|
||||
# -- The period between readiness probes.
|
||||
readinessPeriodSeconds: 2
|
||||
|
||||
# The readiness timeout seconds
|
||||
# -- The readiness timeout seconds
|
||||
readinessTimeoutSeconds: 3
|
||||
|
||||
# Resources for the sidecar.
|
||||
# -- Resources for the sidecar.
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
@@ -177,18 +191,23 @@ global:
|
||||
cpu: 2000m
|
||||
memory: 1024Mi
|
||||
|
||||
# Default port for Pilot agent health checks. A value of 0 will disable health checking.
|
||||
# -- Default port for Pilot agent health checks. A value of 0 will disable health checking.
|
||||
statusPort: 15020
|
||||
|
||||
# Specify which tracer to use. One of: lightstep, datadog, stackdriver.
|
||||
# -- Specify which tracer to use. One of: lightstep, datadog, stackdriver.
|
||||
# If using stackdriver tracer outside GCP, set env GOOGLE_APPLICATION_CREDENTIALS to the GCP credential file.
|
||||
tracer: ""
|
||||
|
||||
# Controls if sidecar is injected at the front of the container list and blocks the start of the other containers until the proxy is ready
|
||||
# -- Controls if sidecar is injected at the front of the container list and blocks the start of the other containers until the proxy is ready
|
||||
holdApplicationUntilProxyStarts: false
|
||||
|
||||
# -- Proxy stats name regexps matcher for inclusion
|
||||
proxyStatsMatcher:
|
||||
inclusionRegexps:
|
||||
- ".*"
|
||||
|
||||
proxy_init:
|
||||
# Base name for the proxy_init container, used to configure iptables.
|
||||
# -- Base name for the proxy_init container, used to configure iptables.
|
||||
image: proxyv2
|
||||
resources:
|
||||
limits:
|
||||
@@ -198,7 +217,7 @@ global:
|
||||
cpu: 10m
|
||||
memory: 10Mi
|
||||
|
||||
# configure remote pilot and istiod service and endpoint
|
||||
# -- configure remote pilot and istiod service and endpoint
|
||||
remotePilotAddress: ""
|
||||
|
||||
##############################################################################################
|
||||
@@ -206,20 +225,20 @@ global:
|
||||
# make sure they are consistent across your Istio helm charts #
|
||||
##############################################################################################
|
||||
|
||||
# The customized CA address to retrieve certificates for the pods in the cluster.
|
||||
# -- The customized CA address to retrieve certificates for the pods in the cluster.
|
||||
# CSR clients such as the Istio Agent and ingress gateways can use this to specify the CA endpoint.
|
||||
# If not set explicitly, default to the Istio discovery address.
|
||||
caAddress: ""
|
||||
|
||||
# Configure a remote cluster data plane controlled by an external istiod.
|
||||
# -- Configure a remote cluster data plane controlled by an external istiod.
|
||||
# When set to true, istiod is not deployed locally and only a subset of the other
|
||||
# discovery charts are enabled.
|
||||
externalIstiod: false
|
||||
|
||||
# Configure a remote cluster as the config cluster for an external istiod.
|
||||
# -- Configure a remote cluster as the config cluster for an external istiod.
|
||||
configCluster: false
|
||||
|
||||
# Configure the policy for validating JWT.
|
||||
# -- Configure the policy for validating JWT.
|
||||
# Currently, two options are supported: "third-party-jwt" and "first-party-jwt".
|
||||
jwtPolicy: "third-party-jwt"
|
||||
|
||||
@@ -241,7 +260,7 @@ global:
|
||||
# of migration TBD, and it may be a disruptive operation to change the Mesh
|
||||
# ID post-install.
|
||||
#
|
||||
# If the mesh admin does not specify a value, Istio will use the value of the
|
||||
# -- If the mesh admin does not specify a value, Istio will use the value of the
|
||||
# mesh's Trust Domain. The best practice is to select a proper Trust Domain
|
||||
# value.
|
||||
meshID: ""
|
||||
@@ -275,68 +294,69 @@ global:
|
||||
#
|
||||
meshNetworks: {}
|
||||
|
||||
# Use the user-specified, secret volume mounted key and certs for Pilot and workloads.
|
||||
# -- Use the user-specified, secret volume mounted key and certs for Pilot and workloads.
|
||||
mountMtlsCerts: false
|
||||
|
||||
multiCluster:
|
||||
# Set to true to connect two kubernetes clusters via their respective
|
||||
# -- Set to true to connect two kubernetes clusters via their respective
|
||||
# ingressgateway services when pods in each cluster cannot directly
|
||||
# talk to one another. All clusters should be using Istio mTLS and must
|
||||
# have a shared root CA for this model to work.
|
||||
enabled: true
|
||||
# Should be set to the name of the cluster this installation will run in. This is required for sidecar injection
|
||||
# -- Should be set to the name of the cluster this installation will run in. This is required for sidecar injection
|
||||
# to properly label proxies
|
||||
clusterName: ""
|
||||
|
||||
# Network defines the network this cluster belong to. This name
|
||||
# -- Network defines the network this cluster belong to. This name
|
||||
# corresponds to the networks in the map of mesh networks.
|
||||
network: ""
|
||||
|
||||
# Configure the certificate provider for control plane communication.
|
||||
# -- Configure the certificate provider for control plane communication.
|
||||
# Currently, two providers are supported: "kubernetes" and "istiod".
|
||||
# As some platforms may not have kubernetes signing APIs,
|
||||
# Istiod is the default
|
||||
pilotCertProvider: istiod
|
||||
|
||||
sds:
|
||||
# The JWT token for SDS and the aud field of such JWT. See RFC 7519, section 4.1.3.
|
||||
# -- The JWT token for SDS and the aud field of such JWT. See RFC 7519, section 4.1.3.
|
||||
# When a CSR is sent from Istio Agent to the CA (e.g. Istiod), this aud is to make sure the
|
||||
# JWT is intended for the CA.
|
||||
token:
|
||||
aud: istio-ca
|
||||
|
||||
sts:
|
||||
# The service port used by Security Token Service (STS) server to handle token exchange requests.
|
||||
# -- The service port used by Security Token Service (STS) server to handle token exchange requests.
|
||||
# Setting this port to a non-zero value enables STS server.
|
||||
servicePort: 0
|
||||
|
||||
# Configuration for each of the supported tracers
|
||||
# -- Configuration for each of the supported tracers
|
||||
tracer:
|
||||
# Configuration for envoy to send trace data to LightStep.
|
||||
# -- Configuration for envoy to send trace data to LightStep.
|
||||
# Disabled by default.
|
||||
# address: the <host>:<port> of the satellite pool
|
||||
# accessToken: required for sending data to the pool
|
||||
#
|
||||
datadog:
|
||||
# Host:Port for submitting traces to the Datadog agent.
|
||||
# -- Host:Port for submitting traces to the Datadog agent.
|
||||
address: "$(HOST_IP):8126"
|
||||
lightstep:
|
||||
address: "" # example: lightstep-satellite:443
|
||||
accessToken: "" # example: abcdefg1234567
|
||||
# -- example: lightstep-satellite:443
|
||||
address: ""
|
||||
# -- example: abcdefg1234567
|
||||
accessToken: ""
|
||||
stackdriver:
|
||||
# enables trace output to stdout.
|
||||
# -- enables trace output to stdout.
|
||||
debug: false
|
||||
# The global default max number of message events per span.
|
||||
# -- The global default max number of message events per span.
|
||||
maxNumberOfMessageEvents: 200
|
||||
# The global default max number of annotation events per span.
|
||||
# -- The global default max number of annotation events per span.
|
||||
maxNumberOfAnnotations: 200
|
||||
# The global default max number of attributes per span.
|
||||
# -- The global default max number of attributes per span.
|
||||
maxNumberOfAttributes: 200
|
||||
# Use the Mesh Control Protocol (MCP) for configuring Istiod. Requires an MCP source.
|
||||
|
||||
# -- Use the Mesh Control Protocol (MCP) for configuring Istiod. Requires an MCP source.
|
||||
useMCP: false
|
||||
|
||||
# Observability (o11y) configurations
|
||||
# -- Observability (o11y) configurations
|
||||
o11y:
|
||||
enabled: false
|
||||
promtail:
|
||||
@@ -350,7 +370,7 @@ global:
|
||||
memory: 2Gi
|
||||
securityContext: {}
|
||||
|
||||
# The name of the CA for workload certificates.
|
||||
# -- The name of the CA for workload certificates.
|
||||
# For example, when caName=GkeWorkloadCertificate, GKE workload certificates
|
||||
# will be used as the certificates for workloads.
|
||||
# The default value is "" and when caName="", the CA will be configured by other
|
||||
@@ -359,7 +379,7 @@ global:
|
||||
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
|
||||
|
||||
clusterName: ""
|
||||
# meshConfig defines runtime configuration of components, including Istiod and istio-agent behavior
|
||||
# -- meshConfig defines runtime configuration of components, including Istiod and istio-agent behavior
|
||||
# See https://istio.io/docs/reference/config/istio.mesh.v1alpha1/ for all available options
|
||||
meshConfig:
|
||||
enablePrometheusMerge: true
|
||||
@@ -370,14 +390,13 @@ meshConfig:
|
||||
# and gradual adoption by setting capture only on specific workloads. It also allows
|
||||
# VMs to use other DNS options, like dnsmasq or unbound.
|
||||
|
||||
# The namespace to treat as the administrative root namespace for Istio configuration.
|
||||
# -- The namespace to treat as the administrative root namespace for Istio configuration.
|
||||
# When processing a leaf namespace Istio will search for declarations in that namespace first
|
||||
# and if none are found it will search in the root namespace. Any matching declaration found in the root namespace
|
||||
# is processed as if it were declared in the leaf namespace.
|
||||
|
||||
rootNamespace:
|
||||
|
||||
# The trust domain corresponds to the trust root of a system
|
||||
# -- The trust domain corresponds to the trust root of a system
|
||||
# Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain
|
||||
trustDomain: "cluster.local"
|
||||
|
||||
@@ -391,56 +410,57 @@ meshConfig:
|
||||
|
||||
gateway:
|
||||
name: "higress-gateway"
|
||||
# -- Number of Higress Gateway pods
|
||||
replicas: 2
|
||||
image: gateway
|
||||
|
||||
# -- Use a `DaemonSet` or `Deployment`
|
||||
kind: Deployment
|
||||
|
||||
# The number of successive failed probes before indicating readiness failure.
|
||||
# -- The number of successive failed probes before indicating readiness failure.
|
||||
readinessFailureThreshold: 30
|
||||
|
||||
# The number of successive successed probes before indicating readiness success.
|
||||
# -- The number of successive successed probes before indicating readiness success.
|
||||
readinessSuccessThreshold: 1
|
||||
|
||||
# The initial delay for readiness probes in seconds.
|
||||
# -- The initial delay for readiness probes in seconds.
|
||||
readinessInitialDelaySeconds: 1
|
||||
|
||||
# The period between readiness probes.
|
||||
# -- The period between readiness probes.
|
||||
readinessPeriodSeconds: 2
|
||||
|
||||
# The readiness timeout seconds
|
||||
# -- The readiness timeout seconds
|
||||
readinessTimeoutSeconds: 3
|
||||
|
||||
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
|
||||
tag: ""
|
||||
# revision declares which revision this gateway is a part of
|
||||
# -- revision declares which revision this gateway is a part of
|
||||
revision: ""
|
||||
|
||||
rbac:
|
||||
# If enabled, roles will be created to enable accessing certificates from Gateways. This is not needed
|
||||
# -- If enabled, roles will be created to enable accessing certificates from Gateways. This is not needed
|
||||
# when using http://gateway-api.org/.
|
||||
enabled: true
|
||||
|
||||
serviceAccount:
|
||||
# If set, a service account will be created. Otherwise, the default is used
|
||||
# -- If set, a service account will be created. Otherwise, the default is used
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
# -- Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# -- The name of the service account to use.
|
||||
# If not set, the release name is used
|
||||
name: ""
|
||||
|
||||
# Pod environment variables
|
||||
# -- Pod environment variables
|
||||
env: {}
|
||||
httpPort: 80
|
||||
httpsPort: 443
|
||||
hostNetwork: false
|
||||
|
||||
# Labels to apply to all resources
|
||||
# -- Labels to apply to all resources
|
||||
labels: {}
|
||||
|
||||
# Annotations to apply to all resources
|
||||
# -- Annotations to apply to all resources
|
||||
annotations: {}
|
||||
|
||||
podAnnotations:
|
||||
@@ -449,14 +469,18 @@ gateway:
|
||||
prometheus.io/path: "/stats/prometheus"
|
||||
sidecar.istio.io/inject: "false"
|
||||
|
||||
# Define the security context for the pod.
|
||||
# -- Labels to apply to the pod
|
||||
podLabels: {}
|
||||
|
||||
# -- Define the security context for the pod.
|
||||
# If unset, this will be automatically set to the minimum privileges required to bind to port 80 and 443.
|
||||
# On Kubernetes 1.22+, this only requires the `net.ipv4.ip_unprivileged_port_start` sysctl.
|
||||
securityContext: ~
|
||||
containerSecurityContext: ~
|
||||
unprivilegedPortSupported: ~
|
||||
|
||||
service:
|
||||
# Type of service. Set to "None" to disable the service entirely
|
||||
# -- Type of service. Set to "None" to disable the service entirely
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- name: http2
|
||||
@@ -474,6 +498,7 @@ gateway:
|
||||
externalTrafficPolicy: ""
|
||||
|
||||
rollingMaxSurge: 100%
|
||||
# -- If global.local is true, the default value is 100%, otherwise it is 25%
|
||||
rollingMaxUnavailable: 25%
|
||||
|
||||
resources:
|
||||
@@ -496,28 +521,29 @@ gateway:
|
||||
|
||||
affinity: {}
|
||||
|
||||
# If specified, the gateway will act as a network gateway for the given network.
|
||||
# -- If specified, the gateway will act as a network gateway for the given network.
|
||||
networkGateway: ""
|
||||
|
||||
metrics:
|
||||
# If true, create PodMonitor or VMPodScrape for gateway
|
||||
# -- If true, create PodMonitor or VMPodScrape for gateway
|
||||
enabled: false
|
||||
# provider group name for CustomResourceDefinition, can be monitoring.coreos.com or operator.victoriametrics.com
|
||||
# -- provider group name for CustomResourceDefinition, can be monitoring.coreos.com or operator.victoriametrics.com
|
||||
provider: monitoring.coreos.com
|
||||
interval: ""
|
||||
scrapeTimeout: ""
|
||||
honorLabels: false
|
||||
# for monitoring.coreos.com/v1.PodMonitor
|
||||
# -- for monitoring.coreos.com/v1.PodMonitor
|
||||
metricRelabelings: []
|
||||
relabelings: []
|
||||
# for operator.victoriametrics.com/v1beta1.VMPodScrape
|
||||
# -- for operator.victoriametrics.com/v1beta1.VMPodScrape
|
||||
metricRelabelConfigs: []
|
||||
relabelConfigs: []
|
||||
# some more raw podMetricsEndpoints spec
|
||||
# -- some more raw podMetricsEndpoints spec
|
||||
rawSpec: {}
|
||||
|
||||
controller:
|
||||
name: "higress-controller"
|
||||
# -- Number of Higress Controller pods
|
||||
replicas: 1
|
||||
image: higress
|
||||
|
||||
@@ -528,12 +554,12 @@ controller:
|
||||
labels: {}
|
||||
|
||||
probe:
|
||||
{
|
||||
httpGet: { path: /ready, port: 8888 },
|
||||
initialDelaySeconds: 1,
|
||||
periodSeconds: 3,
|
||||
timeoutSeconds: 5,
|
||||
}
|
||||
httpGet:
|
||||
path: /ready
|
||||
port: 8888
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
timeoutSeconds: 5
|
||||
|
||||
imagePullSecrets: []
|
||||
|
||||
@@ -541,31 +567,36 @@ controller:
|
||||
create: true
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
# -- Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
# -- Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
# -- The name of the service account to use.
|
||||
# -- If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
# -- Labels to apply to the pod
|
||||
podLabels: {}
|
||||
|
||||
podSecurityContext:
|
||||
{}
|
||||
# fsGroup: 2000
|
||||
# fsGroup: 2000
|
||||
|
||||
ports:
|
||||
[
|
||||
{ "name": "http", "protocol": "TCP", "port": 8888, "targetPort": 8888 },
|
||||
{
|
||||
"name": "http-solver",
|
||||
"protocol": "TCP",
|
||||
"port": 8889,
|
||||
"targetPort": 8889,
|
||||
},
|
||||
{ "name": "grpc", "protocol": "TCP", "port": 15051, "targetPort": 15051 },
|
||||
]
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 8888
|
||||
targetPort: 8888
|
||||
- name: http-solver
|
||||
protocol: TCP
|
||||
port: 8889
|
||||
targetPort: 8889
|
||||
- name: grpc
|
||||
protocol: TCP
|
||||
port: 15051
|
||||
targetPort: 15051
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
@@ -575,9 +606,9 @@ controller:
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
resources:
|
||||
requests:
|
||||
@@ -602,7 +633,7 @@ controller:
|
||||
enabled: true
|
||||
email: ""
|
||||
|
||||
## Discovery Settings
|
||||
## -- Discovery Settings
|
||||
pilot:
|
||||
autoscaleEnabled: false
|
||||
autoscaleMin: 1
|
||||
@@ -614,11 +645,11 @@ pilot:
|
||||
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
|
||||
tag: ""
|
||||
|
||||
# Can be a full hub/image:tag
|
||||
# -- Can be a full hub/image:tag
|
||||
image: pilot
|
||||
traceSampling: 1.0
|
||||
|
||||
# Resources for a small pilot install
|
||||
# -- Resources for a small pilot install
|
||||
resources:
|
||||
requests:
|
||||
cpu: 500m
|
||||
@@ -633,21 +664,21 @@ pilot:
|
||||
cpu:
|
||||
targetAverageUtilization: 80
|
||||
|
||||
# if protocol sniffing is enabled for outbound
|
||||
# -- if protocol sniffing is enabled for outbound
|
||||
enableProtocolSniffingForOutbound: true
|
||||
# if protocol sniffing is enabled for inbound
|
||||
# -- if protocol sniffing is enabled for inbound
|
||||
enableProtocolSniffingForInbound: true
|
||||
|
||||
nodeSelector: {}
|
||||
podAnnotations: {}
|
||||
serviceAnnotations: {}
|
||||
|
||||
# You can use jwksResolverExtraRootCA to provide a root certificate
|
||||
# -- You can use jwksResolverExtraRootCA to provide a root certificate
|
||||
# in PEM format. This will then be trusted by pilot when resolving
|
||||
# JWKS URIs.
|
||||
jwksResolverExtraRootCA: ""
|
||||
|
||||
# This is used to set the source of configuration for
|
||||
# -- This is used to set the source of configuration for
|
||||
# the associated address in configSource, if nothing is specified
|
||||
# the default MCP is assumed.
|
||||
configSource:
|
||||
@@ -655,21 +686,21 @@ pilot:
|
||||
|
||||
plugins: []
|
||||
|
||||
# The following is used to limit how long a sidecar can be connected
|
||||
# -- The following is used to limit how long a sidecar can be connected
|
||||
# to a pilot. It balances out load across pilot instances at the cost of
|
||||
# increasing system churn.
|
||||
keepaliveMaxServerConnectionAge: 30m
|
||||
|
||||
# Additional labels to apply to the deployment.
|
||||
# -- Additional labels to apply to the deployment.
|
||||
deploymentLabels: {}
|
||||
|
||||
## Mesh config settings
|
||||
|
||||
# Install the mesh config map, generated from values.yaml.
|
||||
# -- Install the mesh config map, generated from values.yaml.
|
||||
# If false, pilot wil use default values (by default) or user-supplied values.
|
||||
configMap: true
|
||||
|
||||
# Additional labels to apply on the pod level for monitoring and logging configuration.
|
||||
# -- Additional labels to apply on the pod level for monitoring and logging configuration.
|
||||
podLabels: {}
|
||||
|
||||
# Tracing config settings
|
||||
@@ -684,3 +715,56 @@ tracing:
|
||||
# zipkin:
|
||||
# service: ""
|
||||
# port: 9411
|
||||
|
||||
# -- Downstream config settings
|
||||
downstream:
|
||||
idleTimeout: 180
|
||||
maxRequestHeadersKb: 60
|
||||
connectionBufferLimits: 32768
|
||||
http2:
|
||||
maxConcurrentStreams: 100
|
||||
initialStreamWindowSize: 65535
|
||||
initialConnectionWindowSize: 1048576
|
||||
routeTimeout: 0
|
||||
|
||||
# -- Upstream config settings
|
||||
upstream:
|
||||
idleTimeout: 10
|
||||
connectionBufferLimits: 10485760
|
||||
|
||||
redis:
|
||||
redis:
|
||||
name: redis-stack-server
|
||||
# -- Specify the image
|
||||
image: "redis-stack-server"
|
||||
# -- Specify the tag
|
||||
tag: "7.4.0-v3"
|
||||
# -- Specify the number of replicas
|
||||
replicas: 1
|
||||
# -- Specify the password, if not set, no password is used
|
||||
password: ""
|
||||
# -- Service parameters
|
||||
service:
|
||||
# -- Exporter service type
|
||||
type: ClusterIP
|
||||
# -- Exporter service port
|
||||
port: 6379
|
||||
# -- Specify the resources
|
||||
resources: {}
|
||||
# -- NodeSelector Node labels for Redis
|
||||
nodeSelector: {}
|
||||
# -- Tolerations for Redis
|
||||
tolerations: []
|
||||
# -- Affinity for Redis
|
||||
affinity: {}
|
||||
persistence:
|
||||
# -- Enable persistence on Redis, default is false
|
||||
enabled: false
|
||||
# -- If defined, storageClassName: <storageClass>
|
||||
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner
|
||||
storageClass: ""
|
||||
# -- Persistent Volume access modes
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
# -- Persistent Volume size
|
||||
size: 1Gi
|
||||
@@ -1,9 +1,9 @@
|
||||
dependencies:
|
||||
- name: higress-core
|
||||
repository: file://../core
|
||||
version: 2.0.1
|
||||
version: 2.1.2-rc.1
|
||||
- name: higress-console
|
||||
repository: https://higress.io/helm-charts/
|
||||
version: 1.4.4
|
||||
digest: sha256:6e4d77c31c834a404a728ec5a8379dd5df27a7e9b998a08e6524dc6534b07c1d
|
||||
generated: "2024-10-09T20:07:21.857942+08:00"
|
||||
version: 2.1.2
|
||||
digest: sha256:0933dd97b646ae2e1740ccfb6606793b088abeeeb03f687a94c02fe34f227d87
|
||||
generated: "2025-04-28T20:34:11.26913+08:00"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: 2.0.1
|
||||
appVersion: 2.1.2-rc.1
|
||||
description: Helm chart for deploying Higress gateways
|
||||
icon: https://higress.io/img/higress_logo_small.png
|
||||
home: http://higress.io/
|
||||
@@ -12,9 +12,9 @@ sources:
|
||||
dependencies:
|
||||
- name: higress-core
|
||||
repository: "file://../core"
|
||||
version: 2.0.1
|
||||
version: 2.1.2-rc.1
|
||||
- name: higress-console
|
||||
repository: "https://higress.io/helm-charts/"
|
||||
version: 1.4.4
|
||||
version: 2.1.2
|
||||
type: application
|
||||
version: 2.0.1
|
||||
version: 2.1.2-rc.1
|
||||
|
||||
@@ -1,57 +1,298 @@
|
||||
# Higress Helm Chart
|
||||
|
||||
Installs the cloud-native gateway [Higress](http://higress.io/)
|
||||
|
||||
## Get Repo Info
|
||||
|
||||
```console
|
||||
helm repo add higress.io https://higress.io/helm-charts
|
||||
helm repo update
|
||||
```
|
||||
|
||||
_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `higress`:
|
||||
|
||||
```console
|
||||
helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes
|
||||
```
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall/delete the higress deployment:
|
||||
|
||||
```console
|
||||
helm delete higress -n higress-system
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
|
||||
## Configuration
|
||||
|
||||
| **Parameter** | **Description** | **Default** |
|
||||
|---|---|---|
|
||||
| **Global Parameters** | | |
|
||||
| global.local | Set to `true` if installing to a local K8s cluster (e.g.: Kind, Rancher Desktop, etc.) | false |
|
||||
| global.ingressClass | [IngressClass](https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/#ingress-class) which is used to filter Ingress resources Higress Controller watches.<br />If there are multiple gateway instances deployed in the cluster, this parameter can be used to distinguish the scope of each gateway instance.<br />There are some special cases for special IngressClass values:<br />1. If set to "nginx", Higress Controller will watch Ingress resources with the `nginx` IngressClass or without any Ingress class.<br />2. If set to empty, Higress Controller will watch all Ingress resources in the K8s cluster. | higress |
|
||||
| global.watchNamespace | If not empty, Higress Controller will only watch resources in the specified namespace. When isolating different business systems using K8s namespace, if each namespace requires a standalone gateway instance, this parameter can be used to confine the Ingress watching of Higress within the given namespace. | "" |
|
||||
| global.disableAlpnH2 | Whether to disable HTTP/2 in ALPN | true |
|
||||
| global.enableStatus | If `true`, Higress Controller will update the `status` field of Ingress resources.<br />When migrating from Nginx Ingress, in order to avoid `status` field of Ingress objects being overwritten, this parameter needs to be set to false, so Higress won't write the entry IP to the `status` field of the corresponding Ingress object. | true |
|
||||
| global.enableIstioAPI | If `true`, Higress Controller will monitor istio resources as well | false |
|
||||
| global.enableGatewayAPI | If `true`, Higress Controller will monitor Gateway API resources as well | false |
|
||||
| global.istioNamespace | The namespace istio is installed to | istio-system |
|
||||
| **Core Paramters** | | |
|
||||
| higress-core.gateway.replicas | Number of Higress Gateway pods | 2 |
|
||||
| higress-core.controller.replicas | Number of Higress Controller pods | 1 |
|
||||
| **Console Paramters** | | |
|
||||
| higress-console.replicaCount | Number of Higress Console pods | 1 |
|
||||
| higress-console.service.type | K8s service type used by Higress Console | ClusterIP |
|
||||
| higress-console.domain | Domain used to access Higress Console | console.higress.io |
|
||||
| higress-console.tlsSecretName | Name of Secret resource used by TLS connections. | "" |
|
||||
| higress-console.web.login.prompt | Prompt message to be displayed on the login page | "" |
|
||||
| higress-console.admin.password.value | If not empty, the admin password will be configured to the specified value. | "" |
|
||||
| higress-console.admin.password.length | The length of random admin password generated during installation. Only works when `higress-console.admin.password.value` is not set. | 8 |
|
||||
| higress-console.o11y.enabled | If `true`, o11y suite (Grafana + Promethues) will be installed. | false |
|
||||
| higress-console.pvc.rwxSupported | Set to `false` when installing to a standard K8s cluster and the target cluster doesn't support the ReadWriteMany access mode of PersistentVolumeClaim. | true |
|
||||
## Higress for Kubernetes
|
||||
|
||||
Higress is a cloud-native api gateway based on Alibaba's internal gateway practices.
|
||||
|
||||
Powered by Istio and Envoy, Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway and security gateway, thereby greatly reducing the costs of deployment, operation and maintenance.
|
||||
|
||||
## Setup Repo Info
|
||||
|
||||
```console
|
||||
helm repo add higress.io https://higress.io/helm-charts
|
||||
helm repo update
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
To install the chart with the release name `higress`:
|
||||
|
||||
```console
|
||||
helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
|
||||
To uninstall/delete the higress deployment:
|
||||
|
||||
```console
|
||||
helm delete higress -n higress-system
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
|
||||
## Parameters
|
||||
|
||||
## Values
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| clusterName | string | `""` | |
|
||||
| controller.affinity | object | `{}` | |
|
||||
| controller.automaticHttps.email | string | `""` | |
|
||||
| controller.automaticHttps.enabled | bool | `true` | |
|
||||
| controller.autoscaling.enabled | bool | `false` | |
|
||||
| controller.autoscaling.maxReplicas | int | `5` | |
|
||||
| controller.autoscaling.minReplicas | int | `1` | |
|
||||
| controller.autoscaling.targetCPUUtilizationPercentage | int | `80` | |
|
||||
| controller.env | object | `{}` | |
|
||||
| controller.hub | string | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | |
|
||||
| controller.image | string | `"higress"` | |
|
||||
| controller.imagePullSecrets | list | `[]` | |
|
||||
| controller.labels | object | `{}` | |
|
||||
| controller.name | string | `"higress-controller"` | |
|
||||
| controller.nodeSelector | object | `{}` | |
|
||||
| controller.podAnnotations | object | `{}` | |
|
||||
| controller.podLabels | object | `{}` | Labels to apply to the pod |
|
||||
| controller.podSecurityContext | object | `{}` | |
|
||||
| controller.ports[0].name | string | `"http"` | |
|
||||
| controller.ports[0].port | int | `8888` | |
|
||||
| controller.ports[0].protocol | string | `"TCP"` | |
|
||||
| controller.ports[0].targetPort | int | `8888` | |
|
||||
| controller.ports[1].name | string | `"http-solver"` | |
|
||||
| controller.ports[1].port | int | `8889` | |
|
||||
| controller.ports[1].protocol | string | `"TCP"` | |
|
||||
| controller.ports[1].targetPort | int | `8889` | |
|
||||
| controller.ports[2].name | string | `"grpc"` | |
|
||||
| controller.ports[2].port | int | `15051` | |
|
||||
| controller.ports[2].protocol | string | `"TCP"` | |
|
||||
| controller.ports[2].targetPort | int | `15051` | |
|
||||
| controller.probe.httpGet.path | string | `"/ready"` | |
|
||||
| controller.probe.httpGet.port | int | `8888` | |
|
||||
| controller.probe.initialDelaySeconds | int | `1` | |
|
||||
| controller.probe.periodSeconds | int | `3` | |
|
||||
| controller.probe.timeoutSeconds | int | `5` | |
|
||||
| controller.rbac.create | bool | `true` | |
|
||||
| controller.replicas | int | `1` | Number of Higress Controller pods |
|
||||
| controller.resources.limits.cpu | string | `"1000m"` | |
|
||||
| controller.resources.limits.memory | string | `"2048Mi"` | |
|
||||
| controller.resources.requests.cpu | string | `"500m"` | |
|
||||
| controller.resources.requests.memory | string | `"2048Mi"` | |
|
||||
| controller.securityContext | object | `{}` | |
|
||||
| controller.service.type | string | `"ClusterIP"` | |
|
||||
| controller.serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
|
||||
| controller.serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
|
||||
| controller.serviceAccount.name | string | `""` | If not set and create is true, a name is generated using the fullname template |
|
||||
| controller.tag | string | `""` | |
|
||||
| controller.tolerations | list | `[]` | |
|
||||
| downstream | object | `{"connectionBufferLimits":32768,"http2":{"initialConnectionWindowSize":1048576,"initialStreamWindowSize":65535,"maxConcurrentStreams":100},"idleTimeout":180,"maxRequestHeadersKb":60,"routeTimeout":0}` | Downstream config settings |
|
||||
| gateway.affinity | object | `{}` | |
|
||||
| gateway.annotations | object | `{}` | Annotations to apply to all resources |
|
||||
| gateway.autoscaling.enabled | bool | `false` | |
|
||||
| gateway.autoscaling.maxReplicas | int | `5` | |
|
||||
| gateway.autoscaling.minReplicas | int | `1` | |
|
||||
| gateway.autoscaling.targetCPUUtilizationPercentage | int | `80` | |
|
||||
| gateway.containerSecurityContext | string | `nil` | |
|
||||
| gateway.env | object | `{}` | Pod environment variables |
|
||||
| gateway.hostNetwork | bool | `false` | |
|
||||
| gateway.httpPort | int | `80` | |
|
||||
| gateway.httpsPort | int | `443` | |
|
||||
| gateway.hub | string | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | |
|
||||
| gateway.image | string | `"gateway"` | |
|
||||
| gateway.kind | string | `"Deployment"` | Use a `DaemonSet` or `Deployment` |
|
||||
| gateway.labels | object | `{}` | Labels to apply to all resources |
|
||||
| gateway.metrics.enabled | bool | `false` | If true, create PodMonitor or VMPodScrape for gateway |
|
||||
| gateway.metrics.honorLabels | bool | `false` | |
|
||||
| gateway.metrics.interval | string | `""` | |
|
||||
| gateway.metrics.metricRelabelConfigs | list | `[]` | for operator.victoriametrics.com/v1beta1.VMPodScrape |
|
||||
| gateway.metrics.metricRelabelings | list | `[]` | for monitoring.coreos.com/v1.PodMonitor |
|
||||
| gateway.metrics.provider | string | `"monitoring.coreos.com"` | provider group name for CustomResourceDefinition, can be monitoring.coreos.com or operator.victoriametrics.com |
|
||||
| gateway.metrics.rawSpec | object | `{}` | some more raw podMetricsEndpoints spec |
|
||||
| gateway.metrics.relabelConfigs | list | `[]` | |
|
||||
| gateway.metrics.relabelings | list | `[]` | |
|
||||
| gateway.metrics.scrapeTimeout | string | `""` | |
|
||||
| gateway.name | string | `"higress-gateway"` | |
|
||||
| gateway.networkGateway | string | `""` | If specified, the gateway will act as a network gateway for the given network. |
|
||||
| gateway.nodeSelector | object | `{}` | |
|
||||
| gateway.podAnnotations."prometheus.io/path" | string | `"/stats/prometheus"` | |
|
||||
| gateway.podAnnotations."prometheus.io/port" | string | `"15020"` | |
|
||||
| gateway.podAnnotations."prometheus.io/scrape" | string | `"true"` | |
|
||||
| gateway.podAnnotations."sidecar.istio.io/inject" | string | `"false"` | |
|
||||
| gateway.podLabels | object | `{}` | Labels to apply to the pod |
|
||||
| gateway.rbac.enabled | bool | `true` | If enabled, roles will be created to enable accessing certificates from Gateways. This is not needed when using http://gateway-api.org/. |
|
||||
| gateway.readinessFailureThreshold | int | `30` | The number of successive failed probes before indicating readiness failure. |
|
||||
| gateway.readinessInitialDelaySeconds | int | `1` | The initial delay for readiness probes in seconds. |
|
||||
| gateway.readinessPeriodSeconds | int | `2` | The period between readiness probes. |
|
||||
| gateway.readinessSuccessThreshold | int | `1` | The number of successive successed probes before indicating readiness success. |
|
||||
| gateway.readinessTimeoutSeconds | int | `3` | The readiness timeout seconds |
|
||||
| gateway.replicas | int | `2` | Number of Higress Gateway pods |
|
||||
| gateway.resources.limits.cpu | string | `"2000m"` | |
|
||||
| gateway.resources.limits.memory | string | `"2048Mi"` | |
|
||||
| gateway.resources.requests.cpu | string | `"2000m"` | |
|
||||
| gateway.resources.requests.memory | string | `"2048Mi"` | |
|
||||
| gateway.revision | string | `""` | revision declares which revision this gateway is a part of |
|
||||
| gateway.rollingMaxSurge | string | `"100%"` | |
|
||||
| gateway.rollingMaxUnavailable | string | `"25%"` | If global.local is true, the default value is 100%, otherwise it is 25% |
|
||||
| gateway.securityContext | string | `nil` | Define the security context for the pod. If unset, this will be automatically set to the minimum privileges required to bind to port 80 and 443. On Kubernetes 1.22+, this only requires the `net.ipv4.ip_unprivileged_port_start` sysctl. |
|
||||
| gateway.service.annotations | object | `{}` | |
|
||||
| gateway.service.externalTrafficPolicy | string | `""` | |
|
||||
| gateway.service.loadBalancerClass | string | `""` | |
|
||||
| gateway.service.loadBalancerIP | string | `""` | |
|
||||
| gateway.service.loadBalancerSourceRanges | list | `[]` | |
|
||||
| gateway.service.ports[0].name | string | `"http2"` | |
|
||||
| gateway.service.ports[0].port | int | `80` | |
|
||||
| gateway.service.ports[0].protocol | string | `"TCP"` | |
|
||||
| gateway.service.ports[0].targetPort | int | `80` | |
|
||||
| gateway.service.ports[1].name | string | `"https"` | |
|
||||
| gateway.service.ports[1].port | int | `443` | |
|
||||
| gateway.service.ports[1].protocol | string | `"TCP"` | |
|
||||
| gateway.service.ports[1].targetPort | int | `443` | |
|
||||
| gateway.service.type | string | `"LoadBalancer"` | Type of service. Set to "None" to disable the service entirely |
|
||||
| gateway.serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
|
||||
| gateway.serviceAccount.create | bool | `true` | If set, a service account will be created. Otherwise, the default is used |
|
||||
| gateway.serviceAccount.name | string | `""` | The name of the service account to use. If not set, the release name is used |
|
||||
| gateway.tag | string | `""` | |
|
||||
| gateway.tolerations | list | `[]` | |
|
||||
| gateway.unprivilegedPortSupported | string | `nil` | |
|
||||
| global.autoscalingv2API | bool | `true` | whether to use autoscaling/v2 template for HPA settings for internal usage only, not to be configured by users. |
|
||||
| global.caAddress | string | `""` | The customized CA address to retrieve certificates for the pods in the cluster. CSR clients such as the Istio Agent and ingress gateways can use this to specify the CA endpoint. If not set explicitly, default to the Istio discovery address. |
|
||||
| global.caName | string | `""` | The name of the CA for workload certificates. For example, when caName=GkeWorkloadCertificate, GKE workload certificates will be used as the certificates for workloads. The default value is "" and when caName="", the CA will be configured by other mechanisms (e.g., environmental variable CA_PROVIDER). |
|
||||
| global.configCluster | bool | `false` | Configure a remote cluster as the config cluster for an external istiod. |
|
||||
| global.defaultPodDisruptionBudget | object | `{"enabled":false}` | enable pod disruption budget for the control plane, which is used to ensure Istio control plane components are gradually upgraded or recovered. |
|
||||
| global.defaultResources | object | `{"requests":{"cpu":"10m"}}` | A minimal set of requested resources to applied to all deployments so that Horizontal Pod Autoscaler will be able to function (if set). Each component can overwrite these default values by adding its own resources block in the relevant section below and setting the desired resources values. |
|
||||
| global.defaultUpstreamConcurrencyThreshold | int | `10000` | |
|
||||
| global.disableAlpnH2 | bool | `false` | Whether to disable HTTP/2 in ALPN |
|
||||
| global.enableGatewayAPI | bool | `false` | If true, Higress Controller will monitor Gateway API resources as well |
|
||||
| global.enableH3 | bool | `false` | |
|
||||
| global.enableIPv6 | bool | `false` | |
|
||||
| global.enableIstioAPI | bool | `true` | If true, Higress Controller will monitor istio resources as well |
|
||||
| global.enableLDSCache | bool | `false` | |
|
||||
| global.enableProxyProtocol | bool | `false` | |
|
||||
| global.enablePushAllMCPClusters | bool | `true` | |
|
||||
| global.enableRedis | bool | `false` | Whether to enable Redis(redis-stack-server) for Higress, default is false. |
|
||||
| global.enableSRDS | bool | `true` | |
|
||||
| global.enableStatus | bool | `true` | If true, Higress Controller will update the status field of Ingress resources. When migrating from Nginx Ingress, in order to avoid status field of Ingress objects being overwritten, this parameter needs to be set to false, so Higress won't write the entry IP to the status field of the corresponding Ingress object. |
|
||||
| global.externalIstiod | bool | `false` | Configure a remote cluster data plane controlled by an external istiod. When set to true, istiod is not deployed locally and only a subset of the other discovery charts are enabled. |
|
||||
| global.hostRDSMergeSubset | bool | `false` | |
|
||||
| global.hub | string | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | Default hub for Istio images. Releases are published to docker hub under 'istio' project. Dev builds from prow are on gcr.io |
|
||||
| global.imagePullPolicy | string | `""` | Specify image pull policy if default behavior isn't desired. Default behavior: latest images will be Always else IfNotPresent. |
|
||||
| global.imagePullSecrets | list | `[]` | ImagePullSecrets for all ServiceAccount, list of secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. For components that don't use ServiceAccounts (i.e. grafana, servicegraph, tracing) ImagePullSecrets will be added to the corresponding Deployment(StatefulSet) objects. Must be set for any cluster configured with private docker registry. |
|
||||
| global.ingressClass | string | `"higress"` | IngressClass filters which ingress resources the higress controller watches. The default ingress class is higress. There are some special cases for special ingress class. 1. When the ingress class is set as nginx, the higress controller will watch ingress resources with the nginx ingress class or without any ingress class. 2. When the ingress class is set empty, the higress controller will watch all ingress resources in the k8s cluster. |
|
||||
| global.istioNamespace | string | `"istio-system"` | Used to locate istiod. |
|
||||
| global.istiod | object | `{"enableAnalysis":false}` | Enabled by default in master for maximising testing. |
|
||||
| global.jwtPolicy | string | `"third-party-jwt"` | Configure the policy for validating JWT. Currently, two options are supported: "third-party-jwt" and "first-party-jwt". |
|
||||
| global.kind | bool | `false` | |
|
||||
| global.liteMetrics | bool | `false` | |
|
||||
| global.local | bool | `false` | When deploying to a local cluster (e.g.: kind cluster), set this to true. |
|
||||
| global.logAsJson | bool | `false` | |
|
||||
| global.logging | object | `{"level":"default:info"}` | Comma-separated minimum per-scope logging level of messages to output, in the form of <scope>:<level>,<scope>:<level> The control plane has different scopes depending on component, but can configure default log level across all components If empty, default scope and level will be used as configured in code |
|
||||
| global.meshID | string | `""` | If the mesh admin does not specify a value, Istio will use the value of the mesh's Trust Domain. The best practice is to select a proper Trust Domain value. |
|
||||
| global.meshNetworks | object | `{}` | |
|
||||
| global.mountMtlsCerts | bool | `false` | Use the user-specified, secret volume mounted key and certs for Pilot and workloads. |
|
||||
| global.multiCluster.clusterName | string | `""` | Should be set to the name of the cluster this installation will run in. This is required for sidecar injection to properly label proxies |
|
||||
| global.multiCluster.enabled | bool | `true` | Set to true to connect two kubernetes clusters via their respective ingressgateway services when pods in each cluster cannot directly talk to one another. All clusters should be using Istio mTLS and must have a shared root CA for this model to work. |
|
||||
| global.network | string | `""` | Network defines the network this cluster belong to. This name corresponds to the networks in the map of mesh networks. |
|
||||
| global.o11y | object | `{"enabled":false,"promtail":{"image":{"repository":"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/promtail","tag":"2.9.4"},"port":3101,"resources":{"limits":{"cpu":"500m","memory":"2Gi"}},"securityContext":{}}}` | Observability (o11y) configurations |
|
||||
| global.omitSidecarInjectorConfigMap | bool | `false` | |
|
||||
| global.onDemandRDS | bool | `false` | |
|
||||
| global.oneNamespace | bool | `false` | Whether to restrict the applications namespace the controller manages; If not set, controller watches all namespaces |
|
||||
| global.onlyPushRouteCluster | bool | `true` | |
|
||||
| global.operatorManageWebhooks | bool | `false` | Configure whether Operator manages webhook configurations. The current behavior of Istiod is to manage its own webhook configurations. When this option is set as true, Istio Operator, instead of webhooks, manages the webhook configurations. When this option is set as false, webhooks manage their own webhook configurations. |
|
||||
| global.pilotCertProvider | string | `"istiod"` | Configure the certificate provider for control plane communication. Currently, two providers are supported: "kubernetes" and "istiod". As some platforms may not have kubernetes signing APIs, Istiod is the default |
|
||||
| global.priorityClassName | string | `""` | Kubernetes >=v1.11.0 will create two PriorityClass, including system-cluster-critical and system-node-critical, it is better to configure this in order to make sure your Istio pods will not be killed because of low priority class. Refer to https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass for more detail. |
|
||||
| global.proxy.autoInject | string | `"enabled"` | This controls the 'policy' in the sidecar injector. |
|
||||
| global.proxy.clusterDomain | string | `"cluster.local"` | CAUTION: It is important to ensure that all Istio helm charts specify the same clusterDomain value cluster domain. Default value is "cluster.local". |
|
||||
| global.proxy.componentLogLevel | string | `"misc:error"` | Per Component log level for proxy, applies to gateways and sidecars. If a component level is not set, then the global "logLevel" will be used. |
|
||||
| global.proxy.enableCoreDump | bool | `false` | If set, newly injected sidecars will have core dumps enabled. |
|
||||
| global.proxy.excludeIPRanges | string | `""` | |
|
||||
| global.proxy.excludeInboundPorts | string | `""` | |
|
||||
| global.proxy.excludeOutboundPorts | string | `""` | |
|
||||
| global.proxy.holdApplicationUntilProxyStarts | bool | `false` | Controls if sidecar is injected at the front of the container list and blocks the start of the other containers until the proxy is ready |
|
||||
| global.proxy.image | string | `"proxyv2"` | |
|
||||
| global.proxy.includeIPRanges | string | `"*"` | istio egress capture allowlist https://istio.io/docs/tasks/traffic-management/egress.html#calling-external-services-directly example: includeIPRanges: "172.30.0.0/16,172.20.0.0/16" would only capture egress traffic on those two IP Ranges, all other outbound traffic would be allowed by the sidecar |
|
||||
| global.proxy.includeInboundPorts | string | `"*"` | |
|
||||
| global.proxy.includeOutboundPorts | string | `""` | |
|
||||
| global.proxy.logLevel | string | `"warning"` | Log level for proxy, applies to gateways and sidecars. Expected values are: trace|debug|info|warning|error|critical|off |
|
||||
| global.proxy.privileged | bool | `false` | If set to true, istio-proxy container will have privileged securityContext |
|
||||
| global.proxy.proxyStatsMatcher | object | `{"inclusionRegexps":[".*"]}` | Proxy stats name regexps matcher for inclusion |
|
||||
| global.proxy.readinessFailureThreshold | int | `30` | The number of successive failed probes before indicating readiness failure. |
|
||||
| global.proxy.readinessInitialDelaySeconds | int | `1` | The initial delay for readiness probes in seconds. |
|
||||
| global.proxy.readinessPeriodSeconds | int | `2` | The period between readiness probes. |
|
||||
| global.proxy.readinessSuccessThreshold | int | `30` | The number of successive successed probes before indicating readiness success. |
|
||||
| global.proxy.readinessTimeoutSeconds | int | `3` | The readiness timeout seconds |
|
||||
| global.proxy.resources | object | `{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}` | Resources for the sidecar. |
|
||||
| global.proxy.statusPort | int | `15020` | Default port for Pilot agent health checks. A value of 0 will disable health checking. |
|
||||
| global.proxy.tracer | string | `""` | Specify which tracer to use. One of: lightstep, datadog, stackdriver. If using stackdriver tracer outside GCP, set env GOOGLE_APPLICATION_CREDENTIALS to the GCP credential file. |
|
||||
| global.proxy_init.image | string | `"proxyv2"` | Base name for the proxy_init container, used to configure iptables. |
|
||||
| global.proxy_init.resources.limits.cpu | string | `"2000m"` | |
|
||||
| global.proxy_init.resources.limits.memory | string | `"1024Mi"` | |
|
||||
| global.proxy_init.resources.requests.cpu | string | `"10m"` | |
|
||||
| global.proxy_init.resources.requests.memory | string | `"10Mi"` | |
|
||||
| global.remotePilotAddress | string | `""` | configure remote pilot and istiod service and endpoint |
|
||||
| global.sds.token | object | `{"aud":"istio-ca"}` | The JWT token for SDS and the aud field of such JWT. See RFC 7519, section 4.1.3. When a CSR is sent from Istio Agent to the CA (e.g. Istiod), this aud is to make sure the JWT is intended for the CA. |
|
||||
| global.sts.servicePort | int | `0` | The service port used by Security Token Service (STS) server to handle token exchange requests. Setting this port to a non-zero value enables STS server. |
|
||||
| global.tracer | object | `{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":""},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200}}` | Configuration for each of the supported tracers |
|
||||
| global.tracer.datadog | object | `{"address":"$(HOST_IP):8126"}` | Configuration for envoy to send trace data to LightStep. Disabled by default. address: the <host>:<port> of the satellite pool accessToken: required for sending data to the pool |
|
||||
| global.tracer.datadog.address | string | `"$(HOST_IP):8126"` | Host:Port for submitting traces to the Datadog agent. |
|
||||
| global.tracer.lightstep.accessToken | string | `""` | example: abcdefg1234567 |
|
||||
| global.tracer.lightstep.address | string | `""` | example: lightstep-satellite:443 |
|
||||
| global.tracer.stackdriver.debug | bool | `false` | enables trace output to stdout. |
|
||||
| global.tracer.stackdriver.maxNumberOfAnnotations | int | `200` | The global default max number of annotation events per span. |
|
||||
| global.tracer.stackdriver.maxNumberOfAttributes | int | `200` | The global default max number of attributes per span. |
|
||||
| global.tracer.stackdriver.maxNumberOfMessageEvents | int | `200` | The global default max number of message events per span. |
|
||||
| global.useMCP | bool | `false` | Use the Mesh Control Protocol (MCP) for configuring Istiod. Requires an MCP source. |
|
||||
| global.watchNamespace | string | `""` | If not empty, Higress Controller will only watch resources in the specified namespace. When isolating different business systems using K8s namespace, if each namespace requires a standalone gateway instance, this parameter can be used to confine the Ingress watching of Higress within the given namespace. |
|
||||
| global.xdsMaxRecvMsgSize | string | `"104857600"` | |
|
||||
| hub | string | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | |
|
||||
| meshConfig | object | `{"enablePrometheusMerge":true,"rootNamespace":null,"trustDomain":"cluster.local"}` | meshConfig defines runtime configuration of components, including Istiod and istio-agent behavior See https://istio.io/docs/reference/config/istio.mesh.v1alpha1/ for all available options |
|
||||
| meshConfig.rootNamespace | string | `nil` | The namespace to treat as the administrative root namespace for Istio configuration. When processing a leaf namespace Istio will search for declarations in that namespace first and if none are found it will search in the root namespace. Any matching declaration found in the root namespace is processed as if it were declared in the leaf namespace. |
|
||||
| meshConfig.trustDomain | string | `"cluster.local"` | The trust domain corresponds to the trust root of a system Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain |
|
||||
| pilot.autoscaleEnabled | bool | `false` | |
|
||||
| pilot.autoscaleMax | int | `5` | |
|
||||
| pilot.autoscaleMin | int | `1` | |
|
||||
| pilot.configMap | bool | `true` | Install the mesh config map, generated from values.yaml. If false, pilot wil use default values (by default) or user-supplied values. |
|
||||
| pilot.configSource | object | `{"subscribedResources":[]}` | This is used to set the source of configuration for the associated address in configSource, if nothing is specified the default MCP is assumed. |
|
||||
| pilot.cpu.targetAverageUtilization | int | `80` | |
|
||||
| pilot.deploymentLabels | object | `{}` | Additional labels to apply to the deployment. |
|
||||
| pilot.enableProtocolSniffingForInbound | bool | `true` | if protocol sniffing is enabled for inbound |
|
||||
| pilot.enableProtocolSniffingForOutbound | bool | `true` | if protocol sniffing is enabled for outbound |
|
||||
| pilot.env.PILOT_ENABLE_CROSS_CLUSTER_WORKLOAD_ENTRY | string | `"false"` | |
|
||||
| pilot.env.PILOT_ENABLE_METADATA_EXCHANGE | string | `"false"` | |
|
||||
| pilot.env.PILOT_SCOPE_GATEWAY_TO_NAMESPACE | string | `"false"` | |
|
||||
| pilot.env.VALIDATION_ENABLED | string | `"false"` | |
|
||||
| pilot.hub | string | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | |
|
||||
| pilot.image | string | `"pilot"` | Can be a full hub/image:tag |
|
||||
| pilot.jwksResolverExtraRootCA | string | `""` | You can use jwksResolverExtraRootCA to provide a root certificate in PEM format. This will then be trusted by pilot when resolving JWKS URIs. |
|
||||
| pilot.keepaliveMaxServerConnectionAge | string | `"30m"` | The following is used to limit how long a sidecar can be connected to a pilot. It balances out load across pilot instances at the cost of increasing system churn. |
|
||||
| pilot.nodeSelector | object | `{}` | |
|
||||
| pilot.plugins | list | `[]` | |
|
||||
| pilot.podAnnotations | object | `{}` | |
|
||||
| pilot.podLabels | object | `{}` | Additional labels to apply on the pod level for monitoring and logging configuration. |
|
||||
| pilot.replicaCount | int | `1` | |
|
||||
| pilot.resources | object | `{"requests":{"cpu":"500m","memory":"2048Mi"}}` | Resources for a small pilot install |
|
||||
| pilot.rollingMaxSurge | string | `"100%"` | |
|
||||
| pilot.rollingMaxUnavailable | string | `"25%"` | |
|
||||
| pilot.serviceAnnotations | object | `{}` | |
|
||||
| pilot.tag | string | `""` | |
|
||||
| pilot.traceSampling | float | `1` | |
|
||||
| redis.redis.affinity | object | `{}` | Affinity for Redis |
|
||||
| redis.redis.image | string | `"redis-stack-server"` | Specify the image |
|
||||
| redis.redis.name | string | `"redis-stack-server"` | |
|
||||
| redis.redis.nodeSelector | object | `{}` | NodeSelector Node labels for Redis |
|
||||
| redis.redis.password | string | `""` | Specify the password, if not set, no password is used |
|
||||
| redis.redis.persistence.accessModes | list | `["ReadWriteOnce"]` | Persistent Volume access modes |
|
||||
| redis.redis.persistence.enabled | bool | `false` | Enable persistence on Redis, default is false |
|
||||
| redis.redis.persistence.size | string | `"1Gi"` | Persistent Volume size |
|
||||
| redis.redis.persistence.storageClass | string | `""` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner |
|
||||
| redis.redis.replicas | int | `1` | Specify the number of replicas |
|
||||
| redis.redis.resources | object | `{}` | Specify the resources |
|
||||
| redis.redis.service | object | `{"port":6379,"type":"ClusterIP"}` | Service parameters |
|
||||
| redis.redis.service.port | int | `6379` | Exporter service port |
|
||||
| redis.redis.service.type | string | `"ClusterIP"` | Exporter service type |
|
||||
| redis.redis.tag | string | `"7.4.0-v3"` | Specify the tag |
|
||||
| redis.redis.tolerations | list | `[]` | Tolerations for Redis |
|
||||
| revision | string | `""` | |
|
||||
| tracing.enable | bool | `false` | |
|
||||
| tracing.sampling | int | `100` | |
|
||||
| tracing.skywalking.port | int | `11800` | |
|
||||
| tracing.skywalking.service | string | `""` | |
|
||||
| tracing.timeout | int | `500` | |
|
||||
| upstream | object | `{"connectionBufferLimits":10485760,"idleTimeout":10}` | Upstream config settings |
|
||||
34
helm/higress/README.md.gotmpl
Normal file
34
helm/higress/README.md.gotmpl
Normal file
@@ -0,0 +1,34 @@
|
||||
## Higress for Kubernetes
|
||||
|
||||
Higress is a cloud-native api gateway based on Alibaba's internal gateway practices.
|
||||
|
||||
Powered by Istio and Envoy, Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway and security gateway, thereby greatly reducing the costs of deployment, operation and maintenance.
|
||||
|
||||
## Setup Repo Info
|
||||
|
||||
```console
|
||||
helm repo add higress.io https://higress.io/helm-charts
|
||||
helm repo update
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
To install the chart with the release name `higress`:
|
||||
|
||||
```console
|
||||
helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
|
||||
To uninstall/delete the higress deployment:
|
||||
|
||||
```console
|
||||
helm delete higress -n higress-system
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
|
||||
## Parameters
|
||||
|
||||
{{ template "chart.valuesSection" . }}
|
||||
188
helm/higress/README.zh.md
Normal file
188
helm/higress/README.zh.md
Normal file
@@ -0,0 +1,188 @@
|
||||
## Higress for Kubernetes
|
||||
|
||||
Higress 是基于阿里巴巴内部网关实践构建的云原生 API 网关。
|
||||
|
||||
依托 Istio 和 Envoy,Higress 实现了流量网关、微服务网关和安全网关三重架构的融合,从而大幅降低了部署、运维成本。
|
||||
|
||||
## 设置仓库信息
|
||||
|
||||
```console
|
||||
helm repo add higress.io https://higress.io/helm-charts
|
||||
helm repo update
|
||||
```
|
||||
|
||||
## 安装
|
||||
|
||||
以 `higress` 为发布名称安装 chart:
|
||||
|
||||
```console
|
||||
helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes
|
||||
```
|
||||
|
||||
## 卸载
|
||||
|
||||
要卸载/删除 higress 部署:
|
||||
|
||||
```console
|
||||
helm delete higress -n higress-system
|
||||
```
|
||||
|
||||
该命令会移除与 chart 相关的所有 Kubernetes 组件,并删除发布。
|
||||
|
||||
## 参数
|
||||
|
||||
## 值
|
||||
|
||||
| 键 | 类型 | 默认值 | 描述 |
|
||||
|-----|------|---------|-------------|
|
||||
| clusterName | 字符串 | `""` | |
|
||||
| controller.affinity | 对象 | `{}` | |
|
||||
| controller.automaticHttps.email | 字符串 | `""` | |
|
||||
| controller.automaticHttps.enabled | 布尔值 | `true` | |
|
||||
| controller.autoscaling.enabled | 布尔值 | `false` | |
|
||||
| controller.autoscaling.maxReplicas | 整数 | `5` | |
|
||||
| controller.autoscaling.minReplicas | 整数 | `1` | |
|
||||
| controller.autoscaling.targetCPUUtilizationPercentage | 整数 | `80` | |
|
||||
| controller.env | 对象 | `{}` | |
|
||||
| controller.hub | 字符串 | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | |
|
||||
| controller.image | 字符串 | `"higress"` | |
|
||||
| controller.imagePullSecrets | 列表 | `[]` | |
|
||||
| controller.labels | 对象 | `{}` | |
|
||||
| controller.name | 字符串 | `"higress-controller"` | |
|
||||
| controller.nodeSelector | 对象 | `{}` | |
|
||||
| controller.podAnnotations | 对象 | `{}` | |
|
||||
| controller.podSecurityContext | 对象 | `{}` | |
|
||||
| controller.ports[0].name | 字符串 | `"http"` | |
|
||||
| controller.ports[0].port | 整数 | `8888` | |
|
||||
| controller.ports[0].protocol | 字符串 | `"TCP"` | |
|
||||
| controller.ports[0].targetPort | 整数 | `8888` | |
|
||||
| controller.ports[1].name | 字符串 | `"http-solver"` | |
|
||||
| controller.ports[1].port | 整数 | `8889` | |
|
||||
| controller.ports[1].protocol | 字符串 | `"TCP"` | |
|
||||
| controller.ports[1].targetPort | 整数 | `8889` | |
|
||||
| controller.ports[2].name | 字符串 | `"grpc"` | |
|
||||
| controller.ports[2].port | 整数 | `15051` | |
|
||||
| controller.ports[2].protocol | 字符串 | `"TCP"` | |
|
||||
| controller.ports[2].targetPort | 整数 | `15051` | |
|
||||
| controller.probe.httpGet.path | 字符串 | `"/ready"` | |
|
||||
| controller.probe.httpGet.port | 整数 | `8888` | |
|
||||
| controller.probe.initialDelaySeconds | 整数 | `1` | |
|
||||
| controller.probe.periodSeconds | 整数 | `3` | |
|
||||
| controller.probe.timeoutSeconds | 整数 | `5` | |
|
||||
| controller.rbac.create | 布尔值 | `true` | |
|
||||
| controller.replicas | 整数 | `1` | Higress Controller 的 Pod 数量 |
|
||||
| controller.resources.limits.cpu | 字符串 | `"1000m"` | |
|
||||
| controller.resources.limits.memory | 字符串 | `"2048Mi"` | |
|
||||
| controller.resources.requests.cpu | 字符串 | `"500m"` | |
|
||||
| controller.resources.requests.memory | 字符串 | `"2048Mi"` | |
|
||||
| controller.securityContext | 对象 | `{}` | |
|
||||
| controller.service.type | 字符串 | `"ClusterIP"` | |
|
||||
| controller.serviceAccount.annotations | 对象 | `{}` | 添加到服务账户的注解 |
|
||||
| controller.serviceAccount.create | 布尔值 | `true` | 指定是否创建服务账户 |
|
||||
| controller.serviceAccount.name | 字符串 | `""` | 如果未设置且 create 为 true,则使用 fullname 模板生成名称 |
|
||||
| controller.tag | 字符串 | `""` | |
|
||||
| controller.tolerations | 列表 | `[]` | |
|
||||
| downstream | 对象 | `{"connectionBufferLimits":32768,"http2":{"initialConnectionWindowSize":1048576,"initialStreamWindowSize":65535,"maxConcurrentStreams":100},"idleTimeout":180,"maxRequestHeadersKb":60,"routeTimeout":0}` | 下游配置设置 |
|
||||
| gateway.affinity | 对象 | `{}` | |
|
||||
| gateway.annotations | 对象 | `{}` | 应用到所有资源的注解 |
|
||||
| gateway.autoscaling.enabled | 布尔值 | `false` | |
|
||||
| gateway.autoscaling.maxReplicas | 整数 | `5` | |
|
||||
| gateway.autoscaling.minReplicas | 整数 | `1` | |
|
||||
| gateway.autoscaling.targetCPUUtilizationPercentage | 整数 | `80` | |
|
||||
| gateway.containerSecurityContext | 字符串 | `nil` | |
|
||||
| gateway.env | 对象 | `{}` | Pod 环境变量 |
|
||||
| gateway.hostNetwork | 布尔值 | `false` | |
|
||||
| gateway.httpPort | 整数 | `80` | |
|
||||
| gateway.httpsPort | 整数 | `443` | |
|
||||
| gateway.hub | 字符串 | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | |
|
||||
| gateway.image | 字符串 | `"gateway"` | |
|
||||
| gateway.kind | 字符串 | `"Deployment"` | 使用 `DaemonSet` 或 `Deployment` |
|
||||
| gateway.labels | 对象 | `{}` | 应用到所有资源的标签 |
|
||||
| gateway.metrics.enabled | 布尔值 | `false` | 如果为 true,则为网关创建 PodMonitor 或 VMPodScrape |
|
||||
| gateway.metrics.honorLabels | 布尔值 | `false` | |
|
||||
| gateway.metrics.interval | 字符串 | `""` | |
|
||||
| gateway.metrics.metricRelabelConfigs | 列表 | `[]` | 用于 operator.victoriametrics.com/v1beta1.VMPodScrape |
|
||||
| gateway.metrics.metricRelabelings | 列表 | `[]` | 用于 monitoring.coreos.com/v1.PodMonitor |
|
||||
| gateway.metrics.provider | 字符串 | `"monitoring.coreos.com"` | CustomResourceDefinition 的提供者组名,可以是 monitoring.coreos.com 或 operator.victoriametrics.com |
|
||||
| gateway.metrics.rawSpec | 对象 | `{}` | 更多原始的 podMetricsEndpoints 规范 |
|
||||
| gateway.metrics.relabelConfigs | 列表 | `[]` | |
|
||||
| gateway.metrics.relabelings | 列表 | `[]` | |
|
||||
| gateway.metrics.scrapeTimeout | 字符串 | `""` | |
|
||||
| gateway.name | 字符串 | `"higress-gateway"` | |
|
||||
| gateway.networkGateway | 字符串 | `""` | 如果指定,网关将作为给定网络的网络网关。 |
|
||||
| gateway.nodeSelector | 对象 | `{}` | |
|
||||
| gateway.podAnnotations."prometheus.io/path" | 字符串 | `"/stats/prometheus"` | |
|
||||
| gateway.podAnnotations."prometheus.io/port" | 字符串 | `"15020"` | |
|
||||
| gateway.podAnnotations."prometheus.io/scrape" | 字符串 | `"true"` | |
|
||||
| gateway.podAnnotations."sidecar.istio.io/inject" | 字符串 | `"false"` | |
|
||||
| gateway.rbac.enabled | 布尔值 | `true` | 如果启用,将创建角色以启用从网关访问证书。当使用 http://gateway-api.org/ 时不需要。 |
|
||||
| gateway.readinessFailureThreshold | 整数 | `30` | 指示准备失败前的连续失败探测次数。 |
|
||||
| gateway.readinessInitialDelaySeconds | 整数 | `1` | 准备探测的初始延迟秒数。 |
|
||||
| gateway.readinessPeriodSeconds | 整数 | `2` | 准备探测之间的间隔。 |
|
||||
| gateway.readinessSuccessThreshold | 整数 | `1` | 指示准备成功前的连续成功探测次数。 |
|
||||
| gateway.readinessTimeoutSeconds | 整数 | `3` | 准备探测的超时秒数 |
|
||||
| gateway.replicas | 整数 | `2` | Higress Gateway 的 Pod 数量 |
|
||||
| gateway.resources.limits.cpu | 字符串 | `"2000m"` | |
|
||||
| gateway.resources.limits.memory | 字符串 | `"2048Mi"` | |
|
||||
| gateway.resources.requests.cpu | 字符串 | `"2000m"` | |
|
||||
| gateway.resources.requests.memory | 字符串 | `"2048Mi"` | |
|
||||
| gateway.revision | 字符串 | `""` | 修订声明此网关属于哪个修订 |
|
||||
| gateway.rollingMaxSurge | 字符串 | `"100%"` | |
|
||||
| gateway.rollingMaxUnavailable | 字符串 | `"25%"` | |
|
||||
| gateway.securityContext | 字符串 | `nil` | 定义 Pod 的安全上下文。如果未设置,将自动设置为绑定到端口 80 和 443 所需的最小权限。在 Kubernetes 1.22+ 上,这只需要 `net.ipv4.ip_unprivileged_port_start` 系统调用。 |
|
||||
| gateway.service.annotations | 对象 | `{}` | |
|
||||
| gateway.service.externalTrafficPolicy | 字符串 | `""` | |
|
||||
| gateway.service.loadBalancerClass | 字符串 | `""` | |
|
||||
| gateway.service.loadBalancerIP | 字符串 | `""` | |
|
||||
| gateway.service.loadBalancerSourceRanges | 列表 | `[]` | |
|
||||
| gateway.service.ports[0].name | 字符串 | `"http2"` | |
|
||||
| gateway.service.ports[0].port | 整数 | `80` | |
|
||||
| gateway.service.ports[0].protocol | 字符串 | `"TCP"` | |
|
||||
| gateway.service.ports[0].targetPort | 整数 | `80` | |
|
||||
| gateway.service.ports[1].name | 字符串 | `"https"` | |
|
||||
| gateway.service.ports[1].port | 整数 | `443` | |
|
||||
| gateway.service.ports[1].protocol | 字符串 | `"TCP"` | |
|
||||
| gateway.service.ports[1].targetPort | 整数 | `443` | |
|
||||
| gateway.service.type | 字符串 | `"LoadBalancer"` | 服务类型。设置为 "None" 以完全禁用服务 |
|
||||
| gateway.serviceAccount.annotations | 对象 | `{}` | 添加到服务账户的注解 |
|
||||
| gateway.serviceAccount.create | 布尔值 | `true` | 如果设置,将创建服务账户。否则,使用默认值 |
|
||||
| gateway.serviceAccount.name | 字符串 | `""` | 要使用的服务账户名称。如果未设置,则使用发布名称 |
|
||||
| gateway.tag | 字符串 | `""` | |
|
||||
| gateway.tolerations | 列表 | `[]` | |
|
||||
| gateway.unprivilegedPortSupported | 字符串 | `nil` | |
|
||||
| global.autoscalingv2API | 布尔值 | `true` | 是否使用 autoscaling/v2 模板进行 HPA 设置,仅供内部使用,用户不应配置。 |
|
||||
| global.caAddress | 字符串 | `""` | 自定义的 CA 地址,用于为集群中的 Pod 检索证书。CSR 客户端(如 Istio Agent 和 ingress gateways)可以使用此地址指定 CA 端点。如果未明确设置,则默认为 Istio 发现地址。 |
|
||||
| global.caName | 字符串 | `""` | 工作负载证书的 CA 名称。例如,当 caName=GkeWorkloadCertificate 时,GKE 工作负载证书将用作工作负载的证书。默认值为 "",当 caName="" 时,CA 将通过其他机制(如环境变量 CA_PROVIDER)配置。 |
|
||||
| global.configCluster | 布尔值 | `false` | 将远程集群配置为外部 istiod 的配置集群。 |
|
||||
| global.defaultPodDisruptionBudget | 对象 | `{"enabled":false}` | 为控制平面启用 Pod 中断预算,用于确保 Istio 控制平面组件逐步升级或恢复。 |
|
||||
| global.defaultResources | 对象 | `{"requests":{"cpu":"10m"}}` | 应用于所有部署的最小请求资源集,以便 Horizontal Pod Autoscaler 能够正常工作(如果设置)。每个组件可以通过在相关部分添加自己的资源块并设置所需的资源值来覆盖这些默认值。 |
|
||||
| global.defaultUpstreamConcurrencyThreshold | 整数 | `10000` | |
|
||||
| global.disableAlpnH2 | 布尔值 | `false` | 是否在 ALPN 中禁用 HTTP/2 |
|
||||
| global.enableGatewayAPI | 布尔值 | `false` | 如果为 true,Higress Controller 还将监控 Gateway API 资源 |
|
||||
| global.enableH3 | 布尔值 | `false` | |
|
||||
| global.enableIPv6 | 布尔值 | `false` | |
|
||||
| global.enableIstioAPI | 布尔值 | `true` | 如果为 true,Higress Controller 还将监控 istio 资源 |
|
||||
| global.enableLDSCache | 布尔值 | `true` | |
|
||||
| global.enableProxyProtocol | 布尔值 | `false` | |
|
||||
| global.enablePushAllMCPClusters | 布尔值 | `true` | |
|
||||
| global.enableSRDS | 布尔值 | `true` | |
|
||||
| global.enableStatus | 布尔值 | `true` | 如果为 true,Higress Controller 将更新 Ingress 资源的状态字段。从 Nginx Ingress 迁移时,为了避免 Ingress 对象的状态字段被覆盖,需要将此参数设置为 false,以便 Higress 不会将入口 IP 写入相应 Ingress 对象的状态字段。 |
|
||||
| global.externalIstiod | 布尔值 | `false` | 配置由外部 istiod 控制的远程集群数据平面。当设置为 true 时,本地不部署 istiod,仅启用其他发现 chart 的子集。 |
|
||||
| global.hostRDSMergeSubset | 布尔值 | `false` | |
|
||||
| global.hub | 字符串 | `"higress-registry.cn-hangzhou.cr.aliyuncs.com/higress"` | Istio 镜像的默认仓库。发布版本发布到 docker hub 的 'istio' 项目下。来自 prow 的开发构建位于 gcr.io |
|
||||
| global.imagePullPolicy | 字符串 | `""` | 如果不需要默认行为,则指定镜像拉取策略。默认行为:最新镜像将始终拉取,否则 IfNotPresent。 |
|
||||
| global.imagePullSecrets | 列表 | `[]` | 所有 ServiceAccount 的 ImagePullSecrets,用于引用此 ServiceAccount 的 Pod 拉取任何镜像的同一命名空间中的秘密列表。对于不使用 ServiceAccount 的组件(即 grafana、servicegraph、tracing),ImagePullSecrets 将添加到相应的 Deployment(StatefulSet) 对象中。对于配置了私有 docker 注册表的任何集群,必须设置。 |
|
||||
| global.ingressClass | 字符串 | `"higress"` | IngressClass 过滤 higress controller 监听的 ingress 资源。默认的 ingress class 是 higress。有一些特殊情况用于特殊的 ingress class。1. 当 ingress class 设置为 nginx 时,higress controller 将监听带有 nginx ingress class 或没有任何 ingress class 的 ingress 资源。2. 当 ingress class 设置为空时,higress controller 将监听 k8s 集群中的所有 ingress 资源。 |
|
||||
| global.istioNamespace | 字符串 | `"istio-system"` | 用于定位 istiod。 |
|
||||
| global.istiod | 对象 | `{"enableAnalysis":false}` | 默认在主分支中启用以最大化测试。 |
|
||||
| global.jwtPolicy | 字符串 | `"third-party-jwt"` | 配置验证 JWT 的策略。目前支持两个选项:"third-party-jwt" 和 "first-party-jwt"。 |
|
||||
| global.kind | 布尔值 | `false` | |
|
||||
| global.liteMetrics | 布尔值 | `false` | |
|
||||
| global.local | 布尔值 | `false` | 当部署到本地集群(如:kind 集群)时,将此设置为 true。 |
|
||||
| global.logAsJson | 布尔值 | `false` | |
|
||||
| global.logging | 对象 | `{"level":"default:info"}` | 以逗号分隔的每个范围的最小日志级别,格式为 <scope>:<level>,<scope>:<level> 控制平面根据组件不同有不同的范围,但可以配置所有组件的默认日志级别 如果为空,将使用代码中配置的默认范围和级别 |
|
||||
| global.meshID | 字符串 | `""` | 如果网格管理员未指定值,Istio 将使用网格的信任域的值。最佳实践是选择一个合适的信任域值。 |
|
||||
| global.meshNetworks | 对象 | `{}` | |
|
||||
| global.mountMtlsCerts | 布尔值 | `false` | 使用用户指定的、挂载的密钥和证书用于 Pilot 和工作负载。 |
|
||||
| global.multiCluster.clusterName | 字符串 | `""` | 应设置为此安装运行的集群的名称。这是为了正确标记代理的 sidecar 注入所必需的 |
|
||||
| global.multiCluster.enabled | 布尔值 | `true` | 设置为 true 以通过各自的 ingressgateway 服务连接两个 kubernetes 集群,当每个集群中的 Pod 无法直接相互通信时。
|
||||
17
hgctl/go.mod
17
hgctl/go.mod
@@ -1,9 +1,8 @@
|
||||
module github.com/alibaba/higress/hgctl
|
||||
|
||||
go 1.21.0
|
||||
|
||||
toolchain go1.22.2
|
||||
go 1.22.2
|
||||
|
||||
toolchain go1.23.7
|
||||
|
||||
replace github.com/spf13/viper => github.com/istio/viper v1.3.3-0.20190515210538-2789fed3109c
|
||||
|
||||
@@ -243,15 +242,15 @@ require (
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.25.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/oauth2 v0.13.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/term v0.27.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
|
||||
18
hgctl/go.sum
18
hgctl/go.sum
@@ -1789,8 +1789,9 @@ golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
|
||||
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
@@ -1909,8 +1910,9 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1961,8 +1963,9 @@ golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -2069,8 +2072,9 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -2086,8 +2090,9 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -2108,8 +2113,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
Submodule istio/istio updated: d380470e53...1492505b14
Submodule istio/proxy updated: 2a5416fcfa...d411a4f019
@@ -41,11 +41,11 @@ import (
|
||||
"istio.io/istio/pkg/config/schema/kind"
|
||||
"istio.io/istio/pkg/keepalive"
|
||||
istiokube "istio.io/istio/pkg/kube"
|
||||
"istio.io/istio/pkg/log"
|
||||
"istio.io/istio/pkg/security"
|
||||
"istio.io/istio/security/pkg/server/ca/authenticate"
|
||||
"istio.io/istio/security/pkg/server/ca/authenticate/kubeauth"
|
||||
"istio.io/pkg/ledger"
|
||||
"istio.io/pkg/log"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
@@ -235,7 +235,7 @@ func (s *Server) initConfigController() error {
|
||||
options.ClusterId = ""
|
||||
}
|
||||
|
||||
ingressConfig := translation.NewIngressTranslation(s.kubeClient, s.xdsServer, ns, options.ClusterId)
|
||||
ingressConfig := translation.NewIngressTranslation(s.kubeClient, s.xdsServer, ns, options)
|
||||
ingressConfig.AddLocalCluster(options)
|
||||
|
||||
s.configStores = append(s.configStores, ingressConfig)
|
||||
|
||||
@@ -173,7 +173,7 @@ func (s *CertMgr) Reconcile(ctx context.Context, oldConfig *Config, newConfig *C
|
||||
s.cache.Start()
|
||||
// sync domains
|
||||
s.configMgr.SetConfig(newConfig)
|
||||
CertLog.Infof("certMgr start to manageSync domains:+v%", newDomains)
|
||||
CertLog.Infof("certMgr start to manageSync domains: %+v", newDomains)
|
||||
s.manageSync(context.Background(), newDomains)
|
||||
CertLog.Infof("certMgr manageSync domains done")
|
||||
} else {
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
|
||||
package cert
|
||||
|
||||
import "istio.io/pkg/log"
|
||||
import "istio.io/istio/pkg/log"
|
||||
|
||||
var CertLog = log.RegisterScope("cert", "Higress Cert process.", 0)
|
||||
var CertLog = log.RegisterScope("cert", "Higress Cert process.")
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"istio.io/istio/pkg/config/constants"
|
||||
"istio.io/istio/pkg/env"
|
||||
"istio.io/istio/pkg/keepalive"
|
||||
"istio.io/pkg/log"
|
||||
"istio.io/istio/pkg/log"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -19,7 +19,9 @@ import "istio.io/pkg/env"
|
||||
var (
|
||||
PodNamespace = env.RegisterStringVar("POD_NAMESPACE", "higress-system", "").Get()
|
||||
PodName = env.RegisterStringVar("POD_NAME", "", "").Get()
|
||||
GatewayName = env.RegisterStringVar("GATEWAY_NAME", "higress-gateway", "").Get()
|
||||
// Revision is the value of the Istio control plane revision, e.g. "canary",
|
||||
// and is the value used by the "istio.io/rev" label.
|
||||
Revision = env.Register("REVISION", "", "").Get()
|
||||
Revision = env.Register("REVISION", "", "").Get()
|
||||
McpServerWasmImageUrl = env.RegisterStringVar("MCP_SERVER_WASM_IMAGE_URL", "oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/mcp-server/all-in-one:1.0.0", "").Get()
|
||||
)
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
extensions "istio.io/api/extensions/v1alpha1"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
istiotype "istio.io/api/type/v1beta1"
|
||||
"istio.io/istio/pilot/pkg/features"
|
||||
istiomodel "istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pilot/pkg/util/protoconv"
|
||||
"istio.io/istio/pkg/cluster"
|
||||
@@ -150,9 +151,38 @@ type IngressConfig struct {
|
||||
clusterId cluster.ID
|
||||
|
||||
httpsConfigMgr *cert.ConfigMgr
|
||||
|
||||
commonOptions common.Options
|
||||
// templateProcessor processes template variables in config
|
||||
templateProcessor *TemplateProcessor
|
||||
|
||||
// secretConfigMgr manages secret dependencies
|
||||
secretConfigMgr *SecretConfigMgr
|
||||
}
|
||||
|
||||
func NewIngressConfig(localKubeClient kube.Client, xdsUpdater istiomodel.XDSUpdater, namespace string, clusterId cluster.ID) *IngressConfig {
|
||||
// getSecretValue implements the getValue function for secret references
|
||||
func (m *IngressConfig) getSecretValue(valueType, namespace, name, key string) (string, error) {
|
||||
if valueType != "secret" {
|
||||
return "", fmt.Errorf("unsupported value type: %s", valueType)
|
||||
}
|
||||
|
||||
m.mutex.RLock()
|
||||
defer m.mutex.RUnlock()
|
||||
|
||||
for _, controller := range m.remoteIngressControllers {
|
||||
secret, err := controller.SecretLister().Secrets(namespace).Get(name)
|
||||
if err == nil {
|
||||
if value, exists := secret.Data[key]; exists {
|
||||
return string(value), nil
|
||||
}
|
||||
return "", fmt.Errorf("key %s not found in secret %s/%s", key, namespace, name)
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("secret %s/%s not found", namespace, name)
|
||||
}
|
||||
|
||||
func NewIngressConfig(localKubeClient kube.Client, xdsUpdater istiomodel.XDSUpdater, namespace string, options common.Options) *IngressConfig {
|
||||
clusterId := options.ClusterId
|
||||
if clusterId == "Kubernetes" {
|
||||
clusterId = ""
|
||||
}
|
||||
@@ -168,18 +198,26 @@ func NewIngressConfig(localKubeClient kube.Client, xdsUpdater istiomodel.XDSUpda
|
||||
namespace: namespace,
|
||||
wasmPlugins: make(map[string]*extensions.WasmPlugin),
|
||||
http2rpcs: make(map[string]*higressv1.Http2Rpc),
|
||||
commonOptions: options,
|
||||
}
|
||||
mcpbridgeController := mcpbridge.NewController(localKubeClient, clusterId)
|
||||
|
||||
// Initialize secret config manager
|
||||
config.secretConfigMgr = NewSecretConfigMgr(xdsUpdater)
|
||||
|
||||
// Initialize template processor with value getter function
|
||||
config.templateProcessor = NewTemplateProcessor(config.getSecretValue, namespace, config.secretConfigMgr)
|
||||
|
||||
mcpbridgeController := mcpbridge.NewController(localKubeClient, options)
|
||||
mcpbridgeController.AddEventHandler(config.AddOrUpdateMcpBridge, config.DeleteMcpBridge)
|
||||
config.mcpbridgeController = mcpbridgeController
|
||||
config.mcpbridgeLister = mcpbridgeController.Lister()
|
||||
|
||||
wasmPluginController := wasmplugin.NewController(localKubeClient, clusterId)
|
||||
wasmPluginController := wasmplugin.NewController(localKubeClient, options)
|
||||
wasmPluginController.AddEventHandler(config.AddOrUpdateWasmPlugin, config.DeleteWasmPlugin)
|
||||
config.wasmPluginController = wasmPluginController
|
||||
config.wasmPluginLister = wasmPluginController.Lister()
|
||||
|
||||
http2rpcController := http2rpc.NewController(localKubeClient, clusterId)
|
||||
http2rpcController := http2rpc.NewController(localKubeClient, options)
|
||||
http2rpcController.AddEventHandler(config.AddOrUpdateHttp2Rpc, config.DeleteHttp2Rpc)
|
||||
config.http2rpcController = http2rpcController
|
||||
config.http2rpcLister = http2rpcController.Lister()
|
||||
@@ -224,8 +262,9 @@ func (m *IngressConfig) RegisterEventHandler(kind config.GroupVersionKind, f ist
|
||||
}
|
||||
|
||||
func (m *IngressConfig) AddLocalCluster(options common.Options) {
|
||||
secretController := secret.NewController(m.localKubeClient, options.ClusterId)
|
||||
secretController := secret.NewController(m.localKubeClient, options)
|
||||
secretController.AddEventHandler(m.ReflectSecretChanges)
|
||||
secretController.AddEventHandler(m.secretConfigMgr.HandleSecretChange)
|
||||
|
||||
var ingressController common.IngressController
|
||||
v1 := common.V1Available(m.localKubeClient)
|
||||
@@ -235,8 +274,9 @@ func (m *IngressConfig) AddLocalCluster(options common.Options) {
|
||||
ingressController = ingressv1.NewController(m.localKubeClient, m.localKubeClient, options, secretController)
|
||||
}
|
||||
m.remoteIngressControllers[options.ClusterId] = ingressController
|
||||
|
||||
m.remoteGatewayControllers[options.ClusterId] = gateway.NewController(m.localKubeClient, options)
|
||||
if features.EnableGatewayAPI {
|
||||
m.remoteGatewayControllers[options.ClusterId] = gateway.NewController(m.localKubeClient, options)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *IngressConfig) List(typ config.GroupVersionKind, namespace string) []config.Config {
|
||||
@@ -251,10 +291,24 @@ func (m *IngressConfig) List(typ config.GroupVersionKind, namespace string) []co
|
||||
var configs = make([]config.Config, 0)
|
||||
|
||||
if configsFromIngress := m.listFromIngressControllers(typ, namespace); configsFromIngress != nil {
|
||||
// Process templates for ingress configs
|
||||
for i := range configsFromIngress {
|
||||
if err := m.templateProcessor.ProcessConfig(&configsFromIngress[i]); err != nil {
|
||||
IngressLog.Errorf("Failed to process template for config %s/%s: %v",
|
||||
configsFromIngress[i].Namespace, configsFromIngress[i].Name, err)
|
||||
}
|
||||
}
|
||||
configs = append(configs, configsFromIngress...)
|
||||
}
|
||||
|
||||
if configsFromGateway := m.listFromGatewayControllers(typ, namespace); configsFromGateway != nil {
|
||||
// Process templates for gateway configs
|
||||
for i := range configsFromGateway {
|
||||
if err := m.templateProcessor.ProcessConfig(&configsFromGateway[i]); err != nil {
|
||||
IngressLog.Errorf("Failed to process template for config %s/%s: %v",
|
||||
configsFromGateway[i].Namespace, configsFromGateway[i].Name, err)
|
||||
}
|
||||
}
|
||||
configs = append(configs, configsFromGateway...)
|
||||
}
|
||||
|
||||
@@ -301,21 +355,21 @@ func (m *IngressConfig) listFromIngressControllers(typ config.GroupVersionKind,
|
||||
common.SortIngressByCreationTime(configs)
|
||||
wrapperConfigs := m.createWrapperConfigs(configs)
|
||||
|
||||
IngressLog.Infof("resource type %s, configs number %d", typ, len(wrapperConfigs))
|
||||
var result []config.Config
|
||||
switch typ {
|
||||
case gvk.Gateway:
|
||||
return m.convertGateways(wrapperConfigs)
|
||||
result = m.convertGateways(wrapperConfigs)
|
||||
case gvk.VirtualService:
|
||||
return m.convertVirtualService(wrapperConfigs)
|
||||
result = m.convertVirtualService(wrapperConfigs)
|
||||
case gvk.DestinationRule:
|
||||
return m.convertDestinationRule(wrapperConfigs)
|
||||
result = m.convertDestinationRule(wrapperConfigs)
|
||||
case gvk.ServiceEntry:
|
||||
return m.convertServiceEntry(wrapperConfigs)
|
||||
result = m.convertServiceEntry(wrapperConfigs)
|
||||
case gvk.WasmPlugin:
|
||||
return m.convertWasmPlugin(wrapperConfigs)
|
||||
result = m.convertWasmPlugin(wrapperConfigs)
|
||||
}
|
||||
|
||||
return nil
|
||||
IngressLog.Infof("resource type %s, ingress number %d, convert configs number %d", typ, len(configs), len(result))
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *IngressConfig) listFromGatewayControllers(typ config.GroupVersionKind, namespace string) []config.Config {
|
||||
@@ -536,6 +590,13 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
Spec: vs,
|
||||
})
|
||||
}
|
||||
// add vs from naco3 for mcp server
|
||||
if m.RegistryReconciler != nil {
|
||||
allConfigsFromMcp := m.RegistryReconciler.GetAllConfigs(gvk.VirtualService)
|
||||
for _, cfg := range allConfigsFromMcp {
|
||||
out = append(out, *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
// We generate some specific envoy filter here to avoid duplicated computation.
|
||||
m.convertEnvoyFilter(&convertOptions)
|
||||
@@ -622,6 +683,13 @@ func (m *IngressConfig) convertWasmPlugin([]common.WrapperConfig) []config.Confi
|
||||
Spec: wasmPlugin,
|
||||
})
|
||||
}
|
||||
// add wasm plugin from nacos for mcp server
|
||||
if m.RegistryReconciler != nil {
|
||||
wasmFromMcp := m.RegistryReconciler.GetAllConfigs(gvk.WasmPlugin)
|
||||
for _, cfg := range wasmFromMcp {
|
||||
out = append(out, *cfg)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -632,6 +700,7 @@ func (m *IngressConfig) convertServiceEntry([]common.WrapperConfig) []config.Con
|
||||
serviceEntries := m.RegistryReconciler.GetAllServiceWrapper()
|
||||
IngressLog.Infof("Found mcp serviceEntries %v", serviceEntries)
|
||||
out := make([]config.Config, 0, len(serviceEntries))
|
||||
hostSets := sets.Set[string]{}
|
||||
for _, se := range serviceEntries {
|
||||
out = append(out, config.Config{
|
||||
Meta: config.Meta{
|
||||
@@ -646,6 +715,15 @@ func (m *IngressConfig) convertServiceEntry([]common.WrapperConfig) []config.Con
|
||||
},
|
||||
Spec: se.ServiceEntry,
|
||||
})
|
||||
hostSets.Insert(se.ServiceEntry.Hosts[0])
|
||||
}
|
||||
// add service entry by host from nacos3 for mcp server
|
||||
seFromMcp := m.RegistryReconciler.GetAllConfigs(gvk.ServiceEntry)
|
||||
for _, cfg := range seFromMcp {
|
||||
se := cfg.Spec.(*networking.ServiceEntry)
|
||||
if !hostSets.Contains(se.Hosts[0]) {
|
||||
out = append(out, *cfg)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -710,18 +788,21 @@ func (m *IngressConfig) convertDestinationRule(configs []common.WrapperConfig) [
|
||||
|
||||
if m.RegistryReconciler != nil {
|
||||
drws := m.RegistryReconciler.GetAllDestinationRuleWrapper()
|
||||
IngressLog.Infof("Found mcp destinationRules: %v", drws)
|
||||
for _, destinationRuleWrapper := range drws {
|
||||
serviceName := destinationRuleWrapper.ServiceKey.ServiceFQDN
|
||||
dr, exist := destinationRules[serviceName]
|
||||
if !exist {
|
||||
destinationRules[serviceName] = destinationRuleWrapper
|
||||
} else if dr.DestinationRule.TrafficPolicy != nil {
|
||||
if dr.DestinationRule.TrafficPolicy.LoadBalancer == nil &&
|
||||
destinationRuleWrapper.DestinationRule.TrafficPolicy.LoadBalancer != nil {
|
||||
dr.DestinationRule.TrafficPolicy.LoadBalancer = destinationRuleWrapper.DestinationRule.TrafficPolicy.LoadBalancer
|
||||
}
|
||||
portTrafficPolicy := destinationRuleWrapper.DestinationRule.TrafficPolicy.PortLevelSettings[0]
|
||||
portUpdated := false
|
||||
for _, portTrafficPolicy := range dr.DestinationRule.TrafficPolicy.PortLevelSettings {
|
||||
if portTrafficPolicy.Port.Number == portTrafficPolicy.Port.Number {
|
||||
portTrafficPolicy.Tls = portTrafficPolicy.Tls
|
||||
for _, policy := range dr.DestinationRule.TrafficPolicy.PortLevelSettings {
|
||||
if policy.Port.Number == portTrafficPolicy.Port.Number {
|
||||
policy.Tls = portTrafficPolicy.Tls
|
||||
portUpdated = true
|
||||
break
|
||||
}
|
||||
@@ -853,7 +934,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
result := &extensions.WasmPlugin{
|
||||
Selector: &istiotype.WorkloadSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"higress": m.namespace + "-higress-gateway",
|
||||
m.commonOptions.GatewaySelectorKey: m.commonOptions.GatewaySelectorValue,
|
||||
},
|
||||
},
|
||||
Url: obj.Url,
|
||||
@@ -880,7 +961,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
if result.PluginConfig != nil {
|
||||
return result, nil
|
||||
}
|
||||
if !obj.DefaultConfigDisable {
|
||||
if !isBoolValueTrue(obj.DefaultConfigDisable) {
|
||||
result.PluginConfig = obj.DefaultConfig
|
||||
}
|
||||
hasValidRule := false
|
||||
@@ -892,7 +973,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
}
|
||||
var ruleValues []*_struct.Value
|
||||
for _, rule := range obj.MatchRules {
|
||||
if rule.ConfigDisable {
|
||||
if isBoolValueTrue(rule.ConfigDisable) {
|
||||
continue
|
||||
}
|
||||
if rule.Config == nil {
|
||||
@@ -904,6 +985,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
StructValue: rule.Config,
|
||||
}
|
||||
|
||||
validRule := false
|
||||
var matchItems []*_struct.Value
|
||||
// match ingress
|
||||
for _, ing := range rule.Ingress {
|
||||
@@ -914,6 +996,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
})
|
||||
}
|
||||
if len(matchItems) > 0 {
|
||||
validRule = true
|
||||
v.StructValue.Fields["_match_route_"] = &_struct.Value{
|
||||
Kind: &_struct.Value_ListValue{
|
||||
ListValue: &_struct.ListValue{
|
||||
@@ -921,12 +1004,9 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
},
|
||||
},
|
||||
}
|
||||
ruleValues = append(ruleValues, &_struct.Value{
|
||||
Kind: v,
|
||||
})
|
||||
continue
|
||||
}
|
||||
// match service
|
||||
matchItems = nil
|
||||
for _, service := range rule.Service {
|
||||
matchItems = append(matchItems, &_struct.Value{
|
||||
Kind: &_struct.Value_StringValue{
|
||||
@@ -935,6 +1015,7 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
})
|
||||
}
|
||||
if len(matchItems) > 0 {
|
||||
validRule = true
|
||||
v.StructValue.Fields["_match_service_"] = &_struct.Value{
|
||||
Kind: &_struct.Value_ListValue{
|
||||
ListValue: &_struct.ListValue{
|
||||
@@ -942,12 +1023,9 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
},
|
||||
},
|
||||
}
|
||||
ruleValues = append(ruleValues, &_struct.Value{
|
||||
Kind: v,
|
||||
})
|
||||
continue
|
||||
}
|
||||
// match domain
|
||||
matchItems = nil
|
||||
for _, domain := range rule.Domain {
|
||||
matchItems = append(matchItems, &_struct.Value{
|
||||
Kind: &_struct.Value_StringValue{
|
||||
@@ -955,19 +1033,23 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
},
|
||||
})
|
||||
}
|
||||
if len(matchItems) == 0 {
|
||||
if len(matchItems) > 0 {
|
||||
validRule = true
|
||||
v.StructValue.Fields["_match_domain_"] = &_struct.Value{
|
||||
Kind: &_struct.Value_ListValue{
|
||||
ListValue: &_struct.ListValue{
|
||||
Values: matchItems,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
if validRule {
|
||||
ruleValues = append(ruleValues, &_struct.Value{
|
||||
Kind: v,
|
||||
})
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid match rule has no match condition, rule:%v", rule)
|
||||
}
|
||||
v.StructValue.Fields["_match_domain_"] = &_struct.Value{
|
||||
Kind: &_struct.Value_ListValue{
|
||||
ListValue: &_struct.ListValue{
|
||||
Values: matchItems,
|
||||
},
|
||||
},
|
||||
}
|
||||
ruleValues = append(ruleValues, &_struct.Value{
|
||||
Kind: v,
|
||||
})
|
||||
}
|
||||
if len(ruleValues) > 0 {
|
||||
hasValidRule = true
|
||||
@@ -980,11 +1062,14 @@ func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*ext
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasValidRule && obj.DefaultConfigDisable {
|
||||
if !hasValidRule && isBoolValueTrue(obj.DefaultConfigDisable) {
|
||||
return nil, nil
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func isBoolValueTrue(b *wrappers.BoolValue) bool {
|
||||
return b != nil && b.Value
|
||||
}
|
||||
|
||||
func (m *IngressConfig) AddOrUpdateWasmPlugin(clusterNamespacedName util.ClusterNamespacedName) {
|
||||
@@ -1080,6 +1165,28 @@ func (m *IngressConfig) AddOrUpdateMcpBridge(clusterNamespacedName util.ClusterN
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
vsMetadata := config.Meta{
|
||||
Name: "mcpbridge-virtualservice",
|
||||
Namespace: m.namespace,
|
||||
GroupVersionKind: gvk.VirtualService,
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
wasmMetadata := config.Meta{
|
||||
Name: "mcpbridge-wasmplugin",
|
||||
Namespace: m.namespace,
|
||||
GroupVersionKind: gvk.WasmPlugin,
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
efMetadata := config.Meta{
|
||||
Name: "mcpbridge-envoyfilter",
|
||||
Namespace: m.namespace,
|
||||
GroupVersionKind: gvk.EnvoyFilter,
|
||||
// Set this label so that we do not compare configs and just push.
|
||||
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
|
||||
}
|
||||
|
||||
for _, f := range m.serviceEntryHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd serviceEntry update")
|
||||
f(config.Config{Meta: seMetadata}, config.Config{Meta: seMetadata}, istiomodel.EventUpdate)
|
||||
@@ -1088,9 +1195,22 @@ func (m *IngressConfig) AddOrUpdateMcpBridge(clusterNamespacedName util.ClusterN
|
||||
IngressLog.Debug("McpBridge triggerd destinationRule update")
|
||||
f(config.Config{Meta: drMetadata}, config.Config{Meta: drMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
}, m.localKubeClient, m.namespace)
|
||||
for _, f := range m.virtualServiceHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd virtualservice update")
|
||||
f(config.Config{Meta: vsMetadata}, config.Config{Meta: vsMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
for _, f := range m.wasmPluginHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd wasmplugin update")
|
||||
f(config.Config{Meta: wasmMetadata}, config.Config{Meta: wasmMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
for _, f := range m.envoyFilterHandlers {
|
||||
IngressLog.Debug("McpBridge triggerd envoyfilter update")
|
||||
f(config.Config{Meta: efMetadata}, config.Config{Meta: efMetadata}, istiomodel.EventUpdate)
|
||||
}
|
||||
}, m.localKubeClient, m.namespace, m.clusterId.String())
|
||||
}
|
||||
reconciler := m.RegistryReconciler
|
||||
m.configmapMgr.SetMcpReconciler(m.RegistryReconciler)
|
||||
err = reconciler.Reconcile(mcpbridge)
|
||||
if err != nil {
|
||||
IngressLog.Errorf("Mcpbridge reconcile failed, err:%v", err)
|
||||
|
||||
@@ -127,7 +127,14 @@ func TestConvertGatewaysForIngress(t *testing.T) {
|
||||
}
|
||||
ingressV1Beta1Controller := controllerv1beta1.NewController(fake, fake, v1Beta1Options, nil)
|
||||
ingressV1Controller := controllerv1.NewController(fake, fake, v1Options, nil)
|
||||
m := NewIngressConfig(fake, nil, "wakanda", "gw-123-istio")
|
||||
options := common.Options{
|
||||
Enable: true,
|
||||
ClusterId: "gw-123-istio",
|
||||
RawClusterId: "gw-123-istio__",
|
||||
GatewayHttpPort: 80,
|
||||
GatewayHttpsPort: 443,
|
||||
}
|
||||
m := NewIngressConfig(fake, nil, "wakanda", options)
|
||||
m.remoteIngressControllers = map[cluster.ID]common.IngressController{
|
||||
"ingress-v1beta1": ingressV1Beta1Controller,
|
||||
"ingress-v1": ingressV1Controller,
|
||||
|
||||
119
pkg/ingress/config/ingress_template.go
Normal file
119
pkg/ingress/config/ingress_template.go
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"istio.io/istio/pkg/config"
|
||||
)
|
||||
|
||||
// TemplateProcessor handles template substitution in configs
|
||||
type TemplateProcessor struct {
|
||||
// getValue is a function that retrieves values by type, namespace, name and key
|
||||
getValue func(valueType, namespace, name, key string) (string, error)
|
||||
namespace string
|
||||
secretConfigMgr *SecretConfigMgr
|
||||
}
|
||||
|
||||
// NewTemplateProcessor creates a new TemplateProcessor with the given value getter function
|
||||
func NewTemplateProcessor(getValue func(valueType, namespace, name, key string) (string, error), namespace string, secretConfigMgr *SecretConfigMgr) *TemplateProcessor {
|
||||
return &TemplateProcessor{
|
||||
getValue: getValue,
|
||||
namespace: namespace,
|
||||
secretConfigMgr: secretConfigMgr,
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessConfig processes a config and substitutes any template variables
|
||||
func (p *TemplateProcessor) ProcessConfig(cfg *config.Config) error {
|
||||
// Convert spec to JSON string to process substitutions
|
||||
jsonBytes, err := json.Marshal(cfg.Spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config spec: %v", err)
|
||||
}
|
||||
|
||||
configStr := string(jsonBytes)
|
||||
// Find all value references in format:
|
||||
// ${type.name.key} or ${type.namespace/name.key}
|
||||
valueRegex := regexp.MustCompile(`\$\{([^.}]+)\.(?:([^/]+)/)?([^.}]+)\.([^}]+)\}`)
|
||||
matches := valueRegex.FindAllStringSubmatch(configStr, -1)
|
||||
// If there are no value references, return immediately
|
||||
if len(matches) == 0 {
|
||||
if p.secretConfigMgr != nil {
|
||||
if err := p.secretConfigMgr.DeleteConfig(cfg); err != nil {
|
||||
IngressLog.Errorf("failed to delete secret dependency: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
foundSecretSource := false
|
||||
IngressLog.Infof("start to apply config %s/%s with %d variables", cfg.Namespace, cfg.Name, len(matches))
|
||||
for _, match := range matches {
|
||||
valueType := match[1]
|
||||
var namespace, name, key string
|
||||
if match[2] != "" {
|
||||
// Format: ${type.namespace/name.key}
|
||||
namespace = match[2]
|
||||
} else {
|
||||
// Format: ${type.name.key} - use default namespace
|
||||
namespace = p.namespace
|
||||
}
|
||||
name = match[3]
|
||||
key = match[4]
|
||||
|
||||
// Get value using the provided getter function
|
||||
value, err := p.getValue(valueType, namespace, name, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s value for %s/%s.%s: %v", valueType, namespace, name, key, err)
|
||||
}
|
||||
|
||||
// Add secret dependency if this is a secret reference
|
||||
if valueType == "secret" && p.secretConfigMgr != nil {
|
||||
foundSecretSource = true
|
||||
secretKey := fmt.Sprintf("%s/%s", namespace, name)
|
||||
if err := p.secretConfigMgr.AddConfig(secretKey, cfg); err != nil {
|
||||
IngressLog.Errorf("failed to add secret dependency: %v", err)
|
||||
}
|
||||
}
|
||||
// Replace placeholder with actual value
|
||||
configStr = strings.Replace(configStr, match[0], value, 1)
|
||||
}
|
||||
|
||||
// Create a new instance of the same type as cfg.Spec
|
||||
newSpec := proto.Clone(cfg.Spec.(proto.Message))
|
||||
if err := json.Unmarshal([]byte(configStr), newSpec); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal substituted config: %v", err)
|
||||
}
|
||||
cfg.Spec = newSpec
|
||||
|
||||
// Delete secret dependency if no secret reference is found
|
||||
if !foundSecretSource {
|
||||
if p.secretConfigMgr != nil {
|
||||
if err := p.secretConfigMgr.DeleteConfig(cfg); err != nil {
|
||||
IngressLog.Errorf("failed to delete secret dependency: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IngressLog.Infof("end to process config %s/%s", cfg.Namespace, cfg.Name)
|
||||
return nil
|
||||
}
|
||||
166
pkg/ingress/config/ingress_template_test.go
Normal file
166
pkg/ingress/config/ingress_template_test.go
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
extensions "istio.io/api/extensions/v1alpha1"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
)
|
||||
|
||||
func TestTemplateProcessor_ProcessConfig(t *testing.T) {
|
||||
// Create test values map
|
||||
values := map[string]string{
|
||||
"secret.default/test-secret.api_key": "test-api-key",
|
||||
"secret.default/test-secret.plugin_conf.timeout": "5000",
|
||||
"secret.default/test-secret.plugin_conf.max_retries": "3",
|
||||
"secret.higress-system/auth-secret.auth_config.type": "basic",
|
||||
"secret.higress-system/auth-secret.auth_config.credentials": "base64-encoded",
|
||||
}
|
||||
|
||||
// Mock value getter function
|
||||
getValue := func(valueType, namespace, name, key string) (string, error) {
|
||||
fullKey := fmt.Sprintf("%s.%s/%s.%s", valueType, namespace, name, key)
|
||||
fmt.Printf("Getting value for %s", fullKey)
|
||||
if value, exists := values[fullKey]; exists {
|
||||
return value, nil
|
||||
}
|
||||
return "", fmt.Errorf("value not found for %s", fullKey)
|
||||
}
|
||||
|
||||
// Create template processor
|
||||
processor := NewTemplateProcessor(getValue, "higress-system", nil)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
wasmPlugin *extensions.WasmPlugin
|
||||
expected *extensions.WasmPlugin
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "simple api key reference",
|
||||
wasmPlugin: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"api_key": "${secret.default/test-secret.api_key}",
|
||||
}),
|
||||
},
|
||||
expected: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"api_key": "test-api-key",
|
||||
}),
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "config with multiple fields",
|
||||
wasmPlugin: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"config": map[string]interface{}{
|
||||
"timeout": "${secret.default/test-secret.plugin_conf.timeout}",
|
||||
"max_retries": "${secret.default/test-secret.plugin_conf.max_retries}",
|
||||
},
|
||||
}),
|
||||
},
|
||||
expected: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"config": map[string]interface{}{
|
||||
"timeout": "5000",
|
||||
"max_retries": "3",
|
||||
},
|
||||
}),
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "auth config with default namespace",
|
||||
wasmPlugin: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"auth": map[string]interface{}{
|
||||
"type": "${secret.auth-secret.auth_config.type}",
|
||||
"credentials": "${secret.auth-secret.auth_config.credentials}",
|
||||
},
|
||||
}),
|
||||
},
|
||||
expected: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"auth": map[string]interface{}{
|
||||
"type": "basic",
|
||||
"credentials": "base64-encoded",
|
||||
},
|
||||
}),
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "non-existent secret",
|
||||
wasmPlugin: &extensions.WasmPlugin{
|
||||
PluginName: "test-plugin",
|
||||
PluginConfig: makeStructValue(t, map[string]interface{}{
|
||||
"api_key": "${secret.default/non-existent.api_key}",
|
||||
}),
|
||||
},
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.WasmPlugin,
|
||||
Name: "test-plugin",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: tt.wasmPlugin,
|
||||
}
|
||||
|
||||
err := processor.ProcessConfig(cfg)
|
||||
if tt.expectError {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
processedPlugin := cfg.Spec.(*extensions.WasmPlugin)
|
||||
|
||||
// Compare plugin name
|
||||
assert.Equal(t, tt.expected.PluginName, processedPlugin.PluginName)
|
||||
|
||||
// Compare plugin configs
|
||||
if tt.expected.PluginConfig != nil {
|
||||
assert.NotNil(t, processedPlugin.PluginConfig)
|
||||
assert.Equal(t, tt.expected.PluginConfig.AsMap(), processedPlugin.PluginConfig.AsMap())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to create structpb.Struct from map
|
||||
func makeStructValue(t *testing.T, m map[string]interface{}) *structpb.Struct {
|
||||
s, err := structpb.NewStruct(m)
|
||||
assert.NoError(t, err, "Failed to create struct value")
|
||||
return s
|
||||
}
|
||||
@@ -75,10 +75,11 @@ type KIngressConfig struct {
|
||||
clusterId cluster.ID
|
||||
}
|
||||
|
||||
func NewKIngressConfig(localKubeClient kube.Client, XDSUpdater istiomodel.XDSUpdater, namespace string, clusterId cluster.ID) *KIngressConfig {
|
||||
func NewKIngressConfig(localKubeClient kube.Client, XDSUpdater istiomodel.XDSUpdater, namespace string, options common.Options) *KIngressConfig {
|
||||
if localKubeClient.KIngressInformer() == nil {
|
||||
return nil
|
||||
}
|
||||
clusterId := options.ClusterId
|
||||
if clusterId == "Kubernetes" {
|
||||
clusterId = ""
|
||||
}
|
||||
@@ -114,7 +115,7 @@ func (m *KIngressConfig) RegisterEventHandler(kind config.GroupVersionKind, f is
|
||||
}
|
||||
|
||||
func (m *KIngressConfig) AddLocalCluster(options common.Options) common.KIngressController {
|
||||
secretController := secret.NewController(m.localKubeClient, options.ClusterId)
|
||||
secretController := secret.NewController(m.localKubeClient, options)
|
||||
secretController.AddEventHandler(m.ReflectSecretChanges)
|
||||
|
||||
var ingressController common.KIngressController
|
||||
@@ -493,7 +494,7 @@ func (m *KIngressConfig) HasSynced() bool {
|
||||
defer m.mutex.RUnlock()
|
||||
|
||||
for _, remoteIngressController := range m.remoteIngressControllers {
|
||||
IngressLog.Info("In Kingress Synced.", remoteIngressController)
|
||||
IngressLog.Info("In Kingress Synced.")
|
||||
if !remoteIngressController.HasSynced() {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -118,7 +118,14 @@ func TestConvertGatewaysForKIngress(t *testing.T) {
|
||||
RawClusterId: "kingress__",
|
||||
}
|
||||
kingressV1Controller := kcontrollerv1.NewController(fake, fake, v1Options, nil)
|
||||
m := NewKIngressConfig(fake, nil, "wakanda", "gw-123-istio")
|
||||
options := common.Options{
|
||||
Enable: true,
|
||||
ClusterId: "gw-123-istio",
|
||||
RawClusterId: "gw-123-istio__",
|
||||
GatewayHttpPort: 80,
|
||||
GatewayHttpsPort: 443,
|
||||
}
|
||||
m := NewKIngressConfig(fake, nil, "wakanda", options)
|
||||
m.remoteIngressControllers = map[cluster.ID]common.KIngressController{
|
||||
"kingress": kingressV1Controller,
|
||||
}
|
||||
|
||||
157
pkg/ingress/config/secret_config_mgr.go
Normal file
157
pkg/ingress/config/secret_config_mgr.go
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
istiomodel "istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/kind"
|
||||
"istio.io/istio/pkg/util/sets"
|
||||
)
|
||||
|
||||
// toConfigKey converts config.Config to istiomodel.ConfigKey
|
||||
func toConfigKey(cfg *config.Config) (istiomodel.ConfigKey, error) {
|
||||
return istiomodel.ConfigKey{
|
||||
Kind: kind.MustFromGVK(cfg.GroupVersionKind),
|
||||
Name: cfg.Name,
|
||||
Namespace: cfg.Namespace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SecretConfigMgr maintains the mapping between secrets and configs
|
||||
type SecretConfigMgr struct {
|
||||
mutex sync.RWMutex
|
||||
|
||||
// configSet tracks all configs that have been added
|
||||
// key format: namespace/name
|
||||
configSet sets.Set[string]
|
||||
|
||||
// secretToConfigs maps secret key to dependent configs
|
||||
// key format: namespace/name
|
||||
secretToConfigs map[string]sets.Set[istiomodel.ConfigKey]
|
||||
|
||||
// watchedSecrets tracks which secrets are being watched
|
||||
watchedSecrets sets.Set[string]
|
||||
|
||||
// xdsUpdater is used to push config updates
|
||||
xdsUpdater istiomodel.XDSUpdater
|
||||
}
|
||||
|
||||
// NewSecretConfigMgr creates a new SecretConfigMgr
|
||||
func NewSecretConfigMgr(xdsUpdater istiomodel.XDSUpdater) *SecretConfigMgr {
|
||||
return &SecretConfigMgr{
|
||||
secretToConfigs: make(map[string]sets.Set[istiomodel.ConfigKey]),
|
||||
watchedSecrets: sets.New[string](),
|
||||
configSet: sets.New[string](),
|
||||
xdsUpdater: xdsUpdater,
|
||||
}
|
||||
}
|
||||
|
||||
// AddConfig adds a config and its secret dependencies
|
||||
func (m *SecretConfigMgr) AddConfig(secretKey string, cfg *config.Config) error {
|
||||
configKey, _ := toConfigKey(cfg)
|
||||
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
configId := fmt.Sprintf("%s/%s", cfg.Namespace, cfg.Name)
|
||||
m.configSet.Insert(configId)
|
||||
|
||||
if configs, exists := m.secretToConfigs[secretKey]; exists {
|
||||
configs.Insert(configKey)
|
||||
} else {
|
||||
m.secretToConfigs[secretKey] = sets.New(configKey)
|
||||
}
|
||||
|
||||
// Add to watched secrets
|
||||
m.watchedSecrets.Insert(secretKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteConfig removes a config from all secret dependencies
|
||||
func (m *SecretConfigMgr) DeleteConfig(cfg *config.Config) error {
|
||||
configKey, _ := toConfigKey(cfg)
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
configId := fmt.Sprintf("%s/%s", cfg.Namespace, cfg.Name)
|
||||
if !m.configSet.Contains(configId) {
|
||||
return nil
|
||||
}
|
||||
|
||||
removeKeys := make([]string, 0)
|
||||
// Find and remove the config from all secrets
|
||||
for secretKey, configs := range m.secretToConfigs {
|
||||
if configs.Contains(configKey) {
|
||||
configs.Delete(configKey)
|
||||
// If no more configs depend on this secret, remove it
|
||||
if configs.Len() == 0 {
|
||||
removeKeys = append(removeKeys, secretKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the secrets from the secretToConfigs map
|
||||
for _, secretKey := range removeKeys {
|
||||
delete(m.secretToConfigs, secretKey)
|
||||
m.watchedSecrets.Delete(secretKey)
|
||||
}
|
||||
// Remove the config from the config set
|
||||
m.configSet.Delete(configId)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetConfigsForSecret returns all configs that depend on the given secret
|
||||
func (m *SecretConfigMgr) GetConfigsForSecret(secretKey string) []istiomodel.ConfigKey {
|
||||
m.mutex.RLock()
|
||||
defer m.mutex.RUnlock()
|
||||
|
||||
if configs, exists := m.secretToConfigs[secretKey]; exists {
|
||||
return configs.UnsortedList()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsSecretWatched checks if a secret is being watched
|
||||
func (m *SecretConfigMgr) IsSecretWatched(secretKey string) bool {
|
||||
m.mutex.RLock()
|
||||
defer m.mutex.RUnlock()
|
||||
return m.watchedSecrets.Contains(secretKey)
|
||||
}
|
||||
|
||||
// HandleSecretChange handles secret changes and updates affected configs
|
||||
func (m *SecretConfigMgr) HandleSecretChange(name util.ClusterNamespacedName) {
|
||||
secretKey := fmt.Sprintf("%s/%s", name.Namespace, name.Name)
|
||||
// Check if this secret is being watched
|
||||
if !m.IsSecretWatched(secretKey) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get affected configs
|
||||
configKeys := m.GetConfigsForSecret(secretKey)
|
||||
if len(configKeys) == 0 {
|
||||
return
|
||||
}
|
||||
IngressLog.Infof("SecretConfigMgr Secret %s changed, updating %d dependent configs and push", secretKey, len(configKeys))
|
||||
m.xdsUpdater.ConfigUpdate(&istiomodel.PushRequest{
|
||||
Full: true,
|
||||
Reason: istiomodel.NewReasonStats(istiomodel.SecretTrigger),
|
||||
})
|
||||
}
|
||||
155
pkg/ingress/config/secret_config_mgr_test.go
Normal file
155
pkg/ingress/config/secret_config_mgr_test.go
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"testing"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
istiomodel "istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pkg/cluster"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
"istio.io/istio/pkg/config/schema/kind"
|
||||
)
|
||||
|
||||
type mockXdsUpdater struct {
|
||||
lastPushRequest *istiomodel.PushRequest
|
||||
}
|
||||
|
||||
func (m *mockXdsUpdater) EDSUpdate(shard istiomodel.ShardKey, hostname string, namespace string, entry []*istiomodel.IstioEndpoint) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockXdsUpdater) EDSCacheUpdate(shard istiomodel.ShardKey, hostname string, namespace string, entry []*istiomodel.IstioEndpoint) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockXdsUpdater) SvcUpdate(shard istiomodel.ShardKey, hostname string, namespace string, event istiomodel.Event) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockXdsUpdater) ProxyUpdate(clusterID cluster.ID, ip string) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockXdsUpdater) RemoveShard(shardKey istiomodel.ShardKey) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockXdsUpdater) ConfigUpdate(req *istiomodel.PushRequest) {
|
||||
m.lastPushRequest = req
|
||||
}
|
||||
|
||||
func TestSecretConfigMgr(t *testing.T) {
|
||||
updater := &mockXdsUpdater{}
|
||||
mgr := NewSecretConfigMgr(updater)
|
||||
|
||||
// Test AddConfig
|
||||
t.Run("AddConfig", func(t *testing.T) {
|
||||
wasmPlugin := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.WasmPlugin,
|
||||
Name: "test-plugin",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
|
||||
err := mgr.AddConfig("default/test-secret", wasmPlugin)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, mgr.IsSecretWatched("default/test-secret"))
|
||||
|
||||
configs := mgr.GetConfigsForSecret("default/test-secret")
|
||||
assert.Len(t, configs, 1)
|
||||
assert.Equal(t, kind.WasmPlugin, configs[0].Kind)
|
||||
assert.Equal(t, "test-plugin", configs[0].Name)
|
||||
assert.Equal(t, "default", configs[0].Namespace)
|
||||
})
|
||||
|
||||
// Test DeleteConfig
|
||||
t.Run("DeleteConfig", func(t *testing.T) {
|
||||
wasmPlugin := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.WasmPlugin,
|
||||
Name: "test-plugin",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
|
||||
err := mgr.DeleteConfig(wasmPlugin)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, mgr.IsSecretWatched("default/test-secret"))
|
||||
assert.Empty(t, mgr.GetConfigsForSecret("default/test-secret"))
|
||||
})
|
||||
|
||||
// Test HandleSecretChange
|
||||
t.Run("HandleSecretChange", func(t *testing.T) {
|
||||
// Add a config first
|
||||
wasmPlugin := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.WasmPlugin,
|
||||
Name: "test-plugin",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
err := mgr.AddConfig("default/test-secret", wasmPlugin)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test secret change
|
||||
secretName := util.ClusterNamespacedName{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Name: "test-secret",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
|
||||
mgr.HandleSecretChange(secretName)
|
||||
assert.NotNil(t, updater.lastPushRequest)
|
||||
assert.True(t, updater.lastPushRequest.Full)
|
||||
})
|
||||
|
||||
// Test full push for secret update
|
||||
t.Run("FullPushForSecretUpdate", func(t *testing.T) {
|
||||
// Add a secret config
|
||||
secretConfig := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.Secret,
|
||||
Name: "test-secret",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
err := mgr.AddConfig("default/test-secret", secretConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Update the secret
|
||||
secretName := util.ClusterNamespacedName{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Name: "test-secret",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
|
||||
mgr.HandleSecretChange(secretName)
|
||||
assert.NotNil(t, updater.lastPushRequest)
|
||||
assert.True(t, updater.lastPushRequest.Full)
|
||||
})
|
||||
}
|
||||
@@ -15,12 +15,6 @@
|
||||
package annotations
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
)
|
||||
@@ -57,101 +51,10 @@ func (a auth) Parse(annotations Annotations, config *Ingress, globalContext *Glo
|
||||
if !needAuthConfig(annotations) {
|
||||
return nil
|
||||
}
|
||||
|
||||
authConfig := &AuthConfig{
|
||||
AuthType: defaultAuthType,
|
||||
}
|
||||
|
||||
// Check auth type
|
||||
authType, err := annotations.ParseStringASAP(authType)
|
||||
if err != nil {
|
||||
IngressLog.Errorf("Parse auth type error %v within ingress %/%s", err, config.Namespace, config.Name)
|
||||
return nil
|
||||
}
|
||||
if authType != defaultAuthType {
|
||||
IngressLog.Errorf("Auth type %s within ingress %/%s is not supported yet.", authType, config.Namespace, config.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
secretName, _ := annotations.ParseStringASAP(authSecretAnn)
|
||||
namespaced := util.SplitNamespacedName(secretName)
|
||||
if namespaced.Name == "" {
|
||||
IngressLog.Errorf("Auth secret name within ingress %s/%s is invalid", config.Namespace, config.Name)
|
||||
return nil
|
||||
}
|
||||
if namespaced.Namespace == "" {
|
||||
namespaced.Namespace = config.Namespace
|
||||
}
|
||||
|
||||
configKey := util.ClusterNamespacedName{
|
||||
NamespacedName: namespaced,
|
||||
ClusterId: config.ClusterId,
|
||||
}
|
||||
authConfig.AuthSecret = configKey
|
||||
|
||||
// Subscribe secret
|
||||
globalContext.WatchedSecrets.Insert(configKey.String())
|
||||
|
||||
secretType := authFileAuthSecretType
|
||||
if rawSecretType, err := annotations.ParseStringASAP(authSecretTypeAnn); err == nil {
|
||||
resultAuthSecretType := authSecretType(rawSecretType)
|
||||
if resultAuthSecretType == authFileAuthSecretType || resultAuthSecretType == authMapAuthSecretType {
|
||||
secretType = resultAuthSecretType
|
||||
}
|
||||
}
|
||||
|
||||
authConfig.AuthRealm, _ = annotations.ParseStringASAP(authRealm)
|
||||
|
||||
// Process credentials.
|
||||
secretLister, exist := globalContext.ClusterSecretLister[config.ClusterId]
|
||||
if !exist {
|
||||
IngressLog.Errorf("secret lister of cluster %s doesn't exist", config.ClusterId)
|
||||
return nil
|
||||
}
|
||||
authSecret, err := secretLister.Secrets(namespaced.Namespace).Get(namespaced.Name)
|
||||
if err != nil {
|
||||
IngressLog.Errorf("Secret %s within ingress %s/%s is not found",
|
||||
namespaced.String(), config.Namespace, config.Name)
|
||||
return nil
|
||||
}
|
||||
credentials, err := convertCredentials(secretType, authSecret)
|
||||
if err != nil {
|
||||
IngressLog.Errorf("Parse auth secret fail, err %v", err)
|
||||
return nil
|
||||
}
|
||||
authConfig.Credentials = credentials
|
||||
|
||||
config.Auth = authConfig
|
||||
IngressLog.Error("The annotation nginx.ingress.kubernetes.io/auth-type is no longer supported after version 2.0.0, please use the higress wasm plugin (e.g., basic-auth) as an alternative.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertCredentials(secretType authSecretType, secret *corev1.Secret) ([]string, error) {
|
||||
var result []string
|
||||
switch secretType {
|
||||
case authFileAuthSecretType:
|
||||
users, exist := secret.Data[authFileKey]
|
||||
if !exist {
|
||||
return nil, errors.New("the auth file type must has auth key in secret data")
|
||||
}
|
||||
userList := strings.Split(string(users), "\n")
|
||||
for _, item := range userList {
|
||||
if !strings.Contains(item, ":") {
|
||||
continue
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
case authMapAuthSecretType:
|
||||
for name, password := range secret.Data {
|
||||
result = append(result, name+":"+string(password))
|
||||
}
|
||||
}
|
||||
sort.SliceStable(result, func(i, j int) bool {
|
||||
return result[i] < result[j]
|
||||
})
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func needAuthConfig(annotations Annotations) bool {
|
||||
return annotations.HasASAP(authType) &&
|
||||
annotations.HasASAP(authSecretAnn)
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package annotations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"istio.io/istio/pkg/cluster"
|
||||
"istio.io/istio/pkg/util/sets"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
listerv1 "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
)
|
||||
|
||||
func TestAuthParse(t *testing.T) {
|
||||
auth := auth{}
|
||||
inputCases := []struct {
|
||||
input map[string]string
|
||||
secret *v1.Secret
|
||||
expect *AuthConfig
|
||||
watchedSecret string
|
||||
}{
|
||||
{
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"auth": []byte("A:a\nB:b"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(authType): "digest",
|
||||
},
|
||||
expect: nil,
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"auth": []byte("A:a\nB:b"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(authType): defaultAuthType,
|
||||
buildHigressAnnotationKey(authSecretAnn): "foo/bar",
|
||||
},
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"auth": []byte("A:a\nB:b"),
|
||||
},
|
||||
},
|
||||
expect: &AuthConfig{
|
||||
AuthType: defaultAuthType,
|
||||
AuthSecret: util.ClusterNamespacedName{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: "foo",
|
||||
Name: "bar",
|
||||
},
|
||||
ClusterId: "cluster",
|
||||
},
|
||||
Credentials: []string{"A:a", "B:b"},
|
||||
},
|
||||
watchedSecret: "cluster/foo/bar",
|
||||
},
|
||||
{
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(authType): defaultAuthType,
|
||||
buildHigressAnnotationKey(authSecretAnn): "foo/bar",
|
||||
buildNginxAnnotationKey(authSecretTypeAnn): string(authMapAuthSecretType),
|
||||
},
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"A": []byte("a"),
|
||||
"B": []byte("b"),
|
||||
},
|
||||
},
|
||||
expect: &AuthConfig{
|
||||
AuthType: defaultAuthType,
|
||||
AuthSecret: util.ClusterNamespacedName{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: "foo",
|
||||
Name: "bar",
|
||||
},
|
||||
ClusterId: "cluster",
|
||||
},
|
||||
Credentials: []string{"A:a", "B:b"},
|
||||
},
|
||||
watchedSecret: "cluster/foo/bar",
|
||||
},
|
||||
{
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(authType): defaultAuthType,
|
||||
buildHigressAnnotationKey(authSecretAnn): "bar",
|
||||
buildNginxAnnotationKey(authSecretTypeAnn): string(authFileAuthSecretType),
|
||||
},
|
||||
secret: &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "default",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"auth": []byte("A:a\nB:b"),
|
||||
},
|
||||
},
|
||||
expect: &AuthConfig{
|
||||
AuthType: defaultAuthType,
|
||||
AuthSecret: util.ClusterNamespacedName{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: "default",
|
||||
Name: "bar",
|
||||
},
|
||||
ClusterId: "cluster",
|
||||
},
|
||||
Credentials: []string{"A:a", "B:b"},
|
||||
},
|
||||
watchedSecret: "cluster/default/bar",
|
||||
},
|
||||
}
|
||||
|
||||
for _, inputCase := range inputCases {
|
||||
t.Run("", func(t *testing.T) {
|
||||
config := &Ingress{
|
||||
Meta: Meta{
|
||||
Namespace: "default",
|
||||
ClusterId: "cluster",
|
||||
},
|
||||
}
|
||||
|
||||
globalContext, cancel := initGlobalContext(inputCase.secret)
|
||||
defer cancel()
|
||||
|
||||
_ = auth.Parse(inputCase.input, config, globalContext)
|
||||
if !reflect.DeepEqual(inputCase.expect, config.Auth) {
|
||||
t.Fatal("Should be equal")
|
||||
}
|
||||
|
||||
if inputCase.watchedSecret != "" {
|
||||
if !globalContext.WatchedSecrets.Contains(inputCase.watchedSecret) {
|
||||
t.Fatalf("Should watch secret %s", inputCase.watchedSecret)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func initGlobalContext(secret *v1.Secret) (*GlobalContext, context.CancelFunc) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
client := fake.NewSimpleClientset(secret)
|
||||
informerFactory := informers.NewSharedInformerFactory(client, time.Hour)
|
||||
secretInformer := informerFactory.Core().V1().Secrets()
|
||||
go secretInformer.Informer().Run(ctx.Done())
|
||||
cache.WaitForCacheSync(ctx.Done(), secretInformer.Informer().HasSynced)
|
||||
|
||||
return &GlobalContext{
|
||||
WatchedSecrets: sets.New[string](),
|
||||
ClusterSecretLister: map[cluster.ID]listerv1.SecretLister{
|
||||
"cluster": secretInformer.Lister(),
|
||||
},
|
||||
}, cancel
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
package annotations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
@@ -27,9 +28,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
authTLSSecret = "auth-tls-secret"
|
||||
sslCipher = "ssl-cipher"
|
||||
gatewaySdsCaSuffix = "-cacert"
|
||||
authTLSSecret = "auth-tls-secret"
|
||||
sslCipher = "ssl-cipher"
|
||||
gatewaySdsCaSuffix = "-cacert"
|
||||
annotationMinTLSVersion = "tls-min-protocol-version"
|
||||
annotationMaxTLSVersion = "tls-max-protocol-version"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -41,6 +44,8 @@ type DownstreamTLSConfig struct {
|
||||
CipherSuites []string
|
||||
Mode networking.ServerTLSSettings_TLSmode
|
||||
CASecretName types.NamespacedName
|
||||
MinVersion string
|
||||
MaxVersion string
|
||||
}
|
||||
|
||||
type downstreamTLS struct{}
|
||||
@@ -82,6 +87,14 @@ func (d downstreamTLS) Parse(annotations Annotations, config *Ingress, _ *Global
|
||||
downstreamTLSConfig.CipherSuites = validCipherSuite
|
||||
}
|
||||
|
||||
if minVersion, err := annotations.ParseStringASAP(annotationMinTLSVersion); err == nil {
|
||||
downstreamTLSConfig.MinVersion = minVersion
|
||||
}
|
||||
|
||||
if maxVersion, err := annotations.ParseStringASAP(annotationMaxTLSVersion); err == nil {
|
||||
downstreamTLSConfig.MaxVersion = maxVersion
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -107,11 +120,44 @@ func (d downstreamTLS) ApplyGateway(gateway *networking.Gateway, config *Ingress
|
||||
if len(downstreamTLSConfig.CipherSuites) != 0 {
|
||||
server.Tls.CipherSuites = downstreamTLSConfig.CipherSuites
|
||||
}
|
||||
|
||||
if downstreamTLSConfig.MinVersion != "" {
|
||||
if version, err := convertTLSVersion(downstreamTLSConfig.MinVersion); err != nil {
|
||||
IngressLog.Errorf("Invalid minimum TLS version: %v", err)
|
||||
} else {
|
||||
server.Tls.MinProtocolVersion = version
|
||||
}
|
||||
}
|
||||
|
||||
if downstreamTLSConfig.MaxVersion != "" {
|
||||
if version, err := convertTLSVersion(downstreamTLSConfig.MaxVersion); err != nil {
|
||||
IngressLog.Errorf("Invalid maximum TLS version: %v", err)
|
||||
} else {
|
||||
server.Tls.MaxProtocolVersion = version
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func needDownstreamTLS(annotations Annotations) bool {
|
||||
return annotations.HasASAP(sslCipher) ||
|
||||
annotations.HasASAP(authTLSSecret)
|
||||
annotations.HasASAP(authTLSSecret) ||
|
||||
annotations.HasASAP(annotationMinTLSVersion) ||
|
||||
annotations.HasASAP(annotationMaxTLSVersion)
|
||||
}
|
||||
|
||||
func convertTLSVersion(version string) (networking.ServerTLSSettings_TLSProtocol, error) {
|
||||
switch version {
|
||||
case "TLSv1.0":
|
||||
return networking.ServerTLSSettings_TLSV1_0, nil
|
||||
case "TLSv1.1":
|
||||
return networking.ServerTLSSettings_TLSV1_1, nil
|
||||
case "TLSv1.2":
|
||||
return networking.ServerTLSSettings_TLSV1_2, nil
|
||||
case "TLSv1.3":
|
||||
return networking.ServerTLSSettings_TLSV1_3, nil
|
||||
}
|
||||
return networking.ServerTLSSettings_TLS_AUTO, fmt.Errorf("invalid TLS version: %s. Valid values are: TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3", version)
|
||||
}
|
||||
|
||||
@@ -26,11 +26,15 @@ var parser = downstreamTLS{}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input map[string]string
|
||||
expect *DownstreamTLSConfig
|
||||
}{
|
||||
{},
|
||||
{
|
||||
name: "empty config",
|
||||
},
|
||||
{
|
||||
name: "ssl cipher only",
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(sslCipher): "ECDHE-RSA-AES256-GCM-SHA384:AES128-SHA",
|
||||
},
|
||||
@@ -40,9 +44,24 @@ func TestParse(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with TLS version config",
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(authTLSSecret): "test",
|
||||
buildNginxAnnotationKey(sslCipher): "ECDHE-RSA-AES256-GCM-SHA384:AES128-SHA",
|
||||
buildNginxAnnotationKey(annotationMinTLSVersion): "TLSv1.2",
|
||||
buildNginxAnnotationKey(annotationMaxTLSVersion): "TLSv1.3",
|
||||
},
|
||||
expect: &DownstreamTLSConfig{
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
MinVersion: "TLSv1.2",
|
||||
MaxVersion: "TLSv1.3",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "complete config",
|
||||
input: map[string]string{
|
||||
buildNginxAnnotationKey(authTLSSecret): "test",
|
||||
buildNginxAnnotationKey(sslCipher): "ECDHE-RSA-AES256-GCM-SHA384:AES128-SHA",
|
||||
buildNginxAnnotationKey(annotationMinTLSVersion): "TLSv1.2",
|
||||
buildNginxAnnotationKey(annotationMaxTLSVersion): "TLSv1.3",
|
||||
},
|
||||
expect: &DownstreamTLSConfig{
|
||||
CASecretName: types.NamespacedName{
|
||||
@@ -51,34 +70,79 @@ func TestParse(t *testing.T) {
|
||||
},
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384", "AES128-SHA"},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: map[string]string{
|
||||
buildHigressAnnotationKey(authTLSSecret): "test/foo",
|
||||
DefaultAnnotationsPrefix + "/" + sslCipher: "ECDHE-RSA-AES256-GCM-SHA384:AES128-SHA",
|
||||
},
|
||||
expect: &DownstreamTLSConfig{
|
||||
CASecretName: types.NamespacedName{
|
||||
Namespace: "test",
|
||||
Name: "foo",
|
||||
},
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384", "AES128-SHA"},
|
||||
MinVersion: "TLSv1.2",
|
||||
MaxVersion: "TLSv1.3",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run("", func(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
config := &Ingress{
|
||||
Meta: Meta{
|
||||
Namespace: "foo",
|
||||
},
|
||||
}
|
||||
_ = parser.Parse(testCase.input, config, nil)
|
||||
if !reflect.DeepEqual(testCase.expect, config.DownstreamTLS) {
|
||||
t.Fatalf("Should be equal")
|
||||
err := parser.Parse(tc.input, config, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(tc.expect, config.DownstreamTLS) {
|
||||
t.Fatalf("Parse result mismatch:\nExpect: %+v\nGot: %+v", tc.expect, config.DownstreamTLS)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertTLSVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
expect networking.ServerTLSSettings_TLSProtocol
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "TLS 1.0",
|
||||
version: "TLSv1.0",
|
||||
expect: networking.ServerTLSSettings_TLSV1_0,
|
||||
},
|
||||
{
|
||||
name: "TLS 1.1",
|
||||
version: "TLSv1.1",
|
||||
expect: networking.ServerTLSSettings_TLSV1_1,
|
||||
},
|
||||
{
|
||||
name: "TLS 1.2",
|
||||
version: "TLSv1.2",
|
||||
expect: networking.ServerTLSSettings_TLSV1_2,
|
||||
},
|
||||
{
|
||||
name: "TLS 1.3",
|
||||
version: "TLSv1.3",
|
||||
expect: networking.ServerTLSSettings_TLSV1_3,
|
||||
},
|
||||
{
|
||||
name: "invalid version",
|
||||
version: "invalid",
|
||||
expect: networking.ServerTLSSettings_TLS_AUTO,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := convertTLSVersion(tc.version)
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Error("Expected error but got none")
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if result != tc.expect {
|
||||
t.Errorf("Expected %v but got %v", tc.expect, result)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -86,11 +150,13 @@ func TestParse(t *testing.T) {
|
||||
|
||||
func TestApplyGateway(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input *networking.Gateway
|
||||
config *Ingress
|
||||
expect *networking.Gateway
|
||||
}{
|
||||
{
|
||||
name: "apply TLS version",
|
||||
input: &networking.Gateway{
|
||||
Servers: []*networking.Server{
|
||||
{
|
||||
@@ -105,7 +171,8 @@ func TestApplyGateway(t *testing.T) {
|
||||
},
|
||||
config: &Ingress{
|
||||
DownstreamTLS: &DownstreamTLSConfig{
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
MinVersion: "TLSv1.2",
|
||||
MaxVersion: "TLSv1.3",
|
||||
},
|
||||
},
|
||||
expect: &networking.Gateway{
|
||||
@@ -115,14 +182,16 @@ func TestApplyGateway(t *testing.T) {
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
Tls: &networking.ServerTLSSettings{
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
MinProtocolVersion: networking.ServerTLSSettings_TLSV1_2,
|
||||
MaxProtocolVersion: networking.ServerTLSSettings_TLSV1_3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "complete config",
|
||||
input: &networking.Gateway{
|
||||
Servers: []*networking.Server{
|
||||
{
|
||||
@@ -144,24 +213,28 @@ func TestApplyGateway(t *testing.T) {
|
||||
},
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
MinVersion: "TLSv1.2",
|
||||
MaxVersion: "TLSv1.3",
|
||||
},
|
||||
},
|
||||
expect: &networking.Gateway{
|
||||
Servers: []*networking.Server{
|
||||
{
|
||||
Port: &networking.Port{
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
{Port: &networking.Port{
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
Tls: &networking.ServerTLSSettings{
|
||||
CredentialName: "kubernetes-ingress://cluster/foo/bar",
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
CredentialName: "kubernetes-ingress://cluster/foo/bar",
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
MinProtocolVersion: networking.ServerTLSSettings_TLSV1_2,
|
||||
MaxProtocolVersion: networking.ServerTLSSettings_TLSV1_3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid TLS version",
|
||||
input: &networking.Gateway{
|
||||
Servers: []*networking.Server{
|
||||
{
|
||||
@@ -169,20 +242,15 @@ func TestApplyGateway(t *testing.T) {
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
Tls: &networking.ServerTLSSettings{
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
CredentialName: "kubernetes-ingress://cluster/foo/bar",
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
config: &Ingress{
|
||||
DownstreamTLS: &DownstreamTLSConfig{
|
||||
CASecretName: types.NamespacedName{
|
||||
Namespace: "foo",
|
||||
Name: "bar-cacert",
|
||||
},
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
MinVersion: "invalid",
|
||||
MaxVersion: "invalid",
|
||||
},
|
||||
},
|
||||
expect: &networking.Gateway{
|
||||
@@ -192,48 +260,10 @@ func TestApplyGateway(t *testing.T) {
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
Tls: &networking.ServerTLSSettings{
|
||||
CredentialName: "kubernetes-ingress://cluster/foo/bar",
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: &networking.Gateway{
|
||||
Servers: []*networking.Server{
|
||||
{
|
||||
Port: &networking.Port{
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
Tls: &networking.ServerTLSSettings{
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
CredentialName: "kubernetes-ingress://cluster/foo/bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
config: &Ingress{
|
||||
DownstreamTLS: &DownstreamTLSConfig{
|
||||
CASecretName: types.NamespacedName{
|
||||
Namespace: "bar",
|
||||
Name: "foo",
|
||||
},
|
||||
Mode: networking.ServerTLSSettings_MUTUAL,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
},
|
||||
},
|
||||
expect: &networking.Gateway{
|
||||
Servers: []*networking.Server{
|
||||
{
|
||||
Port: &networking.Port{
|
||||
Protocol: "HTTPS",
|
||||
},
|
||||
Tls: &networking.ServerTLSSettings{
|
||||
CredentialName: "kubernetes-ingress://cluster/foo/bar",
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
CipherSuites: []string{"ECDHE-RSA-AES256-GCM-SHA384"},
|
||||
Mode: networking.ServerTLSSettings_SIMPLE,
|
||||
// Invalid versions should default to TLS_AUTO
|
||||
MinProtocolVersion: networking.ServerTLSSettings_TLS_AUTO,
|
||||
MaxProtocolVersion: networking.ServerTLSSettings_TLS_AUTO,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -241,11 +271,59 @@ func TestApplyGateway(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run("", func(t *testing.T) {
|
||||
parser.ApplyGateway(testCase.input, testCase.config)
|
||||
if !reflect.DeepEqual(testCase.input, testCase.expect) {
|
||||
t.Fatalf("Should be equal")
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
parser.ApplyGateway(tc.input, tc.config)
|
||||
if !reflect.DeepEqual(tc.input, tc.expect) {
|
||||
t.Fatalf("ApplyGateway result mismatch for %s:\nExpect: %+v\nGot: %+v",
|
||||
tc.name, tc.expect, tc.input)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNeedDownstreamTLS(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
annotations map[string]string
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
name: "empty annotations",
|
||||
annotations: map[string]string{},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
name: "with ssl cipher",
|
||||
annotations: map[string]string{
|
||||
buildNginxAnnotationKey(sslCipher): "ECDHE-RSA-AES256-GCM-SHA384",
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
name: "with TLS version",
|
||||
annotations: map[string]string{
|
||||
buildNginxAnnotationKey(annotationMinTLSVersion): "TLSv1.2",
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
name: "with multiple TLS configs",
|
||||
annotations: map[string]string{
|
||||
buildNginxAnnotationKey(sslCipher): "ECDHE-RSA-AES256-GCM-SHA384",
|
||||
buildNginxAnnotationKey(annotationMinTLSVersion): "TLSv1.2",
|
||||
buildNginxAnnotationKey(annotationMaxTLSVersion): "TLSv1.3",
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := needDownstreamTLS(tc.annotations)
|
||||
if result != tc.expect {
|
||||
t.Errorf("needDownstreamTLS() for %s = %v, want %v",
|
||||
tc.name, result, tc.expect)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
97
pkg/ingress/kube/common/model_test.go
Normal file
97
pkg/ingress/kube/common/model_test.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pkg/config"
|
||||
)
|
||||
|
||||
func TestIngressDomainCache(t *testing.T) {
|
||||
cache := NewIngressDomainCache()
|
||||
assert.NotNil(t, cache)
|
||||
assert.NotNil(t, cache.Valid)
|
||||
assert.Empty(t, cache.Invalid)
|
||||
|
||||
cache.Valid["example.com"] = &IngressDomainBuilder{
|
||||
Host: "example.com",
|
||||
Protocol: HTTP,
|
||||
ClusterId: "cluster-1",
|
||||
Ingress: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Name: "test-ingress",
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cache.Invalid = append(cache.Invalid, model.IngressDomain{
|
||||
Host: "invalid.com",
|
||||
Error: "invalid domain",
|
||||
})
|
||||
|
||||
result := cache.Extract()
|
||||
assert.Equal(t, 1, len(result.Valid))
|
||||
assert.Equal(t, "example.com", result.Valid[0].Host)
|
||||
assert.Equal(t, string(HTTP), result.Valid[0].Protocol)
|
||||
|
||||
assert.Equal(t, 1, len(result.Invalid))
|
||||
assert.Equal(t, "invalid.com", result.Invalid[0].Host)
|
||||
}
|
||||
|
||||
func TestIngressDomainBuilder(t *testing.T) {
|
||||
builder := &IngressDomainBuilder{
|
||||
Host: "example.com",
|
||||
Protocol: HTTP,
|
||||
ClusterId: "cluster-1",
|
||||
Ingress: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Name: "test-ingress",
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
domain := builder.Build()
|
||||
assert.Equal(t, "example.com", domain.Host)
|
||||
assert.Equal(t, string(HTTP), domain.Protocol)
|
||||
|
||||
builder.Event = MissingSecret
|
||||
eventDomain := builder.Build()
|
||||
assert.Contains(t, eventDomain.Error, "misses secret")
|
||||
|
||||
builder.Event = DuplicatedTls
|
||||
builder.PreIngress = &config.Config{
|
||||
Meta: config.Meta{
|
||||
Name: "pre-ingress",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
builder.PreIngress.Meta.Annotations = map[string]string{
|
||||
ClusterIdAnnotation: "pre-cluster",
|
||||
}
|
||||
dupDomain := builder.Build()
|
||||
assert.Contains(t, dupDomain.Error, "conflicted with ingress")
|
||||
|
||||
builder.Protocol = HTTPS
|
||||
builder.SecretName = "test-secret"
|
||||
builder.Event = ""
|
||||
httpsDomain := builder.Build()
|
||||
assert.Equal(t, string(HTTPS), httpsDomain.Protocol)
|
||||
assert.Equal(t, "test-secret", httpsDomain.SecretName)
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"testing"
|
||||
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pkg/config"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -556,3 +557,514 @@ func TestSortHTTPRoutesWithMoreRules(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateBackendResource(t *testing.T) {
|
||||
groupStr := "networking.higress.io"
|
||||
testCases := []struct {
|
||||
name string
|
||||
resource *v1.TypedLocalObjectReference
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "nil resource",
|
||||
resource: nil,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "nil APIGroup",
|
||||
resource: &v1.TypedLocalObjectReference{
|
||||
APIGroup: nil,
|
||||
Kind: "McpBridge",
|
||||
Name: "default",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong APIGroup",
|
||||
resource: &v1.TypedLocalObjectReference{
|
||||
APIGroup: &groupStr,
|
||||
Kind: "McpBridge",
|
||||
Name: "wrong-name",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong Kind",
|
||||
resource: &v1.TypedLocalObjectReference{
|
||||
APIGroup: &groupStr,
|
||||
Kind: "WrongKind",
|
||||
Name: "default",
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "valid resource",
|
||||
resource: &v1.TypedLocalObjectReference{
|
||||
APIGroup: &groupStr,
|
||||
Kind: "McpBridge",
|
||||
Name: "default",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := ValidateBackendResource(tc.resource)
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateOrUpdateAnnotations(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
annotations map[string]string
|
||||
options Options
|
||||
expected map[string]string
|
||||
}{
|
||||
{
|
||||
name: "empty annotations",
|
||||
annotations: map[string]string{},
|
||||
options: Options{
|
||||
ClusterId: "test-cluster",
|
||||
RawClusterId: "raw-test-cluster",
|
||||
},
|
||||
expected: map[string]string{
|
||||
ClusterIdAnnotation: "test-cluster",
|
||||
RawClusterIdAnnotation: "raw-test-cluster",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "existing annotations",
|
||||
annotations: map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
},
|
||||
options: Options{
|
||||
ClusterId: "test-cluster",
|
||||
RawClusterId: "raw-test-cluster",
|
||||
},
|
||||
expected: map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
ClusterIdAnnotation: "test-cluster",
|
||||
RawClusterIdAnnotation: "raw-test-cluster",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "overwrite existing cluster annotations",
|
||||
annotations: map[string]string{
|
||||
ClusterIdAnnotation: "old-cluster",
|
||||
RawClusterIdAnnotation: "old-raw-cluster",
|
||||
"key1": "value1",
|
||||
},
|
||||
options: Options{
|
||||
ClusterId: "new-cluster",
|
||||
RawClusterId: "new-raw-cluster",
|
||||
},
|
||||
expected: map[string]string{
|
||||
ClusterIdAnnotation: "new-cluster",
|
||||
RawClusterIdAnnotation: "new-raw-cluster",
|
||||
"key1": "value1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := CreateOrUpdateAnnotations(tc.annotations, tc.options)
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetClusterId(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
annotations map[string]string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "nil annotations",
|
||||
annotations: nil,
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "empty annotations",
|
||||
annotations: map[string]string{},
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "with cluster id",
|
||||
annotations: map[string]string{
|
||||
ClusterIdAnnotation: "test-cluster",
|
||||
},
|
||||
expected: "test-cluster",
|
||||
},
|
||||
{
|
||||
name: "with other annotations",
|
||||
annotations: map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
},
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := GetClusterId(tc.annotations)
|
||||
assert.Equal(t, tc.expected, string(result))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertToDNSLabelValidAndCleanHost(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input string
|
||||
}{
|
||||
{
|
||||
name: "simple host",
|
||||
input: "example.com",
|
||||
},
|
||||
{
|
||||
name: "wildcard host",
|
||||
input: "*.example.com",
|
||||
},
|
||||
{
|
||||
name: "long host",
|
||||
input: "very-long-subdomain.example-service.my-namespace.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
name: "empty host",
|
||||
input: "",
|
||||
},
|
||||
{
|
||||
name: "ip address",
|
||||
input: "192.168.1.1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Test internal convertToDNSLabelValid function (through CleanHost)
|
||||
result := CleanHost(tc.input)
|
||||
|
||||
// Validate result
|
||||
assert.NotEmpty(t, result)
|
||||
assert.Equal(t, 16, len(result)) // MD5 hash format is fixed length of 16 bytes
|
||||
|
||||
// Consistency check - same input should produce same output
|
||||
result2 := CleanHost(tc.input)
|
||||
assert.Equal(t, result, result2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitServiceFQDN(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
fqdn string
|
||||
expectedSvc string
|
||||
expectedNs string
|
||||
expectedValid bool
|
||||
}{
|
||||
{
|
||||
name: "simple fqdn",
|
||||
fqdn: "service.namespace",
|
||||
expectedSvc: "service",
|
||||
expectedNs: "namespace",
|
||||
expectedValid: true,
|
||||
},
|
||||
{
|
||||
name: "full k8s fqdn",
|
||||
fqdn: "service.namespace.svc.cluster.local",
|
||||
expectedSvc: "service",
|
||||
expectedNs: "namespace",
|
||||
expectedValid: true,
|
||||
},
|
||||
{
|
||||
name: "just service name",
|
||||
fqdn: "service",
|
||||
expectedSvc: "",
|
||||
expectedNs: "",
|
||||
expectedValid: false,
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
fqdn: "",
|
||||
expectedSvc: "",
|
||||
expectedNs: "",
|
||||
expectedValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
svc, ns, valid := SplitServiceFQDN(tc.fqdn)
|
||||
assert.Equal(t, tc.expectedSvc, svc)
|
||||
assert.Equal(t, tc.expectedNs, ns)
|
||||
assert.Equal(t, tc.expectedValid, valid)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertBackendService(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
dest *networking.HTTPRouteDestination
|
||||
expected model.BackendService
|
||||
}{
|
||||
{
|
||||
name: "simple service",
|
||||
dest: &networking.HTTPRouteDestination{
|
||||
Destination: &networking.Destination{
|
||||
Host: "service.namespace",
|
||||
Port: &networking.PortSelector{
|
||||
Number: 80,
|
||||
},
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
expected: model.BackendService{
|
||||
Name: "service",
|
||||
Namespace: "namespace",
|
||||
Port: 80,
|
||||
Weight: 100,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "full k8s FQDN",
|
||||
dest: &networking.HTTPRouteDestination{
|
||||
Destination: &networking.Destination{
|
||||
Host: "service.namespace.svc.cluster.local",
|
||||
Port: &networking.PortSelector{
|
||||
Number: 8080,
|
||||
},
|
||||
},
|
||||
Weight: 50,
|
||||
},
|
||||
expected: model.BackendService{
|
||||
Name: "service",
|
||||
Namespace: "namespace",
|
||||
Port: 8080,
|
||||
Weight: 50,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := ConvertBackendService(tc.dest)
|
||||
assert.Equal(t, tc.expected.Name, result.Name)
|
||||
assert.Equal(t, tc.expected.Namespace, result.Namespace)
|
||||
assert.Equal(t, tc.expected.Port, result.Port)
|
||||
assert.Equal(t, tc.expected.Weight, result.Weight)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateConvertedName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
items []string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "empty slice",
|
||||
items: []string{},
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "single item",
|
||||
items: []string{"example"},
|
||||
expected: "example",
|
||||
},
|
||||
{
|
||||
name: "multiple items",
|
||||
items: []string{"part1", "part2", "part3"},
|
||||
expected: "part1-part2-part3",
|
||||
},
|
||||
{
|
||||
name: "with empty strings",
|
||||
items: []string{"part1", "", "part3"},
|
||||
expected: "part1-part3",
|
||||
},
|
||||
{
|
||||
name: "all empty strings",
|
||||
items: []string{"", "", ""},
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := CreateConvertedName(tc.items...)
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortIngressByCreationTime(t *testing.T) {
|
||||
configs := []config.Config{
|
||||
{
|
||||
Meta: config.Meta{
|
||||
Name: "c-ingress",
|
||||
Namespace: "ns1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: config.Meta{
|
||||
Name: "a-ingress",
|
||||
Namespace: "ns1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: config.Meta{
|
||||
Name: "b-ingress",
|
||||
Namespace: "ns1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := []string{"a-ingress", "b-ingress", "c-ingress"}
|
||||
|
||||
SortIngressByCreationTime(configs)
|
||||
|
||||
var actual []string
|
||||
for _, cfg := range configs {
|
||||
actual = append(actual, cfg.Name)
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, actual, "When the timestamps are the same, the configuration should be sorted by name")
|
||||
|
||||
sameNamespaceConfigs := []config.Config{
|
||||
{
|
||||
Meta: config.Meta{
|
||||
Name: "same-name",
|
||||
Namespace: "c-ns",
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: config.Meta{
|
||||
Name: "same-name",
|
||||
Namespace: "a-ns",
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: config.Meta{
|
||||
Name: "same-name",
|
||||
Namespace: "b-ns",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedNamespace := []string{"a-ns", "b-ns", "c-ns"}
|
||||
|
||||
SortIngressByCreationTime(sameNamespaceConfigs)
|
||||
|
||||
var actualNamespace []string
|
||||
for _, cfg := range sameNamespaceConfigs {
|
||||
actualNamespace = append(actualNamespace, cfg.Namespace)
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedNamespace, actualNamespace, "When the names are the same, the configuration should be sorted by namespace")
|
||||
}
|
||||
|
||||
func TestPartMd5(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input string
|
||||
length int
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
length: 8,
|
||||
},
|
||||
{
|
||||
name: "simple string",
|
||||
input: "test",
|
||||
length: 8,
|
||||
},
|
||||
{
|
||||
name: "complex string",
|
||||
input: "this-is-a-long-string-with-special-chars-!@#$%^&*()",
|
||||
length: 8,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := partMd5(tc.input)
|
||||
|
||||
// Check result format
|
||||
assert.Equal(t, tc.length, len(result), "MD5 hash excerpt should be 8 characters")
|
||||
|
||||
// Run twice to ensure deterministic output
|
||||
result2 := partMd5(tc.input)
|
||||
assert.Equal(t, result, result2, "partMd5 function should be deterministic")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLbStatusListV1AndV1Beta1(t *testing.T) {
|
||||
clusterPrefix = "gw-123-"
|
||||
svcName := clusterPrefix
|
||||
svcList := []*v1.Service{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: svcName,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
},
|
||||
Status: v1.ServiceStatus{
|
||||
LoadBalancer: v1.LoadBalancerStatus{
|
||||
Ingress: []v1.LoadBalancerIngress{
|
||||
{
|
||||
IP: "2.2.2.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: svcName,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
},
|
||||
Status: v1.ServiceStatus{
|
||||
LoadBalancer: v1.LoadBalancerStatus{
|
||||
Ingress: []v1.LoadBalancerIngress{
|
||||
{
|
||||
Hostname: "1.1.1.1" + SvcHostNameSuffix,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Test the V1 version
|
||||
t.Run("GetLbStatusListV1", func(t *testing.T) {
|
||||
lbiList := GetLbStatusListV1(svcList)
|
||||
|
||||
assert.Equal(t, 2, len(lbiList), "There should be 2 entry points")
|
||||
assert.Equal(t, "1.1.1.1", lbiList[0].IP, "The first IP should be 1.1.1.1")
|
||||
assert.Equal(t, "2.2.2.2", lbiList[1].IP, "The second IP should be 2.2.2.2")
|
||||
})
|
||||
|
||||
// Test the V1Beta1 version
|
||||
t.Run("GetLbStatusListV1Beta1", func(t *testing.T) {
|
||||
lbiList := GetLbStatusListV1Beta1(svcList)
|
||||
|
||||
assert.Equal(t, 2, len(lbiList), "There should be 2 entry points")
|
||||
assert.Equal(t, "1.1.1.1", lbiList[0].IP, "The first IP should be 1.1.1.1")
|
||||
assert.Equal(t, "2.2.2.2", lbiList[1].IP, "The second IP should be 2.2.2.2")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ type HigressConfig struct {
|
||||
Upstream *Upstream `json:"upstream,omitempty"`
|
||||
DisableXEnvoyHeaders bool `json:"disableXEnvoyHeaders,omitempty"`
|
||||
AddXRealIpHeader bool `json:"addXRealIpHeader,omitempty"`
|
||||
McpServer *McpServer `json:"mcpServer,omitempty"`
|
||||
}
|
||||
|
||||
func NewDefaultHigressConfig() *HigressConfig {
|
||||
@@ -51,6 +52,7 @@ func NewDefaultHigressConfig() *HigressConfig {
|
||||
Upstream: globalOption.Upstream,
|
||||
DisableXEnvoyHeaders: globalOption.DisableXEnvoyHeaders,
|
||||
AddXRealIpHeader: globalOption.AddXRealIpHeader,
|
||||
McpServer: NewDefaultMcpServer(),
|
||||
}
|
||||
return higressConfig
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
"istio.io/istio/pilot/pkg/model"
|
||||
"istio.io/istio/pkg/cluster"
|
||||
"istio.io/istio/pkg/config"
|
||||
@@ -58,6 +59,7 @@ type ItemController interface {
|
||||
ValidHigressConfig(higressConfig *HigressConfig) error
|
||||
ConstructEnvoyFilters() ([]*config.Config, error)
|
||||
RegisterItemEventHandler(eventHandler ItemEventHandler)
|
||||
RegisterMcpReconciler(reconciler *reconcile.Reconciler)
|
||||
}
|
||||
|
||||
type ConfigmapMgr struct {
|
||||
@@ -89,6 +91,9 @@ func NewConfigmapMgr(XDSUpdater model.XDSUpdater, namespace string, higressConfi
|
||||
globalOptionController := NewGlobalOptionController(namespace)
|
||||
configmapMgr.AddItemControllers(globalOptionController)
|
||||
|
||||
mcpServerController := NewMcpServerController(namespace)
|
||||
configmapMgr.AddItemControllers(mcpServerController)
|
||||
|
||||
configmapMgr.initEventHandlers()
|
||||
|
||||
return configmapMgr
|
||||
@@ -108,6 +113,12 @@ func (c *ConfigmapMgr) GetHigressConfig() *HigressConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConfigmapMgr) SetMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
for _, itemController := range c.ItemControllers {
|
||||
itemController.RegisterMcpReconciler(reconciler)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConfigmapMgr) AddItemControllers(controllers ...ItemController) {
|
||||
c.ItemControllers = append(c.ItemControllers, controllers...)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
@@ -376,6 +377,9 @@ func (g *GlobalOptionController) RegisterItemEventHandler(eventHandler ItemEvent
|
||||
g.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (g *GlobalOptionController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
}
|
||||
|
||||
// generateDownstreamEnvoyFilter generates the downstream envoy filter.
|
||||
func (g *GlobalOptionController) generateDownstreamEnvoyFilter(downstreamValueStruct string, bufferLimitStruct string, routeTimeoutStruct string, namespace string) []*networking.EnvoyFilter_EnvoyConfigObjectPatch {
|
||||
var downstreamConfig []*networking.EnvoyFilter_EnvoyConfigObjectPatch
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
@@ -291,6 +292,9 @@ func (g *GzipController) RegisterItemEventHandler(eventHandler ItemEventHandler)
|
||||
g.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (g *GzipController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
}
|
||||
|
||||
func (g *GzipController) constructGzipStruct(gzip *Gzip, namespace string) string {
|
||||
gzipConfig := ""
|
||||
contentType := ""
|
||||
|
||||
522
pkg/ingress/kube/configmap/mcp_server.go
Normal file
522
pkg/ingress/kube/configmap/mcp_server.go
Normal file
@@ -0,0 +1,522 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package configmap
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
. "github.com/alibaba/higress/pkg/ingress/log"
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
)
|
||||
|
||||
// RedisConfig defines the configuration for Redis connection
|
||||
type RedisConfig struct {
|
||||
// The address of Redis server in the format of "host:port"
|
||||
Address string `json:"address,omitempty"`
|
||||
// The username for Redis authentication
|
||||
Username string `json:"username,omitempty"`
|
||||
// The password for Redis authentication
|
||||
Password string `json:"password,omitempty"`
|
||||
// The database index to use
|
||||
DB int `json:"db,omitempty"`
|
||||
}
|
||||
|
||||
// MCPRatelimitConfig defines the configuration for rate limit
|
||||
type MCPRatelimitConfig struct {
|
||||
// The limit of the rate limit
|
||||
Limit int64 `json:"limit,omitempty"`
|
||||
// The window of the rate limit
|
||||
Window int64 `json:"window,omitempty"`
|
||||
// The white list of the rate limit
|
||||
WhiteList []string `json:"white_list,omitempty"`
|
||||
}
|
||||
|
||||
// SSEServer defines the configuration for Server-Sent Events (SSE) server
|
||||
type SSEServer struct {
|
||||
// The name of the SSE server
|
||||
Name string `json:"name,omitempty"`
|
||||
// The path where the SSE server will be mounted, the full path is (PATH + SsePathSuffix)
|
||||
Path string `json:"path,omitempty"`
|
||||
// The type of the SSE server
|
||||
Type string `json:"type,omitempty"`
|
||||
// Additional Config parameters for the real MCP server implementation
|
||||
Config map[string]interface{} `json:"config,omitempty"`
|
||||
// The domain list of the SSE server
|
||||
DomainList []string `json:"domain_list,omitempty"`
|
||||
}
|
||||
|
||||
// MatchRule defines a rule for matching requests
|
||||
type MatchRule struct {
|
||||
// Domain pattern, supports wildcards
|
||||
MatchRuleDomain string `json:"match_rule_domain,omitempty"`
|
||||
// Path pattern to match
|
||||
MatchRulePath string `json:"match_rule_path,omitempty"`
|
||||
// Type of match rule: exact, prefix, suffix, contains, regex
|
||||
MatchRuleType string `json:"match_rule_type,omitempty"`
|
||||
}
|
||||
|
||||
// McpServer defines the configuration for MCP (Model Context Protocol) server
|
||||
type McpServer struct {
|
||||
// Flag to control whether MCP server is enabled
|
||||
Enable bool `json:"enable,omitempty"`
|
||||
// Redis Config for MCP server
|
||||
Redis *RedisConfig `json:"redis,omitempty"`
|
||||
// The suffix to be appended to SSE paths, default is "/sse"
|
||||
SsePathSuffix string `json:"sse_path_suffix,omitempty"`
|
||||
// List of SSE servers Configs
|
||||
Servers []*SSEServer `json:"servers,omitempty"`
|
||||
// List of match rules for filtering requests
|
||||
MatchList []*MatchRule `json:"match_list,omitempty"`
|
||||
// Flag to control whether user level server is enabled
|
||||
EnableUserLevelServer bool `json:"enable_user_level_server,omitempty"`
|
||||
// Rate limit config for MCP server
|
||||
Ratelimit *MCPRatelimitConfig `json:"rate_limit,omitempty"`
|
||||
}
|
||||
|
||||
func NewDefaultMcpServer() *McpServer {
|
||||
return &McpServer{
|
||||
Enable: false,
|
||||
Servers: make([]*SSEServer, 0),
|
||||
MatchList: make([]*MatchRule, 0),
|
||||
EnableUserLevelServer: false,
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
higressMcpServerEnvoyFilterName = "higress-config-mcp-server"
|
||||
)
|
||||
|
||||
func validMcpServer(m *McpServer) error {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.EnableUserLevelServer && m.Redis == nil {
|
||||
return errors.New("redis config cannot be empty when user level server is enabled")
|
||||
}
|
||||
|
||||
// Validate match rule types
|
||||
if m.MatchList != nil {
|
||||
validTypes := map[string]bool{
|
||||
"exact": true,
|
||||
"prefix": true,
|
||||
"suffix": true,
|
||||
"contains": true,
|
||||
"regex": true,
|
||||
}
|
||||
|
||||
for _, rule := range m.MatchList {
|
||||
if rule.MatchRuleType == "" {
|
||||
return errors.New("match_rule_type cannot be empty, must be one of: exact, prefix, suffix, contains, regex")
|
||||
}
|
||||
if !validTypes[rule.MatchRuleType] {
|
||||
return fmt.Errorf("invalid match_rule_type: %s, must be one of: exact, prefix, suffix, contains, regex", rule.MatchRuleType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func compareMcpServer(old *McpServer, new *McpServer) (Result, error) {
|
||||
if old == nil && new == nil {
|
||||
return ResultNothing, nil
|
||||
}
|
||||
|
||||
if new == nil {
|
||||
return ResultDelete, nil
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(old, new) {
|
||||
return ResultReplace, nil
|
||||
}
|
||||
|
||||
return ResultNothing, nil
|
||||
}
|
||||
|
||||
func deepCopyMcpServer(mcp *McpServer) (*McpServer, error) {
|
||||
newMcp := NewDefaultMcpServer()
|
||||
newMcp.Enable = mcp.Enable
|
||||
|
||||
if mcp.Redis != nil {
|
||||
newMcp.Redis = &RedisConfig{
|
||||
Address: mcp.Redis.Address,
|
||||
Username: mcp.Redis.Username,
|
||||
Password: mcp.Redis.Password,
|
||||
DB: mcp.Redis.DB,
|
||||
}
|
||||
}
|
||||
if mcp.Ratelimit != nil {
|
||||
newMcp.Ratelimit = &MCPRatelimitConfig{
|
||||
Limit: mcp.Ratelimit.Limit,
|
||||
Window: mcp.Ratelimit.Window,
|
||||
WhiteList: mcp.Ratelimit.WhiteList,
|
||||
}
|
||||
}
|
||||
newMcp.SsePathSuffix = mcp.SsePathSuffix
|
||||
|
||||
newMcp.EnableUserLevelServer = mcp.EnableUserLevelServer
|
||||
|
||||
if len(mcp.Servers) > 0 {
|
||||
newMcp.Servers = make([]*SSEServer, len(mcp.Servers))
|
||||
for i, server := range mcp.Servers {
|
||||
newServer := &SSEServer{
|
||||
Name: server.Name,
|
||||
Path: server.Path,
|
||||
Type: server.Type,
|
||||
DomainList: server.DomainList,
|
||||
}
|
||||
if server.Config != nil {
|
||||
newServer.Config = make(map[string]interface{})
|
||||
for k, v := range server.Config {
|
||||
newServer.Config[k] = v
|
||||
}
|
||||
}
|
||||
newMcp.Servers[i] = newServer
|
||||
}
|
||||
}
|
||||
|
||||
if len(mcp.MatchList) > 0 {
|
||||
newMcp.MatchList = make([]*MatchRule, len(mcp.MatchList))
|
||||
for i, rule := range mcp.MatchList {
|
||||
newMcp.MatchList[i] = &MatchRule{
|
||||
MatchRuleDomain: rule.MatchRuleDomain,
|
||||
MatchRulePath: rule.MatchRulePath,
|
||||
MatchRuleType: rule.MatchRuleType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newMcp, nil
|
||||
}
|
||||
|
||||
type McpServerController struct {
|
||||
Namespace string
|
||||
mcpServer atomic.Value
|
||||
Name string
|
||||
eventHandler ItemEventHandler
|
||||
reconclier *reconcile.Reconciler
|
||||
}
|
||||
|
||||
func NewMcpServerController(namespace string) *McpServerController {
|
||||
mcpController := &McpServerController{
|
||||
Namespace: namespace,
|
||||
mcpServer: atomic.Value{},
|
||||
Name: "mcpServer",
|
||||
}
|
||||
mcpController.SetMcpServer(NewDefaultMcpServer())
|
||||
return mcpController
|
||||
}
|
||||
|
||||
func (m *McpServerController) GetName() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
func (m *McpServerController) SetMcpServer(mcp *McpServer) {
|
||||
m.mcpServer.Store(mcp)
|
||||
}
|
||||
|
||||
func (m *McpServerController) GetMcpServer() *McpServer {
|
||||
value := m.mcpServer.Load()
|
||||
if value != nil {
|
||||
if mcp, ok := value.(*McpServer); ok {
|
||||
return mcp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *McpServerController) AddOrUpdateHigressConfig(name util.ClusterNamespacedName, old *HigressConfig, new *HigressConfig) error {
|
||||
if err := validMcpServer(new.McpServer); err != nil {
|
||||
IngressLog.Errorf("data:%+v convert to mcp server, error: %+v", new.McpServer, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
result, _ := compareMcpServer(old.McpServer, new.McpServer)
|
||||
|
||||
switch result {
|
||||
case ResultReplace:
|
||||
if newMcp, err := deepCopyMcpServer(new.McpServer); err != nil {
|
||||
IngressLog.Infof("mcp server deepcopy error:%v", err)
|
||||
} else {
|
||||
m.SetMcpServer(newMcp)
|
||||
IngressLog.Infof("AddOrUpdate Higress config mcp server")
|
||||
m.eventHandler(higressMcpServerEnvoyFilterName)
|
||||
IngressLog.Infof("send event with filter name:%s", higressMcpServerEnvoyFilterName)
|
||||
}
|
||||
case ResultDelete:
|
||||
m.SetMcpServer(NewDefaultMcpServer())
|
||||
IngressLog.Infof("Delete Higress config mcp server")
|
||||
m.eventHandler(higressMcpServerEnvoyFilterName)
|
||||
IngressLog.Infof("send event with filter name:%s", higressMcpServerEnvoyFilterName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *McpServerController) ValidHigressConfig(higressConfig *HigressConfig) error {
|
||||
if higressConfig == nil {
|
||||
return nil
|
||||
}
|
||||
if higressConfig.McpServer == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return validMcpServer(higressConfig.McpServer)
|
||||
}
|
||||
|
||||
func (m *McpServerController) RegisterItemEventHandler(eventHandler ItemEventHandler) {
|
||||
m.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (m *McpServerController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
m.reconclier = reconciler
|
||||
}
|
||||
|
||||
func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
configs := make([]*config.Config, 0)
|
||||
mcpServer := m.GetMcpServer()
|
||||
namespace := m.Namespace
|
||||
|
||||
if mcpServer == nil || !mcpServer.Enable {
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
// mcp-session envoy filter
|
||||
mcpSessionStruct := m.constructMcpSessionStruct(mcpServer)
|
||||
if mcpSessionStruct != "" {
|
||||
sessionConfig := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.EnvoyFilter,
|
||||
Name: higressMcpServerEnvoyFilterName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: &networking.EnvoyFilter{
|
||||
ConfigPatches: []*networking.EnvoyFilter_EnvoyConfigObjectPatch{
|
||||
{
|
||||
ApplyTo: networking.EnvoyFilter_HTTP_FILTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
|
||||
Listener: &networking.EnvoyFilter_ListenerMatch{
|
||||
FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
|
||||
Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
|
||||
Name: "envoy.filters.network.http_connection_manager",
|
||||
SubFilter: &networking.EnvoyFilter_ListenerMatch_SubFilterMatch{
|
||||
Name: "envoy.filters.http.cors",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_INSERT_AFTER,
|
||||
Value: util.BuildPatchStruct(mcpSessionStruct),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configs = append(configs, sessionConfig)
|
||||
}
|
||||
|
||||
// mcp-server envoy filter
|
||||
mcpServerStruct := m.constructMcpServerStruct(mcpServer)
|
||||
if mcpServerStruct != "" {
|
||||
serverConfig := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.EnvoyFilter,
|
||||
Name: higressMcpServerEnvoyFilterName + "-server",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: &networking.EnvoyFilter{
|
||||
ConfigPatches: []*networking.EnvoyFilter_EnvoyConfigObjectPatch{
|
||||
{
|
||||
ApplyTo: networking.EnvoyFilter_HTTP_FILTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
|
||||
Listener: &networking.EnvoyFilter_ListenerMatch{
|
||||
FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
|
||||
Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
|
||||
Name: "envoy.filters.network.http_connection_manager",
|
||||
SubFilter: &networking.EnvoyFilter_ListenerMatch_SubFilterMatch{
|
||||
Name: "envoy.filters.http.router",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_INSERT_BEFORE,
|
||||
Value: util.BuildPatchStruct(mcpServerStruct),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configs = append(configs, serverConfig)
|
||||
}
|
||||
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
func (m *McpServerController) constructMcpSessionStruct(mcp *McpServer) string {
|
||||
// Build match_list configuration
|
||||
matchList := "[]"
|
||||
var matchConfigs []string
|
||||
if len(mcp.MatchList) > 0 {
|
||||
for _, rule := range mcp.MatchList {
|
||||
matchConfigs = append(matchConfigs, fmt.Sprintf(`{
|
||||
"match_rule_domain": "%s",
|
||||
"match_rule_path": "%s",
|
||||
"match_rule_type": "%s"
|
||||
}`, rule.MatchRuleDomain, rule.MatchRulePath, rule.MatchRuleType))
|
||||
}
|
||||
}
|
||||
|
||||
if m.reconclier != nil {
|
||||
vsFromMcp := m.reconclier.GetAllConfigs(gvk.VirtualService)
|
||||
for _, c := range vsFromMcp {
|
||||
vs := c.Spec.(*networking.VirtualService)
|
||||
var host string
|
||||
if len(vs.Hosts) > 1 {
|
||||
host = fmt.Sprintf("(%s)", strings.Join(vs.Hosts, "|"))
|
||||
} else {
|
||||
host = vs.Hosts[0]
|
||||
}
|
||||
path := vs.Http[0].Match[0].Uri.GetPrefix()
|
||||
matchConfigs = append(matchConfigs, fmt.Sprintf(`{
|
||||
"match_rule_domain": "%s",
|
||||
"match_rule_path": "%s",
|
||||
"match_rule_type": "prefix"
|
||||
}`, host, path))
|
||||
}
|
||||
}
|
||||
matchList = fmt.Sprintf("[%s]", strings.Join(matchConfigs, ","))
|
||||
|
||||
// Build redis configuration
|
||||
redisConfig := "null"
|
||||
if mcp.Redis != nil {
|
||||
redisConfig = fmt.Sprintf(`{
|
||||
"address": "%s",
|
||||
"username": "%s",
|
||||
"password": "%s",
|
||||
"db": %d
|
||||
}`, mcp.Redis.Address, mcp.Redis.Username, mcp.Redis.Password, mcp.Redis.DB)
|
||||
}
|
||||
|
||||
// Build rate limit configuration
|
||||
rateLimitConfig := "null"
|
||||
if mcp.Ratelimit != nil {
|
||||
whiteList := "[]"
|
||||
if len(mcp.Ratelimit.WhiteList) > 0 {
|
||||
whiteList = fmt.Sprintf(`["%s"]`, strings.Join(mcp.Ratelimit.WhiteList, `","`))
|
||||
}
|
||||
rateLimitConfig = fmt.Sprintf(`{
|
||||
"limit": %d,
|
||||
"window": %d,
|
||||
"white_list": %s
|
||||
}`, mcp.Ratelimit.Limit, mcp.Ratelimit.Window, whiteList)
|
||||
}
|
||||
|
||||
// Build complete configuration structure
|
||||
return fmt.Sprintf(`{
|
||||
"name": "envoy.filters.http.golang",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
|
||||
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||
"value": {
|
||||
"library_id": "mcp-session",
|
||||
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||
"plugin_name": "mcp-session",
|
||||
"plugin_config": {
|
||||
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||
"value": {
|
||||
"redis": %s,
|
||||
"rate_limit": %s,
|
||||
"sse_path_suffix": "%s",
|
||||
"match_list": %s,
|
||||
"enable_user_level_server": %t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
redisConfig,
|
||||
rateLimitConfig,
|
||||
mcp.SsePathSuffix,
|
||||
matchList,
|
||||
mcp.EnableUserLevelServer)
|
||||
}
|
||||
|
||||
func (m *McpServerController) constructMcpServerStruct(mcp *McpServer) string {
|
||||
// Build servers configuration
|
||||
servers := "[]"
|
||||
if len(mcp.Servers) > 0 {
|
||||
serverConfigs := make([]string, len(mcp.Servers))
|
||||
for i, server := range mcp.Servers {
|
||||
serverConfig := fmt.Sprintf(`{
|
||||
"name": "%s",
|
||||
"path": "%s",
|
||||
"type": "%s"`,
|
||||
server.Name, server.Path, server.Type)
|
||||
if len(server.DomainList) > 0 {
|
||||
domainList := fmt.Sprintf(`["%s"]`, strings.Join(server.DomainList, `","`))
|
||||
serverConfig += fmt.Sprintf(`,
|
||||
"domain_list": %s`, domainList)
|
||||
}
|
||||
if len(server.Config) > 0 {
|
||||
config, _ := json.Marshal(server.Config)
|
||||
serverConfig += fmt.Sprintf(`,
|
||||
"config": %s`, string(config))
|
||||
}
|
||||
serverConfig += "}"
|
||||
serverConfigs[i] = serverConfig
|
||||
}
|
||||
servers = fmt.Sprintf("[%s]", strings.Join(serverConfigs, ","))
|
||||
}
|
||||
|
||||
// Build complete configuration structure
|
||||
return fmt.Sprintf(`{
|
||||
"name": "envoy.filters.http.golang",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
|
||||
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||
"value": {
|
||||
"library_id": "mcp-server",
|
||||
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||
"plugin_name": "mcp-server",
|
||||
"plugin_config": {
|
||||
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||
"value": {
|
||||
"servers": %s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, servers)
|
||||
}
|
||||
733
pkg/ingress/kube/configmap/mcp_server_test.go
Normal file
733
pkg/ingress/kube/configmap/mcp_server_test.go
Normal file
@@ -0,0 +1,733 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed 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.
|
||||
|
||||
package configmap
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_validMcpServer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mcp *McpServer
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
mcp: &McpServer{
|
||||
Enable: false,
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "nil",
|
||||
mcp: nil,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "enabled but no redis config",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
EnableUserLevelServer: false,
|
||||
Redis: nil,
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "enabled with user level server but no redis config",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
EnableUserLevelServer: true,
|
||||
Redis: nil,
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantErr: errors.New("redis config cannot be empty when user level server is enabled"),
|
||||
},
|
||||
{
|
||||
name: "valid config with redis",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
EnableUserLevelServer: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
SsePathSuffix: "/sse",
|
||||
MatchList: []*MatchRule{
|
||||
{
|
||||
MatchRuleDomain: "*",
|
||||
MatchRulePath: "*",
|
||||
MatchRuleType: "exact",
|
||||
},
|
||||
},
|
||||
Servers: []*SSEServer{
|
||||
{
|
||||
Name: "test-server",
|
||||
Path: "/test",
|
||||
Type: "test",
|
||||
Config: map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validMcpServer(tt.mcp)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_compareMcpServer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
old *McpServer
|
||||
new *McpServer
|
||||
wantResult Result
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "compare both nil",
|
||||
old: nil,
|
||||
new: nil,
|
||||
wantResult: ResultNothing,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "compare result delete",
|
||||
old: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
new: nil,
|
||||
wantResult: ResultDelete,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "compare result equal",
|
||||
old: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
new: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantResult: ResultNothing,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "compare result replace",
|
||||
old: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
new: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "redis:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{
|
||||
{
|
||||
MatchRuleDomain: "*",
|
||||
MatchRulePath: "/test",
|
||||
MatchRuleType: "exact",
|
||||
},
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantResult: ResultReplace,
|
||||
wantErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := compareMcpServer(tt.old, tt.new)
|
||||
assert.Equal(t, tt.wantResult, result)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_deepCopyMcpServer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mcp *McpServer
|
||||
wantMcp *McpServer
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "deep copy with redis only",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantMcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "deep copy with full config",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
SsePathSuffix: "/sse",
|
||||
MatchList: []*MatchRule{
|
||||
{
|
||||
MatchRuleDomain: "*",
|
||||
MatchRulePath: "*",
|
||||
MatchRuleType: "exact",
|
||||
},
|
||||
},
|
||||
Servers: []*SSEServer{
|
||||
{
|
||||
Name: "test-server",
|
||||
Path: "/test",
|
||||
Type: "test",
|
||||
Config: map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantMcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
SsePathSuffix: "/sse",
|
||||
MatchList: []*MatchRule{
|
||||
{
|
||||
MatchRuleDomain: "*",
|
||||
MatchRulePath: "*",
|
||||
MatchRuleType: "exact",
|
||||
},
|
||||
},
|
||||
Servers: []*SSEServer{
|
||||
{
|
||||
Name: "test-server",
|
||||
Path: "/test",
|
||||
Type: "test",
|
||||
Config: map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mcp, err := deepCopyMcpServer(tt.mcp)
|
||||
assert.Equal(t, tt.wantMcp, mcp)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMcpServerController_AddOrUpdateHigressConfig(t *testing.T) {
|
||||
eventPush := "default"
|
||||
defaultHandler := func(name string) {
|
||||
eventPush = "push"
|
||||
}
|
||||
|
||||
defaultName := util.ClusterNamespacedName{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
old *HigressConfig
|
||||
new *HigressConfig
|
||||
wantErr error
|
||||
wantEventPush string
|
||||
wantMcp *McpServer
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
old: &HigressConfig{
|
||||
McpServer: NewDefaultMcpServer(),
|
||||
},
|
||||
new: &HigressConfig{
|
||||
McpServer: NewDefaultMcpServer(),
|
||||
},
|
||||
wantErr: nil,
|
||||
wantEventPush: "default",
|
||||
wantMcp: NewDefaultMcpServer(),
|
||||
},
|
||||
{
|
||||
name: "replace and push - enable mcp server",
|
||||
old: &HigressConfig{
|
||||
McpServer: NewDefaultMcpServer(),
|
||||
},
|
||||
new: &HigressConfig{
|
||||
McpServer: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
MatchList: []*MatchRule{},
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
wantEventPush: "push",
|
||||
wantMcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "default",
|
||||
Password: "password",
|
||||
DB: 0,
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
MatchList: []*MatchRule{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "replace and push - update config",
|
||||
old: &HigressConfig{
|
||||
McpServer: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
MatchList: []*MatchRule{},
|
||||
},
|
||||
},
|
||||
new: &HigressConfig{
|
||||
McpServer: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "redis:6379",
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
MatchList: []*MatchRule{},
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
wantEventPush: "push",
|
||||
wantMcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "redis:6379",
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
MatchList: []*MatchRule{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "delete and push",
|
||||
old: &HigressConfig{
|
||||
McpServer: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
Servers: []*SSEServer{},
|
||||
MatchList: []*MatchRule{},
|
||||
},
|
||||
},
|
||||
new: &HigressConfig{
|
||||
McpServer: nil,
|
||||
},
|
||||
wantErr: nil,
|
||||
wantEventPush: "push",
|
||||
wantMcp: NewDefaultMcpServer(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := NewMcpServerController("higress-system")
|
||||
m.eventHandler = defaultHandler
|
||||
eventPush = "default"
|
||||
err := m.AddOrUpdateHigressConfig(defaultName, tt.old, tt.new)
|
||||
assert.Equal(t, tt.wantEventPush, eventPush)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
assert.Equal(t, tt.wantMcp, m.GetMcpServer())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMcpServerController_ValidHigressConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
higressConfig *HigressConfig
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "nil config",
|
||||
higressConfig: nil,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "nil mcp server",
|
||||
higressConfig: &HigressConfig{
|
||||
McpServer: nil,
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "valid config",
|
||||
higressConfig: &HigressConfig{
|
||||
McpServer: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid config - user level server without redis",
|
||||
higressConfig: &HigressConfig{
|
||||
McpServer: &McpServer{
|
||||
Enable: true,
|
||||
EnableUserLevelServer: true,
|
||||
Redis: nil,
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
},
|
||||
wantErr: errors.New("redis config cannot be empty when user level server is enabled"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := NewMcpServerController("test-namespace")
|
||||
err := m.ValidHigressConfig(tt.higressConfig)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMcpServerController_ConstructEnvoyFilters(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mcpServer *McpServer
|
||||
wantConfigs int
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "nil mcp server",
|
||||
mcpServer: nil,
|
||||
wantConfigs: 0,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "disabled mcp server",
|
||||
mcpServer: &McpServer{
|
||||
Enable: false,
|
||||
},
|
||||
wantConfigs: 0,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "valid mcp server with redis",
|
||||
mcpServer: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantConfigs: 2, // Both session and server filters
|
||||
wantErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := NewMcpServerController("test-namespace")
|
||||
m.mcpServer.Store(tt.mcpServer)
|
||||
configs, err := m.ConstructEnvoyFilters()
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
assert.Equal(t, tt.wantConfigs, len(configs))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMcpServerController_constructMcpSessionStruct(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mcp *McpServer
|
||||
wantJSON string
|
||||
}{
|
||||
{
|
||||
name: "minimal config",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
},
|
||||
MatchList: []*MatchRule{},
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantJSON: `{
|
||||
"name": "envoy.filters.http.golang",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
|
||||
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||
"value": {
|
||||
"library_id": "mcp-session",
|
||||
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||
"plugin_name": "mcp-session",
|
||||
"plugin_config": {
|
||||
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||
"value": {
|
||||
"redis": {
|
||||
"address": "localhost:6379",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"db": 0
|
||||
},
|
||||
"rate_limit": null,
|
||||
"sse_path_suffix": "",
|
||||
"match_list": [],
|
||||
"enable_user_level_server": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "full config",
|
||||
mcp: &McpServer{
|
||||
Enable: true,
|
||||
Redis: &RedisConfig{
|
||||
Address: "localhost:6379",
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
DB: 1,
|
||||
},
|
||||
SsePathSuffix: "/sse",
|
||||
MatchList: []*MatchRule{
|
||||
{
|
||||
MatchRuleDomain: "*",
|
||||
MatchRulePath: "/test",
|
||||
MatchRuleType: "exact",
|
||||
},
|
||||
},
|
||||
EnableUserLevelServer: true,
|
||||
Ratelimit: &MCPRatelimitConfig{
|
||||
Limit: 100,
|
||||
Window: 3600,
|
||||
WhiteList: []string{"user1", "user2"},
|
||||
},
|
||||
},
|
||||
wantJSON: `{
|
||||
"name": "envoy.filters.http.golang",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
|
||||
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||
"value": {
|
||||
"library_id": "mcp-session",
|
||||
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||
"plugin_name": "mcp-session",
|
||||
"plugin_config": {
|
||||
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||
"value": {
|
||||
"redis": {
|
||||
"address": "localhost:6379",
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
"db": 1
|
||||
},
|
||||
"rate_limit": {
|
||||
"limit": 100,
|
||||
"window": 3600,
|
||||
"white_list": ["user1","user2"]
|
||||
},
|
||||
"sse_path_suffix": "/sse",
|
||||
"match_list": [{
|
||||
"match_rule_domain": "*",
|
||||
"match_rule_path": "/test",
|
||||
"match_rule_type": "exact"
|
||||
}],
|
||||
"enable_user_level_server": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := NewMcpServerController("test-namespace")
|
||||
got := m.constructMcpSessionStruct(tt.mcp)
|
||||
// Normalize JSON strings for comparison
|
||||
var gotJSON, wantJSON interface{}
|
||||
json.Unmarshal([]byte(got), &gotJSON)
|
||||
json.Unmarshal([]byte(tt.wantJSON), &wantJSON)
|
||||
assert.Equal(t, wantJSON, gotJSON)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMcpServerController_constructMcpServerStruct(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mcp *McpServer
|
||||
wantJSON string
|
||||
}{
|
||||
{
|
||||
name: "no servers",
|
||||
mcp: &McpServer{
|
||||
Servers: []*SSEServer{},
|
||||
},
|
||||
wantJSON: `{
|
||||
"name": "envoy.filters.http.golang",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
|
||||
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||
"value": {
|
||||
"library_id": "mcp-server",
|
||||
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||
"plugin_name": "mcp-server",
|
||||
"plugin_config": {
|
||||
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||
"value": {
|
||||
"servers": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "with servers",
|
||||
mcp: &McpServer{
|
||||
Servers: []*SSEServer{
|
||||
{
|
||||
Name: "test-server",
|
||||
Path: "/test",
|
||||
Type: "test",
|
||||
Config: map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
DomainList: []string{"example.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantJSON: `{
|
||||
"name": "envoy.filters.http.golang",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
|
||||
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
|
||||
"value": {
|
||||
"library_id": "mcp-server",
|
||||
"library_path": "/var/lib/istio/envoy/golang-filter.so",
|
||||
"plugin_name": "mcp-server",
|
||||
"plugin_config": {
|
||||
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
|
||||
"value": {
|
||||
"servers": [{
|
||||
"name": "test-server",
|
||||
"path": "/test",
|
||||
"type": "test",
|
||||
"domain_list": ["example.com"],
|
||||
"config": {"key":"value"}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := NewMcpServerController("test-namespace")
|
||||
got := m.constructMcpServerStruct(tt.mcp)
|
||||
// Normalize JSON strings for comparison
|
||||
var gotJSON, wantJSON interface{}
|
||||
json.Unmarshal([]byte(got), &gotJSON)
|
||||
json.Unmarshal([]byte(tt.wantJSON), &wantJSON)
|
||||
assert.Equal(t, wantJSON, gotJSON)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/alibaba/higress/registry/reconcile"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
|
||||
@@ -237,6 +238,9 @@ func (t *TracingController) RegisterItemEventHandler(eventHandler ItemEventHandl
|
||||
t.eventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (t *TracingController) RegisterMcpReconciler(reconciler *reconcile.Reconciler) {
|
||||
}
|
||||
|
||||
func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
configs := make([]*config.Config, 0)
|
||||
tracing := t.GetTracing()
|
||||
@@ -255,6 +259,59 @@ func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
configPatches := []*networking.EnvoyFilter_EnvoyConfigObjectPatch{
|
||||
{
|
||||
ApplyTo: networking.EnvoyFilter_NETWORK_FILTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
|
||||
Listener: &networking.EnvoyFilter_ListenerMatch{
|
||||
FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
|
||||
Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
|
||||
Name: "envoy.filters.network.http_connection_manager",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_MERGE,
|
||||
Value: util.BuildPatchStruct(tracingConfig),
|
||||
},
|
||||
},
|
||||
{
|
||||
ApplyTo: networking.EnvoyFilter_HTTP_FILTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
|
||||
Listener: &networking.EnvoyFilter_ListenerMatch{
|
||||
FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
|
||||
Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
|
||||
Name: "envoy.filters.network.http_connection_manager",
|
||||
SubFilter: &networking.EnvoyFilter_ListenerMatch_SubFilterMatch{
|
||||
Name: "envoy.filters.http.router",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_MERGE,
|
||||
Value: util.BuildPatchStruct(`{
|
||||
"name":"envoy.filters.http.router",
|
||||
"typed_config":{
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router",
|
||||
"start_child_span": true
|
||||
}
|
||||
}`),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
patches := t.constructTracingExtendPatches(tracing)
|
||||
configPatches = append(configPatches, patches...)
|
||||
|
||||
config := &config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.EnvoyFilter,
|
||||
@@ -262,55 +319,7 @@ func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: &networking.EnvoyFilter{
|
||||
ConfigPatches: []*networking.EnvoyFilter_EnvoyConfigObjectPatch{
|
||||
{
|
||||
ApplyTo: networking.EnvoyFilter_NETWORK_FILTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
|
||||
Listener: &networking.EnvoyFilter_ListenerMatch{
|
||||
FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
|
||||
Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
|
||||
Name: "envoy.filters.network.http_connection_manager",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_MERGE,
|
||||
Value: util.BuildPatchStruct(tracingConfig),
|
||||
},
|
||||
},
|
||||
{
|
||||
ApplyTo: networking.EnvoyFilter_HTTP_FILTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
|
||||
Listener: &networking.EnvoyFilter_ListenerMatch{
|
||||
FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
|
||||
Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
|
||||
Name: "envoy.filters.network.http_connection_manager",
|
||||
SubFilter: &networking.EnvoyFilter_ListenerMatch_SubFilterMatch{
|
||||
Name: "envoy.filters.http.router",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_MERGE,
|
||||
Value: util.BuildPatchStruct(`{
|
||||
"name":"envoy.filters.http.router",
|
||||
"typed_config":{
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router",
|
||||
"start_child_span": true
|
||||
}
|
||||
}`),
|
||||
},
|
||||
},
|
||||
},
|
||||
ConfigPatches: configPatches,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -318,6 +327,52 @@ func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
func tracingClusterName(port, service string) string {
|
||||
return fmt.Sprintf("outbound|%s||%s", port, service)
|
||||
}
|
||||
|
||||
func (t *TracingController) constructHTTP2ProtocolOptionsPatch(port, service string) *networking.EnvoyFilter_EnvoyConfigObjectPatch {
|
||||
http2ProtocolOptions := `{"typed_extension_protocol_options": {
|
||||
"envoy.extensions.upstreams.http.v3.HttpProtocolOptions": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions",
|
||||
"explicit_http_config": {
|
||||
"http2_protocol_options": {}
|
||||
}
|
||||
}
|
||||
}}`
|
||||
|
||||
return &networking.EnvoyFilter_EnvoyConfigObjectPatch{
|
||||
ApplyTo: networking.EnvoyFilter_CLUSTER,
|
||||
Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
|
||||
Context: networking.EnvoyFilter_GATEWAY,
|
||||
ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Cluster{
|
||||
Cluster: &networking.EnvoyFilter_ClusterMatch{
|
||||
Name: tracingClusterName(port, service),
|
||||
},
|
||||
},
|
||||
},
|
||||
Patch: &networking.EnvoyFilter_Patch{
|
||||
Operation: networking.EnvoyFilter_Patch_MERGE,
|
||||
Value: util.BuildPatchStruct(http2ProtocolOptions),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TracingController) constructTracingExtendPatches(tracing *Tracing) []*networking.EnvoyFilter_EnvoyConfigObjectPatch {
|
||||
if tracing == nil {
|
||||
return nil
|
||||
}
|
||||
var patches []*networking.EnvoyFilter_EnvoyConfigObjectPatch
|
||||
if skywalking := tracing.Skywalking; skywalking != nil {
|
||||
patches = append(patches, t.constructHTTP2ProtocolOptionsPatch(skywalking.Port, skywalking.Service))
|
||||
}
|
||||
if otel := tracing.OpenTelemetry; otel != nil {
|
||||
patches = append(patches, t.constructHTTP2ProtocolOptionsPatch(otel.Port, otel.Service))
|
||||
}
|
||||
|
||||
return patches
|
||||
}
|
||||
|
||||
func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace string) string {
|
||||
tracingConfig := ""
|
||||
timeout := float32(tracing.Timeout) / 1000
|
||||
@@ -338,7 +393,7 @@ func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace s
|
||||
},
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "outbound|%s||%s"
|
||||
"cluster_name": "%s"
|
||||
},
|
||||
"timeout": "%.3fs"
|
||||
}
|
||||
@@ -349,7 +404,7 @@ func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace s
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, namespace, skywalking.AccessToken, skywalking.Port, skywalking.Service, timeout, tracing.Sampling)
|
||||
}`, namespace, skywalking.AccessToken, tracingClusterName(skywalking.Port, skywalking.Service), timeout, tracing.Sampling)
|
||||
}
|
||||
|
||||
if tracing.Zipkin != nil {
|
||||
@@ -363,7 +418,7 @@ func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace s
|
||||
"name": "envoy.tracers.zipkin",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
|
||||
"collector_cluster": "outbound|%s||%s",
|
||||
"collector_cluster": "%s",
|
||||
"collector_endpoint": "/api/v2/spans",
|
||||
"collector_hostname": "higress-gateway",
|
||||
"collector_endpoint_version": "HTTP_JSON",
|
||||
@@ -375,7 +430,7 @@ func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace s
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, zipkin.Port, zipkin.Service, tracing.Sampling)
|
||||
}`, tracingClusterName(zipkin.Port, zipkin.Service), tracing.Sampling)
|
||||
}
|
||||
|
||||
if tracing.OpenTelemetry != nil {
|
||||
@@ -392,7 +447,7 @@ func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace s
|
||||
"service_name": "higress-gateway.%s",
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "outbound|%s||%s"
|
||||
"cluster_name": "%s"
|
||||
},
|
||||
"timeout": "%.3fs"
|
||||
}
|
||||
@@ -403,7 +458,7 @@ func (t *TracingController) constructTracingTracer(tracing *Tracing, namespace s
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, namespace, opentelemetry.Port, opentelemetry.Service, timeout, tracing.Sampling)
|
||||
}`, namespace, tracingClusterName(opentelemetry.Port, opentelemetry.Service), timeout, tracing.Sampling)
|
||||
}
|
||||
return tracingConfig
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"strings"
|
||||
|
||||
higressconfig "github.com/alibaba/higress/pkg/config"
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/util"
|
||||
istio "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pilot/pkg/features"
|
||||
"istio.io/istio/pilot/pkg/model"
|
||||
@@ -1880,7 +1881,7 @@ func extractGatewayServices(r GatewayResources, kgw *k8s.GatewaySpec, obj config
|
||||
if len(name) > 0 {
|
||||
return []string{fmt.Sprintf("%s.%s.svc.%v", name, obj.Namespace, r.Domain)}, false, nil
|
||||
}
|
||||
return []string{}, true, nil
|
||||
return []string{fmt.Sprintf("%s.%s.svc.%s", higressconfig.GatewayName, higressconfig.PodNamespace, util.GetDomainSuffix())}, true, nil
|
||||
}
|
||||
gatewayServices := []string{}
|
||||
skippedAddresses := []string{}
|
||||
|
||||
@@ -919,7 +919,7 @@ func TestExtractGatewayServices(t *testing.T) {
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
gatewayServices: []string{},
|
||||
gatewayServices: []string{"higress-gateway.higress-system.svc.cluster.local"},
|
||||
useDefaultService: true,
|
||||
},
|
||||
{
|
||||
@@ -1039,7 +1039,7 @@ func TestExtractGatewayServices(t *testing.T) {
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
gatewayServices: []string{},
|
||||
gatewayServices: []string{"higress-gateway.higress-system.svc.cluster.local"},
|
||||
useDefaultService: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -15,21 +15,33 @@
|
||||
package http2rpc
|
||||
|
||||
import (
|
||||
"istio.io/istio/pkg/cluster"
|
||||
"time"
|
||||
|
||||
"istio.io/istio/pkg/kube/controllers"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
v1 "github.com/alibaba/higress/client/pkg/apis/networking/v1"
|
||||
"github.com/alibaba/higress/client/pkg/clientset/versioned"
|
||||
informersv1 "github.com/alibaba/higress/client/pkg/informers/externalversions/networking/v1"
|
||||
listersv1 "github.com/alibaba/higress/client/pkg/listers/networking/v1"
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/common"
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/controller"
|
||||
kubeclient "github.com/alibaba/higress/pkg/kube"
|
||||
)
|
||||
|
||||
type Http2RpcController controller.Controller[listersv1.Http2RpcLister]
|
||||
|
||||
func NewController(client kubeclient.Client, clusterId cluster.ID) Http2RpcController {
|
||||
informer := client.HigressInformer().Networking().V1().Http2Rpcs().Informer()
|
||||
return controller.NewCommonController("http2rpc", client.HigressInformer().Networking().V1().Http2Rpcs().Lister(),
|
||||
informer, GetHttp2Rpc, clusterId)
|
||||
func NewController(client kubeclient.Client, options common.Options) Http2RpcController {
|
||||
var informer cache.SharedIndexInformer
|
||||
if options.WatchNamespace == "" {
|
||||
informer = client.HigressInformer().Networking().V1().Http2Rpcs().Informer()
|
||||
} else {
|
||||
informer = client.HigressInformer().InformerFor(&v1.Http2Rpc{}, func(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return informersv1.NewHttp2RpcInformer(client, options.WatchNamespace, resyncPeriod, nil)
|
||||
})
|
||||
}
|
||||
return controller.NewCommonController("http2rpc", listersv1.NewHttp2RpcLister(informer.GetIndexer()), informer, GetHttp2Rpc, options.ClusterId)
|
||||
}
|
||||
|
||||
func GetHttp2Rpc(lister listersv1.Http2RpcLister, namespacedName types.NamespacedName) (controllers.Object, error) {
|
||||
|
||||
@@ -100,7 +100,7 @@ type controller struct {
|
||||
// NewController creates a new Kubernetes controller
|
||||
func NewController(localKubeClient, client kubeclient.Client, options common.Options,
|
||||
secretController secret.SecretController) common.IngressController {
|
||||
opts := ktypes.InformerOptions{}
|
||||
opts := ktypes.InformerOptions{Namespace: options.WatchNamespace}
|
||||
ingressInformer := util.GetInformerFiltered(client, opts, gvrIngressV1Beta1, &ingress.Ingress{},
|
||||
func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return client.Kube().NetworkingV1beta1().Ingresses(opts.Namespace).List(context.Background(), options)
|
||||
|
||||
@@ -54,7 +54,7 @@ func TestIngressControllerApplies(t *testing.T) {
|
||||
|
||||
options := common.Options{IngressClass: "mse", ClusterId: ""}
|
||||
|
||||
secretController := secret.NewController(localKubeClient, options.ClusterId)
|
||||
secretController := secret.NewController(localKubeClient, options)
|
||||
ingressController := NewController(localKubeClient, client, options, secretController)
|
||||
|
||||
testcases := map[string]func(*testing.T, common.IngressController){
|
||||
@@ -253,7 +253,7 @@ func TestIngressControllerConventions(t *testing.T) {
|
||||
|
||||
options := common.Options{IngressClass: "mse", ClusterId: "", EnableStatus: true}
|
||||
|
||||
secretController := secret.NewController(localKubeClient, options.ClusterId)
|
||||
secretController := secret.NewController(localKubeClient, options)
|
||||
ingressController := NewController(localKubeClient, client, options, secretController)
|
||||
|
||||
testcases := map[string]func(*testing.T, common.IngressController){
|
||||
@@ -1142,7 +1142,7 @@ func TestIngressControllerProcessing(t *testing.T) {
|
||||
|
||||
options := common.Options{IngressClass: "mse", ClusterId: "", EnableStatus: true}
|
||||
|
||||
secretController := secret.NewController(localKubeClient, options.ClusterId)
|
||||
secretController := secret.NewController(localKubeClient, options)
|
||||
|
||||
opts := ktypes.InformerOptions{}
|
||||
ingressInformer := util.GetInformerFiltered(fakeClient, opts, gvrIngressV1Beta1, &ingress.Ingress{},
|
||||
|
||||
@@ -81,8 +81,6 @@ func (s *statusSyncer) runUpdateStatus() error {
|
||||
return err
|
||||
}
|
||||
|
||||
IngressLog.Debugf("found number %d of svc", len(svcList))
|
||||
|
||||
lbStatusList := common.GetLbStatusListV1Beta1(svcList)
|
||||
if len(lbStatusList) == 0 {
|
||||
return nil
|
||||
|
||||
@@ -92,7 +92,7 @@ type controller struct {
|
||||
|
||||
// NewController creates a new Kubernetes controller
|
||||
func NewController(localKubeClient, client kubeclient.Client, options common.Options, secretController secret.SecretController) common.IngressController {
|
||||
opts := ktypes.InformerOptions{}
|
||||
opts := ktypes.InformerOptions{Namespace: options.WatchNamespace}
|
||||
ingressInformer := schemakubeclient.GetInformerFilteredFromGVR(client, opts, gvr.Ingress)
|
||||
ingressLister := networkinglister.NewIngressLister(ingressInformer.Informer.GetIndexer())
|
||||
serviceInformer := schemakubeclient.GetInformerFilteredFromGVR(client, opts, gvr.Service)
|
||||
@@ -162,6 +162,7 @@ func (c *controller) onEvent(namespacedName types.NamespacedName) error {
|
||||
delete(c.ingresses, namespacedName.String())
|
||||
c.mutex.Unlock()
|
||||
} else {
|
||||
IngressLog.Warnf("ingressLister Get failed, ingress: %s, err: %v", namespacedName, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -171,7 +172,7 @@ func (c *controller) onEvent(namespacedName types.NamespacedName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
IngressLog.Debugf("ingress: %s, event: %s", namespacedName, event)
|
||||
IngressLog.Infof("ingress: %s, event: %s", namespacedName, event)
|
||||
|
||||
// we should check need process only when event is not delete,
|
||||
// if it is delete event, and previously processed, we need to process too.
|
||||
@@ -181,7 +182,7 @@ func (c *controller) onEvent(namespacedName types.NamespacedName) error {
|
||||
return err
|
||||
}
|
||||
if !shouldProcess {
|
||||
IngressLog.Infof("no need process, ingress %s", namespacedName)
|
||||
IngressLog.Infof("no need process, ingress: %s", namespacedName)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -279,10 +280,17 @@ func (c *controller) List() []config.Config {
|
||||
for _, raw := range c.ingressInformer.Informer.GetStore().List() {
|
||||
ing, ok := raw.(*ingress.Ingress)
|
||||
if !ok {
|
||||
IngressLog.Warnf("get ingress from informer failed: %v", raw)
|
||||
continue
|
||||
}
|
||||
|
||||
if should, err := c.shouldProcessIngress(ing); !should || err != nil {
|
||||
should, err := c.shouldProcessIngress(ing)
|
||||
if err != nil {
|
||||
IngressLog.Warnf("check should process ingress failed: %v", err)
|
||||
continue
|
||||
}
|
||||
if !should {
|
||||
IngressLog.Debugf("no need process ingress: %s/%s", ing.Namespace, ing.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -81,8 +81,6 @@ func (s *statusSyncer) runUpdateStatus() error {
|
||||
return err
|
||||
}
|
||||
|
||||
IngressLog.Debugf("found number %d of svc", len(svcList))
|
||||
|
||||
lbStatusList := common.GetLbStatusListV1(svcList)
|
||||
if len(lbStatusList) == 0 {
|
||||
return nil
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
@@ -43,7 +44,9 @@ import (
|
||||
listerv1 "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
ingress "knative.dev/networking/pkg/apis/networking/v1alpha1"
|
||||
networkingv1alpha1 "knative.dev/networking/pkg/client/listers/networking/v1alpha1"
|
||||
"knative.dev/networking/pkg/client/clientset/versioned"
|
||||
informernetworkingv1alpha1 "knative.dev/networking/pkg/client/informers/externalversions/networking/v1alpha1"
|
||||
listernetworkingv1alpha1 "knative.dev/networking/pkg/client/listers/networking/v1alpha1"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/annotations"
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/common"
|
||||
@@ -76,7 +79,7 @@ type controller struct {
|
||||
ingresses map[string]*ingress.Ingress
|
||||
|
||||
ingressInformer cache.SharedInformer
|
||||
ingressLister networkingv1alpha1.IngressLister
|
||||
ingressLister listernetworkingv1alpha1.IngressLister
|
||||
serviceInformer informerfactory.StartableInformer
|
||||
serviceLister listerv1.ServiceLister
|
||||
secretController secret.SecretController
|
||||
@@ -86,16 +89,23 @@ type controller struct {
|
||||
// NewController creates a new Kubernetes controller
|
||||
func NewController(localKubeClient, client kube.Client, options common.Options,
|
||||
secretController secret.SecretController) common.KIngressController {
|
||||
//var namespace string = "default"
|
||||
ingressInformer := client.KIngressInformer().Networking().V1alpha1().Ingresses()
|
||||
serviceInformer := schemakubeclient.GetInformerFilteredFromGVR(client, ktypes.InformerOptions{}, gvr.Service)
|
||||
var ingressInformer cache.SharedIndexInformer
|
||||
if options.WatchNamespace == "" {
|
||||
ingressInformer = client.KIngressInformer().Networking().V1alpha1().Ingresses().Informer()
|
||||
} else {
|
||||
ingressInformer = client.KIngressInformer().InformerFor(&ingress.Ingress{}, func(c versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return informernetworkingv1alpha1.NewIngressInformer(c, options.WatchNamespace, resyncPeriod, nil)
|
||||
})
|
||||
}
|
||||
ingressLister := listernetworkingv1alpha1.NewIngressLister(ingressInformer.GetIndexer())
|
||||
serviceInformer := schemakubeclient.GetInformerFilteredFromGVR(client, ktypes.InformerOptions{Namespace: options.WatchNamespace}, gvr.Service)
|
||||
serviceLister := listerv1.NewServiceLister(serviceInformer.Informer.GetIndexer())
|
||||
|
||||
c := &controller{
|
||||
options: options,
|
||||
ingresses: make(map[string]*ingress.Ingress),
|
||||
ingressInformer: ingressInformer.Informer(),
|
||||
ingressLister: ingressInformer.Lister(),
|
||||
ingressInformer: ingressInformer,
|
||||
ingressLister: ingressLister,
|
||||
serviceInformer: serviceInformer,
|
||||
serviceLister: serviceLister,
|
||||
secretController: secretController,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user