Compare commits

...

32 Commits

Author SHA1 Message Date
澄潭
a771f59422 release 0.6.1 (#158) 2023-02-03 16:47:25 +08:00
澄潭
19570ea100 add wasi stub patch (#157) 2023-02-02 16:37:13 +08:00
charlie
7ceec94a87 unit-test: add unit test for pkg/ingress/kube/annotations (#156)
Signed-off-by: charlie <qianglin98@qq.com>
2023-02-02 15:22:11 +08:00
Yang
1092402516 Default set ingress class as higress and enable ingress status. (#155) 2023-02-02 15:18:04 +08:00
charlie
5ae9151d37 opt: optimize redundant code (#103)
Signed-off-by: charlie <qianglin98@qq.com>
2023-02-01 16:40:07 +08:00
charlie
6c6cb0a8f3 ut: add unit test for pkg/ingress/mcp (#104)
Signed-off-by: charlie <qianglin98@qq.com>
2023-02-01 14:48:30 +08:00
Xunzhuo
9c135e05e7 feat: add more coverages to ingressController (#147)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-02-01 14:45:51 +08:00
chen zhang
e15f77e029 docs: translate the document of bot-detect plugin to English. (#153) 2023-02-01 10:52:53 +08:00
Kent Dong
146b0a5135 Fix incorrect links and branch names in the CONTRIBUTING document. (#151) 2023-01-31 11:00:52 +08:00
Kent Dong
a5ef4cd482 docs: translate the document of request block plugin to English. (#150) 2023-01-31 10:13:04 +08:00
Asher Liu
c8d84a0ad5 unit-test: increase coverage, path: pkg/ingress/kube/secret (#105)
Signed-off-by: iutx <root@viper.run>
2023-01-29 17:43:42 +08:00
澄潭
4cd7975295 adjust wasm plugin doc (#146) 2023-01-28 19:58:56 +08:00
Kent Dong
059f4c682e docs: translate the document of custom response plugin to English. (#144) 2023-01-27 19:31:26 +08:00
Xunzhuo
f262883611 chore: some clean-up to e2e tests (#143)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-26 15:31:59 +08:00
Kent Dong
4fb9efe3bf Improve the UT coverage of cmd/higress. (#142) 2023-01-23 16:35:41 +08:00
罗泽轩
9593cb7340 docs: update higress version (#141)
Signed-off-by: spacewander <spacewanderlzx@gmail.com>
2023-01-23 14:27:58 +08:00
澄潭
b16d5a4d8d Support switching between mesh mode on or off (#140) 2023-01-19 16:29:01 +08:00
澄潭
a58c005dab support simple install without istio (#139) 2023-01-19 09:54:50 +08:00
Xunzhuo
41f66a7e8b feat: add support for ingress e2e test framework (#133)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-18 17:36:10 +08:00
澄潭
d40a7c1f34 Support wasm api (#129) 2023-01-18 14:56:51 +08:00
gczz2022
2133c273e9 opt: remove redundant registration code (#128) 2023-01-18 14:43:44 +08:00
Xunzhuo
20ddb3393a feat: use echoserver to demonstrate ingress abilities (#132)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-18 14:43:16 +08:00
Xunzhuo
a3658ed9b5 chore: just schedule codeQL (#130)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-18 13:52:33 +08:00
Xunzhuo
b410fc96e3 feat: add lint/e2e tests support (#126)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-18 10:14:22 +08:00
Xunzhuo
0bf395a423 feat: init build-and-test workflows (#124)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-17 13:56:48 +08:00
Xunzhuo
7c5542802b chore: add more target to clean (#123)
Signed-off-by: bitliu <bitliu@tencent.com>
2023-01-17 10:51:37 +08:00
charlie
616b37a268 UT: Increase unit test coverage of pkg/bootstrap (#101)
Signed-off-by: charlie <qianglin98@qq.com>
2023-01-14 14:50:15 +08:00
澄潭
926f858a13 support multi destination (#119) 2023-01-12 11:20:24 +08:00
Kent Dong
46487905a2 Add English translation of the key_rate_limit extension. (#118) 2023-01-11 11:06:32 +08:00
澄潭
ad4fbf2c54 Update README.md 2023-01-09 10:19:02 +08:00
澄潭
4a69d9e605 support xds auth (#117) 2023-01-04 17:52:07 +08:00
澄潭
79c894373c Support sidecar inject (#114) 2022-12-21 15:22:22 +08:00
169 changed files with 15544 additions and 507 deletions

82
.github/workflows/build-and-test.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: "Build and Test"
on:
push:
branches: [ main ]
pull_request:
branches: ["*"]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.19
# There are too many lint errors in current code bases
# uncomment when we decide what lint should be addressed or ignored.
# - run: make lint
coverage-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# test
- name: Run Coverage Tests
run: GOPROXY="https://proxy.golang.org,direct" make go.test.coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
files: ./coverage.xml
verbose: true
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
needs: [lint,coverage-test]
steps:
- name: "Setup Go"
uses: actions/setup-go@v3
with:
go-version: 1.19
- name: "checkout ${{ github.ref }}"
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: "Build Higress Binary"
run: GOPROXY="https://proxy.golang.org,direct" make build
- name: Upload Higress Binary
uses: actions/upload-artifact@v3
with:
name: higress
path: out/
gateway-conformance-test:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v3
ingress-conformance-test:
runs-on: ubuntu-latest
needs: [build]
steps:
- name: "Setup Go"
uses: actions/setup-go@v3
with:
go-version: 1.19
- uses: actions/checkout@v3
- name: "Run Ingress Conformance Tests"
run: GOPROXY="https://proxy.golang.org,direct" make ingress-conformance-test
publish:
runs-on: ubuntu-latest
needs: [ingress-conformance-test,gateway-conformance-test]
steps:
- uses: actions/checkout@v3

View File

@@ -1,36 +0,0 @@
name: "build and codecov"
on:
push:
branches: [ main ]
pull_request:
branches: ["*"]
jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
strategy:
matrix:
golang:
- 1.19
steps:
- name: "set up go"
uses: actions/setup-go@v3
with:
go-version: 1.19
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: "checkout ${{ github.ref }}"
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: "run go build"
run: GOPROXY="https://proxy.golang.org,direct" make build
- name: "run go test and out codecov"
run: make prebuild; go test ./cmd/... ./pkg/... -race -coverprofile=coverage.out -covermode=atomic
- name: "upload coverage"
uses: codecov/codecov-action@v3

View File

@@ -12,11 +12,6 @@
name: "CodeQL"
on:
push:
branches: [ develop, main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '36 19 * * 6'

5
.gitignore vendored
View File

@@ -3,8 +3,11 @@ out
*.out
*.tgz
*.wasm
.DS_Store
coverage.xml
.idea/
bazel-bin
bazel-out
bazel-testlogs
bazel-wasm-cpp
bazel-wasm-cpp
tools/bin/

View File

@@ -23,6 +23,9 @@ header:
- '.gitmodules'
- 'plugins/**'
- 'CODEOWNERS'
- 'VERSION'
- 'tools/'
- 'test/README.md'
comment: on-failure
dependency:

View File

@@ -6,12 +6,20 @@
## 话题
* [报告安全问题](#报告安全问题)
* [报告一般问](#报告一般问)
* [代码和文档贡献](#代码和文档贡献)
* [测试用例贡献](#测试用例贡献)
* [参与帮助任何事情](#参与帮助任何事情)
* [代码风格](#代码风格)
- [为 Higress 做贡献](#为-higress-做贡献)
- [](#)
- [报告安全问题](#报告安全问题)
- [报告一般问题](#报告一般问题)
- [代码和文档贡献](#代码和文档贡献)
- [工作区准备](#工作区准备)
- [分支定义](#分支定义)
- [提交规则](#提交规则)
- [提交消息](#提交消息)
- [提交内容](#提交内容)
- [PR说明](#pr说明)
- [测试用例贡献](#测试用例贡献)
- [参与帮助任何事情](#参与帮助任何事情)
- [代码风格](#代码风格)
## 报告安全问题
@@ -96,15 +104,15 @@ upstream no-pushing (push)
### 分支定义
现在我们假设通过拉取请求的每个贡献都是针对Higress 中的 [开发分支](https://github.com/alibaba/higress/tree/develop) 。在贡献之前,请注意分支定义会很有帮助。
现在我们假设通过拉取请求的每个贡献都是针对 Higress 中的 [分支](https://github.com/alibaba/higress/tree/main) 。在贡献之前,请注意分支定义会很有帮助。
作为贡献者,请再次记住,通过拉取请求的每个贡献都是针对分支开发的。而在Higress项目中还有其他几个分支我们一般称它们为release分支如0.6.0、0.6.1、feature分支、hotfix分支和master分支
作为贡献者,请再次记住,通过拉取请求的每个贡献都是针对分支的。而在Higress项目中还有其他几个分支我们一般称它们为release分支如0.6.0、0.6.1、feature分支、hotfix分支。
当正式发布一个版本时,会有一个发布分支并以版本号命名。
在发布之后,我们会将发布分支的提交合并到主分支中。
当我们发现某个版本有bug时我们会决定在以后的版本中修复它或者在特定的hotfix版本中修复它。当我们决定修复hotfix版本时我们会根据对应的release分支checkout hotfix分支进行代码修复和验证合并到develop分支和master分支。
当我们发现某个版本有bug时我们会决定在以后的版本中修复它或者在特定的hotfix版本中修复它。当我们决定修复hotfix版本时我们会根据对应的release分支checkout hotfix分支进行代码修复和验证合并到分支。
对于较大的功能,我们将拉出功能分支进行开发和验证。

View File

@@ -6,12 +6,20 @@ It is warmly welcomed if you have interest to hack on Higress. First, we encoura
## Topics
* [Reporting security issues](#reporting-security-issues)
* [Reporting general issues](#reporting-general-issues)
* [Code and doc contribution](#code-and-doc-contribution)
* [Test case contribution](#test-case-contribution)
* [Engage to help anything](#engage-to-help-anything)
* [Code Style](#code-style)
- [Contributing to Higress](#contributing-to-higress)
- [Topics](#topics)
- [Reporting security issues](#reporting-security-issues)
- [Reporting general issues](#reporting-general-issues)
- [Code and doc contribution](#code-and-doc-contribution)
- [Workspace Preparation](#workspace-preparation)
- [Branch Definition](#branch-definition)
- [Commit Rules](#commit-rules)
- [Commit Message](#commit-message)
- [Commit Content](#commit-content)
- [PR Description](#pr-description)
- [Test case contribution](#test-case-contribution)
- [Engage to help anything](#engage-to-help-anything)
- [Code Style](#code-style)
## Reporting security issues
@@ -98,15 +106,15 @@ Adding this, we can easily synchronize local branches with upstream branches.
### Branch Definition
Right now we assume every contribution via pull request is for [branch develop](https://github.com/alibaba/higress/tree/develop) in Higress. Before contributing, be aware of branch definition would help a lot.
Right now we assume every contribution via pull request is for [branch main](https://github.com/alibaba/higress/tree/main) in Higress. Before contributing, be aware of branch definition would help a lot.
As a contributor, keep in mind again that every contribution via pull request is for branch develop. While in project Higress, there are several other branches, we generally call them release branches(such as 0.6.0,0.6.1), feature branches, hotfix branches and master branch.
As a contributor, keep in mind again that every contribution via pull request is for branch main. While in project Higress, there are several other branches, we generally call them release branches (such as 0.6.0,0.6.1), feature branches, hotfix branches.
When officially releasing a version, there will be a release branch and named with the version number.
After the release, we will merge the commit of the release branch into the master branch.
After the release, we will merge the commit of the release branch into the main branch.
When we find that there is a bug in a certain version, we will decide to fix it in a later version or fix it in a specific hotfix version. When we decide to fix the hotfix version, we will checkout the hotfix branch based on the corresponding release branch, perform code repair and verification, and merge it into the develop branch and the master branch.
When we find that there is a bug in a certain version, we will decide to fix it in a later version or fix it in a specific hotfix version. When we decide to fix the hotfix version, we will checkout the hotfix branch based on the corresponding release branch, perform code repair and verification, and merge it into the main branch.
For larger features, we will pull out the feature branch for development and verification.

View File

@@ -36,9 +36,9 @@ ifeq ($(BUILD_WITH_CONTAINER),1)
# environment. This is needed to allow overrides from Makefile.overrides.mk.
export
$(shell $(shell pwd)/script/setup_env.sh)
$(shell $(shell pwd)/tools/hack/setup_env.sh)
RUN = ./script/run.sh
RUN = ./tools/hack/run.sh
MAKE_DOCKER = $(RUN) make --no-print-directory -e -f Makefile.core.mk
@@ -58,7 +58,7 @@ else
# If we are not in build container, we need a workaround to get environment properly set
# Write to file, then include
$(shell mkdir -p out)
$(shell $(shell pwd)/script/setup_env.sh envfile > out/.env)
$(shell $(shell pwd)/tools/hack/setup_env.sh envfile > out/.env)
include out/.env
# An export free of arugments in a Makefile places all variables in the Makefile into the
# environment. This behavior may be surprising to many that use shell often, which simply

View File

@@ -41,18 +41,22 @@ submodule:
git submodule update --init
prebuild: submodule
./script/prebuild.sh
./tools/hack/prebuild.sh
.PHONY: default
default: build
.PHONY: go.test.coverage
go.test.coverage: prebuild
go test ./cmd/... ./pkg/... -race -coverprofile=coverage.xml -covermode=atomic
.PHONY: build
build: prebuild $(OUT)
GOPROXY=$(GOPROXY) GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) script/gobuild.sh $(OUT)/ $(BINARIES)
GOPROXY=$(GOPROXY) GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT)/ $(BINARIES)
.PHONY: build-linux
build-linux: prebuild $(OUT)
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) script/gobuild.sh $(OUT_LINUX)/ $(BINARIES)
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ $(BINARIES)
# Create targets for OUT_LINUX/binary
# There are two use cases here:
@@ -65,7 +69,7 @@ ifeq ($(BUILD_ALL),true)
$(OUT_LINUX)/$(shell basename $(1)): build-linux
else
$(OUT_LINUX)/$(shell basename $(1)): $(OUT_LINUX)
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) script/gobuild.sh $(OUT_LINUX)/ -tags=$(2) $(1)
GOPROXY=$(GOPROXY) GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) tools/hack/gobuild.sh $(OUT_LINUX)/ -tags=$(2) $(1)
endif
endef
@@ -86,7 +90,7 @@ include docker/docker.mk
docker-build: docker.higress ## Build and push docker images to registry defined by $HUB and $TAG
export PARENT_GIT_TAG:=$(shell git describe --tags)
export PARENT_GIT_TAG:=$(shell cat VERSION)
export PARENT_GIT_REVISION:=$(TAG)
export ENVOY_TAR_PATH:=/home/package/envoy.tar.gz
@@ -111,13 +115,18 @@ define create_ns
endef
install: pre-install
$(call create_ns,istio-system)
$(call create_ns,higress-system)
helm install istio helm/kind/istio -n istio-system
helm install higress helm/kind/higress -n higress-system
helm install higress helm/kind/higress -n higress-system --create-namespace
ENVOY_LATEST_IMAGE_TAG ?= 0.6.0
ISTIO_LATEST_IMAGE_TAG ?= 0.6.0
install-dev: pre-install
helm install higress helm/higress -n higress-system --create-namespace --set-json='controller.tag="$(TAG)"' --set-json='gateway.replicas=1' --set-json='gateway.tag="$(ENVOY_LATEST_IMAGE_TAG)"' --set-json='global.kind=true'
uninstall:
helm uninstall higress -n higress-system
upgrade: pre-install
helm upgrade istio helm/kind/istio -n istio-system
helm upgrade higress helm/kind/higress -n higress-system
helm-push:
@@ -154,6 +163,48 @@ clean-istio:
clean-gateway: clean-istio
rm -rf external/envoy
rm -rf external/proxy
rm external/package/envoy.tar.gz
rm -rf external/package/envoy.tar.gz
clean: clean-higress clean-gateway
clean-env:
rm -rf out/
clean-tool:
rm -rf tools/bin
clean: clean-higress clean-gateway clean-istio clean-env clean-tool
include tools/tools.mk
include tools/lint.mk
# gateway-conformance-test runs gateway api conformance tests.
.PHONY: gateway-conformance-test
gateway-conformance-test:
# ingress-conformance-test runs ingress api conformance tests.
.PHONY: ingress-conformance-test
ingress-conformance-test: $(tools/kind) delete-cluster create-cluster kube-load-image install-dev run-ingress-e2e-test delete-cluster
# create-cluster creates a kube cluster with kind.
.PHONY: create-cluster
create-cluster: $(tools/kind)
tools/hack/create-cluster.sh
# delete-cluster deletes a kube cluster.
.PHONY: delete-cluster
delete-cluster: $(tools/kind) ## Delete kind cluster.
$(tools/kind) delete cluster --name higress
# kube-load-image loads a local built docker image into kube cluster.
.PHONY: kube-load-image
kube-load-image: docker-build $(tools/kind) ## Install the EG 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)
# run-ingress-e2e-test starts to run ingress e2e tests.
.PHONY: run-ingress-e2e-test
run-ingress-e2e-test:
@echo -e "\n\033[36mRunning higress conformance tests...\033[0m"
@echo -e "\n\033[36mWaiting higress-controller to be ready...\033[0m\n"
kubectl wait --timeout=5m -n higress-system deployment/higress-controller --for=condition=Available
@echo -e "\n\033[36mWaiting higress-gateway to be ready...\033[0m\n"
kubectl wait --timeout=5m -n higress-system deployment/higress-gateway --for=condition=Available
go test -v -tags conformance ./test/ingress/e2e_test.go --ingress-class=higress --debug=true --use-unique-ports=true

View File

@@ -151,11 +151,9 @@ kind.exe create cluster --name higress --config=cluster.conf
kubectl.exe config use-context kind-higress
```
#### 第三步、 安装 istio & higress
#### 第三步、 安装 higress
```bash
kubectl create ns istio-system
helm install istio -n istio-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/istio-local
kubectl create ns higress-system
helm install higress -n higress-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/higress-local
```
@@ -165,7 +163,7 @@ helm install higress -n higress-system oci://higress-registry.cn-hangzhou.cr.ali
#### 第四步、 创建 Ingress 资源并测试
```bash
kubectl apply -f https://github.com/alibaba/higress/releases/download/v0.5.2/quickstart.yaml
kubectl apply -f https://github.com/alibaba/higress/releases/download/v0.6.0/quickstart.yaml
```
测试 Ingress 生效:
@@ -180,40 +178,23 @@ curl localhost/bar
#### 卸载资源
```bash
kubectl delete -f https://github.com/alibaba/higress/releases/download/v0.5.2/quickstart.yaml
helm uninstall istio -n istio-system
kubectl delete -f https://github.com/alibaba/higress/releases/download/v0.6.0/quickstart.yaml
helm uninstall higress -n higress-system
kubectl delete ns istio-system
kubectl delete ns higress-system
```
### 生产环境
#### 第一步、 安装 istio
可以选择安装 higress 发行的 istio 版本:
```bash
kubectl create ns istio-system
helm install istio -n istio-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/istio
```
或者选择安装官方 istio 版本 (将失去部分能力,例如通过 Ingress 注解实现限流的功能):
https://istio.io/latest/docs/setup/install
#### 第二步、 安装 higress
#### 第一步、 安装 higress
```bash
kubectl create ns higress-system
helm install higress -n higress-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/higress
```
#### 第步、 创建 Ingress 资源并测试
#### 第步、 创建 Ingress 资源并测试
假设在 default 命名空间下已经部署了一个 test service服务端口为 80 ,则创建下面这个 K8s Ingress
@@ -223,6 +204,7 @@ kind: Ingress
metadata:
name: simple-example
spec:
ingressClassName: higress
rules:
- host: foo.bar.com
http:
@@ -245,12 +227,8 @@ curl "$(k get svc -n higress-system higress-gateway -o jsonpath='{.status.loadBa
#### 卸载资源
```bash
helm uninstall istio -n istio-system
helm uninstall higress -n higress-system
kubectl delete ns istio-system
kubectl delete ns higress-system
```
@@ -265,8 +243,10 @@ kubectl delete ns higress-system
- Mailing list: higress@googlegroups.com
社区交流群:
![image](https://user-images.githubusercontent.com/6763318/205646934-93b7a711-ac3e-448a-a7ce-2156e31d0f7e.png)
![image](https://img.alicdn.com/imgextra/i1/O1CN01d7LmWu1rMB71rfRhA_!!6000000005616-2-tps-720-405.png)
开发者群:
![image](https://user-images.githubusercontent.com/6763318/205646842-2a636aeb-08e2-458c-9478-7c3d8f8c2cde.png)
![image](https://img.alicdn.com/imgextra/i2/O1CN010jFMgn1qTDaHqeIgH_!!6000000005496-2-tps-406-531.png)

View File

@@ -124,10 +124,10 @@ kind.exe create cluster --name higress --config=cluster.conf
kubectl.exe config use-context kind-higress
```
#### step 3. install istio & higress
#### step 3. install higress
```bash
helm install istio -n istio-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/istio-local
kubectl create ns higress-system
helm install higress -n higress-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/higress-local
```
Note: The helm version needs to be upgraded to **v3.8.0** and above
@@ -151,38 +151,21 @@ curl localhost/bar
```bash
kubectl delete -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml
helm uninstall istio -n istio-system
helm uninstall higress -n higress-system
kubectl delete ns istio-system
kubectl delete ns higress-system
```
### Production Environment
#### step 1. install istio
select higress istio:
```bash
kubectl create ns istio-system
helm install istio -n istio-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/istio
```
or select official istio (lose some abilities, such as using annotation to limit request rate):
https://istio.io/latest/docs/setup/install
#### step 2. install higress
#### step 1. install higress
```bash
kubectl create ns higress-system
helm install higress -n higress-system oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/charts/higress
```
#### step 3. create the ingress and test it
#### step 2. create the ingress and test it
for example there is a service `test` in default namespace.
@@ -192,6 +175,7 @@ kind: Ingress
metadata:
name: simple-example
spec:
ingressClassName: higress
rules:
- host: foo.bar.com
http:
@@ -212,12 +196,8 @@ curl "$(k get svc -n higress-system higress-gateway -o jsonpath='{.status.loadBa
#### Clean-Up
```bash
helm uninstall istio -n istio-system
helm uninstall higress -n higress-system
kubectl delete ns istio-system
kubectl delete ns higress-system
```

1
VERSION Normal file
View File

@@ -0,0 +1 @@
v0.6.1

View File

@@ -9,6 +9,8 @@ openapi:
directories:
networking/v1:
- mode: perFile
extensions/v1alpha1:
- mode: perFile
# All is used when generating all types referenced in the above directories to
# one file.

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
// Copyright Istio Authors
//
// 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.
// Modified by Higress Authors
syntax = "proto3";
import "google/protobuf/wrappers.proto";
import "google/protobuf/struct.proto";
// $schema: higress.extensions.v1alpha1.WasmPlugin
// $title: WasmPlugin
// $description: Extend the functionality provided by the envoy through WebAssembly filters.
package higress.extensions.v1alpha1;
option go_package="github.com/alibaba/higress/api/extensions/v1alpha1";
// <!-- crd generation tags
// +cue-gen:WasmPlugin:groupName:extensions.higress.io
// +cue-gen:WasmPlugin:version:v1alpha1
// +cue-gen:WasmPlugin:storageVersion
// +cue-gen:WasmPlugin:annotations:helm.sh/resource-policy=keep
// +cue-gen:WasmPlugin:subresource:status
// +cue-gen:WasmPlugin:scope:Namespaced
// +cue-gen:WasmPlugin:resource:categories=higress-io,extensions-higress-io
// +cue-gen:WasmPlugin:preserveUnknownFields:pluginConfig,defaultConfig,matchRules.[].config
// +cue-gen:WasmPlugin:printerColumn:name=Age,type=date,JSONPath=.metadata.creationTimestamp,description="CreationTimestamp is a timestamp
// representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations.
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
// Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
// -->
//
// <!-- go code generation tags
// +kubetype-gen
// +kubetype-gen:groupVersion=extensions.higress.io/v1alpha1
// +genclient
// +k8s:deepcopy-gen=true
// -->
message WasmPlugin {
// URL of a Wasm module or OCI container. If no scheme is present,
// defaults to `oci://`, referencing an OCI image. Other valid schemes
// are `file://` for referencing .wasm module files present locally
// within the proxy container, and `http[s]://` for .wasm module files
// hosted remotely.
string url = 2;
// SHA256 checksum that will be used to verify Wasm module or OCI container.
// If the `url` field already references a SHA256 (using the `@sha256:`
// notation), it must match the value of this field. If an OCI image is
// referenced by tag and this field is set, its checksum will be verified
// against the contents of this field after pulling.
string sha256 = 3;
// The pull behaviour to be applied when fetching an OCI image. Only
// relevant when images are referenced by tag instead of SHA. Defaults
// to IfNotPresent, except when an OCI image is referenced in the `url`
// and the `latest` tag is used, in which case `Always` is the default,
// mirroring K8s behaviour.
// Setting is ignored if `url` field is referencing a Wasm module directly
// using `file://` or `http[s]://`
PullPolicy image_pull_policy = 4;
// Credentials to use for OCI image pulling.
// Name of a K8s Secret in the same namespace as the `WasmPlugin` that
// contains a docker pull secret which is to be used to authenticate
// against the registry when pulling the image.
string image_pull_secret = 5;
// Public key that will be used to verify signatures of signed OCI images
// or Wasm modules. Must be supplied in PEM format.
string verification_key = 6;
// The configuration that will be passed on to the plugin.
google.protobuf.Struct plugin_config = 7;
// The plugin name to be used in the Envoy configuration (used to be called
// `rootID`). Some .wasm modules might require this value to select the Wasm
// plugin to execute.
string plugin_name = 8;
// Determines where in the filter chain this `WasmPlugin` is to be injected.
PluginPhase phase = 9;
// Determines ordering of `WasmPlugins` in the same `phase`.
// When multiple `WasmPlugins` are applied to the same workload in the
// same `phase`, they will be applied by priority, in descending order.
// If `priority` is not set, or two `WasmPlugins` exist with the same
// value, the ordering will be deterministically derived from name and
// namespace of the `WasmPlugins`. Defaults to `0`.
google.protobuf.Int64Value priority = 10;
// Extended by Higress, the default configuration takes effect globally
google.protobuf.Struct default_config = 101;
// Extended by Higress, matching rules take effect
repeated MatchRule match_rules = 102;
}
// Extended by Higress
message MatchRule {
repeated string ingress = 1;
repeated string domain = 2;
google.protobuf.Struct config = 3;
}
// The phase in the filter chain where the plugin will be injected.
enum PluginPhase {
// Control plane decides where to insert the plugin. This will generally
// be at the end of the filter chain, right before the Router.
// Do not specify `PluginPhase` if the plugin is independent of others.
UNSPECIFIED_PHASE = 0;
// Insert plugin before Istio authentication filters.
AUTHN = 1;
// Insert plugin before Istio authorization filters and after Istio authentication filters.
AUTHZ = 2;
// Insert plugin before Istio stats filters and after Istio authorization filters.
STATS = 3;
}
// The pull behaviour to be applied when fetching an OCI image,
// mirroring K8s behaviour.
//
// <!--
// buf:lint:ignore ENUM_VALUE_UPPER_SNAKE_CASE
// -->
enum PullPolicy {
// Defaults to IfNotPresent, except for OCI images with tag `latest`, for which
// the default will be Always.
UNSPECIFIED_POLICY = 0;
// If an existing version of the image has been pulled before, that
// will be used. If no version of the image is present locally, we
// will pull the latest version.
IfNotPresent = 1;
// We will always pull the latest version of an image when applying
// this plugin.
Always = 2;
}

View File

@@ -0,0 +1,58 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: extensions/v1alpha1/wasm.proto
package v1alpha1
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
_ "github.com/gogo/protobuf/types"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// DeepCopyInto supports using WasmPlugin within kubernetes types, where deepcopy-gen is used.
func (in *WasmPlugin) DeepCopyInto(out *WasmPlugin) {
p := proto.Clone(in).(*WasmPlugin)
*out = *p
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WasmPlugin. Required by controller-gen.
func (in *WasmPlugin) DeepCopy() *WasmPlugin {
if in == nil {
return nil
}
out := new(WasmPlugin)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WasmPlugin. Required by controller-gen.
func (in *WasmPlugin) DeepCopyInterface() interface{} {
return in.DeepCopy()
}
// DeepCopyInto supports using MatchRule within kubernetes types, where deepcopy-gen is used.
func (in *MatchRule) DeepCopyInto(out *MatchRule) {
p := proto.Clone(in).(*MatchRule)
*out = *p
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchRule. Required by controller-gen.
func (in *MatchRule) DeepCopy() *MatchRule {
if in == nil {
return nil
}
out := new(MatchRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MatchRule. Required by controller-gen.
func (in *MatchRule) DeepCopyInterface() interface{} {
return in.DeepCopy()
}

View File

@@ -0,0 +1,45 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: extensions/v1alpha1/wasm.proto
package v1alpha1
import (
bytes "bytes"
fmt "fmt"
github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb"
proto "github.com/gogo/protobuf/proto"
_ "github.com/gogo/protobuf/types"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// MarshalJSON is a custom marshaler for WasmPlugin
func (this *WasmPlugin) MarshalJSON() ([]byte, error) {
str, err := WasmMarshaler.MarshalToString(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for WasmPlugin
func (this *WasmPlugin) UnmarshalJSON(b []byte) error {
return WasmUnmarshaler.Unmarshal(bytes.NewReader(b), this)
}
// MarshalJSON is a custom marshaler for MatchRule
func (this *MatchRule) MarshalJSON() ([]byte, error) {
str, err := WasmMarshaler.MarshalToString(this)
return []byte(str), err
}
// UnmarshalJSON is a custom unmarshaler for MatchRule
func (this *MatchRule) UnmarshalJSON(b []byte) error {
return WasmUnmarshaler.Unmarshal(bytes.NewReader(b), this)
}
var (
WasmMarshaler = &github_com_gogo_protobuf_jsonpb.Marshaler{}
WasmUnmarshaler = &github_com_gogo_protobuf_jsonpb.Unmarshaler{AllowUnknownFields: true}
)

View File

@@ -4,7 +4,8 @@ set -eu
# Generate all protos
buf generate \
--path networking \
--path networking \
--path extensions
# Generate CRDs
cue-gen -verbose -f=./cue.yaml -crd=true

View File

@@ -1,6 +1,108 @@
# DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
"helm.sh/resource-policy": keep
name: wasmplugins.extensions.higress.io
spec:
group: extensions.higress.io
names:
categories:
- higress-io
- extensions-higress-io
kind: WasmPlugin
listKind: WasmPluginList
plural: wasmplugins
singular: wasmplugin
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: 'CreationTimestamp is a timestamp representing the server time
when this object was created. It is not guaranteed to be set in happens-before
order across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for
lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata'
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
defaultConfig:
type: object
x-kubernetes-preserve-unknown-fields: true
imagePullPolicy:
description: The pull behaviour to be applied when fetching an OCI
image.
enum:
- UNSPECIFIED_POLICY
- IfNotPresent
- Always
type: string
imagePullSecret:
description: Credentials to use for OCI image pulling.
type: string
matchRules:
items:
properties:
config:
type: object
x-kubernetes-preserve-unknown-fields: true
domain:
items:
type: string
type: array
ingress:
items:
type: string
type: array
type: object
type: array
phase:
description: Determines where in the filter chain this `WasmPlugin`
is to be injected.
enum:
- UNSPECIFIED_PHASE
- AUTHN
- AUTHZ
- STATS
type: string
pluginConfig:
description: The configuration that will be passed on to the plugin.
type: object
x-kubernetes-preserve-unknown-fields: true
pluginName:
type: string
priority:
description: Determines ordering of `WasmPlugins` in the same `phase`.
nullable: true
type: integer
sha256:
description: SHA256 checksum that will be used to verify Wasm module
or OCI container.
type: string
url:
description: URL of a Wasm module or OCI container.
type: string
verificationKey:
type: string
type: object
status:
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
"helm.sh/resource-policy": keep

View File

@@ -1,17 +1,3 @@
// 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.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: networking/v1/mcp_bridge.proto

View File

@@ -1,17 +1,3 @@
// 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.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: networking/v1/mcp_bridge.proto

View File

@@ -1,17 +1,3 @@
// 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.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: networking/v1/mcp_bridge.proto

View File

@@ -28,7 +28,8 @@ comma := ,
# source packages to scan for kubetype-gen tags
kube_source_packages = $(subst $(space),$(empty), \
github.com/alibaba/higress/api/networking/v1 \
github.com/alibaba/higress/api/networking/v1, \
github.com/alibaba/higress/api/extensions/v1alpha1 \
)
# base output package for generated files
@@ -38,7 +39,8 @@ kube_api_base_package = $(kube_base_output_package)/apis
# source packages to scan for kubernetes generator tags, e.g. deepcopy-gen, client-gen, etc.
# these should correspond to the output packages from kubetype-gen
kube_api_packages = $(subst $(space),$(empty), \
$(kube_api_base_package)/networking/v1 \
$(kube_api_base_package)/networking/v1, \
$(kube_api_base_package)/extensions/v1alpha1 \
)
# base output package used by kubernetes client-gen
kube_clientset_package = $(kube_base_output_package)/clientset

View File

@@ -0,0 +1,21 @@
// 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.
// Code generated by kubetype-gen. DO NOT EDIT.
// Package has auto-generated kube type wrappers for raw types.
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen=package
// +groupName=extensions.higress.io
package v1alpha1

View File

@@ -0,0 +1,49 @@
// 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.
// Code generated by kubetype-gen. DO NOT EDIT.
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
)
var (
// Package-wide variables from generator "register".
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
const (
// Package-wide consts from generator "register".
GroupName = "extensions.higress.io"
)
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&WasmPlugin{},
&WasmPluginList{},
)
v1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -0,0 +1,69 @@
// 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.
// Code generated by kubetype-gen. DO NOT EDIT.
package v1alpha1
import (
extensionsv1alpha1 "github.com/alibaba/higress/api/extensions/v1alpha1"
metav1alpha1 "istio.io/api/meta/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
//
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// <!-- crd generation tags
// +cue-gen:WasmPlugin:groupName:extensions.higress.io
// +cue-gen:WasmPlugin:version:v1alpha1
// +cue-gen:WasmPlugin:storageVersion
// +cue-gen:WasmPlugin:annotations:helm.sh/resource-policy=keep
// +cue-gen:WasmPlugin:subresource:status
// +cue-gen:WasmPlugin:scope:Namespaced
// +cue-gen:WasmPlugin:resource:categories=higress-io,extensions-higress-io
// +cue-gen:WasmPlugin:preserveUnknownFields:pluginConfig,defaultConfig,matchRules.[].config
// +cue-gen:WasmPlugin:printerColumn:name=Age,type=date,JSONPath=.metadata.creationTimestamp,description="CreationTimestamp is a timestamp
// representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations.
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
// Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
// -->
//
// <!-- go code generation tags
// +kubetype-gen
// +kubetype-gen:groupVersion=extensions.higress.io/v1alpha1
// +genclient
// +k8s:deepcopy-gen=true
// -->
type WasmPlugin struct {
v1.TypeMeta `json:",inline"`
// +optional
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the implementation of this definition.
// +optional
Spec extensionsv1alpha1.WasmPlugin `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
Status metav1alpha1.IstioStatus `json:"status"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// WasmPluginList is a collection of WasmPlugins.
type WasmPluginList struct {
v1.TypeMeta `json:",inline"`
// +optional
v1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []WasmPlugin `json:"items" protobuf:"bytes,2,rep,name=items"`
}

View File

@@ -0,0 +1,85 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// 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.
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WasmPlugin) DeepCopyInto(out *WasmPlugin) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WasmPlugin.
func (in *WasmPlugin) DeepCopy() *WasmPlugin {
if in == nil {
return nil
}
out := new(WasmPlugin)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *WasmPlugin) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WasmPluginList) DeepCopyInto(out *WasmPluginList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]WasmPlugin, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WasmPluginList.
func (in *WasmPluginList) DeepCopy() *WasmPluginList {
if in == nil {
return nil
}
out := new(WasmPluginList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *WasmPluginList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

View File

@@ -19,6 +19,7 @@ package versioned
import (
"fmt"
extensionsv1alpha1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/extensions/v1alpha1"
networkingv1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/networking/v1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
@@ -27,6 +28,7 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
ExtensionsV1alpha1() extensionsv1alpha1.ExtensionsV1alpha1Interface
NetworkingV1() networkingv1.NetworkingV1Interface
}
@@ -34,7 +36,13 @@ type Interface interface {
// version included in a Clientset.
type Clientset struct {
*discovery.DiscoveryClient
networkingV1 *networkingv1.NetworkingV1Client
extensionsV1alpha1 *extensionsv1alpha1.ExtensionsV1alpha1Client
networkingV1 *networkingv1.NetworkingV1Client
}
// ExtensionsV1alpha1 retrieves the ExtensionsV1alpha1Client
func (c *Clientset) ExtensionsV1alpha1() extensionsv1alpha1.ExtensionsV1alpha1Interface {
return c.extensionsV1alpha1
}
// NetworkingV1 retrieves the NetworkingV1Client
@@ -63,6 +71,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
}
var cs Clientset
var err error
cs.extensionsV1alpha1, err = extensionsv1alpha1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.networkingV1, err = networkingv1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@@ -79,6 +91,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.extensionsV1alpha1 = extensionsv1alpha1.NewForConfigOrDie(c)
cs.networkingV1 = networkingv1.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
@@ -88,6 +101,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
// New creates a new Clientset for the given RESTClient.
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.extensionsV1alpha1 = extensionsv1alpha1.New(c)
cs.networkingV1 = networkingv1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)

View File

@@ -18,6 +18,8 @@ package fake
import (
clientset "github.com/alibaba/higress/client/pkg/clientset/versioned"
extensionsv1alpha1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/extensions/v1alpha1"
fakeextensionsv1alpha1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/extensions/v1alpha1/fake"
networkingv1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/networking/v1"
fakenetworkingv1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/networking/v1/fake"
"k8s.io/apimachinery/pkg/runtime"
@@ -74,6 +76,11 @@ func (c *Clientset) Tracker() testing.ObjectTracker {
var _ clientset.Interface = &Clientset{}
// ExtensionsV1alpha1 retrieves the ExtensionsV1alpha1Client
func (c *Clientset) ExtensionsV1alpha1() extensionsv1alpha1.ExtensionsV1alpha1Interface {
return &fakeextensionsv1alpha1.FakeExtensionsV1alpha1{Fake: &c.Fake}
}
// NetworkingV1 retrieves the NetworkingV1Client
func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface {
return &fakenetworkingv1.FakeNetworkingV1{Fake: &c.Fake}

View File

@@ -17,6 +17,7 @@
package fake
import (
extensionsv1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
networkingv1 "github.com/alibaba/higress/client/pkg/apis/networking/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@@ -29,6 +30,7 @@ var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
extensionsv1alpha1.AddToScheme,
networkingv1.AddToScheme,
}

View File

@@ -17,6 +17,7 @@
package scheme
import (
extensionsv1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
networkingv1 "github.com/alibaba/higress/client/pkg/apis/networking/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@@ -29,6 +30,7 @@ var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
extensionsv1alpha1.AddToScheme,
networkingv1.AddToScheme,
}

View File

@@ -0,0 +1,18 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v1alpha1

View File

@@ -0,0 +1,87 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
v1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
"github.com/alibaba/higress/client/pkg/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type ExtensionsV1alpha1Interface interface {
RESTClient() rest.Interface
WasmPluginsGetter
}
// ExtensionsV1alpha1Client is used to interact with features provided by the extensions.higress.io group.
type ExtensionsV1alpha1Client struct {
restClient rest.Interface
}
func (c *ExtensionsV1alpha1Client) WasmPlugins(namespace string) WasmPluginInterface {
return newWasmPlugins(c, namespace)
}
// NewForConfig creates a new ExtensionsV1alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*ExtensionsV1alpha1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &ExtensionsV1alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new ExtensionsV1alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *ExtensionsV1alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new ExtensionsV1alpha1Client for the given RESTClient.
func New(c rest.Interface) *ExtensionsV1alpha1Client {
return &ExtensionsV1alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *ExtensionsV1alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@@ -0,0 +1,18 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake

View File

@@ -0,0 +1,38 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "github.com/alibaba/higress/client/pkg/clientset/versioned/typed/extensions/v1alpha1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeExtensionsV1alpha1 struct {
*testing.Fake
}
func (c *FakeExtensionsV1alpha1) WasmPlugins(namespace string) v1alpha1.WasmPluginInterface {
return &FakeWasmPlugins{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeExtensionsV1alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -0,0 +1,140 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeWasmPlugins implements WasmPluginInterface
type FakeWasmPlugins struct {
Fake *FakeExtensionsV1alpha1
ns string
}
var wasmpluginsResource = schema.GroupVersionResource{Group: "extensions.higress.io", Version: "v1alpha1", Resource: "wasmplugins"}
var wasmpluginsKind = schema.GroupVersionKind{Group: "extensions.higress.io", Version: "v1alpha1", Kind: "WasmPlugin"}
// Get takes name of the wasmPlugin, and returns the corresponding wasmPlugin object, and an error if there is any.
func (c *FakeWasmPlugins) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.WasmPlugin, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(wasmpluginsResource, c.ns, name), &v1alpha1.WasmPlugin{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.WasmPlugin), err
}
// List takes label and field selectors, and returns the list of WasmPlugins that match those selectors.
func (c *FakeWasmPlugins) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.WasmPluginList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(wasmpluginsResource, wasmpluginsKind, c.ns, opts), &v1alpha1.WasmPluginList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.WasmPluginList{ListMeta: obj.(*v1alpha1.WasmPluginList).ListMeta}
for _, item := range obj.(*v1alpha1.WasmPluginList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested wasmPlugins.
func (c *FakeWasmPlugins) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(wasmpluginsResource, c.ns, opts))
}
// Create takes the representation of a wasmPlugin and creates it. Returns the server's representation of the wasmPlugin, and an error, if there is any.
func (c *FakeWasmPlugins) Create(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.CreateOptions) (result *v1alpha1.WasmPlugin, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(wasmpluginsResource, c.ns, wasmPlugin), &v1alpha1.WasmPlugin{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.WasmPlugin), err
}
// Update takes the representation of a wasmPlugin and updates it. Returns the server's representation of the wasmPlugin, and an error, if there is any.
func (c *FakeWasmPlugins) Update(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.UpdateOptions) (result *v1alpha1.WasmPlugin, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(wasmpluginsResource, c.ns, wasmPlugin), &v1alpha1.WasmPlugin{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.WasmPlugin), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeWasmPlugins) UpdateStatus(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.UpdateOptions) (*v1alpha1.WasmPlugin, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(wasmpluginsResource, "status", c.ns, wasmPlugin), &v1alpha1.WasmPlugin{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.WasmPlugin), err
}
// Delete takes name of the wasmPlugin and deletes it. Returns an error if one occurs.
func (c *FakeWasmPlugins) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(wasmpluginsResource, c.ns, name), &v1alpha1.WasmPlugin{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeWasmPlugins) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(wasmpluginsResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.WasmPluginList{})
return err
}
// Patch applies the patch and returns the patched wasmPlugin.
func (c *FakeWasmPlugins) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.WasmPlugin, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(wasmpluginsResource, c.ns, name, pt, data, subresources...), &v1alpha1.WasmPlugin{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.WasmPlugin), err
}

View File

@@ -0,0 +1,19 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
type WasmPluginExpansion interface{}

View File

@@ -0,0 +1,193 @@
// 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.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
v1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
scheme "github.com/alibaba/higress/client/pkg/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// WasmPluginsGetter has a method to return a WasmPluginInterface.
// A group's client should implement this interface.
type WasmPluginsGetter interface {
WasmPlugins(namespace string) WasmPluginInterface
}
// WasmPluginInterface has methods to work with WasmPlugin resources.
type WasmPluginInterface interface {
Create(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.CreateOptions) (*v1alpha1.WasmPlugin, error)
Update(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.UpdateOptions) (*v1alpha1.WasmPlugin, error)
UpdateStatus(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.UpdateOptions) (*v1alpha1.WasmPlugin, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.WasmPlugin, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.WasmPluginList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.WasmPlugin, err error)
WasmPluginExpansion
}
// wasmPlugins implements WasmPluginInterface
type wasmPlugins struct {
client rest.Interface
ns string
}
// newWasmPlugins returns a WasmPlugins
func newWasmPlugins(c *ExtensionsV1alpha1Client, namespace string) *wasmPlugins {
return &wasmPlugins{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the wasmPlugin, and returns the corresponding wasmPlugin object, and an error if there is any.
func (c *wasmPlugins) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.WasmPlugin, err error) {
result = &v1alpha1.WasmPlugin{}
err = c.client.Get().
Namespace(c.ns).
Resource("wasmplugins").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of WasmPlugins that match those selectors.
func (c *wasmPlugins) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.WasmPluginList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.WasmPluginList{}
err = c.client.Get().
Namespace(c.ns).
Resource("wasmplugins").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested wasmPlugins.
func (c *wasmPlugins) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("wasmplugins").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a wasmPlugin and creates it. Returns the server's representation of the wasmPlugin, and an error, if there is any.
func (c *wasmPlugins) Create(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.CreateOptions) (result *v1alpha1.WasmPlugin, err error) {
result = &v1alpha1.WasmPlugin{}
err = c.client.Post().
Namespace(c.ns).
Resource("wasmplugins").
VersionedParams(&opts, scheme.ParameterCodec).
Body(wasmPlugin).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a wasmPlugin and updates it. Returns the server's representation of the wasmPlugin, and an error, if there is any.
func (c *wasmPlugins) Update(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.UpdateOptions) (result *v1alpha1.WasmPlugin, err error) {
result = &v1alpha1.WasmPlugin{}
err = c.client.Put().
Namespace(c.ns).
Resource("wasmplugins").
Name(wasmPlugin.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(wasmPlugin).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *wasmPlugins) UpdateStatus(ctx context.Context, wasmPlugin *v1alpha1.WasmPlugin, opts v1.UpdateOptions) (result *v1alpha1.WasmPlugin, err error) {
result = &v1alpha1.WasmPlugin{}
err = c.client.Put().
Namespace(c.ns).
Resource("wasmplugins").
Name(wasmPlugin.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(wasmPlugin).
Do(ctx).
Into(result)
return
}
// Delete takes name of the wasmPlugin and deletes it. Returns an error if one occurs.
func (c *wasmPlugins) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("wasmplugins").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *wasmPlugins) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("wasmplugins").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched wasmPlugin.
func (c *wasmPlugins) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.WasmPlugin, err error) {
result = &v1alpha1.WasmPlugin{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("wasmplugins").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -0,0 +1,44 @@
// 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.
// Code generated by informer-gen. DO NOT EDIT.
package extensions
import (
v1alpha1 "github.com/alibaba/higress/client/pkg/informers/externalversions/extensions/v1alpha1"
internalinterfaces "github.com/alibaba/higress/client/pkg/informers/externalversions/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha1 provides access to shared informers for resources in V1alpha1.
V1alpha1() v1alpha1.Interface
}
type group struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha1 returns a new v1alpha1.Interface.
func (g *group) V1alpha1() v1alpha1.Interface {
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@@ -0,0 +1,43 @@
// 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.
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
internalinterfaces "github.com/alibaba/higress/client/pkg/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// WasmPlugins returns a WasmPluginInformer.
WasmPlugins() WasmPluginInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// WasmPlugins returns a WasmPluginInformer.
func (v *version) WasmPlugins() WasmPluginInformer {
return &wasmPluginInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -0,0 +1,88 @@
// 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.
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
time "time"
extensionsv1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
versioned "github.com/alibaba/higress/client/pkg/clientset/versioned"
internalinterfaces "github.com/alibaba/higress/client/pkg/informers/externalversions/internalinterfaces"
v1alpha1 "github.com/alibaba/higress/client/pkg/listers/extensions/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// WasmPluginInformer provides access to a shared informer and lister for
// WasmPlugins.
type WasmPluginInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.WasmPluginLister
}
type wasmPluginInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewWasmPluginInformer constructs a new informer for WasmPlugin type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewWasmPluginInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredWasmPluginInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredWasmPluginInformer constructs a new informer for WasmPlugin type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredWasmPluginInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ExtensionsV1alpha1().WasmPlugins(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ExtensionsV1alpha1().WasmPlugins(namespace).Watch(context.TODO(), options)
},
},
&extensionsv1alpha1.WasmPlugin{},
resyncPeriod,
indexers,
)
}
func (f *wasmPluginInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredWasmPluginInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *wasmPluginInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&extensionsv1alpha1.WasmPlugin{}, f.defaultInformer)
}
func (f *wasmPluginInformer) Lister() v1alpha1.WasmPluginLister {
return v1alpha1.NewWasmPluginLister(f.Informer().GetIndexer())
}

View File

@@ -22,6 +22,7 @@ import (
time "time"
versioned "github.com/alibaba/higress/client/pkg/clientset/versioned"
extensions "github.com/alibaba/higress/client/pkg/informers/externalversions/extensions"
internalinterfaces "github.com/alibaba/higress/client/pkg/informers/externalversions/internalinterfaces"
networking "github.com/alibaba/higress/client/pkg/informers/externalversions/networking"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -170,9 +171,14 @@ type SharedInformerFactory interface {
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
Extensions() extensions.Interface
Networking() networking.Interface
}
func (f *sharedInformerFactory) Extensions() extensions.Interface {
return extensions.New(f, f.namespace, f.tweakListOptions)
}
func (f *sharedInformerFactory) Networking() networking.Interface {
return networking.New(f, f.namespace, f.tweakListOptions)
}

View File

@@ -19,6 +19,7 @@ package externalversions
import (
"fmt"
v1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
v1 "github.com/alibaba/higress/client/pkg/apis/networking/v1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
@@ -50,7 +51,11 @@ func (f *genericInformer) Lister() cache.GenericLister {
// TODO extend this to unknown resources with a client pool
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
switch resource {
// Group=networking.higress.io, Version=v1
// Group=extensions.higress.io, Version=v1alpha1
case v1alpha1.SchemeGroupVersion.WithResource("wasmplugins"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Extensions().V1alpha1().WasmPlugins().Informer()}, nil
// Group=networking.higress.io, Version=v1
case v1.SchemeGroupVersion.WithResource("mcpbridges"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().McpBridges().Informer()}, nil

View File

@@ -0,0 +1,25 @@
// 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.
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
// WasmPluginListerExpansion allows custom methods to be added to
// WasmPluginLister.
type WasmPluginListerExpansion interface{}
// WasmPluginNamespaceListerExpansion allows custom methods to be added to
// WasmPluginNamespaceLister.
type WasmPluginNamespaceListerExpansion interface{}

View File

@@ -0,0 +1,92 @@
// 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.
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
import (
v1alpha1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// WasmPluginLister helps list WasmPlugins.
type WasmPluginLister interface {
// List lists all WasmPlugins in the indexer.
List(selector labels.Selector) (ret []*v1alpha1.WasmPlugin, err error)
// WasmPlugins returns an object that can list and get WasmPlugins.
WasmPlugins(namespace string) WasmPluginNamespaceLister
WasmPluginListerExpansion
}
// wasmPluginLister implements the WasmPluginLister interface.
type wasmPluginLister struct {
indexer cache.Indexer
}
// NewWasmPluginLister returns a new WasmPluginLister.
func NewWasmPluginLister(indexer cache.Indexer) WasmPluginLister {
return &wasmPluginLister{indexer: indexer}
}
// List lists all WasmPlugins in the indexer.
func (s *wasmPluginLister) List(selector labels.Selector) (ret []*v1alpha1.WasmPlugin, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.WasmPlugin))
})
return ret, err
}
// WasmPlugins returns an object that can list and get WasmPlugins.
func (s *wasmPluginLister) WasmPlugins(namespace string) WasmPluginNamespaceLister {
return wasmPluginNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// WasmPluginNamespaceLister helps list and get WasmPlugins.
type WasmPluginNamespaceLister interface {
// List lists all WasmPlugins in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1alpha1.WasmPlugin, err error)
// Get retrieves the WasmPlugin from the indexer for a given namespace and name.
Get(name string) (*v1alpha1.WasmPlugin, error)
WasmPluginNamespaceListerExpansion
}
// wasmPluginNamespaceLister implements the WasmPluginNamespaceLister
// interface.
type wasmPluginNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all WasmPlugins in the indexer for a given namespace.
func (s wasmPluginNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.WasmPlugin, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.WasmPlugin))
})
return ret, err
}
// Get retrieves the WasmPlugin from the indexer for a given namespace and name.
func (s wasmPluginNamespaceLister) Get(name string) (*v1alpha1.WasmPlugin, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha1.Resource("wasmplugin"), name)
}
return obj.(*v1alpha1.WasmPlugin), nil
}

View File

@@ -28,12 +28,21 @@ import (
"istio.io/pkg/version"
"github.com/alibaba/higress/pkg/bootstrap"
innerconstants "github.com/alibaba/higress/pkg/config/constants"
)
var (
serverArgs *bootstrap.ServerArgs
loggingOptions = log.DefaultOptions()
serverProvider = func(args *bootstrap.ServerArgs) (bootstrap.ServerInterface, error) {
return bootstrap.NewServer(serverArgs)
}
waitForMonitorSignal = func(stop chan struct{}) {
cmd.WaitSignal(stop)
}
rootCmd = &cobra.Command{
Use: "higress",
}
@@ -52,7 +61,7 @@ var (
stop := make(chan struct{})
server, err := bootstrap.NewServer(serverArgs)
server, err := serverProvider(serverArgs)
if err != nil {
return fmt.Errorf("fail to create higress server: %v", err)
}
@@ -61,7 +70,7 @@ var (
return fmt.Errorf("fail to start higress server: %v", err)
}
cmd.WaitSignal(stop)
waitForMonitorSignal(stop)
server.WaitUntilCompletion()
return nil
@@ -85,8 +94,8 @@ func init() {
serveCmd.PersistentFlags().StringVar(&serverArgs.GatewaySelectorKey, "gatewaySelectorKey", "higress", "gateway resource selector label key")
serveCmd.PersistentFlags().StringVar(&serverArgs.GatewaySelectorValue, "gatewaySelectorValue", "higress-gateway", "gateway resource selector label value")
serveCmd.PersistentFlags().BoolVar(&serverArgs.EnableStatus, "enableStatus", false, "enable the ingress status syncer which use to update the ip in ingress's status")
serveCmd.PersistentFlags().StringVar(&serverArgs.IngressClass, "ingressClass", "", "if not empty, only watch the ingresses have the specified class, otherwise watch all ingresses")
serveCmd.PersistentFlags().BoolVar(&serverArgs.EnableStatus, "enableStatus", true, "enable the ingress status syncer which use to update the ip in ingress's status")
serveCmd.PersistentFlags().StringVar(&serverArgs.IngressClass, "ingressClass", innerconstants.DefaultIngressClass, "if not empty, only watch the ingresses have the specified class, otherwise watch all ingresses")
serveCmd.PersistentFlags().StringVar(&serverArgs.WatchNamespace, "watchNamespace", "", "if not empty, only wath the ingresses in the specified namespace, otherwise watch in all namespacees")
serveCmd.PersistentFlags().BoolVar(&serverArgs.Debug, "debug", serverArgs.Debug, "if true, enables more debug http api")
serveCmd.PersistentFlags().StringVar(&serverArgs.HttpAddress, "httpAddress", serverArgs.HttpAddress, "the http address")

78
cmd/higress/main_test.go Normal file
View File

@@ -0,0 +1,78 @@
// 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 main
import (
"github.com/alibaba/higress/pkg/bootstrap"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
)
func TestServe(t *testing.T) {
runEBackup := serveCmd.RunE
argsBackup := os.Args
serverProviderBackup := serverProvider
executed := false
serverProvider = func(args *bootstrap.ServerArgs) (bootstrap.ServerInterface, error) {
return &delayedServer{Args: args, Delay: time.Second * 5}, nil
}
serveCmd.RunE = func(cmd *cobra.Command, args []string) error {
executed = true
return runEBackup(cmd, args)
}
defer func() {
serverProvider = serverProviderBackup
os.Args = argsBackup
serveCmd.RunE = runEBackup
}()
a := assert.New(t)
delay := time.Second * 5
start := time.Now()
os.Args = []string{"/app/higress", "serve"}
waitForMonitorSignal = func(stop chan struct{}) {
time.Sleep(delay)
close(stop)
}
main()
end := time.Now()
cost := end.Sub(start)
a.GreaterOrEqual(cost, delay)
a.True(executed)
}
type delayedServer struct {
Args *bootstrap.ServerArgs
Delay time.Duration
stop <-chan struct{}
}
func (d *delayedServer) Start(stop <-chan struct{}) error {
d.stop = stop
return nil
}
func (d *delayedServer) WaitUntilCompletion() {
<-d.stop
}

View File

@@ -0,0 +1,101 @@
diff --git a/bazel/foreign_cc/proxy_wasm_cpp_host.patch b/bazel/foreign_cc/proxy_wasm_cpp_host.patch
new file mode 100644
index 0000000000..a586116e84
--- /dev/null
+++ b/bazel/foreign_cc/proxy_wasm_cpp_host.patch
@@ -0,0 +1,78 @@
+diff --git a/include/proxy-wasm/exports.h b/include/proxy-wasm/exports.h
+index ded6419..334cee4 100644
+--- a/include/proxy-wasm/exports.h
++++ b/include/proxy-wasm/exports.h
+@@ -129,6 +129,11 @@ Word call_foreign_function(Word function_name, Word function_name_size, Word arg
+
+ // Runtime environment functions exported from envoy to wasm.
+
++Word wasi_unstable_path_open(Word fd, Word dir_flags, Word path, Word path_len, Word oflags,
++ int64_t fs_rights_base, int64_t fg_rights_inheriting, Word fd_flags,
++ Word nwritten_ptr);
++Word wasi_unstable_fd_prestat_get(Word fd, Word buf_ptr);
++Word wasi_unstable_fd_prestat_dir_name(Word fd, Word path_ptr, Word path_len);
+ Word wasi_unstable_fd_write(Word fd, Word iovs, Word iovs_len, Word nwritten_ptr);
+ Word wasi_unstable_fd_read(Word, Word, Word, Word);
+ Word wasi_unstable_fd_seek(Word, int64_t, Word, Word);
+@@ -166,7 +171,7 @@ Word pthread_equal(Word left, Word right);
+ #define FOR_ALL_WASI_FUNCTIONS(_f) \
+ _f(fd_write) _f(fd_read) _f(fd_seek) _f(fd_close) _f(fd_fdstat_get) _f(environ_get) \
+ _f(environ_sizes_get) _f(args_get) _f(args_sizes_get) _f(clock_time_get) _f(random_get) \
+- _f(proc_exit)
++ _f(proc_exit) _f(path_open) _f(fd_prestat_get) _f(fd_prestat_dir_name)
+
+ // Helpers to generate a stub to pass to VM, in place of a restricted proxy-wasm capability.
+ #define _CREATE_PROXY_WASM_STUB(_fn) \
+diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h
+index c02bb6e..c13c78c 100644
+--- a/include/proxy-wasm/wasm_vm.h
++++ b/include/proxy-wasm/wasm_vm.h
+@@ -110,6 +110,8 @@ using WasmCallback_WWl = Word (*)(Word, int64_t);
+ using WasmCallback_WWlWW = Word (*)(Word, int64_t, Word, Word);
+ using WasmCallback_WWm = Word (*)(Word, uint64_t);
+ using WasmCallback_WWmW = Word (*)(Word, uint64_t, Word);
++using WasmCallback_WWWWWWllWW = Word (*)(Word, Word, Word, Word, Word, int64_t, int64_t, Word,
++ Word);
+ using WasmCallback_dd = double (*)(double);
+
+ #define FOR_ALL_WASM_VM_IMPORTS(_f) \
+@@ -127,7 +129,8 @@ using WasmCallback_dd = double (*)(double);
+ _f(proxy_wasm::WasmCallback_WWlWW) \
+ _f(proxy_wasm::WasmCallback_WWm) \
+ _f(proxy_wasm::WasmCallback_WWmW) \
+- _f(proxy_wasm::WasmCallback_dd)
++ _f(proxy_wasm::WasmCallback_WWWWWWllWW) \
++ _f(proxy_wasm::WasmCallback_dd)
+
+ enum class Cloneable {
+ NotCloneable, // VMs can not be cloned and should be created from scratch.
+diff --git a/src/exports.cc b/src/exports.cc
+index 0922b2d..d597914 100644
+--- a/src/exports.cc
++++ b/src/exports.cc
+@@ -648,6 +648,25 @@ Word grpc_send(Word token, Word message_ptr, Word message_size, Word end_stream)
+ return context->grpcSend(token, message.value(), end_stream);
+ }
+
++// __wasi_errno_t path_open(__wasi_fd_t fd, __wasi_lookupflags_t dirflags, const char *path,
++// size_t path_len, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, __wasi_rights_t
++// fs_rights_inheriting, __wasi_fdflags_t fdflags, __wasi_fd_t *retptr0)
++Word wasi_unstable_path_open(Word fd, Word dir_flags, Word path, Word path_len, Word oflags,
++ int64_t fs_rights_base, int64_t fg_rights_inheriting, Word fd_flags,
++ Word nwritten_ptr) {
++ return 44; // __WASI_ERRNO_NOENT
++}
++
++// __wasi_errno_t __wasi_fd_prestat_get(__wasi_fd_t fd, __wasi_prestat_t *retptr0)
++Word wasi_unstable_fd_prestat_get(Word fd, Word buf_ptr) {
++ return 8; // __WASI_ERRNO_BADF
++}
++
++// __wasi_errno_t __wasi_fd_prestat_dir_name(__wasi_fd_t fd, uint8_t * path, __wasi_size_t path_len)
++Word wasi_unstable_fd_prestat_dir_name(Word fd, Word path_ptr, Word path_len) {
++ return 52; // __WASI_ERRNO_ENOSYS
++}
++
+ // Implementation of writev-like() syscall that redirects stdout/stderr to Envoy
+ // logs.
+ Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) {
diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl
index bfef00ac85..806100b42d 100644
--- a/bazel/repositories.bzl
+++ b/bazel/repositories.bzl
@@ -943,7 +943,11 @@ def _proxy_wasm_cpp_sdk():
external_http_archive(name = "proxy_wasm_cpp_sdk")
def _proxy_wasm_cpp_host():
- external_http_archive(name = "proxy_wasm_cpp_host")
+ external_http_archive(
+ name = "proxy_wasm_cpp_host",
+ patches = ["@envoy//bazel/foreign_cc:proxy_wasm_cpp_host.patch"],
+ patch_args = ["-p1"],
+ )
def _emscripten_toolchain():
external_http_archive(

4
go.mod
View File

@@ -16,6 +16,7 @@ replace github.com/docker/docker => github.com/moby/moby v17.12.0-ce-rc1.0.20200
replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
require (
github.com/agiledragon/gomonkey/v2 v2.9.0
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.10.2-0.20220325020618-49ff273808a1
@@ -26,7 +27,7 @@ require (
github.com/nacos-group/nacos-sdk-go v1.0.8
github.com/nacos-group/nacos-sdk-go/v2 v2.1.2
github.com/spf13/cobra v1.2.1
github.com/stretchr/testify v1.8.0
github.com/stretchr/testify v1.8.1
go.uber.org/atomic v1.9.0
google.golang.org/grpc v1.48.0
google.golang.org/protobuf v1.28.0
@@ -70,6 +71,7 @@ require (
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa // indirect
github.com/containerd/continuity v0.1.0 // indirect
github.com/coreos/go-oidc/v3 v3.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0 // indirect
github.com/docker/cli v20.10.7+incompatible // indirect

9
go.sum
View File

@@ -156,6 +156,8 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrU
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/agiledragon/gomonkey/v2 v2.9.0 h1:PDiKKybR596O6FHW+RVSG0Z7uGCBNbmbUXh3uCNQ7Hc=
github.com/agiledragon/gomonkey/v2 v2.9.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -354,6 +356,7 @@ github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmeka
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbrRw=
github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -1255,8 +1258,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -1265,8 +1269,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=

View File

@@ -1,5 +1,5 @@
apiVersion: v2
appVersion: 0.5.3
appVersion: 0.6.1
description: Helm chart for deploying higress gateways
icon: https://higress.io/img/higress_logo_small.png
keywords:
@@ -9,4 +9,4 @@ name: higress
sources:
- http://github.com/alibaba/higress
type: application
version: 0.5.3
version: 0.6.1

View File

@@ -1,6 +1,108 @@
# DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
"helm.sh/resource-policy": keep
name: wasmplugins.extensions.higress.io
spec:
group: extensions.higress.io
names:
categories:
- higress-io
- extensions-higress-io
kind: WasmPlugin
listKind: WasmPluginList
plural: wasmplugins
singular: wasmplugin
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: 'CreationTimestamp is a timestamp representing the server time
when this object was created. It is not guaranteed to be set in happens-before
order across separate operations. Clients may not set this value. It is represented
in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for
lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata'
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
defaultConfig:
type: object
x-kubernetes-preserve-unknown-fields: true
imagePullPolicy:
description: The pull behaviour to be applied when fetching an OCI
image.
enum:
- UNSPECIFIED_POLICY
- IfNotPresent
- Always
type: string
imagePullSecret:
description: Credentials to use for OCI image pulling.
type: string
matchRules:
items:
properties:
config:
type: object
x-kubernetes-preserve-unknown-fields: true
domain:
items:
type: string
type: array
ingress:
items:
type: string
type: array
type: object
type: array
phase:
description: Determines where in the filter chain this `WasmPlugin`
is to be injected.
enum:
- UNSPECIFIED_PHASE
- AUTHN
- AUTHZ
- STATS
type: string
pluginConfig:
description: The configuration that will be passed on to the plugin.
type: object
x-kubernetes-preserve-unknown-fields: true
pluginName:
type: string
priority:
description: Determines ordering of `WasmPlugins` in the same `phase`.
nullable: true
type: integer
sha256:
description: SHA256 checksum that will be used to verify Wasm module
or OCI container.
type: string
url:
description: URL of a Wasm module or OCI container.
type: string
verificationKey:
type: string
type: object
status:
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
"helm.sh/resource-policy": keep

View File

@@ -1,8 +1,85 @@
{{- define "mesh" }}
# 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"
accessLogEncoding: TEXT
accessLogFile: "/dev/stdout"
accessLogFormat: '{"authority":"%REQ(: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)%"}
'
dnsRefreshRate: 200s
enableAutoMtls: false
enablePrometheusMerge: false
protocolDetectionTimeout: 100ms
# 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.
{{- if .Values.global.enableMesh }}
rootNamespace: {{ .Values.meshConfig.rootNamespace | default .Values.global.istioNamespace }}
{{- else }}
rootNamespace: {{ .Release.Namespace }}
{{- end }}
configSources:
- address: "xds://127.0.0.1:15051"
defaultConfig:
discoveryAddress: {{ printf "istiod.%s.svc" .Values.istioNamespace }}:15012
{{- if .Values.global.meshID }}
meshId: {{ .Values.global.meshID }}
{{- end }}
tracing:
{{- if eq .Values.global.proxy.tracer "lightstep" }}
lightstep:
# Address of the LightStep Satellite pool
address: {{ .Values.global.tracer.lightstep.address }}
# Access Token used to communicate with the Satellite pool
accessToken: {{ .Values.global.tracer.lightstep.accessToken }}
{{- else if eq .Values.global.proxy.tracer "zipkin" }}
zipkin:
# Address of the Zipkin collector
address: {{ .Values.global.tracer.zipkin.address | default (print "zipkin." .Release.Namespace ":9411") }}
{{- else if eq .Values.global.proxy.tracer "datadog" }}
datadog:
# Address of the Datadog Agent
address: {{ .Values.global.tracer.datadog.address | default "$(HOST_IP):8126" }}
{{- else if eq .Values.global.proxy.tracer "stackdriver" }}
stackdriver:
# enables trace output to stdout.
{{- if $.Values.global.tracer.stackdriver.debug }}
debug: {{ $.Values.global.tracer.stackdriver.debug }}
{{- end }}
{{- if $.Values.global.tracer.stackdriver.maxNumberOfAttributes }}
# The global default max number of attributes per span.
maxNumberOfAttributes: {{ $.Values.global.tracer.stackdriver.maxNumberOfAttributes | default "200" }}
{{- end }}
{{- if $.Values.global.tracer.stackdriver.maxNumberOfAnnotations }}
# The global default max number of annotation events per span.
maxNumberOfAnnotations: {{ $.Values.global.tracer.stackdriver.maxNumberOfAnnotations | default "200" }}
{{- end }}
{{- if $.Values.global.tracer.stackdriver.maxNumberOfMessageEvents }}
# The global default max number of message events per span.
maxNumberOfMessageEvents: {{ $.Values.global.tracer.stackdriver.maxNumberOfMessageEvents | default "200" }}
{{- end }}
{{- else if eq .Values.global.proxy.tracer "openCensusAgent" }}
{{/* Fill in openCensusAgent configuration from meshConfig so it isn't overwritten below */}}
{{ toYaml $.Values.meshConfig.defaultConfig.tracing | indent 8 }}
{{- else }}
{}
{{- end }}
{{- if .Values.global.remotePilotAddress }}
{{- if not .Values.global.externalIstiod }}
discoveryAddress: {{ printf "istiod-remote.%s.svc" .Release.Namespace }}:15012
{{- else }}
discoveryAddress: {{ printf "istiod.%s.svc" .Release.Namespace }}:15012
{{- end }}
{{- else }}
{{- if .Values.global.enableMesh }}
discoveryAddress: {{ printf "istiod.%s.svc" .Values.global.istioNamespace }}:15012
{{- else }}
discoveryAddress: higress-controller.{{.Release.Namespace}}.svc:15012
{{- end }}
{{- end }}
proxyStatsMatcher:
inclusionRegexps:
- ".*"
@@ -21,6 +98,16 @@ metadata:
labels:
{{- include "gateway.labels" . | nindent 4 }}
data:
# Configuration file for the mesh networks to be used by the Split Horizon EDS.
meshNetworks: |-
{{- if .Values.global.meshNetworks }}
networks:
{{ toYaml .Values.global.meshNetworks | trim | indent 6 }}
{{- else }}
networks: {}
{{- end }}
mesh: |-
{{- if .Values.meshConfig }}
{{ $mesh | toYaml | indent 4 }}

View File

@@ -42,6 +42,67 @@ rules:
resources: ["mcpbridges"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["extensions.higress.io"]
resources: ["wasmplugins"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "watch", "list", "update", "patch", "create", "delete"]
# auto-detect installed CRD definitions
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["get", "list", "watch"]
# discovery and routing
- apiGroups: [""]
resources: ["pods", "nodes", "services", "namespaces", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["discovery.k8s.io"]
resources: ["endpointslices"]
verbs: ["get", "list", "watch"]
# Istiod and bootstrap.
- apiGroups: ["certificates.k8s.io"]
resources:
- "certificatesigningrequests"
- "certificatesigningrequests/approval"
- "certificatesigningrequests/status"
verbs: ["update", "create", "get", "delete", "watch"]
- apiGroups: ["certificates.k8s.io"]
resources:
- "signers"
resourceNames:
- "kubernetes.io/legacy-unknown"
verbs: ["approve"]
# Used by Istiod to verify the JWT tokens
- apiGroups: ["authentication.k8s.io"]
resources: ["tokenreviews"]
verbs: ["create"]
# Used by Istiod to verify gateway SDS
- apiGroups: ["authorization.k8s.io"]
resources: ["subjectaccessreviews"]
verbs: ["create"]
# Used for MCS serviceexport management
- apiGroups: ["multicluster.x-k8s.io"]
resources: ["serviceexports"]
verbs: [ "get", "watch", "list", "create", "delete"]
# Used for MCS serviceimport management
- apiGroups: ["multicluster.x-k8s.io"]
resources: ["serviceimports"]
verbs: ["get", "watch", "list"]
# sidecar injection controller
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations"]
verbs: ["get", "list", "watch", "update", "patch"]
# configuration validation webhook controller
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["validatingwebhookconfigurations"]
verbs: ["get", "list", "watch", "update"]

View File

@@ -28,6 +28,139 @@ spec:
securityContext:
{{- toYaml .Values.controller.podSecurityContext | nindent 8 }}
containers:
{{- if not .Values.global.enableMesh }}
- name: discovery
{{- if contains "/" .Values.pilot.image }}
image: "{{ .Values.pilot.image }}"
{{- else }}
image: "{{ .Values.pilot.hub | default .Values.global.hub }}/{{ .Values.pilot.image | default "pilot" }}:{{ .Values.pilot.tag | default .Values.global.tag }}"
{{- end }}
{{- if .Values.global.imagePullPolicy }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
{{- end }}
args:
- "discovery"
- --monitoringAddr=:15014
{{- if .Values.global.logging.level }}
- --log_output_level={{ .Values.global.logging.level }}
{{- end}}
{{- if .Values.global.logAsJson }}
- --log_as_json
{{- end }}
- --domain
- {{ .Values.global.proxy.clusterDomain }}
{{- if .Values.global.oneNamespace }}
- "-a"
- {{ .Release.Namespace }}
{{- end }}
{{- if .Values.pilot.plugins }}
- --plugins={{ .Values.pilot.plugins }}
{{- end }}
- --keepaliveMaxServerConnectionAge
- "{{ .Values.pilot.keepaliveMaxServerConnectionAge }}"
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 15010
protocol: TCP
- containerPort: 15017
protocol: TCP
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 5
env:
- name: HIGRESS_CONTROLLER_SVC
value: "127.0.0.1"
- name: HIGRESS_CONTROLLER_PORT
value: "15051"
- name: REVISION
value: "{{ .Values.revision | default `default` }}"
- name: JWT_POLICY
value: {{ .Values.global.jwtPolicy }}
- name: PILOT_CERT_PROVIDER
value: "istiod"
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.serviceAccountName
- name: KUBECONFIG
value: /var/run/secrets/remote/config
{{- if .Values.pilot.env }}
{{- range $key, $val := .Values.pilot.env }}
- name: {{ $key }}
value: "{{ $val }}"
{{- end }}
{{- end }}
{{- if .Values.pilot.traceSampling }}
- name: PILOT_TRACE_SAMPLING
value: "{{ .Values.pilot.traceSampling }}"
{{- end }}
- name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND
value: "{{ .Values.pilot.enableProtocolSniffingForOutbound }}"
- name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND
value: "{{ .Values.pilot.enableProtocolSniffingForInbound }}"
- name: ISTIOD_ADDR
value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Release.Namespace }}.svc:15012
- name: PILOT_ENABLE_ANALYSIS
value: "{{ .Values.global.istiod.enableAnalysis }}"
- name: CLUSTER_ID
value: "{{ $.Values.global.multiCluster.clusterName | default `Kubernetes` }}"
{{- if not .Values.global.enableMesh }}
- name: CUSTOM_CA_CERT_NAME
value: "higress-ca-root-cert"
{{- end }}
{{- if not .Values.global.kind }}
resources:
{{- if .Values.pilot.resources }}
{{ toYaml .Values.pilot.resources | trim | indent 12 }}
{{- else }}
{{ toYaml .Values.global.defaultResources | trim | indent 12 }}
{{- end }}
{{- end }}
securityContext:
readOnlyRootFilesystem: true
runAsUser: 1337
runAsGroup: 1337
runAsNonRoot: true
capabilities:
drop:
- ALL
volumeMounts:
- name: config
mountPath: /etc/istio/config
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
mountPath: /var/run/secrets/tokens
readOnly: true
{{- end }}
- name: local-certs
mountPath: /var/run/secrets/istio-dns
- name: cacerts
mountPath: /etc/cacerts
readOnly: true
- name: istio-kubeconfig
mountPath: /var/run/secrets/remote
readOnly: true
{{- if .Values.pilot.jwksResolverExtraRootCA }}
- name: extracacerts
mountPath: /cacerts
{{- end }}
{{- end }}
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.controller.securityContext | nindent 12 }}
@@ -36,10 +169,10 @@ spec:
- "serve"
- --gatewaySelectorKey=higress
- --gatewaySelectorValue={{ .Release.Namespace }}-{{ include "gateway.name" . }}
{{- if not .Values.enableStatus }}
- --enableStatus={{ .Values.enableStatus }}
{{- if .Values.ingressClass }}
- --ingressClass={{ .Values.ingressClass }}
{{- end }}
- --ingressClass={{ .Values.ingressClass }}
{{- if .Values.watchNamespace }}
- --watchNamespace={{ .Values.watchNamespace }}
{{- end }}
@@ -95,3 +228,36 @@ spec:
volumes:
- name: log
emptyDir: {}
{{- if not .Values.global.enableMesh }}
- name: config
configMap:
name: higress-config
# Technically not needed on this pod - but it helps debugging/testing SDS
# Should be removed after everything works.
- emptyDir:
medium: Memory
name: local-certs
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
projected:
sources:
- serviceAccountToken:
audience: {{ .Values.global.sds.token.aud }}
expirationSeconds: 43200
path: istio-token
# Optional: user-generated root
- name: cacerts
secret:
secretName: cacerts
optional: true
- name: istio-kubeconfig
secret:
secretName: istio-kubeconfig
optional: true
{{- if .Values.pilot.jwksResolverExtraRootCA }}
- name: extracacerts
configMap:
name: pilot-jwks-extra-cacerts{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "controller.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "controller.labels" . | nindent 4 }}
rules:
# For storing CA secret
- apiGroups: [""]
resources: ["secrets"]
# TODO lock this down to istio-ca-cert if not using the DNS cert mesh config
verbs: ["create", "get", "watch", "list", "update", "delete"]

View File

@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "controller.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "controller.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "controller.serviceAccountName" . }}
subjects:
- kind: ServiceAccount
name: {{ include "controller.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}

View File

@@ -8,5 +8,20 @@ spec:
type: {{ .Values.controller.service.type }}
ports:
{{- toYaml .Values.controller.ports | nindent 4 }}
{{- if not .Values.global.enableMesh }}
- port: 15010
name: grpc-xds # plaintext
protocol: TCP
- port: 15012
name: https-dns # mTLS with k8s-signed cert
protocol: TCP
- port: 443
name: https-webhook # validation and injection
targetPort: 15017
protocol: TCP
- port: 15014
name: http-monitoring # prometheus stats
protocol: TCP
{{- end }}
selector:
{{- include "controller.selectorLabels" . | nindent 4 }}

View File

@@ -21,12 +21,19 @@ spec:
strategy:
rollingUpdate:
maxSurge: {{ .Values.gateway.rollingMaxSurge }}
{{- if .Values.global.kind }}
maxUnavailable: 100%
{{- else }}
maxUnavailable: {{ .Values.gateway.rollingMaxUnavailable }}
{{- end }}
template:
metadata:
{{- with .Values.gateway.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- if .Values.global.enableMesh }}
"enableMesh": "true"
{{- end }}
{{- if .Values.gateway.podAnnotations }}
{{- toYaml .Values.gateway.podAnnotations | nindent 8 }}
{{- end }}
labels:
sidecar.istio.io/inject: "false"
@@ -122,7 +129,7 @@ spec:
- name: ENABLE_INGRESS_GATEWAY_SDS
value: "false"
- name: JWT_POLICY
value: {{ .Values.gateway.jwtPolicy }}
value: {{ .Values.global.jwtPolicy }}
- name: ISTIO_META_HTTP10
value: "1"
- name: ISTIO_META_CLUSTER_ID
@@ -166,7 +173,7 @@ spec:
{{- toYaml .Values.gateway.resources | nindent 12 }}
{{- end }}
volumeMounts:
{{- if eq .Values.gateway.jwtPolicy "third-party-jwt" }}
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
mountPath: /var/run/secrets/tokens
readOnly: true
@@ -198,7 +205,7 @@ spec:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
{{- if eq .Values.gateway.jwtPolicy "third-party-jwt" }}
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
projected:
sources:
@@ -209,7 +216,11 @@ spec:
{{- end }}
- name: istio-ca-root-cert
configMap:
{{- if .Values.global.enableMesh }}
name: istio-ca-root-cert
{{- else }}
name: higress-ca-root-cert
{{- end }}
- name: config
configMap:
name: higress-config

View File

@@ -1,17 +0,0 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: global
namespace: {{ .Release.Namespace }}
spec:
selector:
higress: {{ .Release.Namespace }}-{{ include "gateway.name" . }}
servers:
- hosts:
- "*"
port:
name: http-80
number: 80
protocol: HTTP
---

View File

@@ -3,18 +3,368 @@ global:
# for internal usage only, not to be configured by users.
autoscalingv2API: true
kind: false
enableMesh: false
# Used to locate istiod.
istioNamespace: istio-system
# 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
# 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.
defaultResources:
requests:
cpu: 10m
# memory: 128Mi
# limits:
# cpu: 100m
# memory: 128Mi
# 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
# Default tag for Istio images.
tag: 0.6.1
# 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
# 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.
imagePullSecrets: []
# - private-registry-key
# 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
logAsJson: false
# 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:
level: "default:info"
omitSidecarInjectorConfigMap: false
# 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
# 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.
operatorManageWebhooks: false
# Custom DNS config for the pod to resolve names of services in other
# clusters. Use this to add additional search domains, and other settings.
# see
# https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#dns-config
# This does not apply to gateway pods as they typically need a different
# set of DNS settings than the normal application pods (e.g., in
# multicluster scenarios).
# NOTE: If using templates, follow the pattern in the commented example below.
#podDNSSearchNamespaces:
#- global
#- "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global"
# 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.
priorityClassName: ""
proxy:
image: proxyv2
# 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
# 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
# not set, then the global "logLevel" will be used.
componentLogLevel: "misc:error"
# If set, newly injected sidecars will have core dumps enabled.
enableCoreDump: false
# istio ingress capture allowlist
# examples:
# Redirect only selected ports: --includeInboundPorts="80,8080"
excludeInboundPorts: ""
includeInboundPorts: "*"
# 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
includeIPRanges: "*"
excludeIPRanges: ""
includeOutboundPorts: ""
excludeOutboundPorts: ""
# 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
privileged: false
# The number of successive failed probes before indicating readiness failure.
readinessFailureThreshold: 30
# The initial delay for readiness probes in seconds.
readinessInitialDelaySeconds: 1
# The period between readiness probes.
readinessPeriodSeconds: 2
# Resources for the sidecar.
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 2000m
memory: 1024Mi
# Default port for Pilot agent health checks. A value of 0 will disable health checking.
statusPort: 15020
# Specify which tracer to use. One of: zipkin, lightstep, datadog, stackdriver.
# If using stackdriver tracer outside GCP, set env GOOGLE_APPLICATION_CREDENTIALS to the GCP credential file.
tracer: "zipkin"
# 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_init:
# Base name for the proxy_init container, used to configure iptables.
image: proxyv2
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 10m
memory: 10Mi
# configure remote pilot and istiod service and endpoint
remotePilotAddress: ""
##############################################################################################
# The following values are found in other charts. To effectively modify these values, make #
# make sure they are consistent across your Istio helm charts #
##############################################################################################
# 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.
# 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.
configCluster: false
# Configure the policy for validating JWT.
# Currently, two options are supported: "third-party-jwt" and "first-party-jwt".
jwtPolicy: "third-party-jwt"
# Mesh ID means Mesh Identifier. It should be unique within the scope where
# meshes will interact with each other, but it is not required to be
# globally/universally unique. For example, if any of the following are true,
# then two meshes must have different Mesh IDs:
# - Meshes will have their telemetry aggregated in one place
# - Meshes will be federated together
# - Policy will be written referencing one mesh from the other
#
# If an administrator expects that any of these conditions may become true in
# the future, they should ensure their meshes have different Mesh IDs
# assigned.
#
# Within a multicluster mesh, each cluster must be (manually or auto)
# configured to have the same Mesh ID value. If an existing cluster 'joins' a
# multicluster mesh, it will need to be migrated to the new mesh ID. Details
# 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
# mesh's Trust Domain. The best practice is to select a proper Trust Domain
# value.
meshID: ""
# Configure the mesh networks to be used by the Split Horizon EDS.
#
# The following example defines two networks with different endpoints association methods.
# For `network1` all endpoints that their IP belongs to the provided CIDR range will be
# mapped to network1. The gateway for this network example is specified by its public IP
# address and port.
# The second network, `network2`, in this example is defined differently with all endpoints
# retrieved through the specified Multi-Cluster registry being mapped to network2. The
# gateway is also defined differently with the name of the gateway service on the remote
# cluster. The public IP for the gateway will be determined from that remote service (only
# LoadBalancer gateway service type is currently supported, for a NodePort type gateway service,
# it still need to be configured manually).
#
# meshNetworks:
# network1:
# endpoints:
# - fromCidr: "192.168.0.1/24"
# gateways:
# - address: 1.1.1.1
# port: 80
# network2:
# endpoints:
# - fromRegistry: reg1
# gateways:
# - registryServiceName: istio-ingressgateway.istio-system.svc.cluster.local
# port: 443
#
meshNetworks: {}
# 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
# 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
# to properly label proxies
clusterName: ""
# 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.
# 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.
# 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.
# Setting this port to a non-zero value enables STS server.
servicePort: 0
# Configuration for each of the supported tracers
tracer:
# 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.
address: "$(HOST_IP):8126"
lightstep:
address: "" # example: lightstep-satellite:443
accessToken: "" # example: abcdefg1234567
stackdriver:
# enables trace output to stdout.
debug: false
# The global default max number of message events per span.
maxNumberOfMessageEvents: 200
# The global default max number of annotation events per span.
maxNumberOfAnnotations: 200
# The global default max number of attributes per span.
maxNumberOfAttributes: 200
zipkin:
# Host:Port for reporting trace data in zipkin format. If not specified, will default to
# zipkin service (port 9411) in the same namespace as the other istio components.
address: ""
# Use the Mesh Control Protocol (MCP) for configuring Istiod. Requires an MCP source.
useMCP: false
# 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).
caName: ""
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
ingressClass: ""
# 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.
ingressClass: "higress"
watchNamespace: ""
enableStatus: false
enableStatus: true
clusterName: ""
istioNamespace: "istio-system"
meshConfig: {}
# 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
# Config for the default ProxyConfig.
# Initially using directly the proxy metadata - can also be activated using annotations
# on the pod. This is an unsupported low-level API, pending review and decisions on
# enabling the feature. Enabling the DNS listener is safe - and allows further testing
# 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.
# 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
# Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain
trustDomain: "cluster.local"
# TODO: the intent is to eventually have this enabled by default when security is used.
# It is not clear if user should normally need to configure - the metadata is typically
# used as an escape and to control testing and rollout, but it is not intended as a long-term
# stable API.
# What we may configure in mesh config is the ".global" - and use of other suffixes.
# No hurry to do this in 1.6, we're trying to prove the code.
gateway:
name: "higress-gateway"
replicas: 2
image: gateway
tag: "bf607ae5541ce5c1cc95b4f98b3fd50a83346d33"
tag: "0.6.1"
# revision declares which revision this gateway is a part of
revision: ""
@@ -35,10 +385,6 @@ gateway:
# Pod environment variables
env: {}
# Configure the policy for validating JWT, it is used for istio authentication.
# Currently, two options are supported: "third-party-jwt" and "first-party-jwt".
jwtPolicy: "third-party-jwt"
hostNetwork: false
# Labels to apply to all resources
@@ -51,8 +397,7 @@ gateway:
prometheus.io/port: "15020"
prometheus.io/scrape: "true"
prometheus.io/path: "/stats/prometheus"
inject.istio.io/templates: "gateway"
sidecar.istio.io/inject: "true"
sidecar.istio.io/inject: "false"
# 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.
@@ -111,7 +456,7 @@ controller:
name: "higress-controller"
replicas: 1
image: higress
tag: "bf607ae5541ce5c1cc95b4f98b3fd50a83346d33"
tag: "0.6.1"
env: {}
labels: {}
@@ -191,3 +536,73 @@ controller:
maxReplicas: 5
targetCPUUtilizationPercentage: 80
## Discovery Settings
pilot:
autoscaleEnabled: false
autoscaleMin: 1
autoscaleMax: 5
replicaCount: 1
rollingMaxSurge: 100%
rollingMaxUnavailable: 25%
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
tag: 0.6.1
# Can be a full hub/image:tag
image: pilot
traceSampling: 1.0
# Resources for a small pilot install
resources:
requests:
cpu: 500m
memory: 2048Mi
env:
PILOT_SCOPE_GATEWAY_TO_NAMESPACE: "true"
PILOT_ENABLE_METADATA_EXCHANGE: "false"
PILOT_ENABLE_CROSS_CLUSTER_WORKLOAD_ENTRY: "false"
VALIDATION_ENABLED: "false"
cpu:
targetAverageUtilization: 80
# if protocol sniffing is enabled for outbound
enableProtocolSniffingForOutbound: true
# if protocol sniffing is enabled for inbound
enableProtocolSniffingForInbound: true
nodeSelector: {}
podAnnotations: {}
serviceAnnotations: {}
# 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
# the associated address in configSource, if nothing is specificed
# the default MCP is assumed.
configSource:
subscribedResources: []
plugins: []
# 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.
deploymentLabels: {}
## Mesh config settings
# 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.
podLabels: {}

View File

@@ -1,5 +1,5 @@
apiVersion: v2
appVersion: 1.12.3
appVersion: 1.12.4
description: Helm chart for deploying higress istio
name: istio
sources:
@@ -12,4 +12,4 @@ dependencies:
repository: "file://../istiod"
version: 1.12.0
type: application
version: 1.12.3
version: 1.12.4

View File

@@ -0,0 +1,215 @@
{{- $containers := list }}
{{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}}
metadata:
labels:
service.istio.io/canonical-name: {{ index .ObjectMeta.Labels `service.istio.io/canonical-name` | default (index .ObjectMeta.Labels `app.kubernetes.io/name`) | default (index .ObjectMeta.Labels `app`) | default .DeploymentMeta.Name | quote }}
service.istio.io/canonical-revision: {{ index .ObjectMeta.Labels `service.istio.io/canonical-revision` | default (index .ObjectMeta.Labels `app.kubernetes.io/version`) | default (index .ObjectMeta.Labels `version`) | default "latest" | quote }}
istio.io/rev: {{ .Revision | default "default" | quote }}
annotations: {
{{- if eq (len $containers) 1 }}
kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}",
kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}",
{{ end }}
}
spec:
containers:
- name: istio-proxy
{{- if contains "/" .Values.global.proxy.image }}
image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"
{{- else }}
image: "{{ .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}"
{{- end }}
ports:
- containerPort: 15090
protocol: TCP
name: http-envoy-prom
args:
- proxy
- router
- --domain
- $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }}
- --proxyLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel }}
- --proxyComponentLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel }}
- --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }}
{{- if .Values.global.sts.servicePort }}
- --stsPort={{ .Values.global.sts.servicePort }}
{{- end }}
{{- if .Values.global.logAsJson }}
- --log_as_json
{{- end }}
{{- if .Values.global.proxy.lifecycle }}
lifecycle:
{{ toYaml .Values.global.proxy.lifecycle | indent 6 }}
{{- end }}
env:
- name: JWT_POLICY
value: {{ .Values.global.jwtPolicy }}
- name: PILOT_CERT_PROVIDER
value: {{ .Values.global.pilotCertProvider }}
- name: CA_ADDR
{{- if .Values.global.caAddress }}
value: {{ .Values.global.caAddress }}
{{- else }}
value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: PROXY_CONFIG
value: |
{{ protoToJSON .ProxyConfig }}
- name: ISTIO_META_POD_PORTS
value: |-
[
{{- $first := true }}
{{- range $index1, $c := .Spec.Containers }}
{{- range $index2, $p := $c.Ports }}
{{- if (structToJSON $p) }}
{{if not $first}},{{end}}{{ structToJSON $p }}
{{- $first = false }}
{{- end }}
{{- end}}
{{- end}}
]
- name: ISTIO_META_APP_CONTAINERS
value: "{{ $containers | join "," }}"
- name: ISTIO_META_CLUSTER_ID
value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}"
- name: ISTIO_META_INTERCEPTION_MODE
value: "{{ .ProxyConfig.InterceptionMode.String }}"
{{- if .Values.global.network }}
- name: ISTIO_META_NETWORK
value: "{{ .Values.global.network }}"
{{- end }}
{{- if .DeploymentMeta.Name }}
- name: ISTIO_META_WORKLOAD_NAME
value: "{{ .DeploymentMeta.Name }}"
{{ end }}
{{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }}
- name: ISTIO_META_OWNER
value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }}
{{- end}}
{{- if .Values.global.meshID }}
- name: ISTIO_META_MESH_ID
value: "{{ .Values.global.meshID }}"
{{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
- name: ISTIO_META_MESH_ID
value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}"
{{- end }}
{{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
- name: TRUST_DOMAIN
value: "{{ . }}"
{{- end }}
{{- range $key, $value := .ProxyConfig.ProxyMetadata }}
- name: {{ $key }}
value: "{{ $value }}"
{{- end }}
{{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}}
readinessProbe:
httpGet:
path: /healthz/ready
port: 15021
initialDelaySeconds: {{.Values.global.proxy.readinessInitialDelaySeconds }}
periodSeconds: {{ .Values.global.proxy.readinessPeriodSeconds }}
timeoutSeconds: 3
failureThreshold: {{ .Values.global.proxy.readinessFailureThreshold }}
volumeMounts:
{{- if eq .Values.global.caName "GkeWorkloadCertificate" }}
- name: gke-workload-certificate
mountPath: /var/run/secrets/workload-spiffe-credentials
readOnly: true
{{- end }}
{{- if eq .Values.global.pilotCertProvider "istiod" }}
- mountPath: /var/run/secrets/istio
name: istiod-ca-cert
{{- end }}
- mountPath: /var/lib/istio/data
name: istio-data
# SDS channel between istioagent and Envoy
- mountPath: /etc/istio/proxy
name: istio-envoy
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- mountPath: /var/run/secrets/tokens
name: istio-token
{{- end }}
{{- if .Values.global.mountMtlsCerts }}
# Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications.
- mountPath: /etc/certs/
name: istio-certs
readOnly: true
{{- end }}
- name: istio-podinfo
mountPath: /etc/istio/pod
volumes:
{{- if eq .Values.global.caName "GkeWorkloadCertificate" }}
- name: gke-workload-certificate
csi:
driver: workloadcertificates.security.cloud.google.com
{{- end }}
# SDS channel between istioagent and Envoy
- emptyDir:
medium: Memory
name: istio-envoy
- name: istio-data
emptyDir: {}
- name: istio-podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
projected:
sources:
- serviceAccountToken:
path: istio-token
expirationSeconds: 43200
audience: {{ .Values.global.sds.token.aud }}
{{- end }}
{{- if eq .Values.global.pilotCertProvider "istiod" }}
- name: istiod-ca-cert
configMap:
name: istio-ca-root-cert
{{- end }}
{{- if .Values.global.mountMtlsCerts }}
# Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications.
- name: istio-certs
secret:
optional: true
{{ if eq .Spec.ServiceAccountName "" }}
secretName: istio.default
{{ else -}}
secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }}
{{ end -}}
{{- end }}
{{- if .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range .Values.global.imagePullSecrets }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- if eq (env "ENABLE_LEGACY_FSGROUP_INJECTION" "true") "true" }}
securityContext:
fsGroup: 1337
{{- end }}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,233 @@
{{- $containers := list }}
{{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}}
metadata:
annotations: {
{{- if eq (len $containers) 1 }}
kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}",
kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}",
{{ end }}
sidecar.istio.io/rewriteAppHTTPProbers: "false",
}
spec:
containers:
{{- range $index, $container := .Spec.Containers }}
{{ if not (eq $container.Name "istio-proxy") }}
- name: {{ $container.Name }}
env:
- name: "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
value: "true"
- name: "GRPC_XDS_BOOTSTRAP"
value: "/etc/istio/proxy/grpc-bootstrap.json"
volumeMounts:
- mountPath: /var/lib/istio/data
name: istio-data
# UDS channel between istioagent and gRPC client for XDS/SDS
- mountPath: /etc/istio/proxy
name: istio-xds
{{- end }}
{{- end }}
- name: istio-proxy
{{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }}
image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"
{{- else }}
image: "{{ .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}"
{{- end }}
args:
- proxy
- sidecar
- --domain
- $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }}
- --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }}
{{- if .Values.global.sts.servicePort }}
- --stsPort={{ .Values.global.sts.servicePort }}
{{- end }}
{{- if .Values.global.logAsJson }}
- --log_as_json
{{- end }}
env:
- name: ISTIO_META_GENERATOR
value: grpc
- name: OUTPUT_CERTS
value: /var/lib/istio/data
{{- if eq (env "PILOT_ENABLE_INBOUND_PASSTHROUGH" "true") "false" }}
- name: REWRITE_PROBE_LEGACY_LOCALHOST_DESTINATION
value: "true"
{{- end }}
- name: JWT_POLICY
value: {{ .Values.global.jwtPolicy }}
- name: PILOT_CERT_PROVIDER
value: {{ .Values.global.pilotCertProvider }}
- name: CA_ADDR
{{- if .Values.global.caAddress }}
value: {{ .Values.global.caAddress }}
{{- else }}
value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: PROXY_CONFIG
value: |
{{ protoToJSON .ProxyConfig }}
- name: ISTIO_META_POD_PORTS
value: |-
[
{{- $first := true }}
{{- range $index1, $c := .Spec.Containers }}
{{- range $index2, $p := $c.Ports }}
{{- if (structToJSON $p) }}
{{if not $first}},{{end}}{{ structToJSON $p }}
{{- $first = false }}
{{- end }}
{{- end}}
{{- end}}
]
- name: ISTIO_META_APP_CONTAINERS
value: "{{ $containers | join "," }}"
- name: ISTIO_META_CLUSTER_ID
value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}"
- name: ISTIO_META_INTERCEPTION_MODE
value: "{{ or (index .ObjectMeta.Annotations `sidecar.istio.io/interceptionMode`) .ProxyConfig.InterceptionMode.String }}"
{{- if .Values.global.network }}
- name: ISTIO_META_NETWORK
value: "{{ .Values.global.network }}"
{{- end }}
{{- if .DeploymentMeta.Name }}
- name: ISTIO_META_WORKLOAD_NAME
value: "{{ .DeploymentMeta.Name }}"
{{ end }}
{{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }}
- name: ISTIO_META_OWNER
value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }}
{{- end}}
{{- if .Values.global.meshID }}
- name: ISTIO_META_MESH_ID
value: "{{ .Values.global.meshID }}"
{{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
- name: ISTIO_META_MESH_ID
value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}"
{{- end }}
{{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
- name: TRUST_DOMAIN
value: "{{ . }}"
{{- end }}
{{- range $key, $value := .ProxyConfig.ProxyMetadata }}
- name: {{ $key }}
value: "{{ $value }}"
{{- end }}
# grpc uses xds:/// to resolve no need to resolve VIP
- name: ISTIO_META_DNS_CAPTURE
value: "false"
- name: DISABLE_ENVOY
value: "true"
{{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}}
{{ if ne (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) `0` }}
readinessProbe:
httpGet:
path: /healthz/ready
port: {{ .Values.global.proxy.statusPort }}
initialDelaySeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/initialDelaySeconds` .Values.global.proxy.readinessInitialDelaySeconds }}
periodSeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/periodSeconds` .Values.global.proxy.readinessPeriodSeconds }}
timeoutSeconds: 3
failureThreshold: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/failureThreshold` .Values.global.proxy.readinessFailureThreshold }}
{{ end -}}
resources:
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }}
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) }}
requests:
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}}
cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}"
{{ end }}
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}}
memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}"
{{ end }}
{{- end }}
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }}
limits:
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) -}}
cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit` }}"
{{ end }}
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) -}}
memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit` }}"
{{ end }}
{{- end }}
{{- else }}
{{- if .Values.global.proxy.resources }}
{{ toYaml .Values.global.proxy.resources | indent 6 }}
{{- end }}
{{- end }}
volumeMounts:
{{- if eq .Values.global.pilotCertProvider "istiod" }}
- mountPath: /var/run/secrets/istio
name: istiod-ca-cert
{{- end }}
- mountPath: /var/lib/istio/data
name: istio-data
# UDS channel between istioagent and gRPC client for XDS/SDS
- mountPath: /etc/istio/proxy
name: istio-xds
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- mountPath: /var/run/secrets/tokens
name: istio-token
{{- end }}
- name: istio-podinfo
mountPath: /etc/istio/pod
{{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount` }}
{{ range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount`) }}
- name: "{{ $index }}"
{{ toYaml $value | indent 6 }}
{{ end }}
{{- end }}
volumes:
# UDS channel between istioagent and gRPC client for XDS/SDS
- emptyDir:
medium: Memory
name: istio-xds
- name: istio-data
emptyDir: {}
- name: istio-podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
projected:
sources:
- serviceAccountToken:
path: istio-token
expirationSeconds: 43200
audience: {{ .Values.global.sds.token.aud }}
{{- end }}
{{- if eq .Values.global.pilotCertProvider "istiod" }}
- name: istiod-ca-cert
configMap:
name: istio-ca-root-cert
{{- end }}
{{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolume` }}
{{range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolume`) }}
- name: "{{ $index }}"
{{ toYaml $value | indent 4 }}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,64 @@
metadata:
sidecar.istio.io/rewriteAppHTTPProbers: "false"
spec:
initContainers:
- name: grpc-bootstrap-init
image: busybox:1.28
volumeMounts:
- mountPath: /var/lib/grpc/data/
name: grpc-io-proxyless-bootstrap
env:
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: ISTIO_NAMESPACE
value: |
{{ .Values.global.istioNamespace }}
command:
- sh
- "-c"
- |-
NODE_ID="sidecar~${INSTANCE_IP}~${POD_NAME}.${POD_NAMESPACE}~cluster.local"
SERVER_URI="dns:///istiod.${ISTIO_NAMESPACE}.svc:15010"
echo '
{
"xds_servers": [
{
"server_uri": "'${SERVER_URI}'",
"channel_creds": [{"type": "insecure"}],
"server_features" : ["xds_v3"]
}
],
"node": {
"id": "'${NODE_ID}'",
"metadata": {
"GENERATOR": "grpc"
}
}
}' > /var/lib/grpc/data/bootstrap.json
containers:
{{- range $index, $container := .Spec.Containers }}
- name: {{ $container.Name }}
env:
- name: GRPC_XDS_BOOTSTRAP
value: /var/lib/grpc/data/bootstrap.json
- name: GRPC_GO_LOG_VERBOSITY_LEVEL
value: "99"
- name: GRPC_GO_LOG_SEVERITY_LEVEL
value: info
volumeMounts:
- mountPath: /var/lib/grpc/data/
name: grpc-io-proxyless-bootstrap
{{- end }}
volumes:
- name: grpc-io-proxyless-bootstrap
emptyDir: {}

View File

@@ -0,0 +1,491 @@
{{- $containers := list }}
{{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}}
metadata:
labels:
security.istio.io/tlsMode: {{ index .ObjectMeta.Labels `security.istio.io/tlsMode` | default "istio" | quote }}
service.istio.io/canonical-name: {{ index .ObjectMeta.Labels `service.istio.io/canonical-name` | default (index .ObjectMeta.Labels `app.kubernetes.io/name`) | default (index .ObjectMeta.Labels `app`) | default .DeploymentMeta.Name | quote }}
service.istio.io/canonical-revision: {{ index .ObjectMeta.Labels `service.istio.io/canonical-revision` | default (index .ObjectMeta.Labels `app.kubernetes.io/version`) | default (index .ObjectMeta.Labels `version`) | default "latest" | quote }}
annotations: {
{{- if eq (len $containers) 1 }}
kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}",
kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}",
{{ end }}
{{- if .Values.istio_cni.enabled }}
{{- if not .Values.istio_cni.chained }}
k8s.v1.cni.cncf.io/networks: '{{ appendMultusNetwork (index .ObjectMeta.Annotations `k8s.v1.cni.cncf.io/networks`) `istio-cni` }}',
{{- end }}
sidecar.istio.io/interceptionMode: "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}",
{{ with annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}traffic.sidecar.istio.io/includeOutboundIPRanges: "{{.}}",{{ end }}
{{ with annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}traffic.sidecar.istio.io/excludeOutboundIPRanges: "{{.}}",{{ end }}
traffic.sidecar.istio.io/includeInboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` `*` }}",
traffic.sidecar.istio.io/excludeInboundPorts: "{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}",
{{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/includeOutboundPorts`) (ne (valueOrDefault .Values.global.proxy.includeOutboundPorts "") "") }}
traffic.sidecar.istio.io/includeOutboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundPorts` .Values.global.proxy.includeOutboundPorts }}",
{{- end }}
{{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne .Values.global.proxy.excludeOutboundPorts "") }}
traffic.sidecar.istio.io/excludeOutboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}",
{{- end }}
{{ with index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}traffic.sidecar.istio.io/kubevirtInterfaces: "{{.}}",{{ end }}
{{- end }}
}
spec:
{{- $holdProxy := or .ProxyConfig.HoldApplicationUntilProxyStarts.GetValue .Values.global.proxy.holdApplicationUntilProxyStarts }}
initContainers:
{{ if ne (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `NONE` }}
{{ if .Values.istio_cni.enabled -}}
- name: istio-validation
{{ else -}}
- name: istio-init
{{ end -}}
{{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image) }}
image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}"
{{- else }}
image: "{{ .Values.global.hub }}/{{ .Values.global.proxy_init.image }}:{{ .Values.global.tag }}"
{{- end }}
args:
- istio-iptables
- "-p"
- {{ .MeshConfig.ProxyListenPort | default "15001" | quote }}
- "-z"
- "15006"
- "-u"
- "1337"
- "-m"
- "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}"
- "-i"
- "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}"
- "-x"
- "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}"
- "-b"
- "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` `*` }}"
- "-d"
{{- if excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}
- "15090,15021,{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}"
{{- else }}
- "15090,15021"
{{- end }}
{{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/includeOutboundPorts`) (ne (valueOrDefault .Values.global.proxy.includeOutboundPorts "") "") -}}
- "-q"
- "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundPorts` .Values.global.proxy.includeOutboundPorts }}"
{{ end -}}
{{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne (valueOrDefault .Values.global.proxy.excludeOutboundPorts "") "") -}}
- "-o"
- "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}"
{{ end -}}
{{ if (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces`) -}}
- "-k"
- "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}"
{{ end -}}
{{ if .Values.istio_cni.enabled -}}
- "--run-validation"
- "--skip-rule-apply"
{{ end -}}
{{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}}
{{- if .ProxyConfig.ProxyMetadata }}
env:
{{- range $key, $value := .ProxyConfig.ProxyMetadata }}
- name: {{ $key }}
value: "{{ $value }}"
{{- end }}
{{- end }}
resources:
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }}
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) }}
requests:
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}}
cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}"
{{ end }}
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}}
memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}"
{{ end }}
{{- end }}
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }}
limits:
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) -}}
cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit` }}"
{{ end }}
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) -}}
memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit` }}"
{{ end }}
{{- end }}
{{- else }}
{{- if .Values.global.proxy.resources }}
{{ toYaml .Values.global.proxy.resources | indent 6 }}
{{- end }}
{{- end }}
securityContext:
allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }}
privileged: {{ .Values.global.proxy.privileged }}
capabilities:
{{- if not .Values.istio_cni.enabled }}
add:
- NET_ADMIN
- NET_RAW
{{- end }}
drop:
- ALL
{{- if not .Values.istio_cni.enabled }}
readOnlyRootFilesystem: false
runAsGroup: 0
runAsNonRoot: false
runAsUser: 0
{{- else }}
readOnlyRootFilesystem: true
runAsGroup: 1337
runAsUser: 1337
runAsNonRoot: true
{{- end }}
restartPolicy: Always
{{ end -}}
{{- if eq (annotation .ObjectMeta `sidecar.istio.io/enableCoreDump` .Values.global.proxy.enableCoreDump) "true" }}
- name: enable-core-dump
args:
- -c
- sysctl -w kernel.core_pattern=/var/lib/istio/data/core.proxy && ulimit -c unlimited
command:
- /bin/sh
{{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image) }}
image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy_init.image }}"
{{- else }}
image: "{{ .Values.global.hub }}/{{ .Values.global.proxy_init.image }}:{{ .Values.global.tag }}"
{{- end }}
{{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}}
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- SYS_ADMIN
drop:
- ALL
privileged: true
readOnlyRootFilesystem: false
runAsGroup: 0
runAsNonRoot: false
runAsUser: 0
{{ end }}
containers:
- name: istio-proxy
{{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }}
image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"
{{- else }}
image: "{{ .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}"
{{- end }}
ports:
- containerPort: 15090
protocol: TCP
name: http-envoy-prom
args:
- proxy
- sidecar
- --domain
- $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }}
- --proxyLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel }}
- --proxyComponentLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel }}
- --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }}
{{- if .Values.global.sts.servicePort }}
- --stsPort={{ .Values.global.sts.servicePort }}
{{- end }}
{{- if .Values.global.logAsJson }}
- --log_as_json
{{- end }}
{{- if gt .EstimatedConcurrency 0 }}
- --concurrency
- "{{ .EstimatedConcurrency }}"
{{- end -}}
{{- if .Values.global.proxy.lifecycle }}
lifecycle:
{{ toYaml .Values.global.proxy.lifecycle | indent 6 }}
{{- else if $holdProxy }}
lifecycle:
postStart:
exec:
command:
- pilot-agent
- wait
{{- end }}
env:
{{- if eq (env "PILOT_ENABLE_INBOUND_PASSTHROUGH" "true") "false" }}
- name: REWRITE_PROBE_LEGACY_LOCALHOST_DESTINATION
value: "true"
{{- end }}
- name: JWT_POLICY
value: {{ .Values.global.jwtPolicy }}
- name: PILOT_CERT_PROVIDER
value: {{ .Values.global.pilotCertProvider }}
- name: CA_ADDR
{{- if .Values.global.caAddress }}
value: {{ .Values.global.caAddress }}
{{- else }}
value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: PROXY_CONFIG
value: |
{{ protoToJSON .ProxyConfig }}
- name: ISTIO_META_POD_PORTS
value: |-
[
{{- $first := true }}
{{- range $index1, $c := .Spec.Containers }}
{{- range $index2, $p := $c.Ports }}
{{- if (structToJSON $p) }}
{{if not $first}},{{end}}{{ structToJSON $p }}
{{- $first = false }}
{{- end }}
{{- end}}
{{- end}}
]
- name: ISTIO_META_APP_CONTAINERS
value: "{{ $containers | join "," }}"
- name: ISTIO_META_CLUSTER_ID
value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}"
- name: ISTIO_META_INTERCEPTION_MODE
value: "{{ or (index .ObjectMeta.Annotations `sidecar.istio.io/interceptionMode`) .ProxyConfig.InterceptionMode.String }}"
{{- if .Values.global.network }}
- name: ISTIO_META_NETWORK
value: "{{ .Values.global.network }}"
{{- end }}
{{- if .DeploymentMeta.Name }}
- name: ISTIO_META_WORKLOAD_NAME
value: "{{ .DeploymentMeta.Name }}"
{{ end }}
{{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }}
- name: ISTIO_META_OWNER
value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }}
{{- end}}
{{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }}
- name: ISTIO_BOOTSTRAP_OVERRIDE
value: "/etc/istio/custom-bootstrap/custom_bootstrap.json"
{{- end }}
{{- if .Values.global.meshID }}
- name: ISTIO_META_MESH_ID
value: "{{ .Values.global.meshID }}"
{{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
- name: ISTIO_META_MESH_ID
value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}"
{{- end }}
{{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
- name: TRUST_DOMAIN
value: "{{ . }}"
{{- end }}
{{- if and (eq .Values.global.proxy.tracer "datadog") (isset .ObjectMeta.Annotations `apm.datadoghq.com/env`) }}
{{- range $key, $value := fromJSON (index .ObjectMeta.Annotations `apm.datadoghq.com/env`) }}
- name: {{ $key }}
value: "{{ $value }}"
{{- end }}
{{- end }}
{{- range $key, $value := .ProxyConfig.ProxyMetadata }}
- name: {{ $key }}
value: "{{ $value }}"
{{- end }}
{{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}}
{{ if ne (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) `0` }}
readinessProbe:
httpGet:
path: /healthz/ready
port: 15021
initialDelaySeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/initialDelaySeconds` .Values.global.proxy.readinessInitialDelaySeconds }}
periodSeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/periodSeconds` .Values.global.proxy.readinessPeriodSeconds }}
timeoutSeconds: 3
failureThreshold: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/failureThreshold` .Values.global.proxy.readinessFailureThreshold }}
{{ end -}}
securityContext:
{{- if eq (index .ProxyConfig.ProxyMetadata "IPTABLES_TRACE_LOGGING") "true" }}
allowPrivilegeEscalation: true
capabilities:
add:
- NET_ADMIN
drop:
- ALL
privileged: true
readOnlyRootFilesystem: {{ ne (annotation .ObjectMeta `sidecar.istio.io/enableCoreDump` .Values.global.proxy.enableCoreDump) "true" }}
runAsGroup: 1337
fsGroup: 1337
runAsNonRoot: false
runAsUser: 0
{{- else }}
allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }}
capabilities:
{{ if or (eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY`) (eq (annotation .ObjectMeta `sidecar.istio.io/capNetBindService` .Values.global.proxy.capNetBindService) `true`) -}}
add:
{{ if eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY` -}}
- NET_ADMIN
{{- end }}
{{ if eq (annotation .ObjectMeta `sidecar.istio.io/capNetBindService` .Values.global.proxy.capNetBindService) `true` -}}
- NET_BIND_SERVICE
{{- end }}
{{- end }}
drop:
- ALL
privileged: {{ .Values.global.proxy.privileged }}
readOnlyRootFilesystem: {{ ne (annotation .ObjectMeta `sidecar.istio.io/enableCoreDump` .Values.global.proxy.enableCoreDump) "true" }}
runAsGroup: 1337
fsGroup: 1337
{{ if or (eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY`) (eq (annotation .ObjectMeta `sidecar.istio.io/capNetBindService` .Values.global.proxy.capNetBindService) `true`) -}}
runAsNonRoot: false
runAsUser: 0
{{- else -}}
runAsNonRoot: true
runAsUser: 1337
{{- end }}
{{- end }}
resources:
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }}
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) }}
requests:
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}}
cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}"
{{ end }}
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}}
memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}"
{{ end }}
{{- end }}
{{- if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) }}
limits:
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit`) -}}
cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPULimit` }}"
{{ end }}
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit`) -}}
memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemoryLimit` }}"
{{ end }}
{{- end }}
{{- else }}
{{- if .Values.global.proxy.resources }}
{{ toYaml .Values.global.proxy.resources | indent 6 }}
{{- end }}
{{- end }}
volumeMounts:
{{- if eq .Values.global.caName "GkeWorkloadCertificate" }}
- name: gke-workload-certificate
mountPath: /var/run/secrets/workload-spiffe-credentials
readOnly: true
{{- end }}
{{- if eq .Values.global.pilotCertProvider "istiod" }}
- mountPath: /var/run/secrets/istio
name: istiod-ca-cert
{{- end }}
- mountPath: /var/lib/istio/data
name: istio-data
{{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }}
- mountPath: /etc/istio/custom-bootstrap
name: custom-bootstrap-volume
{{- end }}
# SDS channel between istioagent and Envoy
- mountPath: /etc/istio/proxy
name: istio-envoy
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- mountPath: /var/run/secrets/tokens
name: istio-token
{{- end }}
{{- if .Values.global.mountMtlsCerts }}
# Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications.
- mountPath: /etc/certs/
name: istio-certs
readOnly: true
{{- end }}
- name: istio-podinfo
mountPath: /etc/istio/pod
{{- if and (eq .Values.global.proxy.tracer "lightstep") .ProxyConfig.GetTracing.GetTlsSettings }}
- mountPath: {{ directory .ProxyConfig.GetTracing.GetTlsSettings.GetCaCertificates }}
name: lightstep-certs
readOnly: true
{{- end }}
{{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount` }}
{{ range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount`) }}
- name: "{{ $index }}"
{{ toYaml $value | indent 6 }}
{{ end }}
{{- end }}
volumes:
{{- if eq .Values.global.caName "GkeWorkloadCertificate" }}
- name: gke-workload-certificate
csi:
driver: workloadcertificates.security.cloud.google.com
{{- end }}
{{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }}
- name: custom-bootstrap-volume
configMap:
name: {{ annotation .ObjectMeta `sidecar.istio.io/bootstrapOverride` "" }}
{{- end }}
# SDS channel between istioagent and Envoy
- emptyDir:
medium: Memory
name: istio-envoy
- name: istio-data
emptyDir: {}
- name: istio-podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
{{- if eq .Values.global.jwtPolicy "third-party-jwt" }}
- name: istio-token
projected:
sources:
- serviceAccountToken:
path: istio-token
expirationSeconds: 43200
audience: {{ .Values.global.sds.token.aud }}
{{- end }}
{{- if eq .Values.global.pilotCertProvider "istiod" }}
- name: istiod-ca-cert
configMap:
name: istio-ca-root-cert
{{- end }}
{{- if .Values.global.mountMtlsCerts }}
# Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications.
- name: istio-certs
secret:
optional: true
{{ if eq .Spec.ServiceAccountName "" }}
secretName: istio.default
{{ else -}}
secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }}
{{ end -}}
{{- end }}
{{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolume` }}
{{range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolume`) }}
- name: "{{ $index }}"
{{ toYaml $value | indent 4 }}
{{ end }}
{{ end }}
{{- if and (eq .Values.global.proxy.tracer "lightstep") .ProxyConfig.GetTracing.GetTlsSettings }}
- name: lightstep-certs
secret:
optional: true
secretName: lightstep.cacert
{{- end }}
{{- if .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range .Values.global.imagePullSecrets }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- if eq (env "ENABLE_LEGACY_FSGROUP_INJECTION" "true") "true" }}
securityContext:
fsGroup: 1337
{{- end }}

View File

@@ -1,5 +1,5 @@
{{- if and .Values.pilot.autoscaleEnabled .Values.pilot.autoscaleMin .Values.pilot.autoscaleMax }}
{{- if not .Values.global.autoscalingv2API }}
{{- if not .Values.extra.autoscalingv2API }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:

View File

@@ -19,7 +19,7 @@
configSources:
- address: k8s://
- address: {{ printf "xds://%s.%s:%s" .Values.global.higressName .Values.global.higressNamespace .Values.global.higressPort }}
- address: {{ printf "xds://%s.%s:%s" .Values.extra.higressName .Values.extra.higressNamespace .Values.extra.higressPort }}
defaultConfig:
{{- if .Values.global.meshID }}

View File

@@ -113,9 +113,9 @@ spec:
timeoutSeconds: 5
env:
- name: HIGRESS_CONTROLLER_SVC
value: {{ printf "%s.%s" .Values.global.higressName .Values.global.higressNamespace }}
value: {{ printf "%s.%s" .Values.extra.higressName .Values.extra.higressNamespace }}
- name: HIGRESS_CONTROLLER_PORT
value: "{{ .Values.global.higressPort }}"
value: "{{ .Values.extra.higressPort }}"
- name: REVISION
value: "{{ .Values.revision | default `default` }}"
- name: JWT_POLICY
@@ -159,7 +159,7 @@ spec:
value: "{{ .Values.global.istiod.enableAnalysis }}"
- name: CLUSTER_ID
value: "{{ $.Values.global.multiCluster.clusterName | default `Kubernetes` }}"
{{- if not .Values.global.kind }}
{{- if not .Values.extra.kind }}
resources:
{{- if .Values.pilot.resources }}
{{ toYaml .Values.pilot.resources | trim | indent 12 }}

View File

@@ -10,7 +10,7 @@ pilot:
rollingMaxUnavailable: 25%
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
tag: bf607ae5541ce5c1cc95b4f98b3fd50a83346d33
tag: 0.6.1
# Can be a full hub/image:tag
image: pilot
@@ -220,7 +220,7 @@ meshConfig:
# What we may configure in mesh config is the ".global" - and use of other suffixes.
# No hurry to do this in 1.6, we're trying to prove the code.
global:
extra:
kind: false
# whether to use autoscaling/v2 template for HPA settings
# for internal usage only, not to be configured by users.
@@ -228,6 +228,8 @@ global:
higressName: "higress-controller"
higressNamespace: "higress-system"
higressPort: "15051"
global:
# Used to locate istiod.
istioNamespace: istio-system
# enable pod disruption budget for the control plane, which is used to
@@ -254,7 +256,7 @@ global:
# Dev builds from prow are on gcr.io
hub: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress
# Default tag for Istio images.
tag: bf607ae5541ce5c1cc95b4f98b3fd50a83346d33
tag: 0.6.1
# Specify image pull policy if default behavior isn't desired.
# Default behavior: latest images will be Always else IfNotPresent.

View File

@@ -1,6 +1,6 @@
dependencies:
- name: higress
repository: file://../../higress
version: 0.5.3
digest: sha256:31fd001a558b73f3a5b86d607ccf2c4ff7f206fc232068cfc6722ccd02081031
generated: "2022-12-16T17:21:23.630507+08:00"
version: 0.6.1
digest: sha256:35e6287d96a2268039a5b2a2fee5413424616275211bc46aec3f7ff0256c00e5
generated: "2023-02-03T16:36:04.629269+08:00"

View File

@@ -1,5 +1,5 @@
apiVersion: v2
appVersion: 0.5.3
appVersion: 0.6.1
description: Helm chart for deploying higress gateways
icon: https://higress.io/img/higress_logo_small.png
keywords:
@@ -11,6 +11,6 @@ sources:
dependencies:
- name: higress
repository: "file://../../higress"
version: 0.5.3
version: 0.6.1
type: application
version: 0.5.3
version: 0.6.1

View File

@@ -1,5 +1,5 @@
apiVersion: v2
appVersion: 1.12.3
appVersion: 1.12.4
description: Helm chart for deploying higress istio
name: istio-local
sources:
@@ -12,4 +12,4 @@ dependencies:
repository: "file://../../istiod"
version: 1.12.0
type: application
version: 1.12.3
version: 1.12.4

View File

@@ -0,0 +1,30 @@
diff -Naur istio/pilot/pkg/features/pilot.go istio_new/pilot/pkg/features/pilot.go
--- istio/pilot/pkg/features/pilot.go 2023-01-19 11:17:16.000000000 +0800
+++ istio_new/pilot/pkg/features/pilot.go 2023-01-19 11:03:37.000000000 +0800
@@ -562,6 +562,11 @@
PrioritizedLeaderElection = env.RegisterBoolVar("PRIORITIZED_LEADER_ELECTION", true,
"If enabled, the default revision will steal leader locks from non-default revisions").Get()
+
+ // Added by ingress
+ CustomCACertConfigMapName = env.RegisterStringVar("CUSTOM_CA_CERT_NAME", "",
+ "Defines the configmap's name of istio's root ca certificate").Get()
+ // End added by ingress
)
// UnsafeFeaturesEnabled returns true if any unsafe features are enabled.
diff -Naur istio/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go istio_new/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go
--- istio/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go 2023-01-19 11:17:19.000000000 +0800
+++ istio_new/pilot/pkg/serviceregistry/kube/controller/namespacecontroller.go 2023-01-19 11:20:32.000000000 +0800
@@ -50,6 +50,11 @@
if features.ClusterName != "" && features.ClusterName != "Kubernetes" {
dynamicCACertNamespaceConfigMap = fmt.Sprintf("%s-ca-root-cert", features.ClusterName)
}
+ // Added by ingress
+ if features.CustomCACertConfigMapName != "" {
+ dynamicCACertNamespaceConfigMap = features.CustomCACertConfigMapName
+ }
+ // End added by ingress
}
// NamespaceController manages reconciles a configmap in each namespace with a desired set of data.

View File

@@ -25,6 +25,7 @@ import (
"google.golang.org/grpc/reflection"
"istio.io/api/mesh/v1alpha1"
configaggregate "istio.io/istio/pilot/pkg/config/aggregate"
"istio.io/istio/pilot/pkg/features"
istiogrpc "istio.io/istio/pilot/pkg/grpc"
"istio.io/istio/pilot/pkg/model"
"istio.io/istio/pilot/pkg/server"
@@ -37,6 +38,9 @@ import (
"istio.io/istio/pkg/config/schema/gvk"
"istio.io/istio/pkg/keepalive"
istiokube "istio.io/istio/pkg/kube"
"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/env"
"istio.io/pkg/ledger"
"istio.io/pkg/log"
@@ -84,12 +88,20 @@ type RegistryOptions struct {
}
type ServerArgs struct {
Debug bool
MeshId string
RegionId string
NativeIstio bool
HttpAddress string
GrpcAddress string
Debug bool
MeshId string
RegionId string
NativeIstio bool
HttpAddress string
GrpcAddress string
// 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.
IngressClass string
EnableStatus bool
WatchNamespace string
@@ -103,6 +115,11 @@ type ServerArgs struct {
type readinessProbe func() (bool, error)
type ServerInterface interface {
Start(stop <-chan struct{}) error
WaitUntilCompletion()
}
type Server struct {
*ServerArgs
environment *model.Environment
@@ -149,6 +166,7 @@ func NewServer(args *ServerArgs) (*Server, error) {
s.initHttpServer,
s.initConfigController,
s.initRegistryEventHandlers,
s.initAuthenticators,
}
for _, f := range initFuncList {
@@ -156,6 +174,7 @@ func NewServer(args *ServerArgs) (*Server, error) {
return nil, err
}
}
s.server.RunComponent(func(stop <-chan struct{}) error {
s.kubeClient.RunAndWait(stop)
return nil
@@ -223,7 +242,9 @@ func (s *Server) initConfigController() error {
// Defer starting the controller until after the service is created.
s.server.RunComponent(func(stop <-chan struct{}) error {
ingressConfig.InitializeCluster(ingressController, stop)
if err := ingressConfig.InitializeCluster(ingressController, stop); err != nil {
return err
}
go s.configController.Run(stop)
return nil
})
@@ -316,8 +337,7 @@ func (s *Server) initXdsServer() error {
s.xdsServer.Start(stop)
return nil
})
s.initGrpcServer()
return nil
return s.initGrpcServer()
}
func (s *Server) initGrpcServer() error {
@@ -332,6 +352,18 @@ func (s *Server) initGrpcServer() error {
return nil
}
func (s *Server) initAuthenticators() error {
authenticators := []security.Authenticator{
&authenticate.ClientCertAuthenticator{},
}
authenticators = append(authenticators,
kubeauth.NewKubeJWTAuthenticator(s.environment.Watcher, s.kubeClient, s.RegistryOptions.KubeOptions.ClusterID, nil, features.JwtPolicy))
if features.XDSAuth {
s.xdsServer.Authenticators = authenticators
}
return nil
}
func (s *Server) initKubeClient() error {
if s.kubeClient != nil {
// Already initialized by startup arguments
@@ -363,6 +395,7 @@ func (s *Server) initHttpServer() error {
return nil
}
// readyHandler checks whether the http server is ready
func (s *Server) readyHandler(w http.ResponseWriter, _ *http.Request) {
for name, fn := range s.readinessProbes {
if ready, err := fn(); !ready {
@@ -376,10 +409,7 @@ func (s *Server) readyHandler(w http.ResponseWriter, _ *http.Request) {
// cachesSynced checks whether caches have been synced.
func (s *Server) cachesSynced() bool {
if !s.configController.HasSynced() {
return false
}
return true
return s.configController.HasSynced()
}
func (s *Server) waitForCacheSync(stop <-chan struct{}) bool {

View File

@@ -0,0 +1,66 @@
// 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 bootstrap
import (
"context"
"testing"
"github.com/agiledragon/gomonkey/v2"
"istio.io/istio/pilot/pkg/features"
"istio.io/istio/pkg/keepalive"
higresskube "github.com/alibaba/higress/pkg/kube"
)
func TestStartWithNoError(t *testing.T) {
var (
s *Server
err error
)
mockFn := func(s *Server) error {
s.kubeClient = higresskube.NewFakeClient()
return nil
}
gomonkey.ApplyFunc((*Server).initKubeClient, mockFn)
if s, err = NewServer(newServerArgs()); err != nil {
t.Errorf("failed to create server: %v", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if err = s.Start(ctx.Done()); err != nil {
t.Errorf("failed to start the server: %v", err)
}
}
func newServerArgs() *ServerArgs {
return &ServerArgs{
Debug: true,
NativeIstio: true,
HttpAddress: ":8888",
GrpcAddress: ":15051",
GrpcKeepAliveOptions: keepalive.DefaultOption(),
XdsOptions: XdsOptions{
DebounceAfter: features.DebounceAfter,
DebounceMax: features.DebounceMax,
EnableEDSDebounce: features.EnableEDSDebounce,
},
}
}

View File

@@ -0,0 +1,17 @@
// 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 constants
const DefaultIngressClass = "higress"

View File

@@ -16,6 +16,8 @@ package config
import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
@@ -23,9 +25,12 @@ import (
wasm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3"
httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3"
"github.com/gogo/protobuf/types"
"github.com/golang/protobuf/ptypes/wrappers"
"google.golang.org/protobuf/types/known/anypb"
extensions "istio.io/api/extensions/v1alpha1"
networking "istio.io/api/networking/v1alpha3"
istiotype "istio.io/api/type/v1beta1"
"istio.io/istio/pilot/pkg/model"
networkingutil "istio.io/istio/pilot/pkg/networking/util"
"istio.io/istio/pilot/pkg/util/sets"
@@ -36,6 +41,8 @@ import (
listersv1 "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache"
higressext "github.com/alibaba/higress/api/extensions/v1alpha1"
extlisterv1 "github.com/alibaba/higress/client/pkg/listers/extensions/v1alpha1"
netlisterv1 "github.com/alibaba/higress/client/pkg/listers/networking/v1"
"github.com/alibaba/higress/pkg/ingress/kube/annotations"
"github.com/alibaba/higress/pkg/ingress/kube/common"
@@ -44,6 +51,7 @@ import (
"github.com/alibaba/higress/pkg/ingress/kube/mcpbridge"
"github.com/alibaba/higress/pkg/ingress/kube/secret"
"github.com/alibaba/higress/pkg/ingress/kube/util"
"github.com/alibaba/higress/pkg/ingress/kube/wasmplugin"
. "github.com/alibaba/higress/pkg/ingress/log"
"github.com/alibaba/higress/pkg/kube"
"github.com/alibaba/higress/registry/reconcile"
@@ -69,6 +77,7 @@ type IngressConfig struct {
destinationRuleHandlers []model.EventHandler
envoyFilterHandlers []model.EventHandler
serviceEntryHandlers []model.EventHandler
wasmPluginHandlers []model.EventHandler
watchErrorHandler cache.WatchErrorHandler
cachedEnvoyFilters []config.Config
@@ -83,6 +92,12 @@ type IngressConfig struct {
mcpbridgeLister netlisterv1.McpBridgeLister
wasmPluginController wasmplugin.WasmPluginController
wasmPluginLister extlisterv1.WasmPluginLister
wasmPlugins map[string]*extensions.WasmPlugin
XDSUpdater model.XDSUpdater
annotationHandler annotations.AnnotationHandler
@@ -109,11 +124,17 @@ func NewIngressConfig(localKubeClient kube.Client, XDSUpdater model.XDSUpdater,
watchedSecretSet: sets.NewSet(),
namespace: namespace,
mcpbridgeReconciled: true,
wasmPlugins: make(map[string]*extensions.WasmPlugin),
}
mcpbridgeController := mcpbridge.NewController(localKubeClient, clusterId)
mcpbridgeController.AddEventHandler(config.AddOrUpdateMcpBridge, config.DeleteMcpBridge)
config.mcpbridgeController = mcpbridgeController
config.mcpbridgeLister = mcpbridgeController.Lister()
wasmPluginController := wasmplugin.NewController(localKubeClient, clusterId)
wasmPluginController.AddEventHandler(config.AddOrUpdateWasmPlugin, config.DeleteWasmPlugin)
config.wasmPluginController = wasmPluginController
config.wasmPluginLister = wasmPluginController.Lister()
return config
}
@@ -134,6 +155,9 @@ func (m *IngressConfig) RegisterEventHandler(kind config.GroupVersionKind, f mod
case gvk.ServiceEntry:
m.serviceEntryHandlers = append(m.serviceEntryHandlers, f)
case gvk.WasmPlugin:
m.wasmPluginHandlers = append(m.wasmPluginHandlers, f)
}
for _, remoteIngressController := range m.remoteIngressControllers {
@@ -158,19 +182,6 @@ func (m *IngressConfig) AddLocalCluster(options common.Options) common.IngressCo
}
func (m *IngressConfig) InitializeCluster(ingressController common.IngressController, stop <-chan struct{}) error {
for _, handler := range m.virtualServiceHandlers {
ingressController.RegisterEventHandler(gvk.VirtualService, handler)
}
for _, handler := range m.gatewayHandlers {
ingressController.RegisterEventHandler(gvk.Gateway, handler)
}
for _, handler := range m.destinationRuleHandlers {
ingressController.RegisterEventHandler(gvk.DestinationRule, handler)
}
for _, handler := range m.envoyFilterHandlers {
ingressController.RegisterEventHandler(gvk.EnvoyFilter, handler)
}
_ = ingressController.SetWatchErrorHandler(m.watchErrorHandler)
go ingressController.Run(stop)
@@ -182,7 +193,8 @@ func (m *IngressConfig) List(typ config.GroupVersionKind, namespace string) ([]c
typ != gvk.VirtualService &&
typ != gvk.DestinationRule &&
typ != gvk.EnvoyFilter &&
typ != gvk.ServiceEntry {
typ != gvk.ServiceEntry &&
typ != gvk.WasmPlugin {
return nil, common.ErrUnsupportedOp
}
@@ -219,6 +231,8 @@ func (m *IngressConfig) List(typ config.GroupVersionKind, namespace string) ([]c
return m.convertDestinationRule(wrapperConfigs), nil
case gvk.ServiceEntry:
return m.convertServiceEntry(wrapperConfigs), nil
case gvk.WasmPlugin:
return m.convertWasmPlugin(wrapperConfigs), nil
}
return nil, nil
@@ -485,6 +499,23 @@ func (m *IngressConfig) convertEnvoyFilter(convertOptions *common.ConvertOptions
m.mutex.Unlock()
}
func (m *IngressConfig) convertWasmPlugin([]common.WrapperConfig) []config.Config {
m.mutex.RLock()
defer m.mutex.RUnlock()
out := make([]config.Config, 0, len(m.wasmPlugins))
for name, wasmPlugin := range m.wasmPlugins {
out = append(out, config.Config{
Meta: config.Meta{
GroupVersionKind: gvk.WasmPlugin,
Name: name,
Namespace: m.namespace,
},
Spec: wasmPlugin,
})
}
return out
}
func (m *IngressConfig) convertServiceEntry([]common.WrapperConfig) []config.Config {
if m.RegistryReconciler == nil {
return nil
@@ -656,6 +687,153 @@ func (m *IngressConfig) applyInternalActiveRedirect(convertOptions *common.Conve
}
}
func (m *IngressConfig) convertIstioWasmPlugin(obj *higressext.WasmPlugin) (*extensions.WasmPlugin, error) {
result := &extensions.WasmPlugin{
Selector: &istiotype.WorkloadSelector{
MatchLabels: map[string]string{
"higress": m.namespace + "-higress-gateway",
},
},
Url: obj.Url,
Sha256: obj.Sha256,
ImagePullPolicy: extensions.PullPolicy(obj.ImagePullPolicy),
ImagePullSecret: obj.ImagePullSecret,
VerificationKey: obj.VerificationKey,
PluginConfig: obj.PluginConfig,
PluginName: obj.PluginName,
Phase: extensions.PluginPhase(obj.Phase),
Priority: obj.Priority,
}
if result.PluginConfig != nil {
return result, nil
}
result.PluginConfig = obj.DefaultConfig
if len(obj.MatchRules) > 0 {
if result.PluginConfig == nil {
result.PluginConfig = &types.Struct{
Fields: map[string]*types.Value{},
}
}
var ruleValues []*types.Value
for _, rule := range obj.MatchRules {
if rule.Config == nil {
return nil, errors.New("invalid rule has no config")
}
v := &types.Value_StructValue{
StructValue: rule.Config,
}
var matchItems []*types.Value
for _, ing := range rule.Ingress {
matchItems = append(matchItems, &types.Value{
Kind: &types.Value_StringValue{
StringValue: ing,
},
})
}
if len(matchItems) > 0 {
v.StructValue.Fields["_match_route_"] = &types.Value{
Kind: &types.Value_ListValue{
ListValue: &types.ListValue{
Values: matchItems,
},
},
}
ruleValues = append(ruleValues, &types.Value{
Kind: v,
})
continue
}
for _, domain := range rule.Domain {
matchItems = append(matchItems, &types.Value{
Kind: &types.Value_StringValue{
StringValue: domain,
},
})
}
if len(matchItems) == 0 {
return nil, fmt.Errorf("invalid match rule has no match condition, rule:%v", rule)
}
v.StructValue.Fields["_match_domain_"] = &types.Value{
Kind: &types.Value_ListValue{
ListValue: &types.ListValue{
Values: matchItems,
},
},
}
ruleValues = append(ruleValues, &types.Value{
Kind: v,
})
}
result.PluginConfig.Fields["_rules_"] = &types.Value{
Kind: &types.Value_ListValue{
ListValue: &types.ListValue{
Values: ruleValues,
},
},
}
}
return result, nil
}
func (m *IngressConfig) AddOrUpdateWasmPlugin(clusterNamespacedName util.ClusterNamespacedName) {
if clusterNamespacedName.Namespace != m.namespace {
return
}
wasmPlugin, err := m.wasmPluginLister.WasmPlugins(clusterNamespacedName.Namespace).Get(clusterNamespacedName.Name)
if err != nil {
IngressLog.Errorf("wasmPlugin is not found, namespace:%s, name:%s",
clusterNamespacedName.Namespace, clusterNamespacedName.Name)
return
}
metadata := config.Meta{
Name: clusterNamespacedName.Name + "-wasmplugin",
Namespace: clusterNamespacedName.Namespace,
GroupVersionKind: gvk.WasmPlugin,
// Set this label so that we do not compare configs and just push.
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
}
for _, f := range m.wasmPluginHandlers {
IngressLog.Debug("WasmPlugin triggerd update")
f(config.Config{Meta: metadata}, config.Config{Meta: metadata}, model.EventUpdate)
}
istioWasmPlugin, err := m.convertIstioWasmPlugin(&wasmPlugin.Spec)
if err != nil {
IngressLog.Errorf("invalid wasmPlugin:%s, err:%v", clusterNamespacedName.Name, err)
return
}
IngressLog.Debugf("wasmPlugin:%s convert to istioWasmPlugin:%v", clusterNamespacedName.Name, istioWasmPlugin)
m.mutex.Lock()
m.wasmPlugins[clusterNamespacedName.Name] = istioWasmPlugin
m.mutex.Unlock()
}
func (m *IngressConfig) DeleteWasmPlugin(clusterNamespacedName util.ClusterNamespacedName) {
if clusterNamespacedName.Namespace != m.namespace {
return
}
var hit bool
m.mutex.Lock()
if _, ok := m.wasmPlugins[clusterNamespacedName.Name]; ok {
delete(m.wasmPlugins, clusterNamespacedName.Name)
hit = true
}
m.mutex.Unlock()
if hit {
metadata := config.Meta{
Name: clusterNamespacedName.Name + "-wasmplugin",
Namespace: clusterNamespacedName.Namespace,
GroupVersionKind: gvk.WasmPlugin,
// Set this label so that we do not compare configs and just push.
Labels: map[string]string{constants.AlwaysPushLabel: "true"},
}
for _, f := range m.wasmPluginHandlers {
IngressLog.Debug("WasmPlugin triggerd update")
f(config.Config{Meta: metadata}, config.Config{Meta: metadata}, model.EventDelete)
}
}
}
func (m *IngressConfig) AddOrUpdateMcpBridge(clusterNamespacedName util.ClusterNamespacedName) {
// TODO: get resource name from config
if clusterNamespacedName.Name != "default" || clusterNamespacedName.Namespace != m.namespace {
@@ -873,7 +1051,8 @@ func constructBasicAuthEnvoyFilter(rules *common.BasicAuthRules, namespace strin
}
func (m *IngressConfig) Run(stop <-chan struct{}) {
m.mcpbridgeController.Run(stop)
go m.mcpbridgeController.Run(stop)
go m.wasmPluginController.Run(stop)
}
func (m *IngressConfig) HasSynced() bool {
@@ -887,6 +1066,9 @@ func (m *IngressConfig) HasSynced() bool {
if !m.mcpbridgeController.HasSynced() || !m.mcpbridgeReconciled {
return false
}
if !m.wasmPluginController.HasSynced() {
return false
}
IngressLog.Info("Ingress config controller synced.")
return true
}

View File

@@ -18,9 +18,112 @@ import (
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
networking "istio.io/api/networking/v1alpha3"
)
func TestCanaryParse(t *testing.T) {
parser := canary{}
testCases := []struct {
name string
input Annotations
expect *CanaryConfig
}{
{
name: "Don't contain the 'enableCanary' key",
input: Annotations{},
expect: nil,
},
{
name: "the 'enableCanary' is false",
input: Annotations{
buildNginxAnnotationKey(enableCanary): "false",
},
expect: &CanaryConfig{
Enabled: false,
WeightTotal: defaultCanaryWeightTotal,
},
},
{
name: "By header",
input: Annotations{
buildNginxAnnotationKey(enableCanary): "true",
buildNginxAnnotationKey(canaryByHeader): "header",
},
expect: &CanaryConfig{
Enabled: true,
Header: "header",
WeightTotal: defaultCanaryWeightTotal,
},
},
{
name: "By headerValue",
input: Annotations{
buildNginxAnnotationKey(enableCanary): "true",
buildNginxAnnotationKey(canaryByHeader): "header",
buildNginxAnnotationKey(canaryByHeaderValue): "headerValue",
},
expect: &CanaryConfig{
Enabled: true,
Header: "header",
HeaderValue: "headerValue",
WeightTotal: defaultCanaryWeightTotal,
},
},
{
name: "By headerPattern",
input: Annotations{
buildNginxAnnotationKey(enableCanary): "true",
buildNginxAnnotationKey(canaryByHeader): "header",
buildNginxAnnotationKey(canaryByHeaderPattern): "headerPattern",
},
expect: &CanaryConfig{
Enabled: true,
Header: "header",
HeaderPattern: "headerPattern",
WeightTotal: defaultCanaryWeightTotal,
},
},
{
name: "By cookie",
input: Annotations{
buildNginxAnnotationKey(enableCanary): "true",
buildNginxAnnotationKey(canaryByCookie): "cookie",
},
expect: &CanaryConfig{
Enabled: true,
Cookie: "cookie",
WeightTotal: defaultCanaryWeightTotal,
},
},
{
name: "By weight",
input: Annotations{
buildNginxAnnotationKey(enableCanary): "true",
buildNginxAnnotationKey(canaryWeight): "50",
buildNginxAnnotationKey(canaryWeightTotal): "100",
},
expect: &CanaryConfig{
Enabled: true,
Weight: 50,
WeightTotal: 100,
},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
config := &Ingress{}
_ = parser.Parse(tt.input, config, nil)
if diff := cmp.Diff(tt.expect, config.Canary); diff != "" {
t.Fatalf("TestCanaryParse() mismatch (-want +got):\n%s", diff)
}
})
}
}
func TestApplyWeight(t *testing.T) {
route := &networking.HTTPRoute{
Headers: &networking.Headers{

View File

@@ -32,11 +32,12 @@ var _ Parser = destination{}
type DestinationConfig struct {
McpDestination []*networking.HTTPRouteDestination
WeightSum int64
}
type destination struct{}
func (a destination) Parse(annotations Annotations, config *Ingress, globalContext *GlobalContext) error {
func (a destination) Parse(annotations Annotations, config *Ingress, _ *GlobalContext) error {
if !needDestinationConfig(annotations) {
return nil
}
@@ -54,6 +55,9 @@ func (a destination) Parse(annotations Annotations, config *Ingress, globalConte
pairs := strings.Fields(line)
var weight int64 = 100
var addrIndex int
if len(pairs) == 0 {
continue
}
if strings.HasSuffix(pairs[0], "%") {
weight, err = strconv.ParseInt(strings.TrimSuffix(pairs[0], "%"), 10, 32)
if err != nil {
@@ -99,11 +103,11 @@ func (a destination) Parse(annotations Annotations, config *Ingress, globalConte
destinations = append(destinations, dest)
}
if weightSum != 100 {
IngressLog.Errorf("destination has invalid weight sum %d within ingress %s/%s", weightSum, config.Namespace, config.Name)
return nil
IngressLog.Warnf("destination has invalid weight sum %d within ingress %s/%s", weightSum, config.Namespace, config.Name)
}
config.Destination = &DestinationConfig{
McpDestination: destinations,
WeightSum: weightSum,
}
return nil
}

View File

@@ -0,0 +1,98 @@
// 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 (
"testing"
"github.com/google/go-cmp/cmp"
networking "istio.io/api/networking/v1alpha3"
)
func TestDestinationParse(t *testing.T) {
parser := destination{}
testCases := []struct {
input Annotations
expect *DestinationConfig
}{
{
input: Annotations{},
expect: nil,
},
{
input: Annotations{
buildHigressAnnotationKey(destinationKey): "",
},
expect: nil,
},
{
input: Annotations{
buildHigressAnnotationKey(destinationKey): "100% my-svc.DEFAULT-GROUP.xxxx.nacos:8080 v1",
},
expect: &DestinationConfig{
McpDestination: []*networking.HTTPRouteDestination{
{
Destination: &networking.Destination{
Host: "my-svc.DEFAULT-GROUP.xxxx.nacos",
Subset: "v1",
Port: &networking.PortSelector{Number: 8080},
},
Weight: 100,
},
},
WeightSum: 100,
},
},
{
input: Annotations{
buildHigressAnnotationKey(destinationKey): "50% my-svc.DEFAULT-GROUP.xxxx.nacos:8080 v1\n\n" +
"50% my-svc.DEFAULT-GROUP.xxxx.nacos:8080 v2",
},
expect: &DestinationConfig{
McpDestination: []*networking.HTTPRouteDestination{
{
Destination: &networking.Destination{
Host: "my-svc.DEFAULT-GROUP.xxxx.nacos",
Subset: "v1",
Port: &networking.PortSelector{Number: 8080},
},
Weight: 50,
},
{
Destination: &networking.Destination{
Host: "my-svc.DEFAULT-GROUP.xxxx.nacos",
Subset: "v2",
Port: &networking.PortSelector{Number: 8080},
},
Weight: 50,
},
},
WeightSum: 100,
},
},
}
for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
config := &Ingress{}
_ = parser.Parse(testCase.input, config, nil)
if diff := cmp.Diff(config.Destination, testCase.expect); diff != "" {
t.Fatalf("TestDestinationParse() mismatch: (-want +got)\n%s", diff)
}
})
}
}

View File

@@ -0,0 +1,89 @@
// 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 (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestRedirectParse(t *testing.T) {
parser := redirect{}
testCases := []struct {
name string
input Annotations
expect *RedirectConfig
}{
{
name: "Don't contain any redirect keys",
input: Annotations{},
expect: nil,
},
{
name: "By appRoot",
input: Annotations{
buildHigressAnnotationKey(appRoot): "/root",
buildHigressAnnotationKey(sslRedirect): "true",
buildHigressAnnotationKey(forceSSLRedirect): "true",
},
expect: &RedirectConfig{
AppRoot: "/root",
httpsRedirect: true,
Code: defaultPermanentRedirectCode,
},
},
{
name: "By temporalRedirect",
input: Annotations{
buildHigressAnnotationKey(temporalRedirect): "http://www.xxx.org",
},
expect: &RedirectConfig{
URL: "http://www.xxx.org",
Code: defaultTemporalRedirectCode,
},
},
{
name: "By temporalRedirect with invalid url",
input: Annotations{
buildHigressAnnotationKey(temporalRedirect): "tcp://www.xxx.org",
},
expect: &RedirectConfig{
Code: defaultPermanentRedirectCode,
},
},
{
name: "By permanentRedirect",
input: Annotations{
buildHigressAnnotationKey(permanentRedirect): "http://www.xxx.org",
},
expect: &RedirectConfig{
URL: "http://www.xxx.org",
Code: defaultPermanentRedirectCode,
},
},
}
for _, tt := range testCases {
t.Run("", func(t *testing.T) {
config := &Ingress{}
_ = parser.Parse(tt.input, config, nil)
if diff := cmp.Diff(tt.expect, config.Redirect, cmp.AllowUnexported(RedirectConfig{})); diff != "" {
t.Fatalf("TestRedirectParse() mismatch (-want +got):\n%s", diff)
}
})
}
}

View File

@@ -0,0 +1,152 @@
// 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 (
"testing"
"github.com/google/go-cmp/cmp"
networking "istio.io/api/networking/v1alpha3"
)
func TestUpstreamTLSParse(t *testing.T) {
parser := upstreamTLS{}
testCases := []struct {
input Annotations
expect *UpstreamTLSConfig
}{
{
input: Annotations{},
expect: nil,
},
{
input: Annotations{
buildNginxAnnotationKey(proxySSLSecret): "",
buildNginxAnnotationKey(backendProtocol): "HTTP2",
buildNginxAnnotationKey(proxySSLSecret): "namespace/SSLSecret",
buildNginxAnnotationKey(proxySSLVerify): "on",
buildNginxAnnotationKey(proxySSLName): "SSLName",
buildNginxAnnotationKey(proxySSLServerName): "on",
},
expect: &UpstreamTLSConfig{
BackendProtocol: "HTTP2",
SSLVerify: true,
SNI: "SSLName",
SecretName: "namespace/SSLSecret",
},
},
{
input: Annotations{
buildNginxAnnotationKey(proxySSLSecret): "",
buildNginxAnnotationKey(backendProtocol): "HTTP2",
buildNginxAnnotationKey(proxySSLSecret): "", // if there is no ssl secret, it will be return directly
buildNginxAnnotationKey(proxySSLVerify): "on",
buildNginxAnnotationKey(proxySSLName): "SSLName",
buildNginxAnnotationKey(proxySSLServerName): "on",
},
expect: &UpstreamTLSConfig{
BackendProtocol: "HTTP2",
SSLVerify: false,
SNI: "",
SecretName: "",
},
},
}
for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
config := &Ingress{}
_ = parser.Parse(testCase.input, config, nil)
if diff := cmp.Diff(testCase.expect, config.UpstreamTLS); diff != "" {
t.Fatalf("TestUpstreamTLSParse() mismatch: \n%s", diff)
}
})
}
}
func TestApplyTrafficPolicy(t *testing.T) {
parser := upstreamTLS{}
testCases := []struct {
input *networking.TrafficPolicy_PortTrafficPolicy
config *Ingress
expect *networking.TrafficPolicy_PortTrafficPolicy
}{
{
input: &networking.TrafficPolicy_PortTrafficPolicy{},
config: &Ingress{
UpstreamTLS: &UpstreamTLSConfig{},
},
expect: &networking.TrafficPolicy_PortTrafficPolicy{},
},
{
input: &networking.TrafficPolicy_PortTrafficPolicy{},
config: &Ingress{
UpstreamTLS: &UpstreamTLSConfig{
BackendProtocol: "HTTP2",
},
},
expect: &networking.TrafficPolicy_PortTrafficPolicy{
ConnectionPool: &networking.ConnectionPoolSettings{
Http: &networking.ConnectionPoolSettings_HTTPSettings{
H2UpgradePolicy: networking.ConnectionPoolSettings_HTTPSettings_UPGRADE,
},
},
},
},
{
input: &networking.TrafficPolicy_PortTrafficPolicy{},
config: &Ingress{
UpstreamTLS: &UpstreamTLSConfig{
BackendProtocol: "HTTPS",
EnableSNI: true,
SNI: "SNI",
},
},
expect: &networking.TrafficPolicy_PortTrafficPolicy{
Tls: &networking.ClientTLSSettings{
Mode: networking.ClientTLSSettings_SIMPLE,
Sni: "SNI",
},
},
},
{
input: &networking.TrafficPolicy_PortTrafficPolicy{},
config: &Ingress{
UpstreamTLS: &UpstreamTLSConfig{
SecretName: "namespace/secretName",
SSLVerify: true,
},
},
expect: &networking.TrafficPolicy_PortTrafficPolicy{
Tls: &networking.ClientTLSSettings{
Mode: networking.ClientTLSSettings_MUTUAL,
CredentialName: "kubernetes-ingress://Kubernetes/namespace/secretName",
},
},
},
}
for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
parser.ApplyTrafficPolicy(testCase.input, testCase.config)
if diff := cmp.Diff(testCase.expect, testCase.input); diff != "" {
t.Fatalf("TestApplyTrafficPolicy() mismatch (-want +got): \n%s", diff)
}
})
}
}

View File

@@ -18,6 +18,7 @@ import (
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
"istio.io/istio/pilot/pkg/model"
)
@@ -51,3 +52,35 @@ func TestExtraSecret(t *testing.T) {
})
}
}
func TestSplitBySeparator(t *testing.T) {
testCases := []struct {
input string
sep string
expect []string
}{
{
input: "a b c d",
sep: " ",
expect: []string{"a", "b", "c", "d"},
},
{
input: ".1.2.3.4.",
sep: ".",
expect: []string{"1", "2", "3", "4"},
},
{
input: "1....2....3....4",
sep: ".",
expect: []string{"1", "2", "3", "4"},
},
}
for _, tt := range testCases {
got := splitBySeparator(tt.input, tt.sep)
if diff := cmp.Diff(tt.expect, got); diff != "" {
t.Errorf("TestSplitBySeparator() mismatch (-want +got):\n%s", diff)
}
}
}

View File

@@ -25,4 +25,5 @@ var IngressIR = collection.NewSchemasBuilder().
MustAdd(collections.IstioNetworkingV1Alpha3Gateways).
MustAdd(collections.IstioNetworkingV1Alpha3Serviceentries).
MustAdd(collections.IstioNetworkingV1Alpha3Virtualservices).
MustAdd(collections.IstioExtensionsV1Alpha1Wasmplugins).
Build()

View File

@@ -277,12 +277,15 @@ func partMd5(raw string) string {
return encoded[:4] + encoded[len(encoded)-4:]
}
func GenerateUniqueRouteName(route *WrapperHTTPRoute) string {
func GenerateUniqueRouteName(defaultNs string, route *WrapperHTTPRoute) string {
if route.WrapperConfig.Config.Namespace == defaultNs {
return route.WrapperConfig.Config.Name
}
return route.Meta()
}
func GenerateUniqueRouteNameWithSuffix(route *WrapperHTTPRoute, suffix string) string {
return CreateConvertedName(route.Meta(), suffix)
func GenerateUniqueRouteNameWithSuffix(defaultNs string, route *WrapperHTTPRoute, suffix string) string {
return CreateConvertedName(GenerateUniqueRouteName(defaultNs, route), suffix)
}
func SplitServiceFQDN(fqdn string) (string, string, bool) {
@@ -295,12 +298,15 @@ func SplitServiceFQDN(fqdn string) (string, string, bool) {
func ConvertBackendService(routeDestination *networking.HTTPRouteDestination) model.BackendService {
parts := strings.Split(routeDestination.Destination.Host, ".")
return model.BackendService{
service := model.BackendService{
Namespace: parts[1],
Name: parts[0],
Port: routeDestination.Destination.Port.Number,
Weight: routeDestination.Weight,
}
if routeDestination.Destination.Port != nil {
service.Port = routeDestination.Destination.Port.Number
}
return service
}
func getLoadBalancerIp(svc *v1.Service) []string {

View File

@@ -198,7 +198,8 @@ func TestGenerateUniqueRouteName(t *testing.T) {
},
}
assert.Equal(t, "bar/foo", GenerateUniqueRouteName(input))
assert.Equal(t, "bar/foo", GenerateUniqueRouteName("xxx", input))
assert.Equal(t, "foo", GenerateUniqueRouteName("bar", input))
}

View File

@@ -348,6 +348,13 @@ func extractTLSSecretName(host string, tls []ingress.IngressTLS) string {
}
func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
if convertOptions == nil {
return fmt.Errorf("convertOptions is nil")
}
if wrapper == nil {
return fmt.Errorf("wrapperConfig is nil")
}
// Ignore canary config.
if wrapper.AnnotationsConfig.IsCanary() {
return nil
@@ -455,6 +462,13 @@ func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapp
}
func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
if convertOptions == nil {
return fmt.Errorf("convertOptions is nil")
}
if wrapper == nil {
return fmt.Errorf("wrapperConfig is nil")
}
// Canary ingress will be processed in the end.
if wrapper.AnnotationsConfig.IsCanary() {
convertOptions.CanaryIngresses = append(convertOptions.CanaryIngresses, wrapper)
@@ -548,7 +562,7 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra
}
wrapperHttpRoute.OriginPath = path
wrapperHttpRoute.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch}
wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(wrapperHttpRoute)
wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, wrapperHttpRoute)
ingressRouteBuilder := convertOptions.IngressRouteCache.New(wrapperHttpRoute)
@@ -575,6 +589,10 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra
destinationConfig := wrapper.AnnotationsConfig.Destination
wrapperHttpRoute.HTTPRoute.Route, event = c.backendToRouteDestination(&httpPath.Backend, cfg.Namespace, ingressRouteBuilder, destinationConfig)
if destinationConfig != nil {
wrapperHttpRoute.WeightTotal = int32(destinationConfig.WeightSum)
}
if ingressRouteBuilder.Event != common.Normal {
event = ingressRouteBuilder.Event
}
@@ -614,6 +632,13 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra
}
func (c *controller) ApplyDefaultBackend(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
if convertOptions == nil {
return fmt.Errorf("convertOptions is nil")
}
if wrapper == nil {
return fmt.Errorf("wrapperConfig is nil")
}
if wrapper.AnnotationsConfig.IsCanary() {
return nil
}
@@ -684,6 +709,13 @@ func (c *controller) ApplyDefaultBackend(convertOptions *common.ConvertOptions,
}
func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
if convertOptions == nil {
return fmt.Errorf("convertOptions is nil")
}
if wrapper == nil {
return fmt.Errorf("wrapperConfig is nil")
}
byHeader, byWeight := wrapper.AnnotationsConfig.CanaryKind()
cfg := wrapper.Config
@@ -749,7 +781,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
}
canary.OriginPath = path
canary.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch}
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(canary)
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary)
ingressRouteBuilder := convertOptions.IngressRouteCache.New(canary)
// backend service check
@@ -777,7 +809,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
if byHeader {
IngressLog.Debug("Insert canary route by header")
annotations.ApplyByHeader(canary.HTTPRoute, route.HTTPRoute, canary.WrapperConfig.AnnotationsConfig)
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(canary)
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary)
} else {
IngressLog.Debug("Merge canary route by weight")
if route.WeightTotal == 0 {
@@ -805,7 +837,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
convertOptions.HTTPRoutes[rule.Host] = routes
// Recreate route name.
ingressRouteBuilder.RouteName = common.GenerateUniqueRouteName(canary)
ingressRouteBuilder.RouteName = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary)
convertOptions.IngressRouteCache.Add(ingressRouteBuilder)
} else {
convertOptions.IngressRouteCache.Update(targetRoute)
@@ -816,6 +848,13 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
}
func (c *controller) ConvertTrafficPolicy(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
if convertOptions == nil {
return fmt.Errorf("convertOptions is nil")
}
if wrapper == nil {
return fmt.Errorf("wrapperConfig is nil")
}
if !wrapper.AnnotationsConfig.NeedTrafficPolicy() {
return nil
}
@@ -931,12 +970,16 @@ func (c *controller) createDefaultRoute(wrapper *common.WrapperConfig, backend *
OriginPathType: common.Prefix,
OriginPath: "/",
}
route.HTTPRoute.Name = common.GenerateUniqueRouteNameWithSuffix(route, "default")
route.HTTPRoute.Name = common.GenerateUniqueRouteNameWithSuffix(c.options.SystemNamespace, route, "default")
return route
}
func (c *controller) createServiceKey(service *ingress.IngressBackend, namespace string) (common.ServiceKey, error) {
if service == nil {
return common.ServiceKey{}, fmt.Errorf("ingressBackend is nil")
}
serviceKey := common.ServiceKey{}
if service.ServiceName == "" {
return serviceKey, errors.New("service name is empty")
@@ -961,7 +1004,7 @@ func (c *controller) createServiceKey(service *ingress.IngressBackend, namespace
}
func isCanaryRoute(canary, route *common.WrapperHTTPRoute) bool {
return !strings.HasSuffix(route.HTTPRoute.Name, "-canary") && canary.OriginPath == route.OriginPath &&
return route != nil && canary != nil && !route.WrapperConfig.AnnotationsConfig.IsCanary() && canary.OriginPath == route.OriginPath &&
canary.OriginPathType == route.OriginPathType
}
@@ -1012,6 +1055,10 @@ func (c *controller) backendToRouteDestination(backend *ingress.IngressBackend,
}
func resolveNamedPort(backend *ingress.IngressBackend, namespace string, serviceLister listerv1.ServiceLister) (int32, error) {
if backend == nil {
return 0, fmt.Errorf("ingressBackend is nil")
}
svc, err := serviceLister.Services(namespace).Get(backend.ServiceName)
if err != nil {
return 0, err
@@ -1128,6 +1175,10 @@ func (c *controller) shouldProcessIngressUpdate(ing *ingress.Ingress) (bool, err
// setDefaultMSEIngressOptionalField sets a default value for optional fields when is not defined.
func setDefaultMSEIngressOptionalField(ing *ingress.Ingress) {
if ing == nil {
return
}
for idx, tls := range ing.Spec.TLS {
if len(tls.Hosts) == 0 {
ing.Spec.TLS[idx].Hosts = []string{common.DefaultHost}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -544,7 +544,7 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra
}
wrapperHttpRoute.OriginPath = path
wrapperHttpRoute.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch}
wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(wrapperHttpRoute)
wrapperHttpRoute.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, wrapperHttpRoute)
ingressRouteBuilder := convertOptions.IngressRouteCache.New(wrapperHttpRoute)
@@ -570,6 +570,11 @@ func (c *controller) ConvertHTTPRoute(convertOptions *common.ConvertOptions, wra
var event common.Event
destinationConfig := wrapper.AnnotationsConfig.Destination
wrapperHttpRoute.HTTPRoute.Route, event = c.backendToRouteDestination(&httpPath.Backend, cfg.Namespace, ingressRouteBuilder, destinationConfig)
if destinationConfig != nil {
wrapperHttpRoute.WeightTotal = int32(destinationConfig.WeightSum)
}
if ingressRouteBuilder.Event != common.Normal {
event = ingressRouteBuilder.Event
}
@@ -745,7 +750,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
}
canary.OriginPath = path
canary.HTTPRoute.Match = []*networking.HTTPMatchRequest{httpMatch}
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(canary)
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary)
ingressRouteBuilder := convertOptions.IngressRouteCache.New(canary)
// backend service check
@@ -773,7 +778,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
if byHeader {
IngressLog.Debug("Insert canary route by header")
annotations.ApplyByHeader(canary.HTTPRoute, route.HTTPRoute, canary.WrapperConfig.AnnotationsConfig)
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(canary)
canary.HTTPRoute.Name = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary)
} else {
IngressLog.Debug("Merge canary route by weight")
if route.WeightTotal == 0 {
@@ -801,7 +806,7 @@ func (c *controller) ApplyCanaryIngress(convertOptions *common.ConvertOptions, w
convertOptions.HTTPRoutes[rule.Host] = routes
// Recreate route name.
ingressRouteBuilder.RouteName = common.GenerateUniqueRouteName(canary)
ingressRouteBuilder.RouteName = common.GenerateUniqueRouteName(c.options.SystemNamespace, canary)
convertOptions.IngressRouteCache.Add(ingressRouteBuilder)
} else {
convertOptions.IngressRouteCache.Update(targetRoute)
@@ -925,7 +930,7 @@ func (c *controller) createDefaultRoute(wrapper *common.WrapperConfig, backend *
OriginPathType: common.Prefix,
OriginPath: "/",
}
route.HTTPRoute.Name = common.GenerateUniqueRouteNameWithSuffix(route, "default")
route.HTTPRoute.Name = common.GenerateUniqueRouteNameWithSuffix(c.options.SystemNamespace, route, "default")
return route
}

View File

@@ -0,0 +1,160 @@
// 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 secret
import (
"context"
"reflect"
"sync"
"testing"
"time"
"istio.io/istio/pilot/pkg/model"
kubeclient "istio.io/istio/pkg/kube"
"istio.io/istio/pkg/test/util/retry"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
"github.com/alibaba/higress/pkg/ingress/kube/util"
)
const (
secretFakeName = "fake-secret"
secretFakeKey = "fake-key"
secretInitValue = "init-value"
secretUpdatedValue = "updated-value"
)
var period = time.Second
func TestController(t *testing.T) {
client := kubeclient.NewFakeClient()
ctrl := NewController(client, "fake-cluster")
stop := make(chan struct{})
t.Cleanup(func() {
close(stop)
})
client.RunAndWait(stop)
// store secret
store := sync.Map{}
// add event handler
ctrl.AddEventHandler(func(name util.ClusterNamespacedName) {
t.Logf("event recived, clusterId: %s, namespacedName: %s", name.ClusterId, name.NamespacedName.String())
retry.UntilSuccessOrFail(t, func() error {
secret, err := ctrl.Lister().Secrets(name.NamespacedName.Namespace).Get(name.NamespacedName.Name)
if err != nil && !kerrors.IsNotFound(err) {
t.Logf("get secret %s error: %v", name.NamespacedName.String(), err)
return err
}
store.Store(name.NamespacedName.String(), secret.Data)
return nil
})
})
// start controller
go ctrl.Run(stop)
// wait for cache sync
cache.WaitForCacheSync(stop, ctrl.Informer().HasSynced)
// init secret
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretFakeName,
},
Type: corev1.SecretTypeOpaque,
Data: map[string][]byte{
secretFakeKey: []byte(secretInitValue),
},
}
testCases := []struct {
name string
do func() error
expect string
}{
{
name: "create secret",
do: func() error {
_, err := client.CoreV1().Secrets(metav1.NamespaceDefault).Create(context.Background(),
secret, metav1.CreateOptions{})
return err
},
expect: secretInitValue,
},
{
name: "update secret",
do: func() error {
var getSecret *corev1.Secret
// get or create secret
getSecret, err := ctrl.Lister().Secrets(metav1.NamespaceDefault).Get(secretFakeName)
if err != nil {
if !kerrors.IsNotFound(err) {
return err
}
getSecret, err = client.CoreV1().Secrets(metav1.NamespaceDefault).Create(context.Background(),
secret, metav1.CreateOptions{})
if err != nil {
return err
}
}
// update secret
getSecret.Data[secretFakeKey] = []byte(secretUpdatedValue)
_, err = client.CoreV1().Secrets(metav1.NamespaceDefault).Update(context.Background(),
getSecret, metav1.UpdateOptions{})
return err
},
expect: secretUpdatedValue,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
if err := testCase.do(); err != nil {
t.Fatalf("do %s error: %v", testCase.name, err)
}
// controller Run() with setting period time to 1s.
time.Sleep(period)
secretFullName := model.NamespacedName{
Namespace: metav1.NamespaceDefault,
Name: secretFakeName,
}.String()
valAny, ok := store.Load(secretFullName)
if !ok {
t.Fatalf("secret %s not found", secretFullName)
}
val, ok := valAny.(map[string][]byte)
if !ok {
t.Fatalf("assert secret %s data type error", secretFullName)
}
if !reflect.DeepEqual(val[secretFakeKey], []byte(testCase.expect)) {
t.Fatalf("secret %s data error, expect: %s, got: %s",
secretFullName, testCase.expect, string(val[secretFakeKey]))
}
})
}
}

View File

@@ -0,0 +1,46 @@
// 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 wasmplugin
import (
"time"
"istio.io/istio/pkg/kube/controllers"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/cache"
v1 "github.com/alibaba/higress/client/pkg/apis/extensions/v1alpha1"
"github.com/alibaba/higress/client/pkg/clientset/versioned"
informersv1 "github.com/alibaba/higress/client/pkg/informers/externalversions/extensions/v1alpha1"
listersv1 "github.com/alibaba/higress/client/pkg/listers/extensions/v1alpha1"
"github.com/alibaba/higress/pkg/ingress/kube/controller"
kubeclient "github.com/alibaba/higress/pkg/kube"
)
type WasmPluginController controller.Controller[listersv1.WasmPluginLister]
func NewController(client kubeclient.Client, clusterId string) WasmPluginController {
informer := client.HigressInformer().InformerFor(&v1.WasmPlugin{}, func(k versioned.Interface, resync time.Duration) cache.SharedIndexInformer {
return informersv1.NewWasmPluginInformer(k, metav1.NamespaceAll, resync,
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
})
return controller.NewCommonController("wasmplugin", listersv1.NewWasmPluginLister(informer.GetIndexer()),
informer, GetWasmPlugin, clusterId)
}
func GetWasmPlugin(lister listersv1.WasmPluginLister, namespacedName types.NamespacedName) (controllers.Object, error) {
return lister.WasmPlugins(namespacedName.Namespace).Get(namespacedName.Name)
}

View File

@@ -14,17 +14,17 @@
package mcp
// nolint
import (
"path"
"github.com/gogo/protobuf/types"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/any"
extensions "istio.io/api/extensions/v1alpha1"
mcp "istio.io/api/mcp/v1alpha1"
networking "istio.io/api/networking/v1alpha3"
"istio.io/istio/pilot/pkg/model"
"istio.io/istio/pilot/pkg/xds"
cfg "istio.io/istio/pkg/config"
)
type ServiceEntryGenerator struct {
@@ -33,31 +33,7 @@ type ServiceEntryGenerator struct {
func (c ServiceEntryGenerator) Generate(proxy *model.Proxy, push *model.PushContext, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
resources := make([]*any.Any, 0)
configs := push.AllServiceEntries
for _, config := range configs {
body, err := types.MarshalAny(config.Spec.(*networking.ServiceEntry))
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
createTime, err := types.TimestampProto(config.CreationTimestamp)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resource := &mcp.Resource{
Body: body,
Metadata: &mcp.Metadata{
Name: path.Join(config.Namespace, config.Name),
CreateTime: createTime,
},
}
mcpAny, err := ptypes.MarshalAny(resource)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resources = append(resources, mcpAny)
}
return resources, model.DefaultXdsLogDetails, nil
return generate(proxy, push.AllServiceEntries, w, updates)
}
func (c ServiceEntryGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
@@ -72,31 +48,7 @@ type VirtualServiceGenerator struct {
func (c VirtualServiceGenerator) Generate(proxy *model.Proxy, push *model.PushContext, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
resources := make([]*any.Any, 0)
configs := push.AllVirtualServices
for _, config := range configs {
body, err := types.MarshalAny(config.Spec.(*networking.VirtualService))
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
createTime, err := types.TimestampProto(config.CreationTimestamp)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resource := &mcp.Resource{
Body: body,
Metadata: &mcp.Metadata{
Name: path.Join(config.Namespace, config.Name),
CreateTime: createTime,
},
}
mcpAny, err := ptypes.MarshalAny(resource)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resources = append(resources, mcpAny)
}
return resources, model.DefaultXdsLogDetails, nil
return generate(proxy, push.AllVirtualServices, w, updates)
}
func (c VirtualServiceGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
@@ -111,31 +63,7 @@ type DestinationRuleGenerator struct {
func (c DestinationRuleGenerator) Generate(proxy *model.Proxy, push *model.PushContext, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
resources := make([]*any.Any, 0)
configs := push.AllDestinationRules
for _, config := range configs {
body, err := types.MarshalAny(config.Spec.(*networking.DestinationRule))
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
createTime, err := types.TimestampProto(config.CreationTimestamp)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resource := &mcp.Resource{
Body: body,
Metadata: &mcp.Metadata{
Name: path.Join(config.Namespace, config.Name),
CreateTime: createTime,
},
}
mcpAny, err := ptypes.MarshalAny(resource)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resources = append(resources, mcpAny)
}
return resources, model.DefaultXdsLogDetails, nil
return generate(proxy, push.AllDestinationRules, w, updates)
}
func (c DestinationRuleGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
@@ -150,31 +78,7 @@ type EnvoyFilterGenerator struct {
func (c EnvoyFilterGenerator) Generate(proxy *model.Proxy, push *model.PushContext, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
resources := make([]*any.Any, 0)
configs := push.AllEnvoyFilters
for _, config := range configs {
body, err := types.MarshalAny(config.Spec.(*networking.EnvoyFilter))
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
createTime, err := types.TimestampProto(config.CreationTimestamp)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resource := &mcp.Resource{
Body: body,
Metadata: &mcp.Metadata{
Name: path.Join(config.Namespace, config.Name),
CreateTime: createTime,
},
}
mcpAny, err := ptypes.MarshalAny(resource)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resources = append(resources, mcpAny)
}
return resources, model.DefaultXdsLogDetails, nil
return generate(proxy, push.AllEnvoyFilters, w, updates)
}
func (c EnvoyFilterGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
@@ -189,31 +93,7 @@ type GatewayGenerator struct {
func (c GatewayGenerator) Generate(proxy *model.Proxy, push *model.PushContext, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
resources := make([]*any.Any, 0)
configs := push.AllGateways
for _, config := range configs {
body, err := types.MarshalAny(config.Spec.(*networking.Gateway))
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
createTime, err := types.TimestampProto(config.CreationTimestamp)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resource := &mcp.Resource{
Body: body,
Metadata: &mcp.Metadata{
Name: path.Join(config.Namespace, config.Name),
CreateTime: createTime,
},
}
mcpAny, err := ptypes.MarshalAny(resource)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
resources = append(resources, mcpAny)
}
return resources, model.DefaultXdsLogDetails, nil
return generate(proxy, push.AllGateways, w, updates)
}
func (c GatewayGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
@@ -227,11 +107,21 @@ type WasmpluginGenerator struct {
}
func (c WasmpluginGenerator) Generate(proxy *model.Proxy, push *model.PushContext, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
return generate(proxy, push.AllWasmplugins, w, updates)
}
func (c WasmpluginGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
w *model.WatchedResource) ([]*any.Any, []string, model.XdsLogDetails, bool, error) {
// TODO: delta implement
return nil, nil, model.DefaultXdsLogDetails, false, nil
}
func generate(proxy *model.Proxy, configs []cfg.Config, w *model.WatchedResource,
updates *model.PushRequest) ([]*any.Any, model.XdsLogDetails, error) {
resources := make([]*any.Any, 0)
configs := push.AllWasmplugins
for _, config := range configs {
body, err := types.MarshalAny(config.Spec.(*extensions.WasmPlugin))
body, err := cfg.ToProtoGogo(config.Spec)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
}
@@ -246,6 +136,7 @@ func (c WasmpluginGenerator) Generate(proxy *model.Proxy, push *model.PushContex
CreateTime: createTime,
},
}
// nolint
mcpAny, err := ptypes.MarshalAny(resource)
if err != nil {
return nil, model.DefaultXdsLogDetails, err
@@ -254,9 +145,3 @@ func (c WasmpluginGenerator) Generate(proxy *model.Proxy, push *model.PushContex
}
return resources, model.DefaultXdsLogDetails, nil
}
func (c WasmpluginGenerator) GenerateDeltas(proxy *model.Proxy, push *model.PushContext, updates *model.PushRequest,
w *model.WatchedResource) ([]*any.Any, []string, model.XdsLogDetails, bool, error) {
// TODO: delta implement
return nil, nil, model.DefaultXdsLogDetails, false, nil
}

View File

@@ -0,0 +1,178 @@
// 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 mcp
import (
"reflect"
"testing"
"github.com/gogo/protobuf/types"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
"google.golang.org/protobuf/types/known/anypb"
extensions "istio.io/api/extensions/v1alpha1"
mcp "istio.io/api/mcp/v1alpha1"
networking "istio.io/api/networking/v1alpha3"
"istio.io/istio/pilot/pkg/model"
"istio.io/istio/pkg/config"
)
func TestGenerate(t *testing.T) {
tests := []struct {
name string
fn func() (*model.PushContext, any)
generator model.McpResourceGenerator
isErr bool
}{
{
name: "VirtualService",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: &networking.VirtualService{},
}
ctx.AllVirtualServices = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: VirtualServiceGenerator{},
isErr: false,
},
{
name: "Gateway",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: &networking.Gateway{},
}
ctx.AllGateways = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: GatewayGenerator{},
isErr: false,
},
{
name: "EnvoyFilter",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: &networking.EnvoyFilter{},
}
ctx.AllEnvoyFilters = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: EnvoyFilterGenerator{},
isErr: false,
},
{
name: "DestinationRule",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: &networking.DestinationRule{},
}
ctx.AllDestinationRules = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: DestinationRuleGenerator{},
isErr: false,
},
{
name: "WasmPlugin",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: &extensions.WasmPlugin{},
}
ctx.AllWasmplugins = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: WasmpluginGenerator{},
isErr: false,
},
{
name: "ServiceEntry",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: &networking.ServiceEntry{},
}
ctx.AllServiceEntries = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: ServiceEntryGenerator{},
isErr: false,
},
{
name: "WasmPlugin with wrong config",
fn: func() (*model.PushContext, any) {
ctx := model.NewPushContext()
cfg := config.Config{
Spec: "string",
}
ctx.AllWasmplugins = []config.Config{cfg}
return ctx, cfg.Spec
},
generator: WasmpluginGenerator{},
isErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var (
err error
val []*anypb.Any
)
pushCtx, spec := test.fn()
func() {
defer func() {
if err := recover(); err != nil && !test.isErr {
t.Fatalf("Failed to generate config: %v", err)
}
}()
val, _, err = test.generator.Generate(nil, pushCtx, nil, nil)
if (err != nil && !test.isErr) || (err == nil && test.isErr) {
t.Fatalf("Failed to generate config: %v", err)
}
}()
if test.isErr { // if the func 'Generate' should occur an error, just return
return
}
resource := &mcp.Resource{}
err = ptypes.UnmarshalAny(val[0], resource)
if err != nil {
t.Fatal(err)
}
specType := reflect.TypeOf(spec)
if specType.Kind() == reflect.Ptr {
specType = specType.Elem()
}
target := reflect.New(specType).Interface().(proto.Message)
if err = types.UnmarshalAny(resource.Body, target); err != nil {
t.Fatal(err)
}
if !test.isErr && !proto.Equal(spec.(proto.Message), target) {
t.Fatal("failed ")
}
})
}
}

View File

@@ -61,6 +61,7 @@ func NewFakeClient(objects ...runtime.Object) Client {
}
c.higress = higressfake.NewSimpleClientset()
c.higressInformer = higressinformer.NewSharedInformerFactoryWithOptions(c.higress, resyncInterval)
c.informerWatchesPending = atomic.NewInt32(0)
// https://github.com/kubernetes/kubernetes/issues/95372
// There is a race condition in the client fakes, where events that happen between the List and Watch

View File

@@ -27,7 +27,7 @@
例如用如下配置使用 request-block 插件 的 1.0.0 版本:
```yaml
apiVersion: extensions.istio.io/v1alpha1
apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
name: request-block
@@ -36,7 +36,7 @@ spec:
selector:
matchLabels:
higress: higress-system-higress-gateway
pluginConfig:
defaultConfig:
block_urls:
- "swagger.html"
url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0

View File

@@ -1,3 +1,7 @@
<p>
<a href="README_EN.md"> English </a> | 中文
</p>
# 功能说明
`bot-detect`插件可以用于识别并阻止互联网爬虫对站点资源的爬取

View File

@@ -0,0 +1,77 @@
<p>
English | <a href="README.md">中文</a>
</p>
# Description
`bot-detect` plugin can be used to identify and prevent web crawlers from crawling websites.
# Configuration Fields
| Name | Type | Requirement | Default Value | Description |
| -------- | -------- | -------- | -------- | -------- |
| allow | array of string | Optional | - | A regular expression to match the User-Agent request header and will allow access if the match hits |
| deny | array of string | Optional | - | A regular expression to match the User-Agent request header and will block the request if the match hits |
| blocked_code | number | Optional | 403 | The HTTP status code returned when a request is blocked |
| blocked_message | string | Optional | - | The HTTP response Body returned when a request is blocked |
If field `allow` and field `deny` are not configured at the same time, the default logic to identify crawlers will be executed. By configuring the `allow` field, requests that would otherwise hit the default logic can be allowed. The judgement can be extended by configuring the `deny` field
The default set of crawler judgment regular expressions is as follows
```bash
# Bots General matcher 'name/0.0'
(?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 \-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50}))[/ ](\d+)(?:\.(\d+)(?:\.(\d+)|)|)
# Bots General matcher 'name 0.0'
(?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 \-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50})) (\d+)(?:\.(\d+)(?:\.(\d+)|)|)
# Bots containing spider|scrape|bot(but not CUBOT)|Crawl
((?:[A-z0-9]{1,50}|[A-z\-]{1,50} ?|)(?: the |)(?:[Ss][Pp][Ii][Dd][Ee][Rr]|[Ss]crape|[Cc][Rr][Aa][Ww][Ll])[A-z0-9]{0,50})(?:(?:[ /]| v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)
# Bots Pattern '/name-0.0'
/((?:Ant-)?Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[ \-](\d+)(?:\.(\d+)(?:\.(\d+))?)?
# Bots Pattern 'name/0.0'
\b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|OgScrper|PathDefender|Peew|PostPost|Steeler|Twitterbot|VSE|WebCrunch|WebZIP|Y!J-BR[A-Z]|YahooSeeker|envolk|sproose|wminer)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)
# More bots
(CSimpleSpider|Cityreview Robot|CrawlDaddy|CrawlFire|Finderbots|Index crawler|Job Roboter|KiwiStatus Spider|Lijit Crawler|QuerySeekerSpider|ScollSpider|Trends Crawler|USyd-NLP-Spider|SiteCat Webbot|BotName\/\$BotVersion|123metaspider-Bot|1470\.net crawler|50\.nu|8bo Crawler Bot|Aboundex|Accoona-[A-z]{1,30}-Agent|AdsBot-Google(?:-[a-z]{1,30}|)|altavista|AppEngine-Google|archive.{0,30}\.org_bot|archiver|Ask Jeeves|[Bb]ai[Dd]u[Ss]pider(?:-[A-Za-z]{1,30})(?:-[A-Za-z]{1,30}|)|bingbot|BingPreview|blitzbot|BlogBridge|Bloglovin|BoardReader Blog Indexer|BoardReader Favicon Fetcher|boitho.com-dc|BotSeer|BUbiNG|\b\w{0,30}favicon\w{0,30}\b|\bYeti(?:-[a-z]{1,30}|)|Catchpoint(?: bot|)|[Cc]harlotte|Checklinks|clumboot|Comodo HTTP\(S\) Crawler|Comodo-Webinspector-Crawler|ConveraCrawler|CRAWL-E|CrawlConvera|Daumoa(?:-feedfetcher|)|Feed Seeker Bot|Feedbin|findlinks|Flamingo_SearchEngine|FollowSite Bot|furlbot|Genieo|gigabot|GomezAgent|gonzo1|(?:[a-zA-Z]{1,30}-|)Googlebot(?:-[a-zA-Z]{1,30}|)|Google SketchUp|grub-client|gsa-crawler|heritrix|HiddenMarket|holmes|HooWWWer|htdig|ia_archiver|ICC-Crawler|Icarus6j|ichiro(?:/mobile|)|IconSurf|IlTrovatore(?:-Setaccio|)|InfuzApp|Innovazion Crawler|InternetArchive|IP2[a-z]{1,30}Bot|jbot\b|KaloogaBot|Kraken|Kurzor|larbin|LEIA|LesnikBot|Linguee Bot|LinkAider|LinkedInBot|Lite Bot|Llaut|lycos|Mail\.RU_Bot|masscan|masidani_bot|Mediapartners-Google|Microsoft .{0,30} Bot|mogimogi|mozDex|MJ12bot|msnbot(?:-media {0,2}|)|msrbot|Mtps Feed Aggregation System|netresearch|Netvibes|NewsGator[^/]{0,30}|^NING|Nutch[^/]{0,30}|Nymesis|ObjectsSearch|OgScrper|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo Screenshot Bot|PlantyNet_WebRobot|Pompos|Qwantify|Read%20Later|Reaper|RedCarpet|Retreiver|Riddler|Rival IQ|scooter|Scrapy|Scrubby|searchsight|seekbot|semanticdiscovery|SemrushBot|Simpy|SimplePie|SEOstats|SimpleRSS|SiteCon|Slackbot-LinkExpanding|Slack-ImgProxy|Slurp|snappy|Speedy Spider|Squrl Java|Stringer|TheUsefulbot|ThumbShotsBot|Thumbshots\.ru|Tiny Tiny RSS|Twitterbot|WhatsApp|URL2PNG|Vagabondo|VoilaBot|^vortex|Votay bot|^voyager|WASALive.Bot|Web-sniffer|WebThumb|WeSEE:[A-z]{1,30}|WhatWeb|WIRE|WordPress|Wotbox|www\.almaden\.ibm\.com|Xenu(?:.s|) Link Sleuth|Xerka [A-z]{1,30}Bot|yacy(?:bot|)|YahooSeeker|Yahoo! Slurp|Yandex\w{1,30}|YodaoBot(?:-[A-z]{1,30}|)|YottaaMonitor|Yowedo|^Zao|^Zao-Crawler|ZeBot_www\.ze\.bz|ZooShot|ZyBorg)(?:[ /]v?(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|)
```
# Configuration Samples
## Release Requests that would otherwise Hit the Crawler Rules
```yaml
allow:
- ".*Go-http-client.*"
```
Without this configuration, the default Golang web library request will be treated as a crawler and access will be denied.
## Add Crawler Judgement
```yaml
deny:
- "spd-tools.*"
```
According to this configuration, the following requests will be denied:
```bash
curl http://example.com -H 'User-Agent: spd-tools/1.1'
curl http://exmaple.com -H 'User-Agent: spd-tools'
```
## Only Enabled for Specific Routes or Domains
```yaml
# Use _rules_ field for fine-grained rule configurations
_rules_:
# Rule 1: Match by route name
- _match_route_:
- route-a
- route-b
# Rule 2: Match by domain
- _match_domain_:
- "*.example.com"
- test.com
allow:
- ".*Go-http-client.*"
```
In the rule sample of `_match_route_`, `route-a` and `route-b` are the route names provided when creating a new gateway route. When the current route names matches the configuration, the rule following shall be applied.
In the rule sample of `_match_domain_`, `*.example.com` and `test.com` are the domain names used for request matching. When the current domain name matches the configuration, the rule following shall be applied.
All rules shall be checked following the order of items in the `_rules_` field, The first matched rule will be applied. All remained will be ignored.

View File

@@ -1,3 +1,7 @@
<p>
<a href="README_EN.md"> English </a> | 中文
</p>
# 功能说明
`custom-response`插件支持配置自定义的响应,包括自定义 HTTP 应答状态码、HTTP 应答头,以及 HTTP 应答 Body。可以用于 Mock 响应,也可以用于判断特定状态码后给出自定义应答,例如在触发网关限流策略时实现自定义响应。

Some files were not shown because too many files have changed in this diff Show More