From e2b68f455812c872d6e5cb49f2b76355542ba898 Mon Sep 17 00:00:00 2001 From: Jintao Zhang Date: Mon, 15 Aug 2022 18:04:44 +0800 Subject: [PATCH 01/30] chore(deps): bump go.uber.org/zap and github.com/prometheus/client_golang (#1244) --- go.mod | 17 ++++++++--------- go.sum | 35 ++++++++++++++++++++--------------- test/e2e/go.mod | 14 +++++++------- test/e2e/go.sum | 33 ++++++++++++++++++--------------- 4 files changed, 53 insertions(+), 46 deletions(-) diff --git a/go.mod b/go.mod index 83720cb4fd..8b4b6c9639 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,14 @@ require ( github.com/hashicorp/go-memdb v1.3.3 github.com/hashicorp/go-multierror v1.1.1 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.12.2 + github.com/prometheus/client_golang v1.13.0 github.com/prometheus/client_model v0.2.0 github.com/slok/kubewebhook/v2 v2.3.0 github.com/spf13/cobra v1.5.0 github.com/stretchr/testify v1.8.0 github.com/xeipuuv/gojsonschema v1.2.0 go.uber.org/multierr v1.8.0 - go.uber.org/zap v1.21.0 + go.uber.org/zap v1.22.0 golang.org/x/net v0.0.0-20220725212005-46097bf591d3 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 @@ -44,7 +44,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.7 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.0 // indirect @@ -62,24 +62,23 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml/v2 v2.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/ugorji/go/codec v1.2.7 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - go.uber.org/atomic v1.7.0 // indirect + go.uber.org/atomic v1.10.0 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.1.11 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/gengo v0.0.0-20220613173612-397b4ae3bce7 // indirect diff --git a/go.sum b/go.sum index a29610c4f2..e1b6b62562 100644 --- a/go.sum +++ b/go.sum @@ -153,9 +153,11 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -249,8 +251,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -447,8 +449,9 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -459,16 +462,18 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -563,11 +568,11 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= @@ -575,8 +580,8 @@ go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95a go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -683,6 +688,7 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220725212005-46097bf591d3 h1:2yWTtPWWRcISTw3/o+s/Y4UOMnQL71DWyToOANFusCg= golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -698,8 +704,9 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -871,8 +878,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gomodules.xyz/jsonpatch/v3 v3.0.1 h1:Te7hKxV52TKCbNYq3t84tzKav3xhThdvSsSp/W89IyI= gomodules.xyz/orderedmap v0.1.0 h1:fM/+TGh/O1KkqGR5xjTKg6bU8OKBkg7p0Y+x/J9m8Os= @@ -984,8 +989,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 1ae45f4db5..2c7fef4ea5 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -73,10 +73,10 @@ require ( github.com/pelletier/go-toml/v2 v2.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/otp v1.2.0 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect + github.com/prometheus/client_golang v1.13.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -90,12 +90,12 @@ require ( github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect - go.uber.org/atomic v1.7.0 // indirect + go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.21.0 // indirect + go.uber.org/zap v1.22.0 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/net v0.0.0-20220725212005-46097bf591d3 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect @@ -104,7 +104,7 @@ require ( google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect google.golang.org/grpc v1.42.0 // indirect google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 3bad5a75bb..deab836fcb 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -68,7 +68,6 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l github.com/aws/aws-sdk-go v1.40.56 h1:FM2yjR0UUYFzDTMx+mH9Vyw1k1EUUxsAFzk+BjkzANA= github.com/aws/aws-sdk-go v1.40.56/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -146,9 +145,11 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -232,7 +233,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -401,8 +402,9 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -411,14 +413,16 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -492,15 +496,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -609,8 +612,9 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -762,7 +766,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -880,8 +883,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 356b220f4b92c644e8a937164fca2517ed3e6a4f Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Mon, 15 Aug 2022 18:05:34 +0800 Subject: [PATCH 02/30] fix: TestRotateLog (#1246) --- cmd/ingress/ingress_test.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cmd/ingress/ingress_test.go b/cmd/ingress/ingress_test.go index a32a00b7b6..c72a2fe1cb 100644 --- a/cmd/ingress/ingress_test.go +++ b/cmd/ingress/ingress_test.go @@ -170,6 +170,8 @@ func TestRotateLog(t *testing.T) { cmd.SetArgs([]string{ "--log-rotate-output-path", "./testlog/test.log", "--log-rotate-max-size", "1", + "--log-level", "debug", + "--log-output", "./testlog/test.log", "--http-listen", listen, "--enable-profiling", "--kubeconfig", "/foo/bar/baz", @@ -185,6 +187,12 @@ func TestRotateLog(t *testing.T) { close(stopCh) }() + fws := &fakeWriteSyncer{} + logger, err := log.NewLogger(log.WithLogLevel("debug"), log.WithWriteSyncer(fws)) + assert.Nil(t, err) + defer logger.Close() + log.DefaultLogger = logger + // fill logs with data until the size > 1m line := "" for i := 0; i < 256; i++ { @@ -192,7 +200,7 @@ func TestRotateLog(t *testing.T) { } for i := 0; i < 4096; i++ { - log.Info(line) + log.Debug(line) } time.Sleep(5 * time.Second) @@ -206,5 +214,4 @@ func TestRotateLog(t *testing.T) { } assert.Equal(t, true, len(files) >= 2) - } From 35c9f6b935454e17384aaefe852a9c25d830b864 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Wed, 17 Aug 2022 16:45:56 +0800 Subject: [PATCH 03/30] fix: nodes convert failed (#1222) --- pkg/apisix/resource_test.go | 45 ++++++++++++++++++++++++++++++++++++ pkg/types/apisix/v1/types.go | 43 ++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/pkg/apisix/resource_test.go b/pkg/apisix/resource_test.go index 2c9699605c..528f801dae 100644 --- a/pkg/apisix/resource_test.go +++ b/pkg/apisix/resource_test.go @@ -78,6 +78,51 @@ func TestItemConvertRoute(t *testing.T) { assert.Equal(t, r.Name, "unknown") } +func TestItemConvertUpstream(t *testing.T) { + ite := &item{ + Key: "/apisix/upstreams/419655639963271872", + Value: json.RawMessage(`{ "nodes":{"httpbin.org:80":1, "foo.com:8080": 2}}`), + } + ups, err := ite.upstream() + assert.Nil(t, err) + assert.Len(t, ups.Nodes, 2) + assert.Equal(t, ups.Nodes[0], v1.UpstreamNode{Host: "httpbin.org", Port: 80, Weight: 1}) + assert.Equal(t, ups.Nodes[1], v1.UpstreamNode{Host: "foo.com", Port: 8080, Weight: 2}) + + ite = &item{ + Key: "/apisix/upstreams/419655639963271872", + Value: json.RawMessage(` +{ + "id": "419655639963271872", + "nodes": [ + { + "host": "httpbin.org", + "port": 80, + "weight": 1 + }, + { + "host": "httpbin.com", + "port": 8080, + "weight": 1 + } + ] +}`), + } + ups, err = ite.upstream() + assert.Nil(t, err) + assert.Len(t, ups.Nodes, 2) + assert.Equal(t, ups.Nodes[0], v1.UpstreamNode{Host: "httpbin.org", Port: 80, Weight: 1}) + assert.Equal(t, ups.Nodes[1], v1.UpstreamNode{Host: "httpbin.com", Port: 8080, Weight: 1}) + + ite = &item{ + Key: "/apisix/upstreams/419655639963271872", + Value: json.RawMessage(`{ "id":"419655639963271872" }`), + } + ups, err = ite.upstream() + assert.Nil(t, err) + assert.Len(t, ups.Nodes, 0) +} + func TestRouteVarsUnmarshalJSONCompatibility(t *testing.T) { var route v1.Route data := `{"vars":{}}` diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go index 3da9d4621c..8ffcd0d373 100644 --- a/pkg/types/apisix/v1/types.go +++ b/pkg/types/apisix/v1/types.go @@ -18,6 +18,7 @@ import ( "bytes" "encoding/json" "errors" + "fmt" "strconv" "strings" "time" @@ -216,14 +217,22 @@ type UpstreamNodes []UpstreamNode // and by default empty array will be encoded as '{}'. // We have to maintain the compatibility. func (n *UpstreamNodes) UnmarshalJSON(p []byte) error { + var data []UpstreamNode if p[0] == '{' { - if len(p) != 2 { - return errors.New("unexpected non-empty object") + value := map[string]float64{} + if err := json.Unmarshal(p, &value); err != nil { + return err + } + for k, v := range value { + node, err := mapKV2Node(k, v) + if err != nil { + return err + } + data = append(data, *node) } - *n = UpstreamNodes{} + *n = data return nil } - var data []UpstreamNode if err := json.Unmarshal(p, &data); err != nil { return err } @@ -231,6 +240,32 @@ func (n *UpstreamNodes) UnmarshalJSON(p []byte) error { return nil } +func mapKV2Node(key string, val float64) (*UpstreamNode, error) { + hp := strings.Split(key, ":") + host := hp[0] + // according to APISIX upstream nodes policy, port is required + port := "80" + + if len(hp) > 2 { + return nil, errors.New("invalid upstream node") + } else if len(hp) == 2 { + port = hp[1] + } + + portInt, err := strconv.Atoi(port) + if err != nil { + return nil, fmt.Errorf("parse port to int fail: %s", err.Error()) + } + + node := &UpstreamNode{ + Host: host, + Port: portInt, + Weight: int(val), + } + + return node, nil +} + // UpstreamNode is the node in upstream // +k8s:deepcopy-gen=true type UpstreamNode struct { From 2fa8a9c00e9fd3baa4884bb679879fc659fd218a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=B1=E7=9C=A0=E6=98=AF=E7=9C=9F=E6=BB=B4=E9=9A=BE?= =?UTF-8?q?=E5=8F=97?= Date: Wed, 17 Aug 2022 17:05:46 +0800 Subject: [PATCH 04/30] fix: log Secret name instead of all data (#1216) * fix: log Secret name instead of all data * fix: remove redundant logs * ci: triger --- pkg/providers/k8s/secret.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/providers/k8s/secret.go b/pkg/providers/k8s/secret.go index 57c36a08e6..1d299eb2c3 100644 --- a/pkg/providers/k8s/secret.go +++ b/pkg/providers/k8s/secret.go @@ -400,8 +400,7 @@ func (c *secretController) onUpdate(prev, curr interface{}) { return } log.Debugw("secret update event arrived", - zap.Any("new object", curr), - zap.Any("old object", prev), + zap.Any("secret name", curr.(*corev1.Secret).ObjectMeta.Name), ) c.workqueue.Add(&types.Event{ Type: types.EventUpdate, From 1a2930646ea6127d41fcf12236b3a0e5fb180dda Mon Sep 17 00:00:00 2001 From: Navendu Pottekkat Date: Thu, 18 Aug 2022 12:41:36 +0530 Subject: [PATCH 05/30] docs: update "Getting started" guide (#1247) Signed-off-by: Navendu Pottekkat Co-authored-by: Jintao Zhang --- docs/en/latest/config.json | 30 +++--- docs/en/latest/deployments/ack.md | 80 ++++++++++++---- docs/en/latest/getting-started.md | 154 +++++++++++++++++++----------- 3 files changed, 174 insertions(+), 90 deletions(-) diff --git a/docs/en/latest/config.json b/docs/en/latest/config.json index f60a79686b..7725f0176f 100644 --- a/docs/en/latest/config.json +++ b/docs/en/latest/config.json @@ -5,6 +5,21 @@ "type": "doc", "id": "getting-started" }, + { + "type": "category", + "label": "Installation", + "items": [ + "deployments/ack", + "deployments/aws", + "deployments/azure", + "deployments/gke", + "deployments/kind", + "deployments/kubesphere", + "deployments/k3s-rke", + "deployments/minikube", + "deployments/tke" + ] + }, { "type": "category", "label": "Tutorials", @@ -23,21 +38,6 @@ "tutorials/how-to-use-go-plugin-runner-in-apisix-ingress" ] }, - { - "type": "category", - "label": "Installation", - "items": [ - "deployments/ack", - "deployments/aws", - "deployments/azure", - "deployments/gke", - "deployments/kind", - "deployments/kubesphere", - "deployments/k3s-rke", - "deployments/minikube", - "deployments/tke" - ] - }, { "type": "category", "label": "References", diff --git a/docs/en/latest/deployments/ack.md b/docs/en/latest/deployments/ack.md index 2632df2f1d..df26464d9b 100644 --- a/docs/en/latest/deployments/ack.md +++ b/docs/en/latest/deployments/ack.md @@ -1,7 +1,12 @@ --- -title: Install Ingress APISIX on ACK +title: ACK (Alibaba Cloud) +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - Alibaba Cloud +description: Guide to install APISIX ingress controller on Alibaba Cloud Container Service for Kubernetes (ACK). --- - -This document explains how to install Ingress APISIX on Alibaba Cloud Container Service for Kubernetes (ACK). +This document explains how you can install APISIX ingress on [Alibaba Cloud Container Service for Kubernetes (ACK)](https://www.alibabacloud.com/product/kubernetes). ## Prerequisites -* Create an ACK Service on ali-cloud. -* Download the kube config for your ACK, follow the [introduction](https://www.alibabacloud.com/help/zh/doc-detail/86378.html). +Setting up APISIX ingress on ACK requires the following: + +* [Create an ACK service](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/create-an-ack-dedicated-cluster). +* [Add the cluster credentials](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/connect-to-ack-clusters-by-using-kubectl) to your kube config file. * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -48,20 +55,35 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +:::note + +By default, APISIX ingress controller will watch the apiVersion of `networking.k8s.io/v1`. + +If the target Kubernetes version is under `v1.19`, add the flag `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1`. + +Else, if your Kubernetes cluster version is under `v1.16`, set the flag `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1`. + +::: -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +This will create the five resources mentioned below: -The gateway service type is set to `LoadBalancer` (See [Access services through SLB](https://www.alibabacloud.com/help/doc-detail/182218.htm) for more details), so that clients can access Apache APISIX through a load balancer. You can find the load balancer ip by running: +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. + +The gateway service type will be set to `LoadBalancer`. See [Use an existing SLB instance to expose an application +](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-an-existing-slb-instance-to-expose-an-application-2) for details on using a load balancer. + +You can find the load balancer IP address by running: ```shell kubectl get service apisix-gateway --namespace ingress-apisix -o jsonpath='{.status.loadBalancer.ingress[].ip}' ``` -`ACK` PV require min_size is `20Gi`,cluster with `flexVolume` component select `alicloud-disk-ssd`,if with `helm values.yml` configure startup `apisix`,[more helm etcd configure](https://hub.kubeapps.com/charts/bitnami/etcd),configure format sample: +ACK PersistentVolume requires the minimum size of `20Gi` using FlexVolume (select `alicloud-disk-ssd`) + +`ACK` PV require min_size is `20Gi`,cluster with `flexVolume` component select `alicloud-disk-ssd`. If you are using Helm, you can use this [etcd configuration file](https://hub.kubeapps.com/charts/bitnami/etcd): ```yaml etcd: @@ -70,16 +92,32 @@ etcd: size: 20Gi ``` -Try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. -### Specify The Ingress Version - -apisix-ingress-controller will watch apiVersion of `networking.k8s.io/v1` by default. If the target kubernetes version is under `v1.19`, add `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1` or `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1` if your kubernetes cluster is under `v1.16` +## Next steps ### Enable SSL -The ssl config is disabled by default, add `--set gateway.tls.enabled=true` to enable tls support. +SSL is disabled by default. You can enable it by adding the flag `--set gateway.tls.enabled=true`. + +### Change default keys + +It is recommended to change the default keys for security: + +```shell +--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF +``` + +:::note -### Change default apikey +The `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same. It is better if these are not same as `admin.credentials.viewer`. -It's Recommended to change the default key by add `--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF`, notice that `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same, and should better not same as `admin.credentials.viewer`. +::: diff --git a/docs/en/latest/getting-started.md b/docs/en/latest/getting-started.md index c950c86a39..a9b7789d34 100644 --- a/docs/en/latest/getting-started.md +++ b/docs/en/latest/getting-started.md @@ -1,5 +1,10 @@ --- -title: Getting Started +title: Getting started +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress +description: Guide to get started with Apache APISIX ingress controller. --- -## What is apisix-ingress-controller - -apisix-ingress-controller is yet another Ingress controller for Kubernetes using [Apache APISIX](https://apisix.apache.org) as the high performance reverse proxy. - -It's configured by using the declarative configurations like [ApisixRoute](./concepts/apisix_route.md), [ApisixUpstream](./concepts/apisix_upstream.md), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/). -All these resources are watched and converted to corresponding resources in Apache APISIX. - -Service Discovery are also supported through [Kubernetes Service](https://kubernetes.io/docs/concepts/services-networking/service/), -and will be reflected to nodes in APISIX Upstream. +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +APISIX ingress controller is a [Kubernetes ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) using [Apache APISIX](https://apisix.apache.org) as the high performance reverse proxy. + +APISIX ingress controller can be configured using native Kubernetes ingress resources as well as a declarative and easy to use custom resources provided by APISIX. The APISIX ingress controller converts these resources to APISIX configuration. + +The examples below show how these differ. Both the examples configure a Route in APISIX that routes to an httpbin service as the Upstream. + + + + + +```yaml title="httpbin-route.yaml" +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpserver-route +spec: + http: + - name: rule1 + match: + hosts: + - local.httpbin.org + paths: + - /* + backends: + - serviceName: httpbin + servicePort: 80 +``` + + + + + +```yaml title="httpbin-route.yaml" +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: httpserver-ingress +spec: + ingressClassName: apisix + rules: + - host: local.httpbin.org + http: + paths: + - backend: + service: + name: httpbin + port: + number: 80 + path: / + pathType: Prefix +``` + + + + +APISIX ingress controller defines the CRDs [ApisixRoute](./concepts/apisix_route.md), [ApisixUpstream](./concepts/apisix_upstream.md), [ApisixTlx](concepts/apisix_tls.md), and [ApisixClusterConfig](concepts/apisix_cluster_config.md). + +APISIX also supports [service discovery](https://apisix.apache.org/docs/apisix/next/discovery/kubernetes/) through [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) abstraction. ![scene](../../assets/images/scene.png) -## Features - -* Declarative configuration -* Full dynamic capabilities to delivery configurations. -* Native Kubernetes Ingress (both v1 and v1beta1) support. -* Service Discovery based on Kubernetes Service. -* Out of box support for node health check. -* Support load balancing based on Pod (upstream nodes). -* Rich plugins support. -* Easy to deploy and use. +See [Design](./design.md) to learn more about how APISIX ingress controller works under the hood. -## How It Works - -See [Design](./design.md) for more details. - -## Installation on Cloud - -apisix-ingress-controller supports to be installed on some clouds such as AWS, GCP. +## Features -* [Install Ingress APISIX on Azure AKS](https://apisix.apache.org/docs/ingress-controller/deployments/azure) -* [Install Ingress APISIX on AWS EKS](https://apisix.apache.org/docs/ingress-controller/deployments/aws) -* [Install Ingress APISIX on ACK](https://apisix.apache.org/docs/ingress-controller/deployments/ack) -* [Install Ingress APISIX on Google Cloud GKE](https://apisix.apache.org/docs/ingress-controller/deployments/gke) -* [Install Ingress APISIX on Minikube](https://apisix.apache.org/docs/ingress-controller/deployments/minikube) -* [Install Ingress APISIX on KubeSphere](https://apisix.apache.org/docs/ingress-controller/deployments/kubesphere) -* [Install Ingress APISIX on K3S and RKE](https://apisix.apache.org/docs/ingress-controller/deployments/k3s-rke) +To summarize, APISIX ingress controller has the following features: -## Installation on Prem +- Declarative configuration with CRDs. +- Fully dynamic configuration. +- Supports native Kubernetes Ingress resource (both v1 and v1beta1). +- Supports service discovery through Kubernetes Service. +- Out-of-the-box node health check support. +- Supports load balancing based on pods (Upstream nodes). +- Rich [Plugins](https://apisix.apache.org/docs/apisix/next/plugins/batch-requests/) with [custom Plugin](https://apisix.apache.org/docs/apisix/next/plugin-develop/) support. -If you want to deploy apisix-ingress-controller on Prem, we recommend you to use [Helm](https://helm.sh/). Just a few steps +## Get involved -## Get Involved to Contribute +You can contribute to the development of APISIX ingress controller. See [Development guide](./contribute.md) for instructions on setting up the project locally. -First, your supports and cooperations to make this project better are appreciated. -But before you start, please read [How to Contribute](./contribute.md) +See the [Contribute to APISIX](https://apisix.apache.org/docs/general/contributor-guide/) section for details on the contributing flow. -## Compatibility with Apache APISIX +## Compatibility with APISIX -The following table describes the compatibility between apisix-ingress-controller and -[Apache APISIX](https://apisix.apache.org). +The table below shows the compatibility between APISIX ingress controller and the APISIX proxy. -| apisix-ingress-controller | Apache APISIX | -| ----:| ---:| -| `master` | `>= 2.7`, `2.11` is recommended. | -| `1.4.0` | `>= 2.7`, `2.11` is recommended. | -| `1.3.0` | `>= 2.7`, `2.10` is recommended. | -| `1.2.0` | `>= 2.7`, `2.8` is recommended. | -| `1.1.0` | `>= 2.7`, `2.7` is recommended. | -| `1.1.0` | `>= 2.7`, `2.7` is recommended. | -| `1.0.0` | `>= 2.7`, `2.7` is recommended. | -| `0.6` | `>= 2.6`, `2.6` is recommended. | -| `0.5` | `>= 2.4`, `2.5` is recommended. | -| `0.4` |`>= 2.4`| +| APISIX ingress controller | Supported APISIX versions | Recommended APISIX version | +| ------------------------- | ------------------------- | -------------------------- | +| `master` | `>= 2.7` | `2.11` | +| `1.4.0` | `>= 2.7` | `2.11` | +| `1.3.0` | `>= 2.7` | `2.10` | +| `1.2.0` | `>= 2.7` | `2.8` | +| `1.1.0` | `>= 2.7` | `2.7` | +| `1.1.0` | `>= 2.7` | `2.7` | +| `1.0.0` | `>= 2.7` | `2.7` | +| `0.6` | `>= 2.6` | `2.6` | +| `0.5` | `>= 2.4` | `2.5` | +| `0.4` | `>= 2.4` | | From 530ce52b278d7e385db3747d33e0d9fe1db0f3d1 Mon Sep 17 00:00:00 2001 From: lsy <70706700+stillfox-lee@users.noreply.github.com> Date: Sun, 21 Aug 2022 22:20:15 +0800 Subject: [PATCH 06/30] feat: add mqtt-proxy plugin in ApisixRoute (#1056) --- .github/workflows/spell-checker.yml | 2 +- docs/en/latest/references/apisix_route_v2.md | 4 + pkg/api/validation/apisix_route_test.go | 2 +- pkg/kube/apisix/apis/config/v2/types.go | 23 ++-- .../apis/config/v2/zz_generated.deepcopy.go | 49 ++++--- .../apisix/translation/apisix_route.go | 15 +++ pkg/types/apisix/v1/types.go | 1 + pkg/types/apisix/v1/zz_generated.deepcopy.go | 1 + samples/deploy/crd/v1/ApisixRoute.yaml | 16 +++ test/e2e/go.mod | 1 + test/e2e/go.sum | 6 + test/e2e/scaffold/scaffold.go | 8 ++ .../suite-plugins-other/mqtt-proxy.go | 122 ++++++++++++++++++ 13 files changed, 217 insertions(+), 33 deletions(-) create mode 100644 test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go diff --git a/.github/workflows/spell-checker.yml b/.github/workflows/spell-checker.yml index ef1d159a66..074f3bda5d 100644 --- a/.github/workflows/spell-checker.yml +++ b/.github/workflows/spell-checker.yml @@ -35,5 +35,5 @@ jobs: wget -O - -q https://git.io/misspell | sh -s -- -b . - name: Misspell run: | - find . -name "*.go" -type f | xargs ./misspell -error + find . -name "*.go" -type f | xargs ./misspell -i mosquitto -error find docs -type f | xargs ./misspell -error diff --git a/docs/en/latest/references/apisix_route_v2.md b/docs/en/latest/references/apisix_route_v2.md index 341b9cbec7..6deb9c2338 100644 --- a/docs/en/latest/references/apisix_route_v2.md +++ b/docs/en/latest/references/apisix_route_v2.md @@ -73,6 +73,10 @@ Meaning of each field in the spec of ApisixRoute are followed, the top level fie | stream[].backend.servicePort | integer or string | The backend service port, can be the port number or the name defined in the service object. | | stream[].backend.resolveGranularity | string | See [Service Resolve Granularity](#service-resolve-granularity) for the details. | | stream[].backend.subset | string | Subset specifies a subset for the target Service. The subset should be pre-definedin ApisixUpstream about this service. | +| stream[].plugins | array | A series of APISIX plugins that will be executed once this route rule is matched | +| stream[].plugins[].name | string | The plugin name, see [docs](http://apisix.apache.org/docs/apisix/getting-started) for learning the available plugins. | +| stream[].plugins[].enable | boolean | Whether the plugin would be used | +| stream[].plugins[].config | object | The configuration of the plugin that must have the same fields as in APISIX. | ## Expression Operators diff --git a/pkg/api/validation/apisix_route_test.go b/pkg/api/validation/apisix_route_test.go index 7249aa939a..f51ba0a7de 100644 --- a/pkg/api/validation/apisix_route_test.go +++ b/pkg/api/validation/apisix_route_test.go @@ -124,7 +124,7 @@ func Test_validatePlugin(t *testing.T) { fakeClient := newFakeSchemaClient() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotValid, _ := validatePlugin(fakeClient, tt.pluginName, v2.ApisixRouteHTTPPluginConfig(tt.pluginConfig)) + gotValid, _ := validatePlugin(fakeClient, tt.pluginName, v2.ApisixRoutePluginConfig(tt.pluginConfig)) if gotValid != tt.wantValid { t.Errorf("validatePlugin() gotValid = %v, want %v", gotValid, tt.wantValid) } diff --git a/pkg/kube/apisix/apis/config/v2/types.go b/pkg/kube/apisix/apis/config/v2/types.go index 6adc5c09ad..666d7b6a11 100644 --- a/pkg/kube/apisix/apis/config/v2/types.go +++ b/pkg/kube/apisix/apis/config/v2/types.go @@ -70,7 +70,7 @@ type ApisixRouteHTTP struct { Backends []ApisixRouteHTTPBackend `json:"backends,omitempty" yaml:"backends,omitempty"` Websocket bool `json:"websocket" yaml:"websocket"` PluginConfigName string `json:"plugin_config_name,omitempty" yaml:"plugin_config_name,omitempty"` - Plugins []ApisixRouteHTTPPlugin `json:"plugins,omitempty" yaml:"plugins,omitempty"` + Plugins []ApisixRoutePlugin `json:"plugins,omitempty" yaml:"plugins,omitempty"` Authentication ApisixRouteAuthentication `json:"authentication,omitempty" yaml:"authentication,omitempty"` } @@ -152,19 +152,19 @@ type ApisixRouteHTTPMatchExprSubject struct { Name string `json:"name" yaml:"name"` } -// ApisixRouteHTTPPlugin represents an APISIX plugin. -type ApisixRouteHTTPPlugin struct { +// ApisixRoutePlugin represents an APISIX plugin. +type ApisixRoutePlugin struct { // The plugin name. Name string `json:"name" yaml:"name"` // Whether this plugin is in use, default is true. Enable bool `json:"enable" yaml:"enable"` // Plugin configuration. - Config ApisixRouteHTTPPluginConfig `json:"config" yaml:"config"` + Config ApisixRoutePluginConfig `json:"config" yaml:"config"` } -// ApisixRouteHTTPPluginConfig is the configuration for +// ApisixRoutePluginConfig is the configuration for // any plugins. -type ApisixRouteHTTPPluginConfig map[string]interface{} +type ApisixRoutePluginConfig map[string]interface{} // ApisixRouteAuthentication is the authentication-related // configuration in ApisixRoute. @@ -189,16 +189,16 @@ type ApisixRouteAuthenticationJwtAuth struct { Cookie string `json:"cookie,omitempty" yaml:"cookie,omitempty"` } -func (p ApisixRouteHTTPPluginConfig) DeepCopyInto(out *ApisixRouteHTTPPluginConfig) { +func (p ApisixRoutePluginConfig) DeepCopyInto(out *ApisixRoutePluginConfig) { b, _ := json.Marshal(&p) _ = json.Unmarshal(b, out) } -func (p *ApisixRouteHTTPPluginConfig) DeepCopy() *ApisixRouteHTTPPluginConfig { +func (p *ApisixRoutePluginConfig) DeepCopy() *ApisixRoutePluginConfig { if p == nil { return nil } - out := new(ApisixRouteHTTPPluginConfig) + out := new(ApisixRoutePluginConfig) p.DeepCopyInto(out) return out } @@ -210,6 +210,7 @@ type ApisixRouteStream struct { Protocol string `json:"protocol" yaml:"protocol"` Match ApisixRouteStreamMatch `json:"match" yaml:"match"` Backend ApisixRouteStreamBackend `json:"backend" yaml:"backend"` + Plugins []ApisixRoutePlugin `json:"plugins,omitempty" yaml:"plugins,omitempty"` } // ApisixRouteStreamMatch represents the match conditions of stream route. @@ -691,9 +692,9 @@ type ApisixPluginConfig struct { // ApisixPluginConfigSpec defines the desired state of ApisixPluginConfigSpec. type ApisixPluginConfigSpec struct { - // Plugins contains a list of ApisixRouteHTTPPlugin + // Plugins contains a list of ApisixRoutePlugin // +required - Plugins []ApisixRouteHTTPPlugin `json:"plugins" yaml:"plugins"` + Plugins []ApisixRoutePlugin `json:"plugins" yaml:"plugins"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go b/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go index 1b94ae8861..63c3ea1ce1 100644 --- a/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go +++ b/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go @@ -669,7 +669,7 @@ func (in *ApisixPluginConfigSpec) DeepCopyInto(out *ApisixPluginConfigSpec) { *out = *in if in.Plugins != nil { in, out := &in.Plugins, &out.Plugins - *out = make([]ApisixRouteHTTPPlugin, len(*in)) + *out = make([]ApisixRoutePlugin, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -783,7 +783,7 @@ func (in *ApisixRouteHTTP) DeepCopyInto(out *ApisixRouteHTTP) { } if in.Plugins != nil { in, out := &in.Plugins, &out.Plugins - *out = make([]ApisixRouteHTTPPlugin, len(*in)) + *out = make([]ApisixRoutePlugin, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -910,23 +910,6 @@ func (in *ApisixRouteHTTPMatchExprSubject) DeepCopy() *ApisixRouteHTTPMatchExprS return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ApisixRouteHTTPPlugin) DeepCopyInto(out *ApisixRouteHTTPPlugin) { - *out = *in - in.Config.DeepCopyInto(&out.Config) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTPPlugin. -func (in *ApisixRouteHTTPPlugin) DeepCopy() *ApisixRouteHTTPPlugin { - if in == nil { - return nil - } - out := new(ApisixRouteHTTPPlugin) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApisixRouteList) DeepCopyInto(out *ApisixRouteList) { *out = *in @@ -960,6 +943,23 @@ func (in *ApisixRouteList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApisixRoutePlugin) DeepCopyInto(out *ApisixRoutePlugin) { + *out = *in + in.Config.DeepCopyInto(&out.Config) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRoutePlugin. +func (in *ApisixRoutePlugin) DeepCopy() *ApisixRoutePlugin { + if in == nil { + return nil + } + out := new(ApisixRoutePlugin) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApisixRouteSpec) DeepCopyInto(out *ApisixRouteSpec) { *out = *in @@ -973,7 +973,9 @@ func (in *ApisixRouteSpec) DeepCopyInto(out *ApisixRouteSpec) { if in.Stream != nil { in, out := &in.Stream, &out.Stream *out = make([]ApisixRouteStream, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } return } @@ -993,6 +995,13 @@ func (in *ApisixRouteStream) DeepCopyInto(out *ApisixRouteStream) { *out = *in out.Match = in.Match out.Backend = in.Backend + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = make([]ApisixRoutePlugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go index bf32f7333d..f91ea1289e 100644 --- a/pkg/providers/apisix/translation/apisix_route.go +++ b/pkg/providers/apisix/translation/apisix_route.go @@ -818,6 +818,20 @@ func (t *translator) translateStreamRouteV2(ctx *translation.TranslateContext, a ) return err } + + // add stream route plugins + pluginMap := make(apisixv1.Plugins) + for _, plugin := range part.Plugins { + if !plugin.Enable { + continue + } + if plugin.Config != nil { + pluginMap[plugin.Name] = plugin.Config + } else { + pluginMap[plugin.Name] = make(map[string]interface{}) + } + } + sr := apisixv1.NewDefaultStreamRoute() name := apisixv1.ComposeStreamRouteName(ar.Namespace, ar.Name, part.Name) sr.ID = id.GenID(name) @@ -827,6 +841,7 @@ func (t *translator) translateStreamRouteV2(ctx *translation.TranslateContext, a return err } sr.UpstreamId = ups.ID + sr.Plugins = pluginMap ctx.AddStreamRoute(sr) if !ctx.CheckUpstreamExist(ups.Name) { ctx.AddUpstream(ups) diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go index 8ffcd0d373..ea326adf34 100644 --- a/pkg/types/apisix/v1/types.go +++ b/pkg/types/apisix/v1/types.go @@ -372,6 +372,7 @@ type StreamRoute struct { SNI string `json:"sni,omitempty" yaml:"sni,omitempty"` UpstreamId string `json:"upstream_id,omitempty" yaml:"upstream_id,omitempty"` Upstream *Upstream `json:"upstream,omitempty" yaml:"upstream,omitempty"` + Plugins Plugins `json:"plugins,omitempty" yaml:"plugins,omitempty"` } // GlobalRule represents the global_rule object in APISIX. diff --git a/pkg/types/apisix/v1/zz_generated.deepcopy.go b/pkg/types/apisix/v1/zz_generated.deepcopy.go index 8da11e6f8c..a353718b64 100644 --- a/pkg/types/apisix/v1/zz_generated.deepcopy.go +++ b/pkg/types/apisix/v1/zz_generated.deepcopy.go @@ -465,6 +465,7 @@ func (in *StreamRoute) DeepCopyInto(out *StreamRoute) { *out = new(Upstream) (*in).DeepCopyInto(*out) } + in.Plugins.DeepCopyInto(&out.Plugins) return } diff --git a/samples/deploy/crd/v1/ApisixRoute.yaml b/samples/deploy/crd/v1/ApisixRoute.yaml index bccb647ce6..cf0f8e586a 100644 --- a/samples/deploy/crd/v1/ApisixRoute.yaml +++ b/samples/deploy/crd/v1/ApisixRoute.yaml @@ -821,6 +821,22 @@ spec: required: - serviceName - servicePort + plugins: + type: array + items: + type: object + properties: + name: + type: string + minLength: 1 + enable: + type: boolean + config: + type: object + x-kubernetes-preserve-unknown-fields: true # we have to enable it since plugin config + required: + - name + - enable status: type: object properties: diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 2c7fef4ea5..846ff78141 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/apache/apisix-ingress-controller v0.0.0-20210105024109-72e53386de5a github.com/apache/apisix-ingress-controller/test/e2e/testbackend v0.0.0 + github.com/eclipse/paho.mqtt.golang v1.3.5 github.com/gavv/httpexpect/v2 v2.3.1 github.com/gorilla/websocket v1.5.0 github.com/gruntwork-io/terratest v0.40.19 diff --git a/test/e2e/go.sum b/test/e2e/go.sum index deab836fcb..287a6e555a 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -101,6 +101,11 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y= +github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -574,6 +579,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go index a8b97be90d..b11a33d850 100644 --- a/test/e2e/scaffold/scaffold.go +++ b/test/e2e/scaffold/scaffold.go @@ -34,6 +34,7 @@ import ( "time" "github.com/apache/apisix-ingress-controller/pkg/config" + mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gavv/httpexpect/v2" "github.com/gruntwork-io/terratest/modules/k8s" "github.com/gruntwork-io/terratest/modules/testing" @@ -283,6 +284,13 @@ func (s *Scaffold) NewAPISIXClientWithTLSOverTCP(host string) *httpexpect.Expect }) } +func (s *Scaffold) NewMQTTClient() mqtt.Client { + opts := mqtt.NewClientOptions() + opts.AddBroker(fmt.Sprintf("tcp://%s", s.apisixTCPTunnel.Endpoint())) + client := mqtt.NewClient(opts) + return client +} + func (s *Scaffold) DNSResolver() *net.Resolver { return &net.Resolver{ PreferGo: false, diff --git a/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go b/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go new file mode 100644 index 0000000000..b906a280ef --- /dev/null +++ b/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go @@ -0,0 +1,122 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugins + +import ( + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/stretchr/testify/assert" + + "github.com/apache/apisix-ingress-controller/test/e2e/scaffold" +) + +var _ = ginkgo.Describe("suite-plugins-other: mqtt-proxy plugin", func() { + opts := &scaffold.Options{ + Name: "mqtt-proxy", + IngressAPISIXReplicas: 1, + ApisixResourceVersion: scaffold.ApisixResourceVersion().V2, + } + s := scaffold.NewScaffold(opts) + // setup mosquito service + ginkgo.It("stream mqtt proxy", func() { + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mosquito +spec: + replicas: 1 + selector: + matchLabels: + app: mosquito + template: + metadata: + labels: + app: mosquito + spec: + containers: + - name: mosquito + image: eclipse-mosquitto:1.6 + livenessProbe: + tcpSocket: + port: 1883 + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + tcpSocket: + port: 1883 + initialDelaySeconds: 5 + periodSeconds: 10 + ports: + - name: mosquito + containerPort: 1883 + protocol: TCP +`)) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(` +apiVersion: v1 +kind: Service +metadata: + name: mosquito +spec: + selector: + app: mosquito + type: ClusterIP + ports: + - port: 1883 + targetPort: 1883 + protocol: TCP +`)) + s.EnsureNumEndpointsReady(ginkgo.GinkgoT(), "mosquito", 1) + // setup Apisix Route for mqtt proxy + apisixRoute := ` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: mqtt-route +spec: + stream: + - name: rule1 + protocol: TCP + match: + ingressPort: 9100 + backend: + serviceName: mosquito + servicePort: 1883 + plugins: + - name: mqtt-proxy + enable: true + config: + protocol_name: MQTT + protocol_level: 4 +` + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(apisixRoute)) + + err := s.EnsureNumApisixStreamRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + sr, err := s.ListApisixStreamRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), sr, 1) + assert.Equal(ginkgo.GinkgoT(), sr[0].ServerPort, int32(9100)) + // test mqtt protocol + c := s.NewMQTTClient() + token := c.Connect() + token.WaitTimeout(3 * time.Second) + assert.Nil(ginkgo.GinkgoT(), token.Error(), "Checking mqtt connection") + }) +}) From f802271de1d0d8a39730a0d177a79b83b7af6c11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Aug 2022 09:39:32 +0800 Subject: [PATCH 07/30] chore(deps): bump github.com/gruntwork-io/terratest in /test/e2e (#1259) Bumps [github.com/gruntwork-io/terratest](https://github.com/gruntwork-io/terratest) from 0.40.19 to 0.40.20. - [Release notes](https://github.com/gruntwork-io/terratest/releases) - [Commits](https://github.com/gruntwork-io/terratest/compare/v0.40.19...v0.40.20) --- updated-dependencies: - dependency-name: github.com/gruntwork-io/terratest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/go.mod | 2 +- test/e2e/go.sum | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 846ff78141..f3bf8b19c8 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -8,7 +8,7 @@ require ( github.com/eclipse/paho.mqtt.golang v1.3.5 github.com/gavv/httpexpect/v2 v2.3.1 github.com/gorilla/websocket v1.5.0 - github.com/gruntwork-io/terratest v0.40.19 + github.com/gruntwork-io/terratest v0.40.20 github.com/onsi/ginkgo/v2 v2.1.4 github.com/stretchr/testify v1.8.0 k8s.io/api v0.24.3 diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 287a6e555a..1531f9d14c 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -101,11 +101,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y= github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -274,8 +271,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= -github.com/gruntwork-io/terratest v0.40.19 h1:slnTF0Amrc9yRVUV/X/fHlVWKNF0H8fwa2OLyeV2IOA= -github.com/gruntwork-io/terratest v0.40.19/go.mod h1:JGeIGgLbxbG9/Oqm06z6YXVr76CfomdmLkV564qov+8= +github.com/gruntwork-io/terratest v0.40.20 h1:pco6s3b62h2Yd13N+HvHQVTAk3aPRz4sdoVwErPCBzQ= +github.com/gruntwork-io/terratest v0.40.20/go.mod h1:JGeIGgLbxbG9/Oqm06z6YXVr76CfomdmLkV564qov+8= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= From 4eede7e96ad60da3388041eeb5a2d4366c4901a3 Mon Sep 17 00:00:00 2001 From: Jintao Zhang Date: Tue, 23 Aug 2022 16:02:07 +0800 Subject: [PATCH 08/30] chore(deps): bump deps from 0.24.3 to 0.24.4 (#1265) * chore(deps): bump k8s.io/apimachinery from 0.24.3 to 0.24.4 in /test/e2e Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.24.3 to 0.24.4. - [Release notes](https://github.com/kubernetes/apimachinery/releases) - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.24.3...v0.24.4) --- updated-dependencies: - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps): bump k8s.io/apimachinery from 0.24.3 to 0.24.4 Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.24.3 to 0.24.4. - [Release notes](https://github.com/kubernetes/apimachinery/releases) - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.24.3...v0.24.4) --- updated-dependencies: - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps): bump k8s.io/code-generator from 0.24.3 to 0.24.4 Bumps [k8s.io/code-generator](https://github.com/kubernetes/code-generator) from 0.24.3 to 0.24.4. - [Release notes](https://github.com/kubernetes/code-generator/releases) - [Commits](https://github.com/kubernetes/code-generator/compare/v0.24.3...v0.24.4) --- updated-dependencies: - dependency-name: k8s.io/code-generator dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps): bump k8s.io/client-go from 0.24.3 to 0.24.4 Signed-off-by: Jintao Zhang Signed-off-by: dependabot[bot] Signed-off-by: Jintao Zhang Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- test/e2e/go.mod | 6 +++--- test/e2e/go.sum | 12 ++++++------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 8b4b6c9639..3eef9caa69 100644 --- a/go.mod +++ b/go.mod @@ -18,10 +18,10 @@ require ( golang.org/x/net v0.0.0-20220725212005-46097bf591d3 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.24.3 - k8s.io/apimachinery v0.24.3 - k8s.io/client-go v0.24.3 - k8s.io/code-generator v0.24.3 + k8s.io/api v0.24.4 + k8s.io/apimachinery v0.24.4 + k8s.io/client-go v0.24.4 + k8s.io/code-generator v0.24.4 sigs.k8s.io/gateway-api v0.4.0 ) diff --git a/go.sum b/go.sum index e1b6b62562..fcd34a7688 100644 --- a/go.sum +++ b/go.sum @@ -1036,22 +1036,22 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= -k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY= -k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= +k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk= +k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M= k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= -k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ= +k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= -k8s.io/client-go v0.24.3 h1:Nl1840+6p4JqkFWEW2LnMKU667BUxw03REfLAVhuKQY= -k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= +k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg= +k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y= k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= k8s.io/code-generator v0.22.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= -k8s.io/code-generator v0.24.3 h1:itd1V1ZAYKM+WT+qQDlFKhU1D/Ff5HcEFL/icfClnZA= -k8s.io/code-generator v0.24.3/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= +k8s.io/code-generator v0.24.4 h1:HLnoAabkTFKy1Ex4cMvffz6KkWFJ7oFN2yX37Icbbyg= +k8s.io/code-generator v0.24.4/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= diff --git a/test/e2e/go.mod b/test/e2e/go.mod index f3bf8b19c8..bf5c023ee2 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -11,9 +11,9 @@ require ( github.com/gruntwork-io/terratest v0.40.20 github.com/onsi/ginkgo/v2 v2.1.4 github.com/stretchr/testify v1.8.0 - k8s.io/api v0.24.3 - k8s.io/apimachinery v0.24.3 - k8s.io/client-go v0.24.3 + k8s.io/api v0.24.4 + k8s.io/apimachinery v0.24.4 + k8s.io/client-go v0.24.4 ) require ( diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 1531f9d14c..1b0d97cbb2 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -922,12 +922,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY= -k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= -k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= -k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/client-go v0.24.3 h1:Nl1840+6p4JqkFWEW2LnMKU667BUxw03REfLAVhuKQY= -k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= +k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk= +k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M= +k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ= +k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg= +k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= From 20eb64ea568ee8acd2e2b1f576cdd154935b6a14 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Thu, 25 Aug 2022 11:02:38 +0800 Subject: [PATCH 09/30] fix: object type should be apisix_upstream and endpointslice and apisix_cluster_config (#1268) --- pkg/providers/apisix/apisix_cluster_config.go | 2 +- pkg/providers/apisix/apisix_upstream.go | 2 +- pkg/providers/k8s/endpoint/endpointslice.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/providers/apisix/apisix_cluster_config.go b/pkg/providers/apisix/apisix_cluster_config.go index d611cbb935..7c1f2c5048 100644 --- a/pkg/providers/apisix/apisix_cluster_config.go +++ b/pkg/providers/apisix/apisix_cluster_config.go @@ -307,7 +307,7 @@ func (c *apisixClusterConfigController) handleSyncErr(obj interface{}, err error if k8serrors.IsNotFound(err) && event.Type != types.EventDelete { log.Infow("sync ApisixClusterConfig but not found, ignore", zap.String("event_type", event.Type.String()), - zap.String("ApisixClusterConfig", event.Object.(string)), + zap.Any("ApisixClusterConfig", event.Object.(kube.ApisixClusterConfigEvent)), ) c.workqueue.Forget(event) return diff --git a/pkg/providers/apisix/apisix_upstream.go b/pkg/providers/apisix/apisix_upstream.go index ff9d067887..92b091ec87 100644 --- a/pkg/providers/apisix/apisix_upstream.go +++ b/pkg/providers/apisix/apisix_upstream.go @@ -339,7 +339,7 @@ func (c *apisixUpstreamController) handleSyncErr(obj interface{}, err error) { if k8serrors.IsNotFound(err) && event.Type != types.EventDelete { log.Infow("sync ApisixUpstream but not found, ignore", zap.String("event_type", event.Type.String()), - zap.String("ApisixUpstream", event.Object.(string)), + zap.Any("ApisixUpstream", event.Object.(kube.ApisixUpstreamEvent)), ) c.workqueue.Forget(event) return diff --git a/pkg/providers/k8s/endpoint/endpointslice.go b/pkg/providers/k8s/endpoint/endpointslice.go index 56faffbfd4..972ecb5a01 100644 --- a/pkg/providers/k8s/endpoint/endpointslice.go +++ b/pkg/providers/k8s/endpoint/endpointslice.go @@ -147,7 +147,7 @@ func (c *endpointSliceController) handleSyncErr(obj interface{}, err error) { if k8serrors.IsNotFound(err) && event.Type != types.EventDelete { log.Infow("sync endpointSlice but not found, ignore", zap.String("event_type", event.Type.String()), - zap.String("endpointSlice", event.Object.(string)), + zap.Any("endpointSlice", event.Object.(endpointSliceEvent)), ) c.workqueue.Forget(event) return From ef07421700cff966a24d6b3b391feaed543be717 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Fri, 26 Aug 2022 14:00:04 +0800 Subject: [PATCH 10/30] ci: set default_branch (#1274) * timer-ci * update default_branch --- .github/workflows/k8s-timer-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/k8s-timer-ci.yml b/.github/workflows/k8s-timer-ci.yml index 8676c2fbee..00d1684874 100644 --- a/.github/workflows/k8s-timer-ci.yml +++ b/.github/workflows/k8s-timer-ci.yml @@ -19,6 +19,8 @@ name: k8s-timer-ci on: + repository_dispatch: + default_branch: master schedule: - cron: '0 1 * * 1' From 5e844e44b4f58458574f9e570b2244945ee92d3a Mon Sep 17 00:00:00 2001 From: Navendu Pottekkat Date: Sat, 27 Aug 2022 07:22:32 +0530 Subject: [PATCH 11/30] docs: update installation guide (#1272) --- docs/en/latest/config.json | 12 ++-- docs/en/latest/deployments/aws.md | 77 ++++++++++++++++------ docs/en/latest/deployments/azure.md | 78 ++++++++++++++++------ docs/en/latest/deployments/gke.md | 75 ++++++++++++++++------ docs/en/latest/deployments/k3s-rke.md | 44 ++++++++----- docs/en/latest/deployments/kind.md | 39 ++++++----- docs/en/latest/deployments/kubesphere.md | 72 +++++++++++++++------ docs/en/latest/deployments/minikube.md | 26 +++++--- docs/en/latest/deployments/tke.md | 82 +++++++++++++++++------- 9 files changed, 352 insertions(+), 153 deletions(-) diff --git a/docs/en/latest/config.json b/docs/en/latest/config.json index 7725f0176f..bff5ed08b7 100644 --- a/docs/en/latest/config.json +++ b/docs/en/latest/config.json @@ -9,15 +9,15 @@ "type": "category", "label": "Installation", "items": [ - "deployments/ack", + "deployments/minikube", + "deployments/kind", "deployments/aws", - "deployments/azure", + "deployments/ack", "deployments/gke", - "deployments/kind", + "deployments/azure", + "deployments/tke", "deployments/kubesphere", - "deployments/k3s-rke", - "deployments/minikube", - "deployments/tke" + "deployments/k3s-rke" ] }, { diff --git a/docs/en/latest/deployments/aws.md b/docs/en/latest/deployments/aws.md index 8e1605614f..0c2777983b 100644 --- a/docs/en/latest/deployments/aws.md +++ b/docs/en/latest/deployments/aws.md @@ -1,7 +1,12 @@ --- -title: Install Ingress APISIX on Amazon EKS +title: EKS (Amazon) +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - Amazon EKS +description: Guide to install APISIX ingress controller on Amazon Elastic Kubernetes Service (EKS). --- - -This document explains how to install Ingress APISIX on [Amazon EKS](https://amazonaws-china.com/eks/?whats-new-cards.sort-by=item.additionalFields.postDateTime&whats-new-cards.sort-order=desc&eks-blogs.sort-by=item.additionalFields.createdDate&eks-blogs.sort-order=desc). +This guide explains how you can install APISIX ingress on [Amazon EKS](https://aws.amazon.com/eks/?whats-new-cards.sort-by=item.additionalFields.postDateTime&whats-new-cards.sort-order=desc&eks-blogs.sort-by=item.additionalFields.createdDate&eks-blogs.sort-order=desc). ## Prerequisites -* Create an EKS Service on AWS. -* Download the kube config for your EKS from [aws cli interface](https://amazonaws-china.com/cli/). +Before installing APISIX, you need to: + +* [Create an EKS cluster](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) on AWS. +* Enable kubectl to communicate with your cluster by adding the credentials to your kube config file. * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -46,31 +53,59 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +:::note + +By default, APISIX ingress controller will watch the apiVersion of `networking.k8s.io/v1`. + +If the target Kubernetes version is under `v1.19`, add the flag `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1`. + +Else, if your Kubernetes cluster version is under `v1.16`, set the flag `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1`. + +::: -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +This will create the five resources mentioned below: -The gateway service type is set to `LoadBalancer` (See [AWS Network Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html) for more details), so that clients can access Apache APISIX through a load balancer. You can find the load balancer hostname by running: +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. + +The gateway service type will be set to `LoadBalancer`. See [Network Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html) for more details on using it in AWS. + +You can find the load balancer IP address by running: ```shell kubectl get service apisix-gateway --namespace ingress-apisix -o jsonpath='{.status.loadBalancer.ingress[].hostname}' ``` -Now open your [EKS console](https://console.aws.amazon.com/eks/home), choosing your cluster and clicking the Workloads tag, you'll see all pods of Apache APISIX, etcd and apisix-ingress-controller are ready. - -Try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +Now, if you open your [EKS console](https://console.aws.amazon.com/eks/home), select your cluster, and click the workloads tag, you will be able to see all APISIX, etcd, and ingress controller pods. -### Specify The Ingress Version +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. -apisix-ingress-controller will watch apiVersion of `networking.k8s.io/v1` by default. If the target kubernetes version is under `v1.19`, add `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1` or `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1` if your kubernetes cluster is under `v1.16` +## Next steps ### Enable SSL -The ssl config is disabled by default, add `--set gateway.tls.enabled=true` to enable tls support. +SSL is disabled by default. You can enable it by adding the flag `--set gateway.tls.enabled=true`. + +### Change default keys + +It is recommended to change the default keys for security: + +```shell +--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF +``` + +:::note -### Change default apikey +The `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same. It is better if these are not same as `admin.credentials.viewer`. -It's Recommended to change the default key by add `--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF`, notice that `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same, and should better not same as `admin.credentials.viewer`. +::: diff --git a/docs/en/latest/deployments/azure.md b/docs/en/latest/deployments/azure.md index 121667d0bd..e9dc7c061d 100644 --- a/docs/en/latest/deployments/azure.md +++ b/docs/en/latest/deployments/azure.md @@ -1,7 +1,12 @@ --- -title: Install Ingress APISIX on Azure AKS +title: AKS (Azure) +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - Microsoft Azure +description: Guide to install APISIX ingress controller on Azure Kubernetes Service (AKS). --- - -This document explains how to install Ingress APISIX on [Azure AKS](https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes#:~:text=Azure%20Kubernetes%20Service%20(AKS)%20makes,managed%20Kubernetes%20cluster%20in%20Azure.&text=The%20Kubernetes%20masters%20are%20managed,clusters%2C%20not%20for%20the%20masters.). +This document explains how you can install APISIX ingress on [Azure AKS](https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes). ## Prerequisites -* Create an Kubernetes Service on Azure. -* Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/#:~:text=The%20Azure%20command%2Dline%20interface,with%20an%20emphasis%20on%20automation.) and download the credentials by running `az aks get-credentials`. +Setting up APISIX ingress on AKS requires the following: + +* [Create an AKS cluster](https://docs.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-portal?tabs=azure-cli). +* Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/#:~:text=The%20Azure%20command%2Dline%20interface,with%20an%20emphasis%20on%20automation.) and update your kube config file by running: + + ```shell + az aks get-credentials + ``` + * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -46,29 +58,55 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +:::note + +By default, APISIX ingress controller will watch the apiVersion of `networking.k8s.io/v1`. + +If the target Kubernetes version is under `v1.19`, add the flag `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1`. -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +Else, if your Kubernetes cluster version is under `v1.16`, set the flag `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1`. -The gateway service type is set to `LoadBalancer`, so that clients can access Apache APISIX through a load balancer IP. You can find the load balancer IP by running: +::: + +This will create the five resources mentioned below: + +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. + +The gateway service type will be set to `LoadBalancer`. You can find the load balancer IP address by running: ```shell kubectl get service apisix-gateway --namespace ingress-apisix -o jsonpath='{.status.loadBalancer.ingress[].ip}' ``` -Now try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. -### Specify The Ingress Version - -apisix-ingress-controller will watch apiVersion of `networking.k8s.io/v1` by default. If the target kubernetes version is under `v1.19`, add `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1` or `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1` if your kubernetes cluster is under `v1.16` +## Next steps ### Enable SSL -The ssl config is disabled by default, add `--set gateway.tls.enabled=true` to enable tls support. +SSL is disabled by default. You can enable it by adding the flag `--set gateway.tls.enabled=true`. + +### Change default keys + +It is recommended to change the default keys for security: + +```shell +--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF +``` + +:::note -### Change default apikey +The `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same. It is better if these are not same as `admin.credentials.viewer`. -It's Recommended to change the default key by add `--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF`, notice that `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same, and should better not same as `admin.credentials.viewer`. +::: diff --git a/docs/en/latest/deployments/gke.md b/docs/en/latest/deployments/gke.md index 9d15a8609a..f63d17dd6c 100644 --- a/docs/en/latest/deployments/gke.md +++ b/docs/en/latest/deployments/gke.md @@ -1,7 +1,12 @@ --- -title: Install Ingress APISIX on Google Cloud GKE +title: GKE (Google) +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - Google Cloud Platform +description: Guide to install APISIX ingress controller on Google Kubernetes Engine (GKE). --- - -This document explains how to install Ingress APISIX on [Google Cloud GKE](https://cloud.google.com/kubernetes-engine). +This guide explains how you can install APISIX ingress on [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine). ## Prerequisites -* Create an Kubernetes Service on GKE. -* Install [Google Cloud SDK](https://cloud.google.com/sdk) and get the credentials or you can just use the [Cloud Shell](https://cloud.google.com/shell). +Setting up APISIX ingress on GKE requires the following: + +* [Create a GKE cluster](https://cloud.google.com/kubernetes-engine/docs/deploy-app-cluster#create_cluster) on Google Cloud. +* Install [Google Cloud SDK](https://cloud.google.com/sdk) and update the credentials in your kube config file or use the [shell](https://cloud.google.com/shell). * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -46,29 +53,57 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +:::note + +By default, APISIX ingress controller will watch the apiVersion of `networking.k8s.io/v1`. + +If the target Kubernetes version is under `v1.19`, add the flag `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1`. + +Else, if your Kubernetes cluster version is under `v1.16`, set the flag `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1`. + +::: -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +This will create the five resources mentioned below: -The gateway service type is set to `LoadBalancer`, so that clients can access Apache APISIX through the [GKE Load Balancer](https://cloud.google.com/kubernetes-engine/docs/concepts/service#services_of_type_loadbalancer) . You can find the load balancer IP by running: +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. + +The gateway service type will be set to `LoadBalancer`. Clients can access Apache APISIX through the [GKE Load Balancer](https://cloud.google.com/kubernetes-engine/docs/concepts/service#services_of_type_loadbalancer). + +You can find the load balancer IP address by running: ```shell kubectl get service apisix-gateway --namespace ingress-apisix -o jsonpath='{.status.loadBalancer.ingress[].ip}' ``` -Now try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. - -### Specify The Ingress Version +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. -apisix-ingress-controller will watch apiVersion of `networking.k8s.io/v1` by default. If the target kubernetes version is under `v1.19`, add `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1` or `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1` if your kubernetes cluster is under `v1.16` +## Next steps ### Enable SSL -The ssl config is disabled by default, add `--set gateway.tls.enabled=true` to enable tls support. +SSL is disabled by default. You can enable it by adding the flag `--set gateway.tls.enabled=true`. + +### Change default keys + +It is recommended to change the default keys for security: + +```shell +--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF +``` + +:::note -### Change default apikey +The `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same. It is better if these are not same as `admin.credentials.viewer`. -It's Recommended to change the default key by add `--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF`, notice that `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same, and should better not same as `admin.credentials.viewer`. +::: diff --git a/docs/en/latest/deployments/k3s-rke.md b/docs/en/latest/deployments/k3s-rke.md index bcf1a82422..a3a3db941b 100644 --- a/docs/en/latest/deployments/k3s-rke.md +++ b/docs/en/latest/deployments/k3s-rke.md @@ -1,7 +1,13 @@ --- -title: Install Ingress APISIX on K3S and Rancher RKE +title: K3s and RKE (Rancher) +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - K3s + - Rancher RKE +description: Guide to install APISIX ingress controller on K3s and Rancher Kubernetes Engine(RKE). --- - -This document explains how to install Ingress APISIX on [k3S](https://k3s.io/) and [Rancher RKE](https://rancher.com/products/rke/). +This document explains how you can install APISIX ingress on [k3S](https://k3s.io/) and [Rancher RKE](https://rancher.com/products/rke/). + +:::tip + +K3s is built for IoT and edge computing applications. Apache APISIX also supports an MQTT Plugin and runs well on ARM processors. APISIX ingress is therefore a good choice to handle North-South traffic in K3s. -K3S is a certified Kubernetes distribution built for IoT and Edge computing, whilst [Apache APISIX](https://apisix.apache.org) is also good at IoT (See [MQTT plugin](https://github.com/apache/apisix/blob/master/docs/en/latest/plugins/mqtt-proxy.md)) and runs well on ARM architecture. -It's a good choice to use Ingress APISIX as the north-south API gateway in K3S. +::: ## Prerequisites * Install [K3S](https://rancher.com/docs/k3s/latest/en/installation/) or [Rancher RKE](https://rancher.com/docs/rke/latest/en/installation/). * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -49,16 +58,19 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -*If you are using K3S, the default kubeconfig file is in /etc/rancher/k3s and root permission may required.* +:::info IMPORTANT + +If you are using K3s, the default kube config file is located in `/etc/rancher/k3s/` and you make require root permission. + +::: -Five Service resources were created. +This will create the five resources mentioned below: -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. -The gateway service type is set to `NodePort`, so that clients can access Apache APISIX through the Node IPs and the assigned port. -If you are using K3S and you want to expose a `LoadBalancer` service, try to use [Klipper](https://github.com/k3s-io/klipper-lb). +The gateway service type is set to `NodePort`. Clients can access APISIX through the Node IPs and the assigned port. To use a service of type `LoadBalancer` with K3s, use a bare-metal load balancer implementation like [Klipper](https://github.com/k3s-io/klipper-lb). -Now try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. diff --git a/docs/en/latest/deployments/kind.md b/docs/en/latest/deployments/kind.md index 7994a23bd8..9249466cce 100644 --- a/docs/en/latest/deployments/kind.md +++ b/docs/en/latest/deployments/kind.md @@ -1,7 +1,12 @@ --- -title: Install Ingress APISIX on Kind +title: kind +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - kind +description: Guide to install APISIX ingress controller on kind. --- - -This document explains how to install Ingress APISIX on [kind](https://kind.sigs.k8s.io/). +This document explains how you can install APISIX ingress locally on [kind](https://kind.sigs.k8s.io/). ## Prerequisites @@ -29,23 +34,25 @@ This document explains how to install Ingress APISIX on [kind](https://kind.sigs * Install [Helm](https://helm.sh/). * Install [kubectl](https://kubernetes.io/docs/tasks/tools/). -If you encounter some strange problems, please consider whether it is a version compatibility issue. +:::tip + +If you encounter issues, check the version you are using. This document uses kind v0.12.0, Helm v3.8.1, and kubectl v1.23.5. -The versions of kind(==v0.12.0), kubectl(==v1.23.5) and helm(==v3.8.1) used in this document are confirmed feasible. +::: -## Create Cluster +## Create a kind cluster -The quickest way to get a taste is to run command as follows and then go to the next section. +Ensure you have Docker running and start the kind cluster: ```shell kind create cluster ``` -You can click this [link](https://kind.sigs.k8s.io/docs/user/ingress/#create-cluster) for more information. +See [Ingress](https://kind.sigs.k8s.io/docs/user/ingress/#create-cluster) to learn more about setting up ingress on a kind cluster. -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -60,11 +67,11 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +This will create the five resources mentioned below: -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. -Now try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running of Ingress APISIX. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. diff --git a/docs/en/latest/deployments/kubesphere.md b/docs/en/latest/deployments/kubesphere.md index 262bcf127f..1029780f6a 100644 --- a/docs/en/latest/deployments/kubesphere.md +++ b/docs/en/latest/deployments/kubesphere.md @@ -1,7 +1,12 @@ --- -title: Install Ingress APISIX on KubeSphere +title: KubeSphere +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - KubeSphere +description: Guide to install APISIX ingress controller on KubeSphere Container Platform. --- - -This document explains how to install Ingress APISIX on [KubeSphere](https://kubesphere.io/). - -KubeSphere is a distributed operating system managing cloud native applications with Kubernetes as its kernel, and provides plug-and-play architecture for the seamless integration of third-party applications to boost its ecosystem. +This guide explains how you can install APISIX ingress on [KubeSphere](https://kubesphere.io/) distributed operating system. ## Prerequisites -* Install [KubeSphere](https://kubesphere.io/docs/quick-start/), you can choose [All-in-one Installation on Linux](https://kubesphere.io/docs/quick-start/all-in-one-on-linux/) or [Minimal KubeSphere on Kubernetes](https://kubesphere.io/docs/quick-start/minimal-kubesphere-on-k8s/). +Setting up APISIX ingress on KubeSphere requires the following: + +* Install [KubeSphere](https://kubesphere.io/docs/quick-start/) on Linux or minimally on Kubernetes. * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -47,26 +52,51 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +:::note + +By default, APISIX ingress controller will watch the apiVersion of `networking.k8s.io/v1`. + +If the target Kubernetes version is under `v1.19`, add the flag `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1`. -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +Else, if your Kubernetes cluster version is under `v1.16`, set the flag `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1`. -The gateway service type is set to `NodePort`, so that clients can access Apache APISIX through the Node IPs and the assigned port. -If you want to expose a `LoadBalancer` service, try to use [Porter](https://github.com/kubesphere/porter). +::: -Now try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +This will create the five resources mentioned below: -### Specify The Ingress Version +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. -apisix-ingress-controller will watch apiVersion of `networking.k8s.io/v1` by default. If the target kubernetes version is under `v1.19`, add `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1` or `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1` if your kubernetes cluster is under `v1.16` +The gateway service type is set to `NodePort`. Clients can access APISIX through the Node IPs and the assigned port. To use a service of type `LoadBalancer` with KubeSphere use a bare-metal load balancer implementation like [openelb](https://github.com/openelb/openelb). + +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. + +## Next steps ### Enable SSL -The ssl config is disabled by default, add `--set gateway.tls.enabled=true` to enable tls support. +SSL is disabled by default. You can enable it by adding the flag `--set gateway.tls.enabled=true`. + +### Change default keys + +It is recommended to change the default keys for security: + +```shell +--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF +``` + +:::note -### Change default apikey +The `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same. It is better if these are not same as `admin.credentials.viewer`. -It's Recommended to change the default key by add `--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF`, notice that `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same, and should better not same as `admin.credentials.viewer`. +::: diff --git a/docs/en/latest/deployments/minikube.md b/docs/en/latest/deployments/minikube.md index 42de539f96..4ff92bc792 100644 --- a/docs/en/latest/deployments/minikube.md +++ b/docs/en/latest/deployments/minikube.md @@ -1,5 +1,11 @@ --- -title: Install Ingress APISIX on Minikube +title: minikube +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - minikube +description: Guide to install APISIX ingress controller on minikube. --- -This document explains how to install Ingress APISIX on [Minikube](https://minikube.sigs.k8s.io/). +This guide explains how you can install APISIX ingress on [minikube](https://minikube.sigs.k8s.io/). ## Prerequisites * Install [Minikube](https://minikube.sigs.k8s.io/docs/start/). * Install [Helm](https://helm.sh/). -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -45,11 +51,11 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Five Service resources were created. +This will create the five resources mentioned below: -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. -Now try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running of Ingress APISIX. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. diff --git a/docs/en/latest/deployments/tke.md b/docs/en/latest/deployments/tke.md index 3acdbca5e7..1f84db1f1a 100644 --- a/docs/en/latest/deployments/tke.md +++ b/docs/en/latest/deployments/tke.md @@ -1,7 +1,13 @@ --- -title: Install Ingress APISIX on Tencent TKE +title: TKE (Tencent) +keywords: + - APISIX ingress + - Apache APISIX + - Kubernetes ingress + - Tencent Cloud Container Service + - Tencent Kubernetes Engine +description: Guide to install APISIX ingress controller on Tencent Kubernetes Engine (TKE). --- - -This document explains how to install Ingress APISIX on [Tencent TKE](https://cloud.tencent.com/product/tke). +This document explains how you can install APISIX ingress on [Tencent TKE](https://cloud.tencent.com/product/tke). ## Prerequisites -* Create a TKE Service on Tencent Cloud and make sure the API Server is accessible from your workspace. +* Create a TKE cluster on Tencent Cloud and make sure that the API server is accessible from your device. * Install [Helm](https://helm.sh/). -* Download the kube config for your TKE Console. +* Update your kube config file with the credentials for your TKE cluster. -## Install APISIX and apisix-ingress-controller +## Install APISIX and ingress controller -As the data plane of apisix-ingress-controller, [Apache APISIX](http://apisix.apache.org/) can be deployed at the same time using Helm chart. +The script below installs APISIX and the ingress controller: ```shell helm repo add apisix https://charts.apiseven.com @@ -47,35 +53,65 @@ helm install apisix apisix/apisix \ kubectl get service --namespace ingress-apisix ``` -Please be careful you must configure the `etcd.persistence.size` to multiples of 10Gi (it's a limitation on TKE), otherwise the [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) creation will fail. +:::info IMPORTANT + +Make sure to configure the attribute `etcd.persistence.size` in multiples of `10Gi` (limitation of TKE). Otherwise, the [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) creation will fail. + +::: + +:::note + +By default, APISIX ingress controller will watch the apiVersion of `networking.k8s.io/v1`. + +If the target Kubernetes version is under `v1.19`, add the flag `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1`. -Five Service resources were created. +Else, if your Kubernetes cluster version is under `v1.16`, set the flag `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1`. -* `apisix-gateway`, which processes the real traffic; -* `apisix-admin`, which acts as the control plane to process all the configuration changes. -* `apisix-ingress-controller`, which exposes apisix-ingress-controller's metrics. -* `apisix-etcd` and `apisix-etcd-headless` for etcd service and internal communication. +::: -Two Service resources were created, one is `apisix-gateway`, which processes the real traffic; another is `apisix-admin`, which acts as the control plane to process all the configuration changes. +This will create the five resources mentioned below: -The gateway service type is set to `LoadBalancer` (see [TKE Service Management](https://cloud.tencent.com/document/product/457/45487?from=10680) for more details), so that clients can access Apache APISIX through a load balancer. You can find the load balancer ip by running: +* `apisix-gateway`: dataplane the process the traffic. +* `apisix-admin`: control plane that processes all configuration changes. +* `apisix-ingress-controller`: ingress controller which exposes APISIX. +* `apisix-etcd` and `apisix-etcd-headless`: stores configuration and handles internal communication. + +The gateway service type will be set to `LoadBalancer`. See [TKE service management](https://cloud.tencent.com/document/product/457/45487?from=10680) for more details on setting this up. + +You can find the load balancer IP address by running: ```shell kubectl get service apisix-gateway --namespace ingress-apisix -o jsonpath='{.status.loadBalancer.ingress[].ip}' ``` -Now open your [TKE console](https://console.cloud.tencent.com/tke2/overview), choosing your cluster and clicking the Workloads tag, you'll see all pods of Apache APISIX, etcd and apisix-ingress-controller are ready. - -Try to create some [resources](https://github.com/apache/apisix-ingress-controller/tree/master/docs/en/latest/concepts) to verify the running status. As a minimalist example, see [proxy-the-httpbin-service](../tutorials/proxy-the-httpbin-service.md) to learn how to apply resources to drive the apisix-ingress-controller. +Now, if you open your [TKE console](https://console.cloud.tencent.com/tke2/overview), choose your cluster and click the workloads tag, you will see all the APISIX. ingress controller, and etcd pods. -### Specify The Ingress Version +You should now be able to use APISIX ingress controller. You can try running this [minimal example](../tutorials/proxy-the-httpbin-service.md) to see if everything is working perfectly. -apisix-ingress-controller will watch apiVersion of `networking.k8s.io/v1` by default. If the target kubernetes version is under `v1.19`, add `--set ingress-controller.config.kubernetes.ingressVersion=networking/v1beta1` or `--set ingress-controller.config.kubernetes.ingressVersion=extensions/v1beta1` if your kubernetes cluster is under `v1.16` +## Next steps ### Enable SSL -The ssl config is disabled by default, add `--set gateway.tls.enabled=true` to enable tls support. +SSL is disabled by default. You can enable it by adding the flag `--set gateway.tls.enabled=true`. + +### Change default keys + +It is recommended to change the default keys for security: + +```shell +--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF +``` + +```shell +--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF +``` + +:::note -### Change default apikey +The `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same. It is better if these are not same as `admin.credentials.viewer`. -It's Recommended to change the default key by add `--set ingress-controller.config.apisix.adminKey=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.admin=ADMIN_KEY_GENERATED_BY_YOURSELF`, `--set admin.credentials.viewer=VIEWER_KEY_GENERATED_BY_YOURSELF`, notice that `ingress-controller.config.apisix.adminKey` and `admin.credentials.admin` must be the same, and should better not same as `admin.credentials.viewer`. +::: From c4b04b3a177e64705124bdc0b1462ac3d3f31e3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Aug 2022 16:16:28 +0800 Subject: [PATCH 12/30] chore(deps): bump github.com/eclipse/paho.mqtt.golang in /test/e2e (#1255) Bumps [github.com/eclipse/paho.mqtt.golang](https://github.com/eclipse/paho.mqtt.golang) from 1.3.5 to 1.4.1. - [Release notes](https://github.com/eclipse/paho.mqtt.golang/releases) - [Commits](https://github.com/eclipse/paho.mqtt.golang/compare/v1.3.5...v1.4.1) --- updated-dependencies: - dependency-name: github.com/eclipse/paho.mqtt.golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/go.mod | 3 ++- test/e2e/go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index bf5c023ee2..0e535df8a5 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/apache/apisix-ingress-controller v0.0.0-20210105024109-72e53386de5a github.com/apache/apisix-ingress-controller/test/e2e/testbackend v0.0.0 - github.com/eclipse/paho.mqtt.golang v1.3.5 + github.com/eclipse/paho.mqtt.golang v1.4.1 github.com/gavv/httpexpect/v2 v2.3.1 github.com/gorilla/websocket v1.5.0 github.com/gruntwork-io/terratest v0.40.20 @@ -97,6 +97,7 @@ require ( golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/net v0.0.0-20220725212005-46097bf591d3 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 1b0d97cbb2..434467857c 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -101,8 +101,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y= -github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= +github.com/eclipse/paho.mqtt.golang v1.4.1 h1:tUSpviiL5G3P9SZZJPC4ZULZJsxQKXxfENpMvdbAXAI= +github.com/eclipse/paho.mqtt.golang v1.4.1/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -629,6 +629,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 1087941d827dbf859b534328368ff8c65635db2a Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Mon, 29 Aug 2022 16:34:30 +0800 Subject: [PATCH 13/30] fix: namespace_selector invalid when restarting (#1238) --- pkg/api/validation/utils.go | 11 - pkg/api/validation/utils_test.go | 9 - .../k8s/namespace/namespace_provider.go | 84 +++--- test/e2e/scaffold/ingress.go | 15 +- test/e2e/scaffold/k8s.go | 16 +- test/e2e/scaffold/scaffold.go | 66 +++-- .../suite-ingress-features/namespace.go | 245 ++++++++++++++++-- 7 files changed, 337 insertions(+), 109 deletions(-) diff --git a/pkg/api/validation/utils.go b/pkg/api/validation/utils.go index 84180be955..5d2145cf9a 100644 --- a/pkg/api/validation/utils.go +++ b/pkg/api/validation/utils.go @@ -99,14 +99,3 @@ func validateSchema(schemaLoader *gojsonschema.JSONLoader, obj interface{}) (boo return false, resultErr } - -func HasValueInSyncMap(m *sync.Map) bool { - hasValue := false - if m != nil { - m.Range(func(k, v interface{}) bool { - hasValue = true - return false - }) - } - return hasValue -} diff --git a/pkg/api/validation/utils_test.go b/pkg/api/validation/utils_test.go index 6e2c2d6716..2faffe574d 100644 --- a/pkg/api/validation/utils_test.go +++ b/pkg/api/validation/utils_test.go @@ -16,10 +16,8 @@ package validation import ( - "sync" "testing" - "github.com/stretchr/testify/assert" "github.com/xeipuuv/gojsonschema" v2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta3" @@ -48,10 +46,3 @@ func Test_validateSchema(t *testing.T) { }) } } - -func TestHasValueInSyncMap(t *testing.T) { - m := new(sync.Map) - assert.False(t, HasValueInSyncMap(m), "sync.Map should be empty") - m.Store("hello", "test") - assert.True(t, HasValueInSyncMap(m), "sync.Map should not be empty") -} diff --git a/pkg/providers/k8s/namespace/namespace_provider.go b/pkg/providers/k8s/namespace/namespace_provider.go index b4a69e9292..b791574384 100644 --- a/pkg/providers/k8s/namespace/namespace_provider.go +++ b/pkg/providers/k8s/namespace/namespace_provider.go @@ -19,17 +19,16 @@ package namespace import ( "context" + "fmt" "strings" "sync" "go.uber.org/zap" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" listerscorev1 "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" - "github.com/apache/apisix-ingress-controller/pkg/api/validation" "github.com/apache/apisix-ingress-controller/pkg/config" "github.com/apache/apisix-ingress-controller/pkg/kube" "github.com/apache/apisix-ingress-controller/pkg/log" @@ -48,44 +47,28 @@ type WatchingNamespaceProvider interface { } func NewWatchingNamespaceProvider(ctx context.Context, kube *kube.KubeClient, cfg *config.Config) (WatchingNamespaceProvider, error) { - var ( - watchingNamespaces = new(sync.Map) - watchingLabels = make(map[string]string) - ) - if len(cfg.Kubernetes.AppNamespaces) > 1 || cfg.Kubernetes.AppNamespaces[0] != v1.NamespaceAll { - for _, ns := range cfg.Kubernetes.AppNamespaces { - watchingNamespaces.Store(ns, struct{}{}) - } + c := &watchingProvider{ + kube: kube, + cfg: cfg, + + watchingNamespaces: new(sync.Map), + watchingLabels: make(map[string]string), + + enableLabelsWatching: false, + } + + if len(cfg.Kubernetes.NamespaceSelector) == 0 { + return c, nil } + // support namespace label-selector + c.enableLabelsWatching = true for _, selector := range cfg.Kubernetes.NamespaceSelector { labelSlice := strings.Split(selector, "=") - watchingLabels[labelSlice[0]] = labelSlice[1] - } - - // watchingNamespaces and watchingLabels are empty means to monitor all namespaces. - if !validation.HasValueInSyncMap(watchingNamespaces) && len(watchingLabels) == 0 { - opts := metav1.ListOptions{} - // list all namespaces - nsList, err := kube.Client.CoreV1().Namespaces().List(ctx, opts) - if err != nil { - log.Error(err.Error()) - ctx.Done() - } else { - wns := new(sync.Map) - for _, v := range nsList.Items { - wns.Store(v.Name, struct{}{}) - } - watchingNamespaces = wns + if len(labelSlice) != 2 { + return nil, fmt.Errorf("Bad namespace-selector format: %s, expected namespace-selector format: xxx=xxx", selector) } - } - - c := &watchingProvider{ - kube: kube, - cfg: cfg, - - watchingNamespaces: watchingNamespaces, - watchingLabels: watchingLabels, + c.watchingLabels[labelSlice[0]] = labelSlice[1] } kubeFactory := kube.NewSharedIndexInformerFactory() @@ -108,6 +91,8 @@ type watchingProvider struct { namespaceLister listerscorev1.NamespaceLister controller *namespaceController + + enableLabelsWatching bool } func (c *watchingProvider) Init(ctx context.Context) error { @@ -138,12 +123,14 @@ func (c *watchingProvider) initWatchingNamespacesByLabels(ctx context.Context) e } func (c *watchingProvider) Run(ctx context.Context) { - e := utils.ParallelExecutor{} + if !c.enableLabelsWatching { + return + } + e := utils.ParallelExecutor{} e.Add(func() { c.namespaceInformer.Run(ctx.Done()) }) - e.Add(func() { c.controller.run(ctx) }) @@ -153,17 +140,30 @@ func (c *watchingProvider) Run(ctx context.Context) { func (c *watchingProvider) WatchingNamespaces() []string { var keys []string - c.watchingNamespaces.Range(func(key, _ interface{}) bool { - keys = append(keys, key.(string)) - return true - }) + if c.enableLabelsWatching { + c.watchingNamespaces.Range(func(key, _ interface{}) bool { + keys = append(keys, key.(string)) + return true + }) + } else { + namespaces, err := c.kube.Client.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{}) + if err != nil { + log.Warnw("Namespace list get failed", + zap.Error(err), + ) + return nil + } + for _, ns := range namespaces.Items { + keys = append(keys, ns.Name) + } + } return keys } // IsWatchingNamespace accepts a resource key, getting the namespace part // and checking whether the namespace is being watched. func (c *watchingProvider) IsWatchingNamespace(key string) (ok bool) { - if !validation.HasValueInSyncMap(c.watchingNamespaces) { + if !c.enableLabelsWatching { ok = true return } diff --git a/test/e2e/scaffold/ingress.go b/test/e2e/scaffold/ingress.go index 5117e33190..42ea50f1b8 100644 --- a/test/e2e/scaffold/ingress.go +++ b/test/e2e/scaffold/ingress.go @@ -428,13 +428,17 @@ func (s *Scaffold) newIngressAPISIXController() error { }) var ingressAPISIXDeployment string - label := fmt.Sprintf("apisix.ingress.watch=%s", s.namespace) + label := `""` + if labels := s.NamespaceSelectorLabelStrings(); labels != nil && !s.opts.DisableNamespaceSelector { + label = labels[0] + } + if s.opts.EnableWebhooks { ingressAPISIXDeployment = fmt.Sprintf(s.FormatRegistry(_ingressAPISIXDeploymentTemplate), s.opts.IngressAPISIXReplicas, s.namespace, s.opts.ApisixResourceSyncInterval, - s.FormatNamespaceLabel(label), s.opts.ApisixResourceVersion, s.opts.APISIXPublishAddress, _volumeMounts, _webhookCertSecret) + label, s.opts.ApisixResourceVersion, s.opts.APISIXPublishAddress, _volumeMounts, _webhookCertSecret) } else { ingressAPISIXDeployment = fmt.Sprintf(s.FormatRegistry(_ingressAPISIXDeploymentTemplate), s.opts.IngressAPISIXReplicas, s.namespace, s.opts.ApisixResourceSyncInterval, - s.FormatNamespaceLabel(label), s.opts.ApisixResourceVersion, s.opts.APISIXPublishAddress, "", _webhookCertSecret) + label, s.opts.ApisixResourceVersion, s.opts.APISIXPublishAddress, "", _webhookCertSecret) } err = k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, ingressAPISIXDeployment) @@ -538,7 +542,10 @@ func (s *Scaffold) GetIngressPodDetails() ([]corev1.Pod, error) { // ScaleIngressController scales the number of Ingress Controller pods to desired. func (s *Scaffold) ScaleIngressController(desired int) error { var ingressDeployment string - label := fmt.Sprintf("apisix.ingress.watch=%s", s.namespace) + var label string + if labels := s.NamespaceSelectorLabelStrings(); labels != nil { + label = labels[0] + } if s.opts.EnableWebhooks { ingressDeployment = fmt.Sprintf(s.FormatRegistry(_ingressAPISIXDeploymentTemplate), desired, s.namespace, s.opts.ApisixResourceSyncInterval, label, s.opts.ApisixResourceVersion, s.opts.APISIXPublishAddress, _volumeMounts, _webhookCertSecret) } else { diff --git a/test/e2e/scaffold/k8s.go b/test/e2e/scaffold/k8s.go index be3689b86e..23f16b76f2 100644 --- a/test/e2e/scaffold/k8s.go +++ b/test/e2e/scaffold/k8s.go @@ -161,16 +161,20 @@ func (s *Scaffold) CreateResourceFromStringWithNamespace(yaml, namespace string) s.kubectlOptions.Namespace = originalNamespace }() s.addFinalizers(func() { - originalNamespace := s.kubectlOptions.Namespace - s.kubectlOptions.Namespace = namespace - defer func() { - s.kubectlOptions.Namespace = originalNamespace - }() - assert.Nil(s.t, k8s.KubectlDeleteFromStringE(s.t, s.kubectlOptions, yaml)) + _ = s.DeleteResourceFromStringWithNamespace(yaml, namespace) }) return k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, yaml) } +func (s *Scaffold) DeleteResourceFromStringWithNamespace(yaml, namespace string) error { + originalNamespace := s.kubectlOptions.Namespace + s.kubectlOptions.Namespace = namespace + defer func() { + s.kubectlOptions.Namespace = originalNamespace + }() + return k8s.KubectlDeleteFromStringE(s.t, s.kubectlOptions, yaml) +} + func (s *Scaffold) ensureNumApisixCRDsCreated(url string, desired int) error { condFunc := func() (bool, error) { req, err := http.NewRequest("GET", url, nil) diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go index b11a33d850..11328d6c90 100644 --- a/test/e2e/scaffold/scaffold.go +++ b/test/e2e/scaffold/scaffold.go @@ -54,9 +54,12 @@ type Options struct { APISIXAdminAPIKey string EnableWebhooks bool APISIXPublishAddress string - disableNamespaceSelector bool ApisixResourceSyncInterval string ApisixResourceVersion string + + NamespaceSelectorLabel map[string]string + DisableNamespaceSelector bool + DisableNamespaceLabel bool } type Scaffold struct { @@ -97,10 +100,10 @@ var ( } createVersionedApisixResourceMap = map[string]struct{}{ - "ApisixRoute": struct{}{}, - "ApisixConsumer": struct{}{}, - "ApisixPluginConfig": struct{}{}, - "ApisixUpstream": struct{}{}, + "ApisixRoute": {}, + "ApisixConsumer": {}, + "ApisixPluginConfig": {}, + "ApisixUpstream": {}, } ) @@ -376,6 +379,19 @@ func (s *Scaffold) RestartAPISIXDeploy() { assert.NoError(s.t, err, "renew apisix tunnels") } +func (s *Scaffold) RestartIngressControllerDeploy() { + pods, err := k8s.ListPodsE(s.t, s.kubectlOptions, metav1.ListOptions{ + LabelSelector: "app=ingress-apisix-controller-deployment-e2e-test", + }) + assert.NoError(s.t, err, "list ingress-controller pod") + for _, pod := range pods { + err = s.KillPod(pod.Name) + assert.NoError(s.t, err, "killing ingress-controller pod") + } + err = s.WaitAllIngressControllerPodsAvailable() + assert.NoError(s.t, err, "waiting for new ingress-controller instance ready") +} + func (s *Scaffold) beforeEach() { var err error s.namespace = fmt.Sprintf("ingress-apisix-e2e-tests-%s-%d", s.opts.Name, time.Now().Nanosecond()) @@ -383,11 +399,19 @@ func (s *Scaffold) beforeEach() { ConfigPath: s.opts.Kubeconfig, Namespace: s.namespace, } - s.finializers = nil - labels := make(map[string]string) - labels["apisix.ingress.watch"] = s.namespace - k8s.CreateNamespaceWithMetadata(s.t, s.kubectlOptions, metav1.ObjectMeta{Name: s.namespace, Labels: labels}) + + label := map[string]string{} + if !s.opts.DisableNamespaceLabel { + if s.opts.NamespaceSelectorLabel == nil { + label["apisix.ingress.watch"] = s.namespace + s.opts.NamespaceSelectorLabel = label + } else { + label = s.opts.NamespaceSelectorLabel + } + } + + k8s.CreateNamespaceWithMetadata(s.t, s.kubectlOptions, metav1.ObjectMeta{Name: s.namespace, Labels: label}) s.nodes, err = k8s.GetReadyNodesE(s.t, s.kubectlOptions) assert.Nil(s.t, err, "querying ready nodes") @@ -549,14 +573,6 @@ func (s *Scaffold) FormatRegistry(workloadTemplate string) string { } } -// FormatNamespaceLabel set label to be empty if s.opts.disableNamespaceSelector is true. -func (s *Scaffold) FormatNamespaceLabel(label string) string { - if s.opts.disableNamespaceSelector { - return "\"\"" - } - return label -} - var ( versionRegex = regexp.MustCompile(`apiVersion: apisix.apache.org/v.*?\n`) kindRegex = regexp.MustCompile(`kind: (.*?)\n`) @@ -574,10 +590,6 @@ func (s *Scaffold) getKindValue(yml string) string { return subStr[1] } -func (s *Scaffold) DisableNamespaceSelector() { - s.opts.disableNamespaceSelector = true -} - func waitExponentialBackoff(condFunc func() (bool, error)) error { backoff := wait.Backoff{ Duration: 500 * time.Millisecond, @@ -622,3 +634,15 @@ func (s *Scaffold) CreateVersionedApisixResourceWithNamespace(yml, namespace str func ApisixResourceVersion() *apisixResourceVersionInfo { return apisixResourceVersion } + +func (s *Scaffold) NamespaceSelectorLabelStrings() []string { + var labels []string + for k, v := range s.opts.NamespaceSelectorLabel { + labels = append(labels, fmt.Sprintf("%s=%s", k, v)) + } + return labels +} + +func (s *Scaffold) NamespaceSelectorLabel() map[string]string { + return s.opts.NamespaceSelectorLabel +} diff --git a/test/e2e/suite-ingress/suite-ingress-features/namespace.go b/test/e2e/suite-ingress/suite-ingress-features/namespace.go index d8e5fd74af..a41b6fb4e3 100644 --- a/test/e2e/suite-ingress/suite-ingress-features/namespace.go +++ b/test/e2e/suite-ingress/suite-ingress-features/namespace.go @@ -16,6 +16,7 @@ package ingress import ( + "context" "encoding/json" "fmt" "net/http" @@ -24,6 +25,8 @@ import ( "github.com/gruntwork-io/terratest/modules/k8s" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/apache/apisix-ingress-controller/test/e2e/scaffold" ) @@ -37,12 +40,37 @@ type headers struct { } var _ = ginkgo.Describe("suite-ingress-features: namespacing filtering enable", func() { - s := scaffold.NewDefaultScaffold() + s := scaffold.NewScaffold(&scaffold.Options{ + Name: "enable-namespace-selector", + IngressAPISIXReplicas: 1, + ApisixResourceVersion: scaffold.ApisixResourceVersion().Default, + NamespaceSelectorLabel: map[string]string{ + fmt.Sprintf("namespace-selector-%d", time.Now().Nanosecond()): "watch", + }, + DisableNamespaceLabel: true, + }) ginkgo.Context("with namespace_selector", func() { + namespace1 := fmt.Sprintf("namespace-selector-1-%d", time.Now().Nanosecond()) + namespace2 := fmt.Sprintf("namespace-selector-2-%d", time.Now().Nanosecond()) + + createNamespaceLabel := func(namespace string) { + k8s.CreateNamespaceWithMetadata(ginkgo.GinkgoT(), &k8s.KubectlOptions{ConfigPath: scaffold.GetKubeconfig()}, metav1.ObjectMeta{Name: namespace, Labels: s.NamespaceSelectorLabel()}) + _, err := s.NewHTTPBINWithNamespace(namespace) + time.Sleep(6 * time.Second) + assert.Nil(ginkgo.GinkgoT(), err, "create second httpbin service") + } + + deleteNamespace := func(namespace string) { + _ = k8s.DeleteNamespaceE(ginkgo.GinkgoT(), &k8s.KubectlOptions{ConfigPath: scaffold.GetKubeconfig()}, namespace) + } + ginkgo.It("resources in other namespaces should be ignored", func() { + createNamespaceLabel(namespace1) + defer deleteNamespace(namespace1) + backendSvc, backendSvcPort := s.DefaultHTTPBackend() - route := fmt.Sprintf(` + route1 := fmt.Sprintf(` apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -61,17 +89,16 @@ spec: port: number: %d `, backendSvc, backendSvcPort[0]) - - assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route), "creating ingress") - time.Sleep(6 * time.Second) - + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route1, namespace1), "creating ingress") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1)) + time.Sleep(time.Second * 6) body := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusOK).Body().Raw() var placeholder ip err := json.Unmarshal([]byte(body), &placeholder) assert.Nil(ginkgo.GinkgoT(), err, "unmarshalling IP") // Now create another ingress in default namespace. - route = fmt.Sprintf(` + route2 := fmt.Sprintf(` apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -79,7 +106,33 @@ metadata: spec: ingressClassName: apisix rules: - - host: httpbin.com + - host: httpbin.org + http: + paths: + - path: /headers + pathType: Exact + backend: + service: + name: %s + port: + number: %d +`, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route2, "default"), "creating ingress") + time.Sleep(6 * time.Second) + routes, err := s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 1) + _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusNotFound) + + route3 := fmt.Sprintf(` +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: httpbin-route +spec: + ingressClassName: apisix + rules: + - host: local.httpbin.org http: paths: - path: /headers @@ -90,18 +143,48 @@ spec: port: number: %d `, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route3), "creating ingress") + time.Sleep(6 * time.Second) + routes, err = s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 1) + _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "local.httpbin.org").Expect().Status(http.StatusNotFound) + + // remove route1 + assert.Nil(ginkgo.GinkgoT(), s.DeleteResourceFromStringWithNamespace(route1, namespace1), "delete ingress") + time.Sleep(6 * time.Second) + + deleteNamespace(namespace1) + time.Sleep(6 * time.Second) + routes, err = s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 0) + + // restart ingress-controller + s.RestartIngressControllerDeploy() + time.Sleep(6 * time.Second) + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 0) - assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route, "default"), "creating ingress") - _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusNotFound) + createNamespaceLabel(namespace2) + defer deleteNamespace(namespace2) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route1, namespace2), "creating ingress") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1)) + _ = s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusOK) + _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusNotFound) + _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "local.httpbin.org").Expect().Status(http.StatusNotFound) }) }) }) var _ = ginkgo.Describe("suite-ingress-features: namespacing filtering disable", func() { - s := scaffold.NewDefaultScaffold() + s := scaffold.NewScaffold(&scaffold.Options{ + Name: "disable-namespace-selector", + IngressAPISIXReplicas: 1, + ApisixResourceVersion: scaffold.ApisixResourceVersion().Default, + DisableNamespaceSelector: true, + }) ginkgo.Context("without namespace_selector", func() { - // make namespace_selector empty - s.DisableNamespaceSelector() namespace := "second-httpbin-service-namespace" // create another http-bin service in a new namespace. @@ -110,13 +193,12 @@ var _ = ginkgo.Describe("suite-ingress-features: namespacing filtering disable", ConfigPath: scaffold.GetKubeconfig(), }, namespace) _, err := s.NewHTTPBINWithNamespace(namespace) - assert.Nil(ginkgo.GinkgoT(), err, "create second httpbin service") + assert.Nil(ginkgo.GinkgoT(), err, "create new httpbin service") }) // clean this tmp namespace when test case is done. ginkgo.AfterEach(func() { - err := k8s.DeleteNamespaceE(ginkgo.GinkgoT(), &k8s.KubectlOptions{ - ConfigPath: scaffold.GetKubeconfig()}, namespace) + err := k8s.DeleteNamespaceE(ginkgo.GinkgoT(), &k8s.KubectlOptions{ConfigPath: scaffold.GetKubeconfig()}, namespace) assert.Nilf(ginkgo.GinkgoT(), err, "deleting namespace %s", namespace) }) @@ -189,3 +271,134 @@ spec: }) }) }) + +var _ = ginkgo.Describe("suite-ingress-features: namespacing un-label", func() { + labelName, labelValue := fmt.Sprintf("namespace-selector-%d", time.Now().Nanosecond()), "watch" + s := scaffold.NewScaffold(&scaffold.Options{ + Name: "un-label", + IngressAPISIXReplicas: 1, + ApisixResourceVersion: scaffold.ApisixResourceVersion().Default, + NamespaceSelectorLabel: map[string]string{ + labelName: labelValue, + }, + DisableNamespaceLabel: true, + }) + namespace1 := fmt.Sprintf("un-label-%d", time.Now().Nanosecond()) + + ginkgo.It("un-label", func() { + client := s.GetKubernetesClient() + + ns := fmt.Sprintf(` +apiVersion: v1 +kind: Namespace +metadata: + name: %s + labels: + %s: %s +`, namespace1, labelName, labelValue) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(ns, namespace1), "creating namespace") + //defer s.DeleteResourceFromStringWithNamespace(ns, namespace1) + _, err := s.NewHTTPBINWithNamespace(namespace1) + assert.Nil(ginkgo.GinkgoT(), err, "create httpbin service in", namespace1) + + backendSvc, backendSvcPort := s.DefaultHTTPBackend() + route1 := fmt.Sprintf(` +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: httpbin-route +spec: + ingressClassName: apisix + rules: + - host: httpbin.com + http: + paths: + - path: /ip + pathType: Exact + backend: + service: + name: %s + port: + number: %d +`, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route1, namespace1), "creating ingress") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1)) + time.Sleep(time.Second * 6) + _ = s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusOK).Body().Raw() + + assert.Nil(ginkgo.GinkgoT(), s.DeleteResourceFromStringWithNamespace(route1, namespace1), "deleting ingress") + // un-label + _, err = client.CoreV1().Namespaces().Update( + context.Background(), + &v1.Namespace{ObjectMeta: metav1.ObjectMeta{ + Name: namespace1, + Labels: map[string]string{}, + }}, + metav1.UpdateOptions{}, + ) + assert.Nil(ginkgo.GinkgoT(), err, "unlabel the namespace") + time.Sleep(6 * time.Second) + routes, err := s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 0) + + route2 := fmt.Sprintf(` +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: httpbin-route +spec: + ingressClassName: apisix + rules: + - host: httpbin.org + http: + paths: + - path: /headers + pathType: Exact + backend: + service: + name: %s + port: + number: %d +`, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route2), "creating ingress") + time.Sleep(6 * time.Second) + routes, err = s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 0) + _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusNotFound) + + route3 := fmt.Sprintf(` +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: httpbin-route +spec: + ingressClassName: apisix + rules: + - host: local.httpbin.org + http: + paths: + - path: /headers + pathType: Exact + backend: + service: + name: %s + port: + number: %d +`, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route3, "default"), "creating ingress") + time.Sleep(6 * time.Second) + routes, err = s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 0) + _ = s.NewAPISIXClient().GET("/headers").WithHeader("Host", "local.httpbin.org").Expect().Status(http.StatusNotFound) + + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(route1, namespace1), "creating ingress") + time.Sleep(time.Second * 6) + routes, err = s.ListApisixRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), routes, 0) + _ = s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusNotFound) + }) +}) From f1bd4c026f1652318afc7b2aabe9590c2882247b Mon Sep 17 00:00:00 2001 From: xiangtianyu Date: Mon, 29 Aug 2022 22:29:37 +0800 Subject: [PATCH 14/30] fix config missing default_cluster_name yaml (#1277) --- pkg/config/config.go | 2 +- pkg/config/config_test.go | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index a3997e0fcb..43b54b08c6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -110,7 +110,7 @@ type KubernetesConfig struct { // APISIXConfig contains all APISIX related config items. type APISIXConfig struct { // DefaultClusterName is the name of default cluster. - DefaultClusterName string `json:"default_cluster_name"` + DefaultClusterName string `json:"default_cluster_name" yaml:"default_cluster_name"` // DefaultClusterBaseURL is the base url configuration for the default cluster. DefaultClusterBaseURL string `json:"default_cluster_base_url" yaml:"default_cluster_base_url"` // DefaultClusterAdminKey is the admin key for the default cluster. diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 5586114992..2114b6821f 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -52,7 +52,7 @@ func TestNewConfigFromFile(t *testing.T) { APIVersion: DefaultAPIVersion, }, APISIX: APISIXConfig{ - DefaultClusterName: "default", + DefaultClusterName: "apisix", DefaultClusterBaseURL: "http://127.0.0.1:8080/apisix", DefaultClusterAdminKey: "123456", }, @@ -98,6 +98,7 @@ kubernetes: apisix: default_cluster_base_url: http://127.0.0.1:8080/apisix default_cluster_admin_key: "123456" + default_cluster_name: "apisix" ` tmpYAML, err := ioutil.TempFile("/tmp", "config-*.yaml") assert.Nil(t, err, "failed to create temporary yaml configuration file: ", err) @@ -140,7 +141,7 @@ func TestConfigWithEnvVar(t *testing.T) { APIVersion: DefaultAPIVersion, }, APISIX: APISIXConfig{ - DefaultClusterName: "default", + DefaultClusterName: "apisix", DefaultClusterBaseURL: "http://127.0.0.1:8080/apisix", DefaultClusterAdminKey: "123456", }, @@ -148,12 +149,14 @@ func TestConfigWithEnvVar(t *testing.T) { defaultClusterBaseURLEnvName := "DEFAULT_CLUSTER_BASE_URL" defaultClusterAdminKeyEnvName := "DEFAULT_CLUSTER_ADMIN_KEY" + defaultClusterNameEnvName := "DEFAULT_CLUSTER_NAME" kubeconfigEnvName := "KUBECONFIG" err := os.Setenv(defaultClusterBaseURLEnvName, "http://127.0.0.1:8080/apisix") assert.Nil(t, err, "failed to set env variable: ", err) _ = os.Setenv(defaultClusterAdminKeyEnvName, "123456") _ = os.Setenv(kubeconfigEnvName, "") + _ = os.Setenv(defaultClusterNameEnvName, "apisix") jsonData := ` { @@ -174,7 +177,8 @@ func TestConfigWithEnvVar(t *testing.T) { }, "apisix": { "default_cluster_base_url": "{{.DEFAULT_CLUSTER_BASE_URL}}", - "default_cluster_admin_key": "{{.DEFAULT_CLUSTER_ADMIN_KEY}}" + "default_cluster_admin_key": "{{.DEFAULT_CLUSTER_ADMIN_KEY}}", + "default_cluster_name": "{{.DEFAULT_CLUSTER_NAME}}" } } ` @@ -210,6 +214,7 @@ kubernetes: apisix: default_cluster_base_url: {{.DEFAULT_CLUSTER_BASE_URL}} default_cluster_admin_key: "{{.DEFAULT_CLUSTER_ADMIN_KEY}}" + default_cluster_name: "{{.DEFAULT_CLUSTER_NAME}}" ` tmpYAML, err := ioutil.TempFile("/tmp", "config-*.yaml") assert.Nil(t, err, "failed to create temporary yaml configuration file: ", err) From 31b3ef84be4e96dc663de883ef5730a03bfb962b Mon Sep 17 00:00:00 2001 From: redtacs <112310508+redtacs@users.noreply.github.com> Date: Tue, 30 Aug 2022 11:15:09 +0800 Subject: [PATCH 15/30] docs: add ApisixUpstream healthCheck explanation to resolveGranularity (#1279) --- docs/en/latest/references/apisix_route_v2.md | 2 +- .../latest/references/apisix_route_v2beta3.md | 106 +++++++++--------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/docs/en/latest/references/apisix_route_v2.md b/docs/en/latest/references/apisix_route_v2.md index 6deb9c2338..89cae10be5 100644 --- a/docs/en/latest/references/apisix_route_v2.md +++ b/docs/en/latest/references/apisix_route_v2.md @@ -99,5 +99,5 @@ The service resolve granularity determines whether the [Serivce ClusterIP](https | Granularity | Meaning | |-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| endpoint | Filled upstream nodes by Pods' IP. | +| endpoint | Filled upstream nodes by Pods' IP. ApisixUpstream healthCheck is only effective on this case. | | service | Filled upstream nodes by Service ClusterIP, in such a case, loadbalacing are implemented by [kube-proxy](https://kubernetes.io/docs/concepts/overview/components/#kube-proxy). | diff --git a/docs/en/latest/references/apisix_route_v2beta3.md b/docs/en/latest/references/apisix_route_v2beta3.md index 242a69ea73..9859f65caa 100644 --- a/docs/en/latest/references/apisix_route_v2beta3.md +++ b/docs/en/latest/references/apisix_route_v2beta3.md @@ -25,65 +25,65 @@ title: ApisixRoute/v2beta3 Reference Meaning of each field in the spec of ApisixRoute are followed, the top level fields (`apiVersion`, `kind` and `metadata`) are same as other Kubernetes Resources. -| Field | Type | Description | -|---------------|----------|----------------------------------------------------| -| http | array | ApisixRoute's HTTP route rules. | -| http[].name | string (required) | The route rule name. | -| http[].priority | integer | The route priority, it's used to determine which route will be hitted when multile routes contains the same URI. Large number means higher priority. | -| http[].match | object | Route match conditions. | -| http[].match.paths | array | A series of URI that should be matched (oneof) to use this route rule. | -| http[].match.hosts | array | A series of hosts that should be matched (oneof) to use this route rule. -| http[].match.methods | array | A series of HTTP methods(`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `CONNECT`, `TRACE`) that should be matched (oneof) to use this route rule. -| http[].match.remoteAddrs | array | A series of IP address (CIDR format) that should be matched (oneof) to use this route rule. -| http[].match.exprs | array | A series expressions that the results should be matched (oneof) to use this route rule. -| http[].match.exprs[].subject | object | Expression subject. -| http[].match.exprs[].subject.scope | string | Specify where to find the subject, values can be `Header`, `Query`, `Cookie` and `Path`. -| http[].match.exprs[].subject.name | string | Specify subject name, when scope is `Path`, this field can be absent. -| http[].match.exprs[].op | string | Expression operator, see [Expression Operators](#expression-operators) for the detail of enumerations. -| http[].match.exprs[].value | string | Expected expression result, it's exclusive with `http[].match.exprs[].set`. -| http[].match.exprs[].set | array | Expected expression result set, only used when the operator is `In` or `NotIn`, it's exclusive with `http[].match.exprs[].value`. -| http[].backends | object | The backend services. When the number of backends more than one, weight based traffic split policy will be applied to shifting traffic between these backends. -| http[].backends[].serviceName | string | The backend service name, note the service and ApisixRoute should be created in the same namespace. Cross namespace referencing is not allowed. -| http[].backends[].servicePort | integer or string | The backend service port, can be the port number or the name defined in the service object. -| http[].backends[].resolveGranularity | string | See [Service Resolve Granularity](#service-resolve-granularity) for the details. -| http[].backends[].weight | int | The backend weight, which is critical when shifting traffic between multiple backends, default is `100`. Weight is ignored when there is only one backend. -| http[].backends[].subset | string | Subset specifies a subset for the target Service. The subset should be pre-definedin ApisixUpstream about this service. -| http[].plugins | array | A series of APISIX plugins that will be executed once this route rule is matched | -| http[].plugins[].name | string | The plugin name, see [docs](http://apisix.apache.org/docs/apisix/getting-started) for learning the available plugins. -| http[].plugins[].enable | boolean | Whether the plugin would be used | -| http[].plugins[].config | object | The configuration of the plugin that must have the same fields as in APISIX. | -| http[].websocket | boolean | Whether enable websocket proxy. | -| stream | array | ApisixRoutes' stream route rules, which contains TCP or UDP rules.| -| stream[].protocol | string (required) | The protocol of rule. Support `TCP` or `UDP`| -| stream[].name | string (required) | The Route rule name. | -| stream[].match | object (required) | The Route match conditions. | -| stream[].match.ingressPort | integer (required) | the Ingress proxy server listening port, note since APISIX doesn't support dynamic listening, this port should be defined in [apisix configuration](https://github.com/apache/apisix/blob/master/conf/config-default.yaml#L101).| -| stream[].backend | object | The backend service. Deprecated: use http[].backends instead. -| stream[].backend.serviceName | string | The backend service name, note the service and ApisixRoute should be created in the same namespace. Cross namespace referencing is not allowed. -| stream[].backend.servicePort | integer or string | The backend service port, can be the port number or the name defined in the service object. -| stream[].backend.resolveGranularity | string | See [Service Resolve Granularity](#service-resolve-granularity) for the details. -| stream[].backend.subset | string | Subset specifies a subset for the target Service. The subset should be pre-definedin ApisixUpstream about this service. +| Field | Type | Description | +|--------------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| http | array | ApisixRoute's HTTP route rules. | +| http[].name | string (required) | The route rule name. | +| http[].priority | integer | The route priority, it's used to determine which route will be hitted when multile routes contains the same URI. Large number means higher priority. | +| http[].match | object | Route match conditions. | +| http[].match.paths | array | A series of URI that should be matched (oneof) to use this route rule. | +| http[].match.hosts | array | A series of hosts that should be matched (oneof) to use this route rule. | +| http[].match.methods | array | A series of HTTP methods(`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `CONNECT`, `TRACE`) that should be matched (oneof) to use this route rule. | +| http[].match.remoteAddrs | array | A series of IP address (CIDR format) that should be matched (oneof) to use this route rule. | +| http[].match.exprs | array | A series expressions that the results should be matched (oneof) to use this route rule. | +| http[].match.exprs[].subject | object | Expression subject. | +| http[].match.exprs[].subject.scope | string | Specify where to find the subject, values can be `Header`, `Query`, `Cookie` and `Path`. | +| http[].match.exprs[].subject.name | string | Specify subject name, when scope is `Path`, this field can be absent. | +| http[].match.exprs[].op | string | Expression operator, see [Expression Operators](#expression-operators) for the detail of enumerations. | +| http[].match.exprs[].value | string | Expected expression result, it's exclusive with `http[].match.exprs[].set`. | +| http[].match.exprs[].set | array | Expected expression result set, only used when the operator is `In` or `NotIn`, it's exclusive with `http[].match.exprs[].value`. | +| http[].backends | object | The backend services. When the number of backends more than one, weight based traffic split policy will be applied to shifting traffic between these backends. | +| http[].backends[].serviceName | string | The backend service name, note the service and ApisixRoute should be created in the same namespace. Cross namespace referencing is not allowed. | +| http[].backends[].servicePort | integer or string | The backend service port, can be the port number or the name defined in the service object. | +| http[].backends[].resolveGranularity | string | See [Service Resolve Granularity](#service-resolve-granularity) for the details. | +| http[].backends[].weight | int | The backend weight, which is critical when shifting traffic between multiple backends, default is `100`. Weight is ignored when there is only one backend. | +| http[].backends[].subset | string | Subset specifies a subset for the target Service. The subset should be pre-definedin ApisixUpstream about this service. | +| http[].plugins | array | A series of APISIX plugins that will be executed once this route rule is matched | +| http[].plugins[].name | string | The plugin name, see [docs](http://apisix.apache.org/docs/apisix/getting-started) for learning the available plugins. | +| http[].plugins[].enable | boolean | Whether the plugin would be used | +| http[].plugins[].config | object | The configuration of the plugin that must have the same fields as in APISIX. | +| http[].websocket | boolean | Whether enable websocket proxy. | +| stream | array | ApisixRoutes' stream route rules, which contains TCP or UDP rules. | +| stream[].protocol | string (required) | The protocol of rule. Support `TCP` or `UDP` | +| stream[].name | string (required) | The Route rule name. | +| stream[].match | object (required) | The Route match conditions. | +| stream[].match.ingressPort | integer (required) | the Ingress proxy server listening port, note since APISIX doesn't support dynamic listening, this port should be defined in [apisix configuration](https://github.com/apache/apisix/blob/master/conf/config-default.yaml#L101). | +| stream[].backend | object | The backend service. Deprecated: use http[].backends instead. | +| stream[].backend.serviceName | string | The backend service name, note the service and ApisixRoute should be created in the same namespace. Cross namespace referencing is not allowed. | +| stream[].backend.servicePort | integer or string | The backend service port, can be the port number or the name defined in the service object. | +| stream[].backend.resolveGranularity | string | See [Service Resolve Granularity](#service-resolve-granularity) for the details. | +| stream[].backend.subset | string | Subset specifies a subset for the target Service. The subset should be pre-definedin ApisixUpstream about this service. | ## Expression Operators -| Operator | Meaning | -|----------|---------| -| Equal| The result of `subject` should be equal to the `value` | -| NotEqual | The result of `subject` should not be equal to `value` | -| GreaterThan | The result of `subject` should be a number and it must larger then `value`. | -| LessThan | The result of `subject` should be a number and it must less than `value`. | -| In | The result of `subject` should be inside the `set`. | -| NotIn | The result of `subject` should not be inside the `set`. | -| RegexMatch | The result of `subject` should be matched by the `value` (a PCRE regex pattern). | -| RegexNotMatch | The result of `subject` should not be matched by the `value` (a PCRE regex pattern). | -| RegexMatchCaseInsensitive | Similar with `RegexMatch` but the match process is case insensitive | +| Operator | Meaning | +|------------------------------|----------------------------------------------------------------------------------------| +| Equal | The result of `subject` should be equal to the `value` | +| NotEqual | The result of `subject` should not be equal to `value` | +| GreaterThan | The result of `subject` should be a number and it must larger then `value`. | +| LessThan | The result of `subject` should be a number and it must less than `value`. | +| In | The result of `subject` should be inside the `set`. | +| NotIn | The result of `subject` should not be inside the `set`. | +| RegexMatch | The result of `subject` should be matched by the `value` (a PCRE regex pattern). | +| RegexNotMatch | The result of `subject` should not be matched by the `value` (a PCRE regex pattern). | +| RegexMatchCaseInsensitive | Similar with `RegexMatch` but the match process is case insensitive | | RegexNotMatchCaseInsensitive | Similar with `RegexNotMatchCaseInsensitive` but the match process is case insensitive. | ## Service Resolve Granularity The service resolve granularity determines whether the [Serivce ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) or its endpoints should be filled in the target upstream of APISIX. -| Granularity | Meaning | -| ----------- | ------- | -| endpoint | Filled upstream nodes by Pods' IP. -| service | Filled upstream nodes by Service ClusterIP, in such a case, loadbalacing are implemented by [kube-proxy](https://kubernetes.io/docs/concepts/overview/components/#kube-proxy).| +| Granularity | Meaning | +|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| endpoint | Filled upstream nodes by Pods' IP. ApisixUpstream healthCheck is only effective on this case. | +| service | Filled upstream nodes by Service ClusterIP, in such a case, loadbalacing are implemented by [kube-proxy](https://kubernetes.io/docs/concepts/overview/components/#kube-proxy). | From 6b86d2a15f9d1e245ec06d2c8fb1d4c65b7c96b2 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Tue, 30 Aug 2022 15:36:09 +0800 Subject: [PATCH 16/30] e2e: delete duplicate log data on failure (#1297) --- test/e2e/scaffold/scaffold.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go index 11328d6c90..4d1d3b24e4 100644 --- a/test/e2e/scaffold/scaffold.go +++ b/test/e2e/scaffold/scaffold.go @@ -37,6 +37,7 @@ import ( mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gavv/httpexpect/v2" "github.com/gruntwork-io/terratest/modules/k8s" + "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/testing" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/assert" @@ -153,6 +154,8 @@ func NewScaffold(o *Options) *Scaffold { opts: o, t: ginkgo.GinkgoT(), } + // Disable logging of terratest library. + logger.Default = logger.Discard ginkgo.BeforeEach(s.beforeEach) ginkgo.AfterEach(s.afterEach) From cb6c6963816aa41a6b843bff351bcdf4dc4e5fa5 Mon Sep 17 00:00:00 2001 From: Jintao Zhang Date: Tue, 30 Aug 2022 16:21:30 +0800 Subject: [PATCH 17/30] docs: add powered-by.md (#1293) --- README.md | 6 +++++- powered-by.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 powered-by.md diff --git a/README.md b/README.md index dacc46ada7..0b7f791896 100644 --- a/README.md +++ b/README.md @@ -75,12 +75,12 @@ Currently, APISIX Ingress Controller automatically manipulates some APISIX resou ## Apache APISIX Ingress vs. Kubernetes Ingress Nginx +* The control plane and data plane are separated, which can improve security and deployment flexibility. * Hot-reload during yaml apply. * [More convenient canary deployment.](./docs/en/latest/concepts/apisix_route.md) * Verify the correctness of the configuration, safe and reliable. * [Rich plugins and ecology.](https://github.com/apache/apisix/tree/master/docs/en/latest/plugins) * Supports APISIX custom resources and Kubernetes native Ingress resources. -* More active community ## Contributing @@ -122,6 +122,10 @@ for us to fix. - [aispeech: Why we create a new k8s ingress controller?(Chinese)](https://mp.weixin.qq.com/s/bmm2ibk2V7-XYneLo9XAPQ) - [Tencent Cloud: Why choose Apache APISIX to implement the k8s ingress controller?(Chinese)](https://www.upyun.com/opentalk/448.html) +If you are willing to share with us some scenarios and use cases when you use APISIX Ingress, +please reply to the [issue](https://github.com/apache/apisix-ingress-controller/issues/501), +or submit PR to update [Powered-BY](./powered-by.md) file + ## Milestone * [Milestone](https://github.com/apache/apisix-ingress-controller/milestones) diff --git a/powered-by.md b/powered-by.md new file mode 100644 index 0000000000..7076759716 --- /dev/null +++ b/powered-by.md @@ -0,0 +1,31 @@ +--- +title: Powered by Apache APISIX Ingress +--- + + + +This page documents an alphabetical list of institutions that are using APISIX Ingress for research and production, +or providing commercial products including APISIX Ingress. + +Users are encouraged to add themselves to this page, [issue](https://github.com/apache/apisix-ingress-controller/issues/501) and PR are welcomed. + +1. AISpeech 思必驰 +1. Tencent Cloud 腾讯云 +1. UPYUN 又拍云 From 9dafeb88c94aa57526e3eb4e33ae439030d34c4f Mon Sep 17 00:00:00 2001 From: Jintao Zhang Date: Tue, 30 Aug 2022 16:21:58 +0800 Subject: [PATCH 18/30] chore: protect v1.5.0 and enable CI for it (#1294) --- .asf.yaml | 3 +++ .github/workflows/codeql-analysis.yml | 4 +++- .github/workflows/dependency-review.yml | 1 + .github/workflows/e2e-test-ci.yml | 1 + .github/workflows/golangci-lint.yml | 1 + .github/workflows/license-checker.yml | 1 + .github/workflows/lint-checker.yml | 1 + .github/workflows/spell-checker.yml | 7 +++++-- .github/workflows/unit-test-ci.yml | 1 + .github/workflows/verify-codegen.yml | 1 + 10 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index c64d3e762e..4ba9dedd38 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -40,3 +40,6 @@ github: master: required_pull_request_reviews: required_approving_review_count: 2 + v1.5.0: + required_pull_request_reviews: + required_approving_review_count: 1 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c229e8e673..6a6df77322 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,7 +24,9 @@ on: pull_request: type: [review_requested, ready_for_review] # The branches below must be a subset of the branches above - branches: [ master ] + branches: + - master + - v1.5.0 schedule: - cron: '25 5 * * 5' diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 99e40b7368..87dc0c458c 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -21,6 +21,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] permissions: diff --git a/.github/workflows/e2e-test-ci.yml b/.github/workflows/e2e-test-ci.yml index a09ec7e369..43a30aca89 100644 --- a/.github/workflows/e2e-test-ci.yml +++ b/.github/workflows/e2e-test-ci.yml @@ -25,6 +25,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] concurrency: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 6f445051c5..5939a90b17 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -25,6 +25,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] jobs: diff --git a/.github/workflows/license-checker.yml b/.github/workflows/license-checker.yml index 8f2bdceb09..5587631b84 100644 --- a/.github/workflows/license-checker.yml +++ b/.github/workflows/license-checker.yml @@ -25,6 +25,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] jobs: diff --git a/.github/workflows/lint-checker.yml b/.github/workflows/lint-checker.yml index bbe6ad5a08..5feeee85a2 100644 --- a/.github/workflows/lint-checker.yml +++ b/.github/workflows/lint-checker.yml @@ -25,6 +25,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] jobs: changes: diff --git a/.github/workflows/spell-checker.yml b/.github/workflows/spell-checker.yml index 074f3bda5d..055041d23c 100644 --- a/.github/workflows/spell-checker.yml +++ b/.github/workflows/spell-checker.yml @@ -19,9 +19,12 @@ name: spell-checker on: push: - branches: [ master ] + branches: + - master pull_request: - branches: [ master ] + branches: + - master + - v1.5.0 type: [review_requested, ready_for_review] jobs: misspell: diff --git a/.github/workflows/unit-test-ci.yml b/.github/workflows/unit-test-ci.yml index 6f162c086f..213bae31fa 100644 --- a/.github/workflows/unit-test-ci.yml +++ b/.github/workflows/unit-test-ci.yml @@ -25,6 +25,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] jobs: changes: diff --git a/.github/workflows/verify-codegen.yml b/.github/workflows/verify-codegen.yml index 3f31871fa1..e497c6f7b5 100644 --- a/.github/workflows/verify-codegen.yml +++ b/.github/workflows/verify-codegen.yml @@ -25,6 +25,7 @@ on: pull_request: branches: - master + - v1.5.0 type: [review_requested, ready_for_review] jobs: changes: From 0b999ec1d3087f7bf0037acbe2d398eaa0efab2a Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Tue, 30 Aug 2022 18:10:55 +0800 Subject: [PATCH 19/30] chore(refactor): annotations handle (#1245) --- .../ingress/translation/annotations.go | 46 ++++++++---- .../annotations/pluginconfig/pluginconfig.go | 29 ++++++++ .../{ => plugins}/authorization.go | 20 ++--- .../annotations/{ => plugins}/cors.go | 22 ++---- .../annotations/{ => plugins}/cors_test.go | 19 ++--- .../annotations/{ => plugins}/csrf.go | 16 ++-- .../annotations/{ => plugins}/forward_auth.go | 25 +++---- .../{ => plugins}/forward_auth_test.go | 23 +++--- .../{ => plugins}/iprestriction.go | 16 ++-- .../{ => plugins}/iprestriction_test.go | 19 ++--- .../annotations/plugins/plugins.go | 70 ++++++++++++++++++ .../annotations/{ => plugins}/redirect.go | 19 ++--- .../annotations/{ => plugins}/rewrite.go | 19 ++--- .../translation/annotations/regex/regex.go | 29 ++++++++ .../ingress/translation/annotations/types.go | 63 +++++++++++++--- .../annotations/websocket/websocket.go | 29 ++++++++ .../ingress/translation/annotations_test.go | 74 +++++++++++++++++++ .../ingress/translation/translator.go | 55 ++++++-------- 18 files changed, 417 insertions(+), 176 deletions(-) create mode 100644 pkg/providers/ingress/translation/annotations/pluginconfig/pluginconfig.go rename pkg/providers/ingress/translation/annotations/{ => plugins}/authorization.go (74%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/cors.go (66%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/cors_test.go (72%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/csrf.go (76%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/forward_auth.go (61%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/forward_auth_test.go (70%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/iprestriction.go (76%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/iprestriction_test.go (76%) create mode 100644 pkg/providers/ingress/translation/annotations/plugins/plugins.go rename pkg/providers/ingress/translation/annotations/{ => plugins}/redirect.go (77%) rename pkg/providers/ingress/translation/annotations/{ => plugins}/rewrite.go (74%) create mode 100644 pkg/providers/ingress/translation/annotations/regex/regex.go create mode 100644 pkg/providers/ingress/translation/annotations/websocket/websocket.go create mode 100644 pkg/providers/ingress/translation/annotations_test.go diff --git a/pkg/providers/ingress/translation/annotations.go b/pkg/providers/ingress/translation/annotations.go index 6b9d3d8155..7ddbeddf1f 100644 --- a/pkg/providers/ingress/translation/annotations.go +++ b/pkg/providers/ingress/translation/annotations.go @@ -15,40 +15,54 @@ package translation import ( + "github.com/imdario/mergo" "go.uber.org/zap" "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/pluginconfig" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/plugins" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/regex" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/websocket" apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) +// Structure extracted by Ingress Resource +type Ingress struct { + Plugins apisix.Plugins + UseRegex bool + EnableWebSocket bool + PluginConfigName string +} + var ( - _handlers = []annotations.Handler{ - annotations.NewCorsHandler(), - annotations.NewIPRestrictionHandler(), - annotations.NewRewriteHandler(), - annotations.NewRedirectHandler(), - annotations.NewForwardAuthHandler(), - annotations.NewBasicAuthHandler(), - annotations.NewKeyAuthHandler(), - annotations.NewCSRFHandler(), + _parsers = map[string]annotations.IngressAnnotationsParser{ + "Plugins": plugins.NewParser(), + "UseRegex": regex.NewParser(), + "EnableWebSocket": websocket.NewParser(), + "PluginConfigName": pluginconfig.NewParser(), } ) -func (t *translator) TranslateAnnotations(anno map[string]string) apisix.Plugins { +func (t *translator) TranslateAnnotations(anno map[string]string) *Ingress { + ing := &Ingress{} extractor := annotations.NewExtractor(anno) - plugins := make(apisix.Plugins) - for _, handler := range _handlers { - out, err := handler.Handle(extractor) + data := make(map[string]interface{}) + for name, parser := range _parsers { + out, err := parser.Parse(extractor) if err != nil { - log.Warnw("failed to handle annotations", + log.Warnw("failed to parse annotations", zap.Error(err), ) continue } if out != nil { - plugins[handler.PluginName()] = out + data[name] = out } } - return plugins + err := mergo.MapWithOverwrite(ing, data) + if err != nil { + log.Errorw("unexpected error merging extracted annotations", zap.Error(err)) + } + return ing } diff --git a/pkg/providers/ingress/translation/annotations/pluginconfig/pluginconfig.go b/pkg/providers/ingress/translation/annotations/pluginconfig/pluginconfig.go new file mode 100644 index 0000000000..1847625aca --- /dev/null +++ b/pkg/providers/ingress/translation/annotations/pluginconfig/pluginconfig.go @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package pluginconfig + +import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" +) + +type pluginconfig struct{} + +func NewParser() annotations.IngressAnnotationsParser { + return &pluginconfig{} +} + +func (w *pluginconfig) Parse(e annotations.Extractor) (interface{}, error) { + return e.GetStringAnnotation(annotations.AnnotationsPluginConfigName), nil +} diff --git a/pkg/providers/ingress/translation/annotations/authorization.go b/pkg/providers/ingress/translation/annotations/plugins/authorization.go similarity index 74% rename from pkg/providers/ingress/translation/annotations/authorization.go rename to pkg/providers/ingress/translation/annotations/plugins/authorization.go index c97567a4a5..246e754a0e 100644 --- a/pkg/providers/ingress/translation/annotations/authorization.go +++ b/pkg/providers/ingress/translation/annotations/plugins/authorization.go @@ -12,22 +12,18 @@ // 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 +package plugins import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - // auth-type: keyAuth | basicAuth - _authType = AnnotationsPrefix + "auth-type" -) - type basicAuth struct{} // NewkeyBasicHandler creates a handler to convert // annotations about basicAuth control to APISIX basic-auth plugin. -func NewBasicAuthHandler() Handler { +func NewBasicAuthHandler() PluginAnnotationsHandler { return &basicAuth{} } @@ -35,8 +31,8 @@ func (b *basicAuth) PluginName() string { return "basic-auth" } -func (b *basicAuth) Handle(e Extractor) (interface{}, error) { - if e.GetStringAnnotation(_authType) != "basicAuth" { +func (b *basicAuth) Handle(e annotations.Extractor) (interface{}, error) { + if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "basicAuth" { return nil, nil } plugin := apisixv1.BasicAuthConfig{} @@ -47,7 +43,7 @@ type keyAuth struct{} // NewkeyAuthHandler creates a handler to convert // annotations about keyAuth control to APISIX key-auth plugin. -func NewKeyAuthHandler() Handler { +func NewKeyAuthHandler() PluginAnnotationsHandler { return &keyAuth{} } @@ -55,8 +51,8 @@ func (k *keyAuth) PluginName() string { return "key-auth" } -func (k *keyAuth) Handle(e Extractor) (interface{}, error) { - if e.GetStringAnnotation(_authType) != "keyAuth" { +func (k *keyAuth) Handle(e annotations.Extractor) (interface{}, error) { + if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "keyAuth" { return nil, nil } plugin := apisixv1.KeyAuthConfig{} diff --git a/pkg/providers/ingress/translation/annotations/cors.go b/pkg/providers/ingress/translation/annotations/plugins/cors.go similarity index 66% rename from pkg/providers/ingress/translation/annotations/cors.go rename to pkg/providers/ingress/translation/annotations/plugins/cors.go index ee88e6c40d..42d63b716a 100644 --- a/pkg/providers/ingress/translation/annotations/cors.go +++ b/pkg/providers/ingress/translation/annotations/plugins/cors.go @@ -12,24 +12,18 @@ // 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 +package plugins import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - _enableCors = AnnotationsPrefix + "enable-cors" - _corsAllowOrigin = AnnotationsPrefix + "cors-allow-origin" - _corsAllowHeaders = AnnotationsPrefix + "cors-allow-headers" - _corsAllowMethods = AnnotationsPrefix + "cors-allow-methods" -) - type cors struct{} // NewCorsHandler creates a handler to convert annotations about // CORS to APISIX cors plugin. -func NewCorsHandler() Handler { +func NewCorsHandler() PluginAnnotationsHandler { return &cors{} } @@ -37,13 +31,13 @@ func (c *cors) PluginName() string { return "cors" } -func (c *cors) Handle(e Extractor) (interface{}, error) { - if !e.GetBoolAnnotation(_enableCors) { +func (c *cors) Handle(e annotations.Extractor) (interface{}, error) { + if !e.GetBoolAnnotation(annotations.AnnotationsEnableCors) { return nil, nil } return &apisixv1.CorsConfig{ - AllowOrigins: e.GetStringAnnotation(_corsAllowOrigin), - AllowMethods: e.GetStringAnnotation(_corsAllowMethods), - AllowHeaders: e.GetStringAnnotation(_corsAllowHeaders), + AllowOrigins: e.GetStringAnnotation(annotations.AnnotationsCorsAllowOrigin), + AllowMethods: e.GetStringAnnotation(annotations.AnnotationsCorsAllowMethods), + AllowHeaders: e.GetStringAnnotation(annotations.AnnotationsCorsAllowHeaders), }, nil } diff --git a/pkg/providers/ingress/translation/annotations/cors_test.go b/pkg/providers/ingress/translation/annotations/plugins/cors_test.go similarity index 72% rename from pkg/providers/ingress/translation/annotations/cors_test.go rename to pkg/providers/ingress/translation/annotations/plugins/cors_test.go index 342c0f2967..cf6a9f95a7 100644 --- a/pkg/providers/ingress/translation/annotations/cors_test.go +++ b/pkg/providers/ingress/translation/annotations/plugins/cors_test.go @@ -12,25 +12,26 @@ // 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 +package plugins import ( "testing" "github.com/stretchr/testify/assert" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) func TestCorsHandler(t *testing.T) { - annotations := map[string]string{ - _enableCors: "true", - _corsAllowHeaders: "abc,def", - _corsAllowOrigin: "https://a.com", - _corsAllowMethods: "GET,HEAD", + anno := map[string]string{ + annotations.AnnotationsEnableCors: "true", + annotations.AnnotationsCorsAllowHeaders: "abc,def", + annotations.AnnotationsCorsAllowOrigin: "https://a.com", + annotations.AnnotationsCorsAllowMethods: "GET,HEAD", } p := NewCorsHandler() - out, err := p.Handle(NewExtractor(annotations)) + out, err := p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") config := out.(*apisixv1.CorsConfig) assert.Equal(t, "abc,def", config.AllowHeaders) @@ -39,8 +40,8 @@ func TestCorsHandler(t *testing.T) { assert.Equal(t, "cors", p.PluginName()) - annotations[_enableCors] = "false" - out, err = p.Handle(NewExtractor(annotations)) + anno[annotations.AnnotationsEnableCors] = "false" + out, err = p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") assert.Nil(t, out, "checking given output") } diff --git a/pkg/providers/ingress/translation/annotations/csrf.go b/pkg/providers/ingress/translation/annotations/plugins/csrf.go similarity index 76% rename from pkg/providers/ingress/translation/annotations/csrf.go rename to pkg/providers/ingress/translation/annotations/plugins/csrf.go index d3cc087b5c..b8d595f5b5 100644 --- a/pkg/providers/ingress/translation/annotations/csrf.go +++ b/pkg/providers/ingress/translation/annotations/plugins/csrf.go @@ -12,22 +12,18 @@ // 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 +package plugins import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - _enableCsrf = AnnotationsPrefix + "enable-csrf" - _csrfKey = AnnotationsPrefix + "csrf-key" -) - type csrf struct{} // NewCSRFHandler creates a handler to convert annotations about // CSRF to APISIX csrf plugin. -func NewCSRFHandler() Handler { +func NewCSRFHandler() PluginAnnotationsHandler { return &csrf{} } @@ -35,12 +31,12 @@ func (c *csrf) PluginName() string { return "csrf" } -func (c *csrf) Handle(e Extractor) (interface{}, error) { - if !e.GetBoolAnnotation(_enableCsrf) { +func (c *csrf) Handle(e annotations.Extractor) (interface{}, error) { + if !e.GetBoolAnnotation(annotations.AnnotationsEnableCsrf) { return nil, nil } var plugin apisixv1.CSRFConfig - plugin.Key = e.GetStringAnnotation(_csrfKey) + plugin.Key = e.GetStringAnnotation(annotations.AnnotationsCsrfKey) if plugin.Key != "" { return &plugin, nil } diff --git a/pkg/providers/ingress/translation/annotations/forward_auth.go b/pkg/providers/ingress/translation/annotations/plugins/forward_auth.go similarity index 61% rename from pkg/providers/ingress/translation/annotations/forward_auth.go rename to pkg/providers/ingress/translation/annotations/plugins/forward_auth.go index c55016d455..b5a7543f10 100644 --- a/pkg/providers/ingress/translation/annotations/forward_auth.go +++ b/pkg/providers/ingress/translation/annotations/plugins/forward_auth.go @@ -12,25 +12,18 @@ // 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 +package plugins import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - _forwardAuthURI = AnnotationsPrefix + "auth-uri" - _forwardAuthSSLVerify = AnnotationsPrefix + "auth-ssl-verify" - _forwardAuthRequestHeaders = AnnotationsPrefix + "auth-request-headers" - _forwardAuthUpstreamHeaders = AnnotationsPrefix + "auth-upstream-headers" - _forwardAuthClientHeaders = AnnotationsPrefix + "auth-client-headers" -) - type forwardAuth struct{} // NewForwardAuthHandler creates a handler to convert // annotations about forward authentication to APISIX forward-auth plugin. -func NewForwardAuthHandler() Handler { +func NewForwardAuthHandler() PluginAnnotationsHandler { return &forwardAuth{} } @@ -38,19 +31,19 @@ func (i *forwardAuth) PluginName() string { return "forward-auth" } -func (i *forwardAuth) Handle(e Extractor) (interface{}, error) { - uri := e.GetStringAnnotation(_forwardAuthURI) +func (i *forwardAuth) Handle(e annotations.Extractor) (interface{}, error) { + uri := e.GetStringAnnotation(annotations.AnnotationsForwardAuthURI) sslVerify := true - if e.GetStringAnnotation(_forwardAuthSSLVerify) == "false" { + if e.GetStringAnnotation(annotations.AnnotationsForwardAuthSSLVerify) == "false" { sslVerify = false } if len(uri) > 0 { return &apisixv1.ForwardAuthConfig{ URI: uri, SSLVerify: sslVerify, - RequestHeaders: e.GetStringsAnnotation(_forwardAuthRequestHeaders), - UpstreamHeaders: e.GetStringsAnnotation(_forwardAuthUpstreamHeaders), - ClientHeaders: e.GetStringsAnnotation(_forwardAuthClientHeaders), + RequestHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthRequestHeaders), + UpstreamHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthUpstreamHeaders), + ClientHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthClientHeaders), }, nil } diff --git a/pkg/providers/ingress/translation/annotations/forward_auth_test.go b/pkg/providers/ingress/translation/annotations/plugins/forward_auth_test.go similarity index 70% rename from pkg/providers/ingress/translation/annotations/forward_auth_test.go rename to pkg/providers/ingress/translation/annotations/plugins/forward_auth_test.go index 06c6c744bb..3ee6b0cfee 100644 --- a/pkg/providers/ingress/translation/annotations/forward_auth_test.go +++ b/pkg/providers/ingress/translation/annotations/plugins/forward_auth_test.go @@ -12,25 +12,26 @@ // 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 +package plugins import ( "testing" "github.com/stretchr/testify/assert" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) func TestForwardAuthHandler(t *testing.T) { - annotations := map[string]string{ - _forwardAuthURI: "http://127.0.0.1:9080", - _forwardAuthRequestHeaders: "Authorization", - _forwardAuthClientHeaders: "Location", - _forwardAuthUpstreamHeaders: "X-User-ID", + anno := map[string]string{ + annotations.AnnotationsForwardAuthURI: "http://127.0.0.1:9080", + annotations.AnnotationsForwardAuthRequestHeaders: "Authorization", + annotations.AnnotationsForwardAuthClientHeaders: "Location", + annotations.AnnotationsForwardAuthUpstreamHeaders: "X-User-ID", } p := NewForwardAuthHandler() - out, err := p.Handle(NewExtractor(annotations)) + out, err := p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") config := out.(*apisixv1.ForwardAuthConfig) assert.Equal(t, "http://127.0.0.1:9080", config.URI) @@ -40,14 +41,14 @@ func TestForwardAuthHandler(t *testing.T) { assert.Equal(t, true, config.SSLVerify) assert.Equal(t, "forward-auth", p.PluginName()) - annotations[_forwardAuthSSLVerify] = "false" - out, err = p.Handle(NewExtractor(annotations)) + anno[annotations.AnnotationsForwardAuthSSLVerify] = "false" + out, err = p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") config = out.(*apisixv1.ForwardAuthConfig) assert.Equal(t, false, config.SSLVerify) - annotations[_forwardAuthURI] = "" - out, err = p.Handle(NewExtractor(annotations)) + anno[annotations.AnnotationsForwardAuthURI] = "" + out, err = p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") assert.Nil(t, out, "checking given output") } diff --git a/pkg/providers/ingress/translation/annotations/iprestriction.go b/pkg/providers/ingress/translation/annotations/plugins/iprestriction.go similarity index 76% rename from pkg/providers/ingress/translation/annotations/iprestriction.go rename to pkg/providers/ingress/translation/annotations/plugins/iprestriction.go index 1d17957b68..f3a3bd6fe5 100644 --- a/pkg/providers/ingress/translation/annotations/iprestriction.go +++ b/pkg/providers/ingress/translation/annotations/plugins/iprestriction.go @@ -12,22 +12,18 @@ // 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 +package plugins import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - _allowlistSourceRange = AnnotationsPrefix + "allowlist-source-range" - _blocklistSourceRange = AnnotationsPrefix + "blocklist-source-range" -) - type ipRestriction struct{} // NewIPRestrictionHandler creates a handler to convert // annotations about client ips control to APISIX ip-restrict plugin. -func NewIPRestrictionHandler() Handler { +func NewIPRestrictionHandler() PluginAnnotationsHandler { return &ipRestriction{} } @@ -35,10 +31,10 @@ func (i *ipRestriction) PluginName() string { return "ip-restriction" } -func (i *ipRestriction) Handle(e Extractor) (interface{}, error) { +func (i *ipRestriction) Handle(e annotations.Extractor) (interface{}, error) { var plugin apisixv1.IPRestrictConfig - allowlist := e.GetStringsAnnotation(_allowlistSourceRange) - blocklist := e.GetStringsAnnotation(_blocklistSourceRange) + allowlist := e.GetStringsAnnotation(annotations.AnnotationsAllowlistSourceRange) + blocklist := e.GetStringsAnnotation(annotations.AnnotationsBlocklistSourceRange) if allowlist != nil || blocklist != nil { plugin.Allowlist = allowlist plugin.Blocklist = blocklist diff --git a/pkg/providers/ingress/translation/annotations/iprestriction_test.go b/pkg/providers/ingress/translation/annotations/plugins/iprestriction_test.go similarity index 76% rename from pkg/providers/ingress/translation/annotations/iprestriction_test.go rename to pkg/providers/ingress/translation/annotations/plugins/iprestriction_test.go index cfc3fca738..56a0dff7cd 100644 --- a/pkg/providers/ingress/translation/annotations/iprestriction_test.go +++ b/pkg/providers/ingress/translation/annotations/plugins/iprestriction_test.go @@ -12,22 +12,23 @@ // 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 +package plugins import ( "testing" "github.com/stretchr/testify/assert" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) func TestIPRestrictionHandler(t *testing.T) { - annotations := map[string]string{ - _allowlistSourceRange: "10.2.2.2,192.168.0.0/16", + anno := map[string]string{ + annotations.AnnotationsAllowlistSourceRange: "10.2.2.2,192.168.0.0/16", } p := NewIPRestrictionHandler() - out, err := p.Handle(NewExtractor(annotations)) + out, err := p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") config := out.(*apisixv1.IPRestrictConfig) assert.Len(t, config.Allowlist, 2, "checking size of white list") @@ -35,8 +36,8 @@ func TestIPRestrictionHandler(t *testing.T) { assert.Equal(t, "192.168.0.0/16", config.Allowlist[1]) assert.Equal(t, "ip-restriction", p.PluginName()) - annotations[_blocklistSourceRange] = "172.17.0.0/16,127.0.0.1" - out, err = p.Handle(NewExtractor(annotations)) + anno[annotations.AnnotationsBlocklistSourceRange] = "172.17.0.0/16,127.0.0.1" + out, err = p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") config = out.(*apisixv1.IPRestrictConfig) assert.Len(t, config.Allowlist, 2, "checking size of white list") @@ -46,9 +47,9 @@ func TestIPRestrictionHandler(t *testing.T) { assert.Equal(t, "172.17.0.0/16", config.Blocklist[0]) assert.Equal(t, "127.0.0.1", config.Blocklist[1]) - delete(annotations, _allowlistSourceRange) - delete(annotations, _blocklistSourceRange) - out, err = p.Handle(NewExtractor(annotations)) + delete(anno, annotations.AnnotationsAllowlistSourceRange) + delete(anno, annotations.AnnotationsBlocklistSourceRange) + out, err = p.Handle(annotations.NewExtractor(anno)) assert.Nil(t, err, "checking given error") assert.Nil(t, out, "checking the given ip-restrction plugin config") } diff --git a/pkg/providers/ingress/translation/annotations/plugins/plugins.go b/pkg/providers/ingress/translation/annotations/plugins/plugins.go new file mode 100644 index 0000000000..b4a4fd1195 --- /dev/null +++ b/pkg/providers/ingress/translation/annotations/plugins/plugins.go @@ -0,0 +1,70 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package plugins + +import ( + "go.uber.org/zap" + + "github.com/apache/apisix-ingress-controller/pkg/log" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" + apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" +) + +// Handler abstracts the behavior so that the apisix-ingress-controller knows +// how to parse some annotations and convert them to APISIX plugins. +type PluginAnnotationsHandler interface { + // Handle parses the target annotation and converts it to the type-agnostic structure. + // The return value might be nil since some features have an explicit switch, users should + // judge whether Handle is failed by the second error value. + Handle(annotations.Extractor) (interface{}, error) + // PluginName returns a string which indicates the target plugin name in APISIX. + PluginName() string +} + +var ( + _handlers = []PluginAnnotationsHandler{ + NewCorsHandler(), + NewIPRestrictionHandler(), + NewRewriteHandler(), + NewRedirectHandler(), + NewForwardAuthHandler(), + NewBasicAuthHandler(), + NewKeyAuthHandler(), + NewCSRFHandler(), + } +) + +type plugins struct{} + +func NewParser() annotations.IngressAnnotationsParser { + return &plugins{} +} + +func (p *plugins) Parse(e annotations.Extractor) (interface{}, error) { + plugins := make(apisix.Plugins) + for _, handler := range _handlers { + out, err := handler.Handle(e) + if err != nil { + log.Warnw("failed to handle annotations", + zap.Error(err), + ) + continue + } + if out != nil { + plugins[handler.PluginName()] = out + } + } + return plugins, nil +} diff --git a/pkg/providers/ingress/translation/annotations/redirect.go b/pkg/providers/ingress/translation/annotations/plugins/redirect.go similarity index 77% rename from pkg/providers/ingress/translation/annotations/redirect.go rename to pkg/providers/ingress/translation/annotations/plugins/redirect.go index 6f2ca9af06..1f073e8587 100644 --- a/pkg/providers/ingress/translation/annotations/redirect.go +++ b/pkg/providers/ingress/translation/annotations/plugins/redirect.go @@ -12,26 +12,21 @@ // 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 +package plugins import ( "net/http" "strconv" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - _httpToHttps = AnnotationsPrefix + "http-to-https" - _httpRedirect = AnnotationsPrefix + "http-redirect" - _httpRedirectCode = AnnotationsPrefix + "http-redirect-code" -) - type redirect struct{} // NewRedirectHandler creates a handler to convert // annotations about redirect control to APISIX redirect plugin. -func NewRedirectHandler() Handler { +func NewRedirectHandler() PluginAnnotationsHandler { return &redirect{} } @@ -39,12 +34,12 @@ func (r *redirect) PluginName() string { return "redirect" } -func (r *redirect) Handle(e Extractor) (interface{}, error) { +func (r *redirect) Handle(e annotations.Extractor) (interface{}, error) { var plugin apisixv1.RedirectConfig - plugin.HttpToHttps = e.GetBoolAnnotation(_httpToHttps) - plugin.URI = e.GetStringAnnotation(_httpRedirect) + plugin.HttpToHttps = e.GetBoolAnnotation(annotations.AnnotationsHttpToHttps) + plugin.URI = e.GetStringAnnotation(annotations.AnnotationsHttpRedirect) // Transformation fail defaults to 0. - plugin.RetCode, _ = strconv.Atoi(e.GetStringAnnotation(_httpRedirectCode)) + plugin.RetCode, _ = strconv.Atoi(e.GetStringAnnotation(annotations.AnnotationsHttpRedirectCode)) // To avoid empty redirect plugin config, adding the check about the redirect. if plugin.HttpToHttps { return &plugin, nil diff --git a/pkg/providers/ingress/translation/annotations/rewrite.go b/pkg/providers/ingress/translation/annotations/plugins/rewrite.go similarity index 74% rename from pkg/providers/ingress/translation/annotations/rewrite.go rename to pkg/providers/ingress/translation/annotations/plugins/rewrite.go index 35a0f9477e..b02e97a273 100644 --- a/pkg/providers/ingress/translation/annotations/rewrite.go +++ b/pkg/providers/ingress/translation/annotations/plugins/rewrite.go @@ -12,25 +12,20 @@ // 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 +package plugins import ( "regexp" + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) -const ( - _rewriteTarget = AnnotationsPrefix + "rewrite-target" - _rewriteTargetRegex = AnnotationsPrefix + "rewrite-target-regex" - _rewriteTargetRegexTemplate = AnnotationsPrefix + "rewrite-target-regex-template" -) - type rewrite struct{} // NewRewriteHandler creates a handler to convert // annotations about request rewrite control to APISIX proxy-rewrite plugin. -func NewRewriteHandler() Handler { +func NewRewriteHandler() PluginAnnotationsHandler { return &rewrite{} } @@ -38,11 +33,11 @@ func (i *rewrite) PluginName() string { return "proxy-rewrite" } -func (i *rewrite) Handle(e Extractor) (interface{}, error) { +func (i *rewrite) Handle(e annotations.Extractor) (interface{}, error) { var plugin apisixv1.RewriteConfig - rewriteTarget := e.GetStringAnnotation(_rewriteTarget) - rewriteTargetRegex := e.GetStringAnnotation(_rewriteTargetRegex) - rewriteTemplate := e.GetStringAnnotation(_rewriteTargetRegexTemplate) + rewriteTarget := e.GetStringAnnotation(annotations.AnnotationsRewriteTarget) + rewriteTargetRegex := e.GetStringAnnotation(annotations.AnnotationsRewriteTargetRegex) + rewriteTemplate := e.GetStringAnnotation(annotations.AnnotationsRewriteTargetRegexTemplate) if rewriteTarget != "" || rewriteTargetRegex != "" || rewriteTemplate != "" { plugin.RewriteTarget = rewriteTarget if rewriteTargetRegex != "" && rewriteTemplate != "" { diff --git a/pkg/providers/ingress/translation/annotations/regex/regex.go b/pkg/providers/ingress/translation/annotations/regex/regex.go new file mode 100644 index 0000000000..a791cf127a --- /dev/null +++ b/pkg/providers/ingress/translation/annotations/regex/regex.go @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package regex + +import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" +) + +type regex struct{} + +func NewParser() annotations.IngressAnnotationsParser { + return ®ex{} +} + +func (r *regex) Parse(e annotations.Extractor) (interface{}, error) { + return e.GetBoolAnnotation(annotations.AnnotationsUseRegex), nil +} diff --git a/pkg/providers/ingress/translation/annotations/types.go b/pkg/providers/ingress/translation/annotations/types.go index 4f8f6421f9..d6c2d80ec2 100644 --- a/pkg/providers/ingress/translation/annotations/types.go +++ b/pkg/providers/ingress/translation/annotations/types.go @@ -21,8 +21,60 @@ import ( const ( // AnnotationsPrefix is the apisix annotation prefix AnnotationsPrefix = "k8s.apisix.apache.org/" + + // Supported annotations + AnnotationsUseRegex = AnnotationsPrefix + "use-regex" + AnnotationsEnableWebSocket = AnnotationsPrefix + "enable-websocket" + AnnotationsPluginConfigName = AnnotationsPrefix + "plugin-config-name" +) + +const ( + // Supported the annotations of the APISIX plugins + + // cors plugin + AnnotationsEnableCors = AnnotationsPrefix + "enable-cors" + AnnotationsCorsAllowOrigin = AnnotationsPrefix + "cors-allow-origin" + AnnotationsCorsAllowHeaders = AnnotationsPrefix + "cors-allow-headers" + AnnotationsCorsAllowMethods = AnnotationsPrefix + "cors-allow-methods" + + // csrf plugin + AnnotationsEnableCsrf = AnnotationsPrefix + "enable-csrf" + AnnotationsCsrfKey = AnnotationsPrefix + "csrf-key" + + // redirect plugin + AnnotationsHttpToHttps = AnnotationsPrefix + "http-to-https" + AnnotationsHttpRedirect = AnnotationsPrefix + "http-redirect" + AnnotationsHttpRedirectCode = AnnotationsPrefix + "http-redirect-code" + + // rewrite plugin + AnnotationsRewriteTarget = AnnotationsPrefix + "rewrite-target" + AnnotationsRewriteTargetRegex = AnnotationsPrefix + "rewrite-target-regex" + AnnotationsRewriteTargetRegexTemplate = AnnotationsPrefix + "rewrite-target-regex-template" + + // forward-auth plugin + AnnotationsForwardAuthURI = AnnotationsPrefix + "auth-uri" + AnnotationsForwardAuthSSLVerify = AnnotationsPrefix + "auth-ssl-verify" + AnnotationsForwardAuthRequestHeaders = AnnotationsPrefix + "auth-request-headers" + AnnotationsForwardAuthUpstreamHeaders = AnnotationsPrefix + "auth-upstream-headers" + AnnotationsForwardAuthClientHeaders = AnnotationsPrefix + "auth-client-headers" + + // ip-restriction plugin + AnnotationsAllowlistSourceRange = AnnotationsPrefix + "allowlist-source-range" + AnnotationsBlocklistSourceRange = AnnotationsPrefix + "blocklist-source-range" + + // key-auth plugin and basic-auth plugin + // auth-type: keyAuth | basicAuth + AnnotationsAuthType = AnnotationsPrefix + "auth-type" ) +// Handler abstracts the behavior so that the apisix-ingress-controller knows +type IngressAnnotationsParser interface { + // Handle parses the target annotation and converts it to the type-agnostic structure. + // The return value might be nil since some features have an explicit switch, users should + // judge whether Handle is failed by the second error value. + Parse(Extractor) (interface{}, error) +} + // Extractor encapsulates some auxiliary methods to extract annotations. type Extractor interface { // GetStringAnnotation returns the string value of the target annotation. @@ -38,17 +90,6 @@ type Extractor interface { GetBoolAnnotation(string) bool } -// Handler abstracts the behavior so that the apisix-ingress-controller knows -// how to parse some annotations and convert them to APISIX plugins. -type Handler interface { - // Handle parses the target annotation and converts it to the type-agnostic structure. - // The return value might be nil since some features have an explicit switch, users should - // judge whether Handle is failed by the second error value. - Handle(Extractor) (interface{}, error) - // PluginName returns a string which indicates the target plugin name in APISIX. - PluginName() string -} - type extractor struct { annotations map[string]string } diff --git a/pkg/providers/ingress/translation/annotations/websocket/websocket.go b/pkg/providers/ingress/translation/annotations/websocket/websocket.go new file mode 100644 index 0000000000..ef73329c23 --- /dev/null +++ b/pkg/providers/ingress/translation/annotations/websocket/websocket.go @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package websocket + +import ( + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" +) + +type websocket struct{} + +func NewParser() annotations.IngressAnnotationsParser { + return &websocket{} +} + +func (w *websocket) Parse(e annotations.Extractor) (interface{}, error) { + return e.GetBoolAnnotation(annotations.AnnotationsEnableWebSocket), nil +} diff --git a/pkg/providers/ingress/translation/annotations_test.go b/pkg/providers/ingress/translation/annotations_test.go new file mode 100644 index 0000000000..f82d52fdc8 --- /dev/null +++ b/pkg/providers/ingress/translation/annotations_test.go @@ -0,0 +1,74 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package translation + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" + apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" +) + +func TestAnnotationsPlugins(t *testing.T) { + anno := map[string]string{ + annotations.AnnotationsAuthType: "basicAuth", + } + + ingress := (&translator{}).TranslateAnnotations(anno) + assert.Len(t, ingress.Plugins, 1) + assert.Equal(t, apisix.Plugins{ + "basic-auth": &apisix.BasicAuthConfig{}, + }, ingress.Plugins) + + anno[annotations.AnnotationsEnableCsrf] = "true" + anno[annotations.AnnotationsCsrfKey] = "csrf-key" + ingress = (&translator{}).TranslateAnnotations(anno) + assert.Len(t, ingress.Plugins, 2) + assert.Equal(t, apisix.Plugins{ + "basic-auth": &apisix.BasicAuthConfig{}, + "csrf": &apisix.CSRFConfig{ + Key: "csrf-key", + }, + }, ingress.Plugins) +} + +func TestAnnotationsPluginConfigName(t *testing.T) { + anno := map[string]string{ + annotations.AnnotationsPluginConfigName: "plugin-config-echo", + } + + ingress := (&translator{}).TranslateAnnotations(anno) + assert.Equal(t, "plugin-config-echo", ingress.PluginConfigName) +} + +func TestAnnotationsEnableWebSocket(t *testing.T) { + anno := map[string]string{ + annotations.AnnotationsEnableWebSocket: "true", + } + + ingress := (&translator{}).TranslateAnnotations(anno) + assert.Equal(t, true, ingress.EnableWebSocket) +} + +func TestAnnotationsUseRegex(t *testing.T) { + anno := map[string]string{ + annotations.AnnotationsUseRegex: "true", + } + + ingress := (&translator{}).TranslateAnnotations(anno) + assert.Equal(t, true, ingress.UseRegex) +} diff --git a/pkg/providers/ingress/translation/translator.go b/pkg/providers/ingress/translation/translator.go index 48b2a87dfa..5a7712a991 100644 --- a/pkg/providers/ingress/translation/translator.go +++ b/pkg/providers/ingress/translation/translator.go @@ -40,7 +40,6 @@ import ( apisixconst "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/const" "github.com/apache/apisix-ingress-controller/pkg/log" apisixtranslation "github.com/apache/apisix-ingress-controller/pkg/providers/apisix/translation" - "github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -102,11 +101,7 @@ const ( func (t *translator) translateIngressV1(ing *networkingv1.Ingress, skipVerify bool) (*translation.TranslateContext, error) { ctx := translation.DefaultEmptyTranslateContext() - plugins := t.TranslateAnnotations(ing.Annotations) - annoExtractor := annotations.NewExtractor(ing.Annotations) - useRegex := annoExtractor.GetBoolAnnotation(annotations.AnnotationsPrefix + "use-regex") - enableWebsocket := annoExtractor.GetBoolAnnotation(annotations.AnnotationsPrefix + "enable-websocket") - pluginConfigName := annoExtractor.GetStringAnnotation(annotations.AnnotationsPrefix + "plugin-config-name") + ingress := t.TranslateAnnotations(ing.Annotations) // add https for _, tls := range ing.Spec.TLS { @@ -179,7 +174,7 @@ func (t *translator) translateIngressV1(ing *networkingv1.Ingress, skipVerify bo prefix += "/*" } uris = append(uris, prefix) - } else if *pathRule.PathType == networkingv1.PathTypeImplementationSpecific && useRegex { + } else if *pathRule.PathType == networkingv1.PathTypeImplementationSpecific && ingress.UseRegex { nginxVars = append(nginxVars, kubev2.ApisixRouteHTTPMatchExpr{ Subject: kubev2.ApisixRouteHTTPMatchExprSubject{ Scope: apisixconst.ScopePath, @@ -195,7 +190,7 @@ func (t *translator) translateIngressV1(ing *networkingv1.Ingress, skipVerify bo route.ID = id.GenID(route.Name) route.Host = rule.Host route.Uris = uris - route.EnableWebsocket = enableWebsocket + route.EnableWebsocket = ingress.EnableWebSocket if len(nginxVars) > 0 { routeVars, err := t.ApisixTranslator.TranslateRouteMatchExprs(nginxVars) if err != nil { @@ -204,12 +199,12 @@ func (t *translator) translateIngressV1(ing *networkingv1.Ingress, skipVerify bo route.Vars = routeVars route.Priority = _regexPriority } - if len(plugins) > 0 { - route.Plugins = *(plugins.DeepCopy()) + if len(ingress.Plugins) > 0 { + route.Plugins = *(ingress.Plugins.DeepCopy()) } - if pluginConfigName != "" { - route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ing.Namespace, pluginConfigName)) + if ingress.PluginConfigName != "" { + route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ing.Namespace, ingress.PluginConfigName)) } if ups != nil { route.UpstreamId = ups.ID @@ -222,11 +217,7 @@ func (t *translator) translateIngressV1(ing *networkingv1.Ingress, skipVerify bo func (t *translator) translateIngressV1beta1(ing *networkingv1beta1.Ingress, skipVerify bool) (*translation.TranslateContext, error) { ctx := translation.DefaultEmptyTranslateContext() - plugins := t.TranslateAnnotations(ing.Annotations) - annoExtractor := annotations.NewExtractor(ing.Annotations) - useRegex := annoExtractor.GetBoolAnnotation(annotations.AnnotationsPrefix + "use-regex") - enableWebsocket := annoExtractor.GetBoolAnnotation(annotations.AnnotationsPrefix + "enable-websocket") - pluginConfigName := annoExtractor.GetStringAnnotation(annotations.AnnotationsPrefix + "plugin-config-name") + ingress := t.TranslateAnnotations(ing.Annotations) // add https for _, tls := range ing.Spec.TLS { @@ -299,7 +290,7 @@ func (t *translator) translateIngressV1beta1(ing *networkingv1beta1.Ingress, ski prefix += "/*" } uris = append(uris, prefix) - } else if *pathRule.PathType == networkingv1beta1.PathTypeImplementationSpecific && useRegex { + } else if *pathRule.PathType == networkingv1beta1.PathTypeImplementationSpecific && ingress.UseRegex { nginxVars = append(nginxVars, kubev2.ApisixRouteHTTPMatchExpr{ Subject: kubev2.ApisixRouteHTTPMatchExprSubject{ Scope: apisixconst.ScopePath, @@ -315,7 +306,7 @@ func (t *translator) translateIngressV1beta1(ing *networkingv1beta1.Ingress, ski route.ID = id.GenID(route.Name) route.Host = rule.Host route.Uris = uris - route.EnableWebsocket = enableWebsocket + route.EnableWebsocket = ingress.EnableWebSocket if len(nginxVars) > 0 { routeVars, err := t.ApisixTranslator.TranslateRouteMatchExprs(nginxVars) if err != nil { @@ -324,12 +315,12 @@ func (t *translator) translateIngressV1beta1(ing *networkingv1beta1.Ingress, ski route.Vars = routeVars route.Priority = _regexPriority } - if len(plugins) > 0 { - route.Plugins = *(plugins.DeepCopy()) + if len(ingress.Plugins) > 0 { + route.Plugins = *(ingress.Plugins.DeepCopy()) } - if pluginConfigName != "" { - route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ing.Namespace, pluginConfigName)) + if ingress.PluginConfigName != "" { + route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ing.Namespace, ingress.PluginConfigName)) } if ups != nil { route.UpstreamId = ups.ID @@ -396,11 +387,7 @@ func (t *translator) translateUpstreamFromIngressV1(namespace string, backend *n func (t *translator) translateIngressExtensionsV1beta1(ing *extensionsv1beta1.Ingress, skipVerify bool) (*translation.TranslateContext, error) { ctx := translation.DefaultEmptyTranslateContext() - plugins := t.TranslateAnnotations(ing.Annotations) - annoExtractor := annotations.NewExtractor(ing.Annotations) - useRegex := annoExtractor.GetBoolAnnotation(annotations.AnnotationsPrefix + "use-regex") - enableWebsocket := annoExtractor.GetBoolAnnotation(annotations.AnnotationsPrefix + "enable-websocket") - pluginConfigName := annoExtractor.GetStringAnnotation(annotations.AnnotationsPrefix + "plugin-config-name") + ingress := t.TranslateAnnotations(ing.Annotations) for _, rule := range ing.Spec.Rules { for _, pathRule := range rule.HTTP.Paths { @@ -444,7 +431,7 @@ func (t *translator) translateIngressExtensionsV1beta1(ing *extensionsv1beta1.In prefix += "/*" } uris = append(uris, prefix) - } else if *pathRule.PathType == extensionsv1beta1.PathTypeImplementationSpecific && useRegex { + } else if *pathRule.PathType == extensionsv1beta1.PathTypeImplementationSpecific && ingress.UseRegex { nginxVars = append(nginxVars, kubev2.ApisixRouteHTTPMatchExpr{ Subject: kubev2.ApisixRouteHTTPMatchExprSubject{ Scope: apisixconst.ScopePath, @@ -460,7 +447,7 @@ func (t *translator) translateIngressExtensionsV1beta1(ing *extensionsv1beta1.In route.ID = id.GenID(route.Name) route.Host = rule.Host route.Uris = uris - route.EnableWebsocket = enableWebsocket + route.EnableWebsocket = ingress.EnableWebSocket if len(nginxVars) > 0 { routeVars, err := t.ApisixTranslator.TranslateRouteMatchExprs(nginxVars) if err != nil { @@ -469,12 +456,12 @@ func (t *translator) translateIngressExtensionsV1beta1(ing *extensionsv1beta1.In route.Vars = routeVars route.Priority = _regexPriority } - if len(plugins) > 0 { - route.Plugins = *(plugins.DeepCopy()) + if len(ingress.Plugins) > 0 { + route.Plugins = *(ingress.Plugins.DeepCopy()) } - if pluginConfigName != "" { - route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ing.Namespace, pluginConfigName)) + if ingress.PluginConfigName != "" { + route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ing.Namespace, ingress.PluginConfigName)) } if ups != nil { From d6f13521af3e89ed9f0408781953adfaeb537378 Mon Sep 17 00:00:00 2001 From: Jintao Zhang Date: Fri, 2 Sep 2022 17:30:01 +0800 Subject: [PATCH 20/30] fix: type assertion failed (#1314) --- pkg/providers/apisix/apisix_consumer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/providers/apisix/apisix_consumer.go b/pkg/providers/apisix/apisix_consumer.go index b2f94a19a0..95b31bf821 100644 --- a/pkg/providers/apisix/apisix_consumer.go +++ b/pkg/providers/apisix/apisix_consumer.go @@ -215,7 +215,7 @@ func (c *apisixConsumerController) handleSyncErr(obj interface{}, err error) { if k8serrors.IsNotFound(err) && event.Type != types.EventDelete { log.Infow("sync ApisixConsumer but not found, ignore", zap.String("event_type", event.Type.String()), - zap.String("ApisixConsumer", event.Object.(string)), + zap.Any("ApisixConsumer", event.Object.(kube.ApisixConsumerEvent)), ) c.workqueue.Forget(event) return From 848a78f494cf42b42858e1a42a3b89f1f2ae158b Mon Sep 17 00:00:00 2001 From: xiangtianyu Date: Fri, 2 Sep 2022 18:54:51 +0800 Subject: [PATCH 21/30] fix: ingress class not effect in resource sync logic (#1311) Co-authored-by: Sarasa Kisaragi Co-authored-by: Xin Rong <1324266492@qq.com> --- pkg/providers/ingress/ingress.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/providers/ingress/ingress.go b/pkg/providers/ingress/ingress.go index 689dd0b416..50381fb161 100644 --- a/pkg/providers/ingress/ingress.go +++ b/pkg/providers/ingress/ingress.go @@ -429,6 +429,12 @@ func (c *ingressController) ResourceSync() { continue } ing := kube.MustNewIngress(obj) + if !c.isIngressEffective(ing) { + return + } + log.Debugw("ingress add event arrived", + zap.Any("object", obj), + ) c.workqueue.Add(&types.Event{ Type: types.EventAdd, Object: kube.IngressEvent{ From 866d40f60eb5909ae9a4fb910f79f21bcd3ca7dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 10:43:21 +0800 Subject: [PATCH 22/30] chore(deps): bump github.com/onsi/ginkgo/v2 in /test/e2e (#1318) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.1.4 to 2.1.6. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.1.4...v2.1.6) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/go.mod | 2 +- test/e2e/go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 0e535df8a5..34ae88a364 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -9,7 +9,7 @@ require ( github.com/gavv/httpexpect/v2 v2.3.1 github.com/gorilla/websocket v1.5.0 github.com/gruntwork-io/terratest v0.40.20 - github.com/onsi/ginkgo/v2 v2.1.4 + github.com/onsi/ginkgo/v2 v2.1.6 github.com/stretchr/testify v1.8.0 k8s.io/api v0.24.4 k8s.io/apimachinery v0.24.4 diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 434467857c..ee709dd744 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -381,13 +381,13 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= From 94dbbed486897ca5ab3790808b779c9a394a1b46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 14:50:33 +0800 Subject: [PATCH 23/30] chore(deps): bump github.com/gruntwork-io/terratest in /test/e2e (#1319) --- test/e2e/go.mod | 2 +- test/e2e/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 34ae88a364..b095801e11 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -8,7 +8,7 @@ require ( github.com/eclipse/paho.mqtt.golang v1.4.1 github.com/gavv/httpexpect/v2 v2.3.1 github.com/gorilla/websocket v1.5.0 - github.com/gruntwork-io/terratest v0.40.20 + github.com/gruntwork-io/terratest v0.40.21 github.com/onsi/ginkgo/v2 v2.1.6 github.com/stretchr/testify v1.8.0 k8s.io/api v0.24.4 diff --git a/test/e2e/go.sum b/test/e2e/go.sum index ee709dd744..58ed983899 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -271,8 +271,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= -github.com/gruntwork-io/terratest v0.40.20 h1:pco6s3b62h2Yd13N+HvHQVTAk3aPRz4sdoVwErPCBzQ= -github.com/gruntwork-io/terratest v0.40.20/go.mod h1:JGeIGgLbxbG9/Oqm06z6YXVr76CfomdmLkV564qov+8= +github.com/gruntwork-io/terratest v0.40.21 h1:BYN/CamnMIHPFqE2Jh+XwaFT0RSZhnlBCOXeImxWrBQ= +github.com/gruntwork-io/terratest v0.40.21/go.mod h1:JGeIGgLbxbG9/Oqm06z6YXVr76CfomdmLkV564qov+8= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= From 5c0ea2b42138b0d0df59d85936d2b72feaa669c5 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Wed, 7 Sep 2022 18:22:25 +0800 Subject: [PATCH 24/30] feat: support update and delete of HTTPRoute (#1315) --- pkg/providers/gateway/gateway_httproute.go | 55 ++++++++++- test/e2e/scaffold/k8s.go | 8 +- test/e2e/suite-gateway/gateway_httproute.go | 92 ++++++++++++++++++- .../suite-plugins-other/mqtt-proxy.go | 1 + 4 files changed, 149 insertions(+), 7 deletions(-) diff --git a/pkg/providers/gateway/gateway_httproute.go b/pkg/providers/gateway/gateway_httproute.go index 92d060907d..f0a901e260 100644 --- a/pkg/providers/gateway/gateway_httproute.go +++ b/pkg/providers/gateway/gateway_httproute.go @@ -211,14 +211,63 @@ func (c *gatewayHTTPRouteController) onAdd(obj interface{}) { return } log.Debugw("gateway HTTPRoute add event arrived", + zap.String("key", key), zap.Any("object", obj), ) - log.Debugw("add HTTPRoute", zap.String("key", key)) c.workqueue.Add(&types.Event{ Type: types.EventAdd, Object: key, }) } -func (c *gatewayHTTPRouteController) onUpdate(oldObj, newObj interface{}) {} -func (c *gatewayHTTPRouteController) OnDelete(obj interface{}) {} + +func (c *gatewayHTTPRouteController) onUpdate(oldObj, newObj interface{}) { + oldHTTPRoute := oldObj.(*gatewayv1alpha2.HTTPRoute) + newHTTPRoute := newObj.(*gatewayv1alpha2.HTTPRoute) + if oldHTTPRoute.ResourceVersion >= newHTTPRoute.ResourceVersion { + return + } + key, err := cache.MetaNamespaceKeyFunc(oldObj) + if err != nil { + log.Errorw("found gateway HTTPRoute resource with bad meta namespace key", + zap.Error(err), + ) + return + } + if !c.controller.NamespaceProvider.IsWatchingNamespace(key) { + return + } + log.Debugw("Gateway HTTPRoute update event arrived", + zap.String("key", key), + zap.Any("old object", oldObj), + zap.Any("new object", newObj), + ) + + c.workqueue.Add(&types.Event{ + Type: types.EventUpdate, + Object: key, + }) +} + +func (c *gatewayHTTPRouteController) OnDelete(obj interface{}) { + key, err := cache.MetaNamespaceKeyFunc(obj) + if err != nil { + log.Errorw("found Gateway HTTPRoute resource with bad meta namespace key", + zap.Error(err), + ) + return + } + if !c.controller.NamespaceProvider.IsWatchingNamespace(key) { + return + } + log.Debugw("Gateway HTTPRoute delete event arrived", + zap.String("key", key), + zap.Any("object", obj), + ) + + c.workqueue.Add(&types.Event{ + Type: types.EventDelete, + Object: key, + Tombstone: obj, + }) +} diff --git a/test/e2e/scaffold/k8s.go b/test/e2e/scaffold/k8s.go index 23f16b76f2..947ad8dec9 100644 --- a/test/e2e/scaffold/k8s.go +++ b/test/e2e/scaffold/k8s.go @@ -121,9 +121,11 @@ func (s *Scaffold) CreateApisixRoute(name string, rules []ApisixRouteRule) { // CreateResourceFromString creates resource from a loaded yaml string. func (s *Scaffold) CreateResourceFromString(yaml string) error { - err := k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, yaml) - time.Sleep(5 * time.Second) - return err + return k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, yaml) +} + +func (s *Scaffold) DeleteResourceFromString(yaml string) error { + return k8s.KubectlDeleteFromStringE(s.t, s.kubectlOptions, yaml) } func (s *Scaffold) GetOutputFromString(shell ...string) (string, error) { diff --git a/test/e2e/suite-gateway/gateway_httproute.go b/test/e2e/suite-gateway/gateway_httproute.go index 9a1f1893a2..f69cf16c4b 100644 --- a/test/e2e/suite-gateway/gateway_httproute.go +++ b/test/e2e/suite-gateway/gateway_httproute.go @@ -107,7 +107,6 @@ spec: ginkgo.It("Basic HTTPRoute with 1 Hosts 1 Rule 2 Match 1 BackendRef", func() { backendSvc, backendPorts := s.DefaultHTTPBackend() - time.Sleep(time.Second * 15) route := fmt.Sprintf(` apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute @@ -146,4 +145,95 @@ spec: Expect(). Status(http.StatusNotFound) }) + + ginkgo.It("Update HTTPRoute", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + route := fmt.Sprintf(` +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: basic-http-route +spec: + hostnames: ["httpbin.org"] + rules: + - matches: + - path: + type: PathPrefix + value: /ip + backendRefs: + - name: %s + port: %d +`, backendSvc, backendPorts[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route), "creating HTTPRoute") + time.Sleep(time.Second * 6) + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixUpstreamsCreated(1), "Checking number of upstreams") + + route = fmt.Sprintf(` +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: basic-http-route +spec: + hostnames: ["httpbin.org"] + rules: + - matches: + - path: + type: PathPrefix + value: /get + backendRefs: + - name: %s + port: %d +`, backendSvc, backendPorts[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route), "update HTTPRoute") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes") + + time.Sleep(6 * time.Second) + + _ = s.NewAPISIXClient().GET("/get"). + WithHeader("Host", "httpbin.org"). + Expect(). + Status(http.StatusOK) + _ = s.NewAPISIXClient().GET("/ip"). + WithHeader("Host", "httpbin.org"). + Expect(). + Status(http.StatusNotFound) + }) + + ginkgo.It("Delete HTTPRoute", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + route := fmt.Sprintf(` +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: basic-http-route +spec: + hostnames: ["httpbin.org"] + rules: + - matches: + - path: + type: PathPrefix + value: /ip + backendRefs: + - name: %s + port: %d +`, backendSvc, backendPorts[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route), "creating HTTPRoute") + time.Sleep(time.Second * 6) + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixUpstreamsCreated(1), "Checking number of upstreams") + + _ = s.NewAPISIXClient().GET("/ip"). + WithHeader("Host", "httpbin.org"). + Expect(). + Status(http.StatusOK) + + assert.Nil(ginkgo.GinkgoT(), s.DeleteResourceFromString(route), "delete HTTPRoute") + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(0), "Checking number of routes") + + _ = s.NewAPISIXClient().GET("/ip"). + WithHeader("Host", "httpbin.org"). + Expect(). + Status(http.StatusNotFound) + }) }) diff --git a/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go b/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go index b906a280ef..e9e0844be0 100644 --- a/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go +++ b/test/e2e/suite-plugins/suite-plugins-other/mqtt-proxy.go @@ -81,6 +81,7 @@ spec: protocol: TCP `)) s.EnsureNumEndpointsReady(ginkgo.GinkgoT(), "mosquito", 1) + time.Sleep(30 * time.Second) // setup Apisix Route for mqtt proxy apisixRoute := ` apiVersion: apisix.apache.org/v2 From 9d663abec02f09ece4af9aa99713de3e878146f6 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Fri, 9 Sep 2022 22:43:46 +0800 Subject: [PATCH 25/30] fix: support resolveGranularity of ApisixRoute (#1251) --- pkg/apisix/apisix.go | 7 +- pkg/apisix/cache/memdb_test.go | 6 +- pkg/apisix/nonexistentclient.go | 4 +- pkg/apisix/resource_test.go | 7 +- pkg/apisix/upstream.go | 7 +- pkg/apisix/upstreamservicerelation.go | 101 +++++---- pkg/apisix/upstreamservicerelation_test.go | 197 ++++++++++++++++++ pkg/providers/apisix/apisix_upstream.go | 89 ++++---- .../apisix/translation/apisix_plugin_test.go | 4 +- .../apisix/translation/apisix_route.go | 24 +-- .../apisix/translation/apisix_upstream.go | 9 +- .../gateway/translation/gateway_httproute.go | 3 +- .../gateway/translation/gateway_tlsroute.go | 3 +- .../ingress/translation/translator.go | 9 +- pkg/providers/k8s/endpoint/base.go | 28 ++- pkg/providers/k8s/endpoint/endpoint.go | 17 +- pkg/providers/k8s/endpoint/endpointslice.go | 72 +++---- pkg/types/apisix/v1/types.go | 26 ++- pkg/types/apisix/v1/zz_generated.deepcopy.go | 7 + pkg/types/service.go | 25 +++ test/e2e/suite-chore/resolvegranularity.go | 127 +++++++++++ 21 files changed, 569 insertions(+), 203 deletions(-) create mode 100644 pkg/apisix/upstreamservicerelation_test.go create mode 100644 pkg/types/service.go create mode 100644 test/e2e/suite-chore/resolvegranularity.go diff --git a/pkg/apisix/apisix.go b/pkg/apisix/apisix.go index 23f3e1b2ba..e4ca42e059 100644 --- a/pkg/apisix/apisix.go +++ b/pkg/apisix/apisix.go @@ -153,10 +153,13 @@ type PluginConfig interface { } type UpstreamServiceRelation interface { + // Get relation based on namespace+"_"+service.name Get(context.Context, string) (*v1.UpstreamServiceRelation, error) List(context.Context) ([]*v1.UpstreamServiceRelation, error) - Delete(context.Context, *v1.UpstreamServiceRelation) error - Create(context.Context, *v1.UpstreamServiceRelation) error + // Delete relation based on namespace+"_"+service.name + Delete(context.Context, string) error + // Build relation based on upstream.name + Create(context.Context, string) error } type apisix struct { diff --git a/pkg/apisix/cache/memdb_test.go b/pkg/apisix/cache/memdb_test.go index 79d9cbd3dc..8181f75839 100644 --- a/pkg/apisix/cache/memdb_test.go +++ b/pkg/apisix/cache/memdb_test.go @@ -486,8 +486,10 @@ func TestMemDBCacheUpstreamServiceRelation(t *testing.T) { assert.Equal(t, us2, us) us3 := &v1.UpstreamServiceRelation{ - ServiceName: "httpbin", - UpstreamName: "upstream", + ServiceName: "httpbin", + UpstreamNames: map[string]struct{}{ + "upstream": {}, + }, } assert.Nil(t, c.InsertUpstreamServiceRelation(us3), "inserting upstream_service 3") diff --git a/pkg/apisix/nonexistentclient.go b/pkg/apisix/nonexistentclient.go index 7ca3da46f8..37c9b90da7 100644 --- a/pkg/apisix/nonexistentclient.go +++ b/pkg/apisix/nonexistentclient.go @@ -248,13 +248,13 @@ type dummyUpstreamServiceRelation struct { func (f *dummyUpstreamServiceRelation) Get(_ context.Context, _ string) (*v1.UpstreamServiceRelation, error) { return nil, ErrClusterNotExist } -func (f *dummyUpstreamServiceRelation) Create(_ context.Context, _ *v1.UpstreamServiceRelation) error { +func (f *dummyUpstreamServiceRelation) Create(_ context.Context, _ string) error { return ErrClusterNotExist } func (f *dummyUpstreamServiceRelation) List(_ context.Context) ([]*v1.UpstreamServiceRelation, error) { return nil, ErrClusterNotExist } -func (f *dummyUpstreamServiceRelation) Delete(_ context.Context, _ *v1.UpstreamServiceRelation) error { +func (f *dummyUpstreamServiceRelation) Delete(_ context.Context, _ string) error { return ErrClusterNotExist } diff --git a/pkg/apisix/resource_test.go b/pkg/apisix/resource_test.go index 528f801dae..5b4c6c18f0 100644 --- a/pkg/apisix/resource_test.go +++ b/pkg/apisix/resource_test.go @@ -86,8 +86,11 @@ func TestItemConvertUpstream(t *testing.T) { ups, err := ite.upstream() assert.Nil(t, err) assert.Len(t, ups.Nodes, 2) - assert.Equal(t, ups.Nodes[0], v1.UpstreamNode{Host: "httpbin.org", Port: 80, Weight: 1}) - assert.Equal(t, ups.Nodes[1], v1.UpstreamNode{Host: "foo.com", Port: 8080, Weight: 2}) + if ups.Nodes[0].Host == "foo.com" { + ups.Nodes[0], ups.Nodes[1] = ups.Nodes[1], ups.Nodes[0] + } + assert.Equal(t, v1.UpstreamNode{Host: "httpbin.org", Port: 80, Weight: 1}, ups.Nodes[0]) + assert.Equal(t, v1.UpstreamNode{Host: "foo.com", Port: 8080, Weight: 2}, ups.Nodes[1]) ite = &item{ Key: "/apisix/upstreams/419655639963271872", diff --git a/pkg/apisix/upstream.go b/pkg/apisix/upstream.go index d50110fe36..4405fbd463 100644 --- a/pkg/apisix/upstream.go +++ b/pkg/apisix/upstream.go @@ -139,7 +139,7 @@ func (u *upstreamClient) Create(ctx context.Context, obj *v1.Upstream) (*v1.Upst zap.String("cluster", "default"), ) - if err := u.cluster.upstreamServiceRelation.Create(ctx, &v1.UpstreamServiceRelation{UpstreamName: obj.Name}); err != nil { + if err := u.cluster.upstreamServiceRelation.Create(ctx, obj.Name); err != nil { log.Errorf("failed to reflect upstreamService create to cache: %s", err) } if err := u.cluster.HasSynced(ctx); err != nil { @@ -187,9 +187,6 @@ func (u *upstreamClient) Delete(ctx context.Context, obj *v1.Upstream) error { return err } } - if err := u.cluster.upstreamServiceRelation.Delete(ctx, &v1.UpstreamServiceRelation{UpstreamName: obj.Name}); err != nil { - log.Errorf("failed to delete upstreamService in cache: %s", err) - } url := u.url + "/" + obj.ID if err := u.cluster.deleteResource(ctx, url, "upstream"); err != nil { u.cluster.metricsCollector.IncrAPISIXRequest("upstream") @@ -207,7 +204,7 @@ func (u *upstreamClient) Update(ctx context.Context, obj *v1.Upstream) (*v1.Upst zap.String("url", u.url), ) - if err := u.cluster.upstreamServiceRelation.Create(ctx, &v1.UpstreamServiceRelation{UpstreamName: obj.Name}); err != nil { + if err := u.cluster.upstreamServiceRelation.Create(ctx, obj.Name); err != nil { log.Errorf("failed to reflect upstreamService create to cache: %s", err) } if err := u.cluster.HasSynced(ctx); err != nil { diff --git a/pkg/apisix/upstreamservicerelation.go b/pkg/apisix/upstreamservicerelation.go index 3ebe1d0cfb..9b026c7f4d 100644 --- a/pkg/apisix/upstreamservicerelation.go +++ b/pkg/apisix/upstreamservicerelation.go @@ -17,6 +17,7 @@ package apisix import ( "context" "fmt" + "strconv" "strings" "go.uber.org/zap" @@ -26,6 +27,11 @@ import ( v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) +// to do: Delete one of the upstreams. Currently, only service is deleted. There will be some +// redundant upstream objects, but the results will not be affected. It is hoped that the service controller +// can complete the update nodes logic to avoid the intrusion of relation modules into more code. + +// Maintain relationships only when resolveGranularity is endpoint // There is no need to ensure the consistency between the upstream to services, only need to ensure that the upstream-node can be delete after deleting the service type upstreamService struct { cluster *cluster @@ -37,79 +43,78 @@ func newUpstreamServiceRelation(c *cluster) *upstreamService { } } -func (u *upstreamService) Get(ctx context.Context, svcId string) (*v1.UpstreamServiceRelation, error) { +func (u *upstreamService) Get(ctx context.Context, serviceName string) (*v1.UpstreamServiceRelation, error) { log.Debugw("try to get upstreamService in cache", - zap.String("svcId", svcId), + zap.String("service_name", serviceName), zap.String("cluster", "default"), ) - us, err := u.cluster.cache.GetUpstreamServiceRelation(svcId) - if err == nil { - return us, nil - } - if err != cache.ErrNotFound { + us, err := u.cluster.cache.GetUpstreamServiceRelation(serviceName) + if err != nil && err != cache.ErrNotFound { log.Error("failed to find upstreamService in cache", - zap.String("svcId", svcId), zap.Error(err)) - } else { - log.Debugw("failed to find upstreamService in cache", - zap.String("svcId", svcId), zap.Error(err)) + zap.String("service_name", serviceName), zap.Error(err)) + return nil, err } - return nil, err + return us, err } -func (u *upstreamService) Delete(ctx context.Context, relation *v1.UpstreamServiceRelation) error { +func (u *upstreamService) Delete(ctx context.Context, serviceName string) error { log.Debugw("try to delete upstreamService in cache", zap.String("cluster", "default"), ) - u.initUpstreamServiceRelation(relation) - if relation == nil || relation.ServiceName == "" && relation.UpstreamName == "" { - return fmt.Errorf("UpstreamServiceRelation is empty object") - } - if relation.UpstreamName != "" { - err := u.cluster.cache.DeleteUpstreamServiceRelation(relation) - if err != nil { - return err - } - } else { - usr, err := u.cluster.cache.GetUpstreamServiceRelation(relation.ServiceName) - if err != nil { - return err + relation, err := u.Get(ctx, serviceName) + if err != nil { + if err == cache.ErrNotFound { + return nil } - ups, err := u.cluster.upstream.Get(ctx, usr.UpstreamName) + return err + } + _ = u.cluster.cache.DeleteUpstreamServiceRelation(relation) + for upsName := range relation.UpstreamNames { + ups, err := u.cluster.upstream.Get(ctx, upsName) if err != nil { - return err + continue } ups.Nodes = make(v1.UpstreamNodes, 0) _, err = u.cluster.upstream.Update(ctx, ups) if err != nil { - return err - } - err = u.cluster.cache.DeleteUpstreamServiceRelation(usr) - if err != nil { - return err + continue } } return nil } -func (u *upstreamService) Create(ctx context.Context, relation *v1.UpstreamServiceRelation) error { +func (u *upstreamService) Create(ctx context.Context, upstreamName string) error { log.Debugw("try to create upstreamService in cache", zap.String("cluster", "default"), ) - u.initUpstreamServiceRelation(relation) - if relation == nil || relation.ServiceName == "" || relation.UpstreamName == "" { - log.Error("UpstreamServiceRelation object ") + + args := strings.Split(upstreamName, "_") + if len(args) < 2 { + return fmt.Errorf("wrong upstream name %s, must contains namespace_name", upstreamName) + } + // The last part of upstreanName should be a port number. + // Please refer to apisixv1.ComposeUpstreamName to see the detailed format. + _, err := strconv.Atoi(args[len(args)-1]) + if err != nil { return nil } - us, err := u.cluster.cache.GetUpstreamServiceRelation(relation.ServiceName) + + serviceName := args[0] + "_" + args[1] + relation, err := u.Get(ctx, serviceName) if err != nil && err != cache.ErrNotFound { return err } - if us != nil { - us.UpstreamName = relation.UpstreamName + if relation == nil { + relation = &v1.UpstreamServiceRelation{ + ServiceName: serviceName, + UpstreamNames: map[string]struct{}{ + upstreamName: {}, + }, + } } else { - us = relation + relation.UpstreamNames[upstreamName] = struct{}{} } - if err := u.cluster.cache.InsertUpstreamServiceRelation(us); err != nil { + if err := u.cluster.cache.InsertUpstreamServiceRelation(relation); err != nil { log.Errorf("failed to reflect upstreamService create to cache: %s", err) return err } @@ -129,15 +134,3 @@ func (u *upstreamService) List(ctx context.Context) ([]*v1.UpstreamServiceRelati } return usrs, nil } - -func (u *upstreamService) initUpstreamServiceRelation(us *v1.UpstreamServiceRelation) { - if us.UpstreamName == "" || us.ServiceName != "" { - return - } - args := strings.Split(us.UpstreamName, "_") - // namespace_service_subset_port - if len(args) < 2 { - return - } - us.ServiceName = args[0] + "_" + args[1] -} diff --git a/pkg/apisix/upstreamservicerelation_test.go b/pkg/apisix/upstreamservicerelation_test.go new file mode 100644 index 0000000000..dce71f1b99 --- /dev/null +++ b/pkg/apisix/upstreamservicerelation_test.go @@ -0,0 +1,197 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package apisix + +import ( + "context" + "net/http" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/apache/apisix-ingress-controller/pkg/apisix/cache" + "github.com/apache/apisix-ingress-controller/pkg/metrics" + v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" +) + +func TestUpstreamServiceRelation(t *testing.T) { + u := url.URL{} + closedCh := make(chan struct{}) + close(closedCh) + cache, err := cache.NewMemDBCache() + assert.Nil(t, err) + cli := newUpstreamServiceRelation(&cluster{ + baseURL: u.String(), + cli: http.DefaultClient, + cache: cache, + cacheSynced: closedCh, + metricsCollector: metrics.NewPrometheusCollector(), + upstream: &dummyUpstream{}, + }) + + upsName := "default_httpbin_80" + upsName2 := "default_httpbin_8080" + svcName := "default_httpbin" + + err = cli.Create(context.TODO(), upsName) + assert.Nil(t, err) + + relation, err := cli.Get(context.TODO(), svcName) + assert.Nil(t, err) + assert.NotNil(t, relation) + assert.Equal(t, &v1.UpstreamServiceRelation{ + ServiceName: svcName, + UpstreamNames: map[string]struct{}{ + upsName: {}, + }, + }, relation) + + err = cli.Create(context.TODO(), upsName2) + assert.Nil(t, err) + + relation, err = cli.Get(context.TODO(), svcName) + assert.Nil(t, err) + assert.NotNil(t, relation) + assert.Equal(t, &v1.UpstreamServiceRelation{ + ServiceName: svcName, + UpstreamNames: map[string]struct{}{ + upsName: {}, + upsName2: {}, + }, + }, relation) + + relations, err := cli.List(context.TODO()) + assert.Nil(t, err) + assert.Len(t, relations, 1) + assert.Equal(t, &v1.UpstreamServiceRelation{ + ServiceName: svcName, + UpstreamNames: map[string]struct{}{ + upsName: {}, + upsName2: {}, + }, + }, relations[0]) + + err = cli.Delete(context.TODO(), svcName) + assert.Nil(t, err) + relations, err = cli.List(context.TODO()) + assert.Nil(t, err) + assert.Len(t, relations, 0) +} + +func TestUpstreamRelatoinClient(t *testing.T) { + srv := runFakeUpstreamSrv(t) + defer func() { + assert.Nil(t, srv.Shutdown(context.Background())) + }() + + cache, err := cache.NewMemDBCache() + assert.Nil(t, err) + u := url.URL{ + Scheme: "http", + Host: srv.Addr, + Path: "/apisix/admin", + } + closedCh := make(chan struct{}) + clu := &cluster{ + baseURL: u.String(), + cli: http.DefaultClient, + cache: cache, + cacheSynced: closedCh, + metricsCollector: metrics.NewPrometheusCollector(), + } + close(closedCh) + relationCli := newUpstreamServiceRelation(clu) + clu.upstreamServiceRelation = relationCli + cli := newUpstreamClient(clu) + clu.upstream = cli + relationCli.cluster = clu + + // Create + key := "upstreams/abc" + lbType := "roundrobin" + upsName := "default_httpbin_80" + upsName2 := "default_httpbin_8080" + svcName := "default_httpbin" + ip := "10.0.11.153" + port := 15006 + weight := 100 + nodes := v1.UpstreamNodes{ + { + Host: ip, + Port: port, + Weight: weight, + }, + } + + obj, err := cli.Create(context.TODO(), &v1.Upstream{ + Metadata: v1.Metadata{ + ID: "1", + Name: upsName, + }, + Type: lbType, + Key: key, + Nodes: nodes, + }) + assert.Nil(t, err) + assert.Equal(t, "1", obj.ID) + relations, err := relationCli.List(context.TODO()) + assert.Nil(t, err) + assert.Len(t, relations, 1) + assert.Equal(t, &v1.UpstreamServiceRelation{ + ServiceName: svcName, + UpstreamNames: map[string]struct{}{ + upsName: {}, + }, + }, relations[0]) + + id2 := "2" + obj, err = cli.Create(context.TODO(), &v1.Upstream{ + Metadata: v1.Metadata{ + ID: id2, + Name: upsName2, + }, + Type: lbType, + Key: key, + Nodes: nodes, + }) + assert.Nil(t, err) + assert.Equal(t, "2", obj.ID) + + // List + objs, err := cli.List(context.Background()) + assert.Nil(t, err) + assert.Len(t, objs, 2) + assert.Equal(t, "1", objs[0].ID) + assert.Equal(t, "2", objs[1].ID) + relations, err = relationCli.List(context.Background()) + assert.Nil(t, err) + assert.Len(t, relations, 1) + assert.Equal(t, &v1.UpstreamServiceRelation{ + ServiceName: svcName, + UpstreamNames: map[string]struct{}{ + upsName: {}, + upsName2: {}, + }, + }, relations[0]) + + err = relationCli.Delete(context.Background(), svcName) + assert.Nil(t, err) + objs, err = clu.Upstream().List(context.Background()) + assert.Nil(t, err) + assert.Len(t, objs, 2) + assert.Equal(t, "1", objs[0].ID) + assert.Equal(t, "2", objs[1].ID) +} diff --git a/pkg/providers/apisix/apisix_upstream.go b/pkg/providers/apisix/apisix_upstream.go index 92b091ec87..b30c3430e0 100644 --- a/pkg/providers/apisix/apisix_upstream.go +++ b/pkg/providers/apisix/apisix_upstream.go @@ -182,7 +182,7 @@ func (c *apisixUpstreamController) sync(ctx context.Context, ev *types.Event) er clusterName := c.Config.APISIX.DefaultClusterName for _, port := range svc.Spec.Ports { for _, subset := range subsets { - upsName := apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port) + upsName := apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port, "") // TODO: multiple cluster ups, err := c.APISIX.Cluster(clusterName).Upstream().Get(ctx, upsName) if err != nil { @@ -266,55 +266,66 @@ func (c *apisixUpstreamController) sync(ctx context.Context, ev *types.Event) er clusterName := c.Config.APISIX.DefaultClusterName for _, port := range svc.Spec.Ports { for _, subset := range subsets { - upsName := apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port) // TODO: multiple cluster - ups, err := c.APISIX.Cluster(clusterName).Upstream().Get(ctx, upsName) - if err != nil { - if err == apisixcache.ErrNotFound { - continue + update := func(upsName string) error { + ups, err := c.APISIX.Cluster(clusterName).Upstream().Get(ctx, upsName) + if err != nil { + if err == apisixcache.ErrNotFound { + return nil + } + log.Errorf("failed to get upstream %s: %s", upsName, err) + c.RecordEvent(au, corev1.EventTypeWarning, utils.ResourceSyncAborted, err) + c.recordStatus(au, utils.ResourceSyncAborted, err, metav1.ConditionFalse, au.GetGeneration()) + return err } - log.Errorf("failed to get upstream %s: %s", upsName, err) - c.RecordEvent(au, corev1.EventTypeWarning, utils.ResourceSyncAborted, err) - c.recordStatus(au, utils.ResourceSyncAborted, err, metav1.ConditionFalse, au.GetGeneration()) - return err - } - var newUps *apisixv1.Upstream - if au.Spec != nil && ev.Type != types.EventDelete { - cfg, ok := portLevelSettings[port.Port] - if !ok { - cfg = &au.Spec.ApisixUpstreamConfig + var newUps *apisixv1.Upstream + if au.Spec != nil && ev.Type != types.EventDelete { + cfg, ok := portLevelSettings[port.Port] + if !ok { + cfg = &au.Spec.ApisixUpstreamConfig + } + // FIXME Same ApisixUpstreamConfig might be translated multiple times. + newUps, err = c.translator.TranslateUpstreamConfigV2(cfg) + if err != nil { + log.Errorw("ApisixUpstream conversion cannot be completed, or the format is incorrect", + zap.Any("object", au), + zap.Error(err), + ) + c.RecordEvent(au, corev1.EventTypeWarning, utils.ResourceSyncAborted, err) + c.recordStatus(au, utils.ResourceSyncAborted, err, metav1.ConditionFalse, au.GetGeneration()) + return err + } + } else { + newUps = apisixv1.NewDefaultUpstream() } - // FIXME Same ApisixUpstreamConfig might be translated multiple times. - newUps, err = c.translator.TranslateUpstreamConfigV2(cfg) - if err != nil { - log.Errorw("found malformed ApisixUpstream", - zap.Any("object", au), + + newUps.Metadata = ups.Metadata + newUps.Nodes = ups.Nodes + log.Debugw("updating upstream since ApisixUpstream changed", + zap.String("event", ev.Type.String()), + zap.Any("upstream", newUps), + zap.Any("ApisixUpstream", au), + ) + if _, err := c.APISIX.Cluster(clusterName).Upstream().Update(ctx, newUps); err != nil { + log.Errorw("failed to update upstream", zap.Error(err), + zap.Any("upstream", newUps), + zap.Any("ApisixUpstream", au), + zap.String("cluster", clusterName), ) c.RecordEvent(au, corev1.EventTypeWarning, utils.ResourceSyncAborted, err) c.recordStatus(au, utils.ResourceSyncAborted, err, metav1.ConditionFalse, au.GetGeneration()) return err } - } else { - newUps = apisixv1.NewDefaultUpstream() + return nil } - newUps.Metadata = ups.Metadata - newUps.Nodes = ups.Nodes - log.Debugw("updating upstream since ApisixUpstream changed", - zap.String("event", ev.Type.String()), - zap.Any("upstream", newUps), - zap.Any("ApisixUpstream", au), - ) - if _, err := c.APISIX.Cluster(clusterName).Upstream().Update(ctx, newUps); err != nil { - log.Errorw("failed to update upstream", - zap.Error(err), - zap.Any("upstream", newUps), - zap.Any("ApisixUpstream", au), - zap.String("cluster", clusterName), - ) - c.RecordEvent(au, corev1.EventTypeWarning, utils.ResourceSyncAborted, err) - c.recordStatus(au, utils.ResourceSyncAborted, err, metav1.ConditionFalse, au.GetGeneration()) + err := update(apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port, types.ResolveGranularity.Endpoint)) + if err != nil { + return err + } + err = update(apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port, types.ResolveGranularity.Service)) + if err != nil { return err } } diff --git a/pkg/providers/apisix/translation/apisix_plugin_test.go b/pkg/providers/apisix/translation/apisix_plugin_test.go index 2c0b224cf6..907c72f98a 100644 --- a/pkg/providers/apisix/translation/apisix_plugin_test.go +++ b/pkg/providers/apisix/translation/apisix_plugin_test.go @@ -198,7 +198,7 @@ func TestTranslateTrafficSplitPlugin(t *testing.T) { assert.Equal(t, "192.168.1.2", ctx.Upstreams[0].Nodes[1].Host) assert.Equal(t, 9080, ctx.Upstreams[0].Nodes[1].Port) - assert.Equal(t, "test_svc-1_443", ctx.Upstreams[1].Name) + assert.Equal(t, "test_svc-1_443_service", ctx.Upstreams[1].Name) assert.Len(t, ctx.Upstreams[1].Nodes, 1) assert.Equal(t, "10.0.5.3", ctx.Upstreams[1].Nodes[0].Host) assert.Equal(t, 443, ctx.Upstreams[1].Nodes[0].Port) @@ -207,7 +207,7 @@ func TestTranslateTrafficSplitPlugin(t *testing.T) { assert.Len(t, cfg.Rules[0].WeightedUpstreams, 3) assert.Equal(t, id.GenID("test_svc-1_80"), cfg.Rules[0].WeightedUpstreams[0].UpstreamID) assert.Equal(t, 10, cfg.Rules[0].WeightedUpstreams[0].Weight) - assert.Equal(t, id.GenID("test_svc-1_443"), cfg.Rules[0].WeightedUpstreams[1].UpstreamID) + assert.Equal(t, id.GenID("test_svc-1_443_service"), cfg.Rules[0].WeightedUpstreams[1].UpstreamID) assert.Equal(t, 20, cfg.Rules[0].WeightedUpstreams[1].Weight) assert.Equal(t, "", cfg.Rules[0].WeightedUpstreams[2].UpstreamID) assert.Equal(t, 30, cfg.Rules[0].WeightedUpstreams[2].Weight) diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go index f91ea1289e..40531158b4 100644 --- a/pkg/providers/apisix/translation/apisix_route.go +++ b/pkg/providers/apisix/translation/apisix_route.go @@ -175,7 +175,7 @@ func (t *translator) translateHTTPRouteV2beta2(ctx *translation.TranslateContext return err } - upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, svcPort) + upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, svcPort, backend.ResolveGranularity) route := apisixv1.NewDefaultRoute() route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name) route.ID = id.GenID(route.Name) @@ -309,7 +309,7 @@ func (t *translator) translateHTTPRouteV2beta3(ctx *translation.TranslateContext return err } - upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, svcPort) + upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, svcPort, backend.ResolveGranularity) route := apisixv1.NewDefaultRoute() route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name) route.ID = id.GenID(route.Name) @@ -445,7 +445,7 @@ func (t *translator) translateHTTPRouteV2(ctx *translation.TranslateContext, ar return err } - upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, svcPort) + upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, svcPort, backend.ResolveGranularity) route := apisixv1.NewDefaultRoute() route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name) route.ID = id.GenID(route.Name) @@ -597,13 +597,13 @@ func (t *translator) translateHTTPRouteV2beta2NotStrictly(ctx *translation.Trans // Use the first backend as the default backend in Route, // others will be configured in traffic-split plugin. backend := backends[0] - upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) route := apisixv1.NewDefaultRoute() route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name) route.ID = id.GenID(route.Name) ctx.AddRoute(route) if !ctx.CheckUpstreamExist(upstreamName) { - ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err } @@ -652,7 +652,7 @@ func (t *translator) translateHTTPRouteV2beta3NotStrictly(ctx *translation.Trans } } - upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) route := apisixv1.NewDefaultRoute() route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name) route.ID = id.GenID(route.Name) @@ -662,7 +662,7 @@ func (t *translator) translateHTTPRouteV2beta3NotStrictly(ctx *translation.Trans ctx.AddRoute(route) if !ctx.CheckUpstreamExist(upstreamName) { - ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err } @@ -711,7 +711,7 @@ func (t *translator) translateHTTPRouteV2NotStrictly(ctx *translation.TranslateC } } - upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) route := apisixv1.NewDefaultRoute() route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name) route.ID = id.GenID(route.Name) @@ -721,7 +721,7 @@ func (t *translator) translateHTTPRouteV2NotStrictly(ctx *translation.TranslateC ctx.AddRoute(route) if !ctx.CheckUpstreamExist(upstreamName) { - ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err } @@ -859,7 +859,7 @@ func (t *translator) translateStreamRouteNotStrictlyV2beta2(ctx *translation.Tra name := apisixv1.ComposeStreamRouteName(ar.Namespace, ar.Name, part.Name) sr.ID = id.GenID(name) sr.ServerPort = part.Match.IngressPort - ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err } @@ -880,7 +880,7 @@ func (t *translator) translateStreamRouteNotStrictlyV2beta3(ctx *translation.Tra name := apisixv1.ComposeStreamRouteName(ar.Namespace, ar.Name, part.Name) sr.ID = id.GenID(name) sr.ServerPort = part.Match.IngressPort - ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err } @@ -901,7 +901,7 @@ func (t *translator) translateStreamRouteNotStrictlyV2(ctx *translation.Translat name := apisixv1.ComposeStreamRouteName(ar.Namespace, ar.Name, part.Name) sr.ID = id.GenID(name) sr.ServerPort = part.Match.IngressPort - ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal) + ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err } diff --git a/pkg/providers/apisix/translation/apisix_upstream.go b/pkg/providers/apisix/translation/apisix_upstream.go index ac1e901b5d..d0052c5d14 100644 --- a/pkg/providers/apisix/translation/apisix_upstream.go +++ b/pkg/providers/apisix/translation/apisix_upstream.go @@ -17,13 +17,14 @@ package translation import ( "github.com/apache/apisix-ingress-controller/pkg/id" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" + "github.com/apache/apisix-ingress-controller/pkg/types" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) // translateUpstreamNotStrictly translates Upstream nodes with a loose way, only generate ID and Name for delete Event. -func (t *translator) translateUpstreamNotStrictly(namespace, svcName, subset string, svcPort int32) (*apisixv1.Upstream, error) { +func (t *translator) translateUpstreamNotStrictly(namespace, svcName, subset string, svcPort int32, resolveGranularity string) (*apisixv1.Upstream, error) { ups := &apisixv1.Upstream{} - ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, subset, svcPort) + ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, subset, svcPort, resolveGranularity) ups.ID = id.GenID(ups.Name) return ups, nil } @@ -33,7 +34,7 @@ func (t *translator) translateService(namespace, svcName, subset, svcResolveGran if err != nil { return nil, err } - if svcResolveGranularity == "service" { + if svcResolveGranularity == types.ResolveGranularity.Service { ups.Nodes = apisixv1.UpstreamNodes{ { Host: svcClusterIP, @@ -42,7 +43,7 @@ func (t *translator) translateService(namespace, svcName, subset, svcResolveGran }, } } - ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, subset, svcPort) + ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, subset, svcPort, svcResolveGranularity) ups.ID = id.GenID(ups.Name) return ups, nil } diff --git a/pkg/providers/gateway/translation/gateway_httproute.go b/pkg/providers/gateway/translation/gateway_httproute.go index e1eaa657cf..68006f60a3 100644 --- a/pkg/providers/gateway/translation/gateway_httproute.go +++ b/pkg/providers/gateway/translation/gateway_httproute.go @@ -29,6 +29,7 @@ import ( "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" "github.com/apache/apisix-ingress-controller/pkg/providers/utils" + "github.com/apache/apisix-ingress-controller/pkg/types" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -96,7 +97,7 @@ func (t *translator) TranslateGatewayHTTPRouteV1Alpha2(httpRoute *gatewayv1alpha if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("failed to translate Rules[%v].BackendRefs[%v]", i, j)) } - name := apisixv1.ComposeUpstreamName(ns, string(backend.Name), "", int32(*backend.Port)) + name := apisixv1.ComposeUpstreamName(ns, string(backend.Name), "", int32(*backend.Port), types.ResolveGranularity.Endpoint) // APISIX limits max length of label value // https://github.com/apache/apisix/blob/5b95b85faea3094d5e466ee2d39a52f1f805abbb/apisix/schema_def.lua#L85 diff --git a/pkg/providers/gateway/translation/gateway_tlsroute.go b/pkg/providers/gateway/translation/gateway_tlsroute.go index 138cc40c2e..4af2c6a29e 100644 --- a/pkg/providers/gateway/translation/gateway_tlsroute.go +++ b/pkg/providers/gateway/translation/gateway_tlsroute.go @@ -29,6 +29,7 @@ import ( "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" "github.com/apache/apisix-ingress-controller/pkg/providers/utils" + "github.com/apache/apisix-ingress-controller/pkg/types" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -90,7 +91,7 @@ func (t *translator) TranslateGatewayTLSRouteV1Alpha2(tlsRoute *gatewayv1alpha2. if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("failed to translate Rules[%v].BackendRefs[%v]", i, j)) } - name := apisixv1.ComposeUpstreamName(ns, string(backend.Name), "", int32(*backend.Port)) + name := apisixv1.ComposeUpstreamName(ns, string(backend.Name), "", int32(*backend.Port), types.ResolveGranularity.Endpoint) ups.Labels["meta_namespace"] = utils.TruncateString(ns, 64) ups.Labels["meta_backend"] = utils.TruncateString(string(backend.Name), 64) diff --git a/pkg/providers/ingress/translation/translator.go b/pkg/providers/ingress/translation/translator.go index 5a7712a991..025df60722 100644 --- a/pkg/providers/ingress/translation/translator.go +++ b/pkg/providers/ingress/translation/translator.go @@ -41,6 +41,7 @@ import ( "github.com/apache/apisix-ingress-controller/pkg/log" apisixtranslation "github.com/apache/apisix-ingress-controller/pkg/providers/apisix/translation" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" + "github.com/apache/apisix-ingress-controller/pkg/types" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -350,7 +351,7 @@ func (t *translator) translateDefaultUpstreamFromIngressV1(namespace string, bac portNumber = backend.Port.Number } ups := apisixv1.NewDefaultUpstream() - ups.Name = apisixv1.ComposeUpstreamName(namespace, backend.Name, "", portNumber) + ups.Name = apisixv1.ComposeUpstreamName(namespace, backend.Name, "", portNumber, types.ResolveGranularity.Endpoint) ups.ID = id.GenID(ups.Name) return ups } @@ -380,7 +381,7 @@ func (t *translator) translateUpstreamFromIngressV1(namespace string, backend *n if err != nil { return nil, err } - ups.Name = apisixv1.ComposeUpstreamName(namespace, backend.Name, "", svcPort) + ups.Name = apisixv1.ComposeUpstreamName(namespace, backend.Name, "", svcPort, types.ResolveGranularity.Endpoint) ups.ID = id.GenID(ups.Name) return ups, nil } @@ -491,7 +492,7 @@ func (t *translator) translateDefaultUpstreamFromIngressV1beta1(namespace string portNumber = svcPort.IntVal } ups := apisixv1.NewDefaultUpstream() - ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, "", portNumber) + ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, "", portNumber, types.ResolveGranularity.Endpoint) ups.ID = id.GenID(ups.Name) return ups } @@ -522,7 +523,7 @@ func (t *translator) translateUpstreamFromIngressV1beta1(namespace string, svcNa if err != nil { return nil, err } - ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, "", portNumber) + ups.Name = apisixv1.ComposeUpstreamName(namespace, svcName, "", portNumber, types.ResolveGranularity.Endpoint) ups.ID = id.GenID(ups.Name) return ups, nil } diff --git a/pkg/providers/k8s/endpoint/base.go b/pkg/providers/k8s/endpoint/base.go index ac67aa870a..7f6af9a648 100644 --- a/pkg/providers/k8s/endpoint/base.go +++ b/pkg/providers/k8s/endpoint/base.go @@ -32,6 +32,7 @@ import ( "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/translation" providertypes "github.com/apache/apisix-ingress-controller/pkg/providers/types" + "github.com/apache/apisix-ingress-controller/pkg/types" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -56,8 +57,7 @@ func (c *baseEndpointController) syncEndpoint(ctx context.Context, ep kube.Endpo svc, err := c.svcLister.Services(namespace).Get(svcName) if err != nil { if k8serrors.IsNotFound(err) { - log.Infof("service %s/%s not found", namespace, svcName) - return nil + return c.syncEmptyEndpoint(ctx, ep) } log.Errorf("failed to get service %s/%s: %s", namespace, svcName, err) return err @@ -87,7 +87,7 @@ func (c *baseEndpointController) syncEndpoint(ctx context.Context, ep kube.Endpo zap.Int32("port", port.Port), ) } - name := apisixv1.ComposeUpstreamName(namespace, svcName, subset.Name, port.Port) + name := apisixv1.ComposeUpstreamName(namespace, svcName, subset.Name, port.Port, types.ResolveGranularity.Endpoint) for _, cluster := range clusters { if err := c.SyncUpstreamNodesChangeToCluster(ctx, cluster, nodes, name); err != nil { return err @@ -118,7 +118,7 @@ func (c *baseEndpointController) syncEndpoint(ctx context.Context, ep kube.Endpo zap.Int32("port", port.Port), ) } - name := apisixv1.ComposeUpstreamName(namespace, svcName, subset.Name, port.Port) + name := apisixv1.ComposeUpstreamName(namespace, svcName, subset.Name, port.Port, types.ResolveGranularity.Endpoint) for _, cluster := range clusters { if err := c.SyncUpstreamNodesChangeToCluster(ctx, cluster, nodes, name); err != nil { return err @@ -131,3 +131,23 @@ func (c *baseEndpointController) syncEndpoint(ctx context.Context, ep kube.Endpo } return nil } + +func (c *baseEndpointController) syncEmptyEndpoint(ctx context.Context, ep kube.Endpoint) error { + namespace, err := ep.Namespace() + if err != nil { + return err + } + svcName := ep.ServiceName() + log.Debugw("The service has been deleted, try to delete upstream relation", + zap.String("namespace", namespace), + zap.String("service_name", svcName), + ) + clusterName := c.Config.APISIX.DefaultClusterName + err = c.APISIX.Cluster(clusterName).UpstreamServiceRelation().Delete(ctx, namespace+"_"+svcName) + if err != nil { + log.Errorw("delete upstream relation failed", + zap.Error(err), + ) + } + return nil +} diff --git a/pkg/providers/k8s/endpoint/endpoint.go b/pkg/providers/k8s/endpoint/endpoint.go index 9b14bf1206..8b817dea78 100644 --- a/pkg/providers/k8s/endpoint/endpoint.go +++ b/pkg/providers/k8s/endpoint/endpoint.go @@ -28,7 +28,6 @@ import ( "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/k8s/namespace" "github.com/apache/apisix-ingress-controller/pkg/types" - v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) type endpointsController struct { @@ -103,22 +102,12 @@ func (c *endpointsController) sync(ctx context.Context, ev *types.Event) error { if err != nil { return err } - if ev.Type == types.EventDelete { - clusterName := c.Config.APISIX.DefaultClusterName - err = c.APISIX.Cluster(clusterName).UpstreamServiceRelation().Delete(ctx, - &v1.UpstreamServiceRelation{ - ServiceName: ns + "_" + ep.ServiceName(), - }) - if err != nil { - return err - } - } newestEp, err := c.epLister.GetEndpoint(ns, ep.ServiceName()) if err != nil { - if !errors.IsNotFound(err) { - return err + if errors.IsNotFound(err) { + return c.syncEmptyEndpoint(ctx, ep) } - newestEp = ep + return err } return c.syncEndpoint(ctx, newestEp) } diff --git a/pkg/providers/k8s/endpoint/endpointslice.go b/pkg/providers/k8s/endpoint/endpointslice.go index 972ecb5a01..01a94af310 100644 --- a/pkg/providers/k8s/endpoint/endpointslice.go +++ b/pkg/providers/k8s/endpoint/endpointslice.go @@ -20,6 +20,7 @@ import ( "go.uber.org/zap" discoveryv1 "k8s.io/api/discovery/v1" + "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -28,18 +29,12 @@ import ( "github.com/apache/apisix-ingress-controller/pkg/log" "github.com/apache/apisix-ingress-controller/pkg/providers/k8s/namespace" "github.com/apache/apisix-ingress-controller/pkg/types" - v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) const ( _endpointSlicesManagedBy = "endpointslice-controller.k8s.io" ) -type endpointSliceEvent struct { - Key string - ServiceName string -} - type endpointSliceController struct { *baseEndpointController @@ -107,34 +102,23 @@ func (c *endpointSliceController) run(ctx context.Context) { } func (c *endpointSliceController) sync(ctx context.Context, ev *types.Event) error { - log.Debugw("process endpoint slice event", + log.Debugw("process endpoint slice sync event", zap.Any("event", ev), ) - epEvent := ev.Object.(endpointSliceEvent) - namespace, _, err := cache.SplitMetaNamespaceKey(epEvent.Key) + ep := ev.Object.(kube.Endpoint) + ns, err := ep.Namespace() if err != nil { - log.Errorf("found endpointSlice object with bad namespace/name: %s, ignore it", epEvent.Key) - return nil - } - if ev.Type == types.EventDelete { - log.Debugw("endpointsplice upstream serviece sync", - zap.String("service_name", epEvent.ServiceName)) - clusterName := c.Config.APISIX.DefaultClusterName - err = c.APISIX.Cluster(clusterName).UpstreamServiceRelation().Delete(ctx, - &v1.UpstreamServiceRelation{ - ServiceName: namespace + "_" + epEvent.ServiceName, - }) - if err != nil { - return err - } + return err } - ep, err := c.epLister.GetEndpoint(namespace, epEvent.ServiceName) + + newestEp, err := c.epLister.GetEndpoint(ns, ep.ServiceName()) if err != nil { - log.Errorf("failed to get all endpointSlices for service %s: %s", - epEvent.ServiceName, err) + if errors.IsNotFound(err) { + return c.syncEmptyEndpoint(ctx, ep) + } return err } - return c.syncEndpoint(ctx, ep) + return c.syncEndpoint(ctx, newestEp) } func (c *endpointSliceController) handleSyncErr(obj interface{}, err error) { @@ -147,7 +131,7 @@ func (c *endpointSliceController) handleSyncErr(obj interface{}, err error) { if k8serrors.IsNotFound(err) && event.Type != types.EventDelete { log.Infow("sync endpointSlice but not found, ignore", zap.String("event_type", event.Type.String()), - zap.Any("endpointSlice", event.Object.(endpointSliceEvent)), + zap.Any("endpointSlice", event.Object.(kube.Endpoint)), ) c.workqueue.Forget(event) return @@ -183,11 +167,8 @@ func (c *endpointSliceController) onAdd(obj interface{}) { ) c.workqueue.Add(&types.Event{ - Type: types.EventAdd, - Object: endpointSliceEvent{ - Key: key, - ServiceName: svcName, - }, + Type: types.EventAdd, + Object: kube.NewEndpointWithSlice(ep), }) c.MetricsCollector.IncrEvents("endpointSlice", "add") @@ -208,15 +189,15 @@ func (c *endpointSliceController) onUpdate(prev, curr interface{}) { if !c.namespaceProvider.IsWatchingNamespace(key) { return } + svcName := currEp.Labels[discoveryv1.LabelServiceName] + if svcName == "" { + return + } if currEp.Labels[discoveryv1.LabelManagedBy] != _endpointSlicesManagedBy { // We only care about endpointSlice objects managed by the EndpointSlices // controller. return } - svcName := currEp.Labels[discoveryv1.LabelServiceName] - if svcName == "" { - return - } log.Debugw("endpointSlice update event arrived", zap.Any("new object", currEp), @@ -225,10 +206,7 @@ func (c *endpointSliceController) onUpdate(prev, curr interface{}) { c.workqueue.Add(&types.Event{ Type: types.EventUpdate, // TODO pass key. - Object: endpointSliceEvent{ - Key: key, - ServiceName: svcName, - }, + Object: kube.NewEndpointWithSlice(currEp), }) c.MetricsCollector.IncrEvents("endpointSlice", "update") @@ -252,21 +230,21 @@ func (c *endpointSliceController) onDelete(obj interface{}) { if !c.namespaceProvider.IsWatchingNamespace(key) { return } + svcName := ep.Labels[discoveryv1.LabelServiceName] + if svcName == "" { + return + } if ep.Labels[discoveryv1.LabelManagedBy] != _endpointSlicesManagedBy { // We only care about endpointSlice objects managed by the EndpointSlices // controller. return } - svcName := ep.Labels[discoveryv1.LabelServiceName] log.Debugw("endpoints delete event arrived", zap.Any("object-key", key), ) c.workqueue.Add(&types.Event{ - Type: types.EventDelete, - Object: endpointSliceEvent{ - Key: key, - ServiceName: svcName, - }, + Type: types.EventDelete, + Object: kube.NewEndpointWithSlice(ep), }) c.MetricsCollector.IncrEvents("endpointSlice", "delete") diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go index ea326adf34..b119c62483 100644 --- a/pkg/types/apisix/v1/types.go +++ b/pkg/types/apisix/v1/types.go @@ -22,6 +22,8 @@ import ( "strconv" "strings" "time" + + "github.com/apache/apisix-ingress-controller/pkg/types" ) const ( @@ -401,8 +403,8 @@ type PluginConfig struct { // UpstreamServiceRelation Upstream association object // +k8s:deepcopy-gen=true type UpstreamServiceRelation struct { - ServiceName string `json:"service_name" yaml:"service_name"` - UpstreamName string `json:"upstream_name,omitempty" yaml:"upstream_name,omitempty"` + ServiceName string `json:"service_name" yaml:"service_name"` + UpstreamNames map[string]struct{} `json:"upstream_name,omitempty" yaml:"upstream_name,omitempty"` } // NewDefaultUpstream returns an empty Upstream with default values. @@ -466,19 +468,23 @@ func NewDefaultPluginConfig() *PluginConfig { } } -// ComposeUpstreamName uses namespace, name, subset (optional) and port info to compose +// ComposeUpstreamName uses namespace, name, subset (optional), port, resolveGranularity info to compose // the upstream name. -func ComposeUpstreamName(namespace, name, subset string, port int32) string { +// the resolveGranularity is not composited in the upstream name when it is endpoint. +func ComposeUpstreamName(namespace, name, subset string, port int32, resolveGranularity string) string { pstr := strconv.Itoa(int(port)) // FIXME Use sync.Pool to reuse this buffer if the upstream // name composing code path is hot. var p []byte - if subset == "" { - p = make([]byte, 0, len(namespace)+len(name)+len(pstr)+2) - } else { - p = make([]byte, 0, len(namespace)+len(name)+len(subset)+len(pstr)+3) + plen := len(namespace) + len(name) + len(pstr) + 2 + if subset != "" { + plen = plen + len(subset) + 1 + } + if resolveGranularity == types.ResolveGranularity.Service { + plen = plen + len(resolveGranularity) + 1 } + p = make([]byte, 0, plen) buf := bytes.NewBuffer(p) buf.WriteString(namespace) buf.WriteByte('_') @@ -489,6 +495,10 @@ func ComposeUpstreamName(namespace, name, subset string, port int32) string { buf.WriteByte('_') } buf.WriteString(pstr) + if resolveGranularity == types.ResolveGranularity.Service { + buf.WriteByte('_') + buf.WriteString(resolveGranularity) + } return buf.String() } diff --git a/pkg/types/apisix/v1/zz_generated.deepcopy.go b/pkg/types/apisix/v1/zz_generated.deepcopy.go index a353718b64..e4eeadd9d3 100644 --- a/pkg/types/apisix/v1/zz_generated.deepcopy.go +++ b/pkg/types/apisix/v1/zz_generated.deepcopy.go @@ -764,6 +764,13 @@ func (in *UpstreamPassiveHealthCheckUnhealthy) DeepCopy() *UpstreamPassiveHealth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UpstreamServiceRelation) DeepCopyInto(out *UpstreamServiceRelation) { *out = *in + if in.UpstreamNames != nil { + in, out := &in.UpstreamNames, &out.UpstreamNames + *out = make(map[string]struct{}, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } return } diff --git a/pkg/types/service.go b/pkg/types/service.go new file mode 100644 index 0000000000..418f4a3b19 --- /dev/null +++ b/pkg/types/service.go @@ -0,0 +1,25 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package types + +var ( + ResolveGranularity = struct { + Endpoint string + Service string + }{ + Endpoint: "endpoint", + Service: "service", + } +) diff --git a/test/e2e/suite-chore/resolvegranularity.go b/test/e2e/suite-chore/resolvegranularity.go new file mode 100644 index 0000000000..e7b036bc27 --- /dev/null +++ b/test/e2e/suite-chore/resolvegranularity.go @@ -0,0 +1,127 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package chore + +import ( + "fmt" + "net/http" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/stretchr/testify/assert" + + "github.com/apache/apisix-ingress-controller/test/e2e/scaffold" +) + +var _ = ginkgo.Describe("suite-chore: ApisixRoute resolvegranularity Testing", func() { + s := scaffold.NewDefaultScaffold() + ginkgo.It("service and upstream [1:m]", func() { + assert.Nil(ginkgo.GinkgoT(), s.ScaleHTTPBIN(2)) + time.Sleep(5 * time.Second) + + backendSvc, backendSvcPort := s.DefaultHTTPBackend() + route1 := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin-route1 +spec: + http: + - name: route1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d + resolveGranularity: service +`, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(route1)) + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "checking number of routes") + ups, err := s.ListApisixUpstreams() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), ups, 1) + assert.Len(ginkgo.GinkgoT(), ups[0].Nodes, 1) + _ = s.NewAPISIXClient().GET("/ip"). + WithHeader("Host", "httpbin.org"). + Expect(). + Status(http.StatusOK) + + route2 := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin-route2 +spec: + http: + - name: route2 + match: + hosts: + - httpbin.com + paths: + - /get + backends: + - serviceName: %s + servicePort: %d + resolveGranularity: endpoint +`, backendSvc, backendSvcPort[0]) + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(route2)) + assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(2), "checking number of routes") + ups, err = s.ListApisixUpstreams() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), ups, 2) + if len(ups[0].Nodes) == 1 { + assert.Len(ginkgo.GinkgoT(), ups[1].Nodes, 2) + } else { + assert.Len(ginkgo.GinkgoT(), ups[0].Nodes, 2) + assert.Len(ginkgo.GinkgoT(), ups[1].Nodes, 1) + } + _ = s.NewAPISIXClient().GET("/get"). + WithHeader("Host", "httpbin.com"). + Expect(). + Status(http.StatusOK) + // Verify consistency after apisix-ingress-controller restart + verify := func() { + s.RestartIngressControllerDeploy() + time.Sleep(15 * time.Second) + + ups, err = s.ListApisixUpstreams() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), ups, 2) + if len(ups[0].Nodes) == 1 { + assert.Len(ginkgo.GinkgoT(), ups[1].Nodes, 2) + } else { + assert.Len(ginkgo.GinkgoT(), ups[0].Nodes, 2) + assert.Len(ginkgo.GinkgoT(), ups[1].Nodes, 1) + } + + _ = s.NewAPISIXClient().GET("/ip"). + WithHeader("Host", "httpbin.org"). + Expect(). + Status(http.StatusOK) + + _ = s.NewAPISIXClient().GET("/get"). + WithHeader("Host", "httpbin.com"). + Expect(). + Status(http.StatusOK) + } + + for i := 0; i < 5; i++ { + verify() + } + }) +}) From 85bcfbc9f5e697f367c33382a7410b446dc39cbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 11:59:51 +0800 Subject: [PATCH 26/30] chore(deps): bump github.com/gruntwork-io/terratest in /test/e2e (#1327) --- test/e2e/go.mod | 2 +- test/e2e/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index b095801e11..8bf96fe3f0 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -8,7 +8,7 @@ require ( github.com/eclipse/paho.mqtt.golang v1.4.1 github.com/gavv/httpexpect/v2 v2.3.1 github.com/gorilla/websocket v1.5.0 - github.com/gruntwork-io/terratest v0.40.21 + github.com/gruntwork-io/terratest v0.40.22 github.com/onsi/ginkgo/v2 v2.1.6 github.com/stretchr/testify v1.8.0 k8s.io/api v0.24.4 diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 58ed983899..7dc09b54af 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -271,8 +271,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= -github.com/gruntwork-io/terratest v0.40.21 h1:BYN/CamnMIHPFqE2Jh+XwaFT0RSZhnlBCOXeImxWrBQ= -github.com/gruntwork-io/terratest v0.40.21/go.mod h1:JGeIGgLbxbG9/Oqm06z6YXVr76CfomdmLkV564qov+8= +github.com/gruntwork-io/terratest v0.40.22 h1:qHIk+feNFspZQK2UTeH+zeMGfTfSuRduU10RCMMTveg= +github.com/gruntwork-io/terratest v0.40.22/go.mod h1:JGeIGgLbxbG9/Oqm06z6YXVr76CfomdmLkV564qov+8= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= From 3fd6112ccc6303231c55cd018af024ac4eca1ef7 Mon Sep 17 00:00:00 2001 From: LinkMaq Date: Thu, 15 Sep 2022 14:10:54 +0800 Subject: [PATCH 27/30] docs: Add KubeGems to powered-by.md (#1334) --- powered-by.md | 1 + 1 file changed, 1 insertion(+) diff --git a/powered-by.md b/powered-by.md index 7076759716..f8bd59009c 100644 --- a/powered-by.md +++ b/powered-by.md @@ -29,3 +29,4 @@ Users are encouraged to add themselves to this page, [issue](https://github.com/ 1. AISpeech 思必驰 1. Tencent Cloud 腾讯云 1. UPYUN 又拍云 +1. KubeGems From 4fa3b56fd6a962c7d389ab1d7903e8015888c363 Mon Sep 17 00:00:00 2001 From: Xin Rong Date: Fri, 16 Sep 2022 09:17:03 +0800 Subject: [PATCH 28/30] fix: crd resource status is not updated (#1335) --- pkg/providers/utils/status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/providers/utils/status.go b/pkg/providers/utils/status.go index e8bd62df8f..3f624aa1c4 100644 --- a/pkg/providers/utils/status.go +++ b/pkg/providers/utils/status.go @@ -59,7 +59,7 @@ func RecorderEventS(recorder record.EventRecorder, object runtime.Object, eventt // VerifyGeneration verify generation to decide whether to update status func VerifyGeneration(conditions *[]metav1.Condition, newCondition metav1.Condition) bool { existingCondition := meta.FindStatusCondition(*conditions, newCondition.Type) - if existingCondition != nil && existingCondition.ObservedGeneration >= newCondition.ObservedGeneration { + if existingCondition != nil && existingCondition.ObservedGeneration > newCondition.ObservedGeneration { return false } return true From f296f118542f93b28b9673197dcc81be181d2685 Mon Sep 17 00:00:00 2001 From: xianshun163 <32457473+xianshun163@users.noreply.github.com> Date: Fri, 16 Sep 2022 11:26:48 +0800 Subject: [PATCH 29/30] fix: Using different protocols at the same time in ApisixUpstream (#1331) Co-authored-by: xianshun --- pkg/providers/apisix/apisix_upstream.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/providers/apisix/apisix_upstream.go b/pkg/providers/apisix/apisix_upstream.go index b30c3430e0..bf27b5104f 100644 --- a/pkg/providers/apisix/apisix_upstream.go +++ b/pkg/providers/apisix/apisix_upstream.go @@ -158,11 +158,11 @@ func (c *apisixUpstreamController) sync(ctx context.Context, ev *types.Event) er case config.ApisixV2beta3: au := multiVersioned.V2beta3() - var portLevelSettings map[int32]*configv2beta3.ApisixUpstreamConfig + var portLevelSettings map[int32]configv2beta3.ApisixUpstreamConfig if au.Spec != nil && len(au.Spec.PortLevelSettings) > 0 { - portLevelSettings = make(map[int32]*configv2beta3.ApisixUpstreamConfig, len(au.Spec.PortLevelSettings)) + portLevelSettings = make(map[int32]configv2beta3.ApisixUpstreamConfig, len(au.Spec.PortLevelSettings)) for _, port := range au.Spec.PortLevelSettings { - portLevelSettings[port.Port] = &port.ApisixUpstreamConfig + portLevelSettings[port.Port] = port.ApisixUpstreamConfig } } @@ -198,10 +198,10 @@ func (c *apisixUpstreamController) sync(ctx context.Context, ev *types.Event) er if au.Spec != nil && ev.Type != types.EventDelete { cfg, ok := portLevelSettings[port.Port] if !ok { - cfg = &au.Spec.ApisixUpstreamConfig + cfg = au.Spec.ApisixUpstreamConfig } // FIXME Same ApisixUpstreamConfig might be translated multiple times. - newUps, err = c.translator.TranslateUpstreamConfigV2beta3(cfg) + newUps, err = c.translator.TranslateUpstreamConfigV2beta3(&cfg) if err != nil { log.Errorw("found malformed ApisixUpstream", zap.Any("object", au), @@ -242,11 +242,11 @@ func (c *apisixUpstreamController) sync(ctx context.Context, ev *types.Event) er case config.ApisixV2: au := multiVersioned.V2() - var portLevelSettings map[int32]*configv2.ApisixUpstreamConfig + var portLevelSettings map[int32]configv2.ApisixUpstreamConfig if au.Spec != nil && len(au.Spec.PortLevelSettings) > 0 { - portLevelSettings = make(map[int32]*configv2.ApisixUpstreamConfig, len(au.Spec.PortLevelSettings)) + portLevelSettings = make(map[int32]configv2.ApisixUpstreamConfig, len(au.Spec.PortLevelSettings)) for _, port := range au.Spec.PortLevelSettings { - portLevelSettings[port.Port] = &port.ApisixUpstreamConfig + portLevelSettings[port.Port] = port.ApisixUpstreamConfig } } @@ -282,10 +282,10 @@ func (c *apisixUpstreamController) sync(ctx context.Context, ev *types.Event) er if au.Spec != nil && ev.Type != types.EventDelete { cfg, ok := portLevelSettings[port.Port] if !ok { - cfg = &au.Spec.ApisixUpstreamConfig + cfg = au.Spec.ApisixUpstreamConfig } // FIXME Same ApisixUpstreamConfig might be translated multiple times. - newUps, err = c.translator.TranslateUpstreamConfigV2(cfg) + newUps, err = c.translator.TranslateUpstreamConfigV2(&cfg) if err != nil { log.Errorw("ApisixUpstream conversion cannot be completed, or the format is incorrect", zap.Any("object", au), From 654aaecde48f972cadd29be884735fc931a90b57 Mon Sep 17 00:00:00 2001 From: Baoyuan Date: Fri, 16 Sep 2022 11:27:37 +0800 Subject: [PATCH 30/30] docs: add slack invitation badge (#1333) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0b7f791896..697f532aff 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ # Apache APISIX for Kubernetes [![Go Report Card](https://goreportcard.com/badge/github.com/apache/apisix-ingress-controller)](https://goreportcard.com/report/github.com/apache/apisix-ingress-controller) +[![Slack](https://badgen.net/badge/Slack/Join%20Apache%20APISIX?icon=slack)](https://apisix.apache.org/slack) Use [Apache APISIX](https://github.com/apache/apisix#apache-apisix) for Kubernetes [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/).