Skip to content

Commit 6c16b00

Browse files
committed
refactor: look for existing APIs in the same namespace only
1 parent 4169821 commit 6c16b00

File tree

7 files changed

+101
-74
lines changed

7 files changed

+101
-74
lines changed

api/v1alpha1/apiv4definition_webhook.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ import (
2222
"net/url"
2323
"strings"
2424

25+
"github.com/gravitee-io/gravitee-kubernetes-operator/internal/env"
26+
27+
"sigs.k8s.io/controller-runtime/pkg/client"
28+
2529
v4 "github.com/gravitee-io/gravitee-kubernetes-operator/api/model/api/v4"
2630
"github.com/gravitee-io/gravitee-kubernetes-operator/internal/k8s"
2731
runtime "k8s.io/apimachinery/pkg/runtime"
@@ -55,7 +59,7 @@ func (*ApiV4Definition) ValidateDelete() (admission.Warnings, error) {
5559

5660
func validateApi(api *ApiV4Definition) (admission.Warnings, error) {
5761
// make sure Management Context exist before creating the API Definition resource
58-
if api.HasContext() {
62+
if api.HasContext() { //nolint:nestif // nested if is needed
5963
mCtx := new(ManagementContext)
6064
if err := k8s.GetClient().Get(context.Background(), api.ContextRef().NamespacedName(), mCtx); err != nil {
6165
return admission.Warnings{}, fmt.Errorf("can't create API [%s] because it is using "+
@@ -64,13 +68,22 @@ func validateApi(api *ApiV4Definition) (admission.Warnings, error) {
6468
} else {
6569
// check for unique context path
6670
apis := new(ApiV4DefinitionList)
67-
if err := k8s.GetClient().List(context.Background(), apis); err != nil {
71+
listOpts := client.ListOptions{}
72+
if !env.Config.CheckApiContextPathConflictInCluster {
73+
listOpts = client.ListOptions{
74+
Namespace: api.Namespace,
75+
}
76+
}
77+
78+
if err := k8s.GetClient().List(context.Background(), apis, &listOpts); err != nil {
6879
return admission.Warnings{}, err
6980
}
7081

7182
existingListeners := make([]*v4.GenericListener, 0)
7283
for _, item := range apis.Items {
73-
existingListeners = append(existingListeners, item.Spec.Listeners...)
84+
if api.Name != item.Name || api.Namespace != item.Namespace {
85+
existingListeners = append(existingListeners, item.Spec.Listeners...)
86+
}
7487
}
7588

7689
if err := validateApiContextPath(existingListeners, api.Spec.Listeners); err != nil {

helm/gko/README.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,27 +54,28 @@ Kube RBAC Proxy is deployed as a sidecar container and restricts access to the p
5454

5555
This is where you can configure the deployment itself and the way the operator will interact with APIM and Custom Resources in your cluster.
5656

57-
| Name | Description | Value |
58-
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
59-
| `manager.image.repository` | Specifies the docker registry and image name to use. | `graviteeio/kubernetes-operator` |
60-
| `manager.image.tag` | Specifies the docker image tag to use. If no value is set, the chart version will be used. | `""` |
61-
| `manager.image.pullPolicy` | Specifies the pullPolicy to use when starting a new container | `IfNotPresent` |
62-
| `manager.logs.json` | Whether to output manager logs in JSON format. | `true` |
63-
| `manager.configMap.name` | The name of the config map used to set the manager config from this values. | `gko-config` |
64-
| `manager.resources.limits.cpu` | The CPU resources limits for the GKO Manager container | `500m` |
65-
| `manager.resources.limits.memory` | The memory resources limits for the GKO Manager container | `128Mi` |
66-
| `manager.resources.requests.cpu` | The requested CPU for the GKO Manager container | `5m` |
67-
| `manager.resources.requests.memory` | The requested memory for the GKO Manager container | `64Mi` |
68-
| `manager.scope.cluster` | Use false to listen only in the release namespace. | `true` |
69-
| `manager.applyCRDs` | 👎 This feature is deprecated and will be replaced in a future release. If true, the manager will patch Custom Resource Definitions on startup. | `true` |
70-
| `manager.metrics.enabled` | If true, a metrics server will be created so that metrics can be scraped using prometheus. | `true` |
71-
| `manager.httpClient.insecureSkipCertVerify` | If true, the manager HTTP client will not verify the certificate used by the Management API. | `false` |
72-
| `manager.httpClient.timeoutSeconds` | he timeout (in seconds) used when issuing request to the Management API. | `5` |
73-
| `manager.webhook.enabled` | If true, the manager will register a webhook server operating on custom resources. | `true` |
74-
| `manager.webhook.service.name` | The service used to expose the webhook server. | `gko-webhook` |
75-
| `manager.webhook.service.port` | Which port the webhook server will listen to. | `9443` |
76-
| `manager.webhook.cert.create` | If true, a secret will be created to store the webhook server certificate. | `true` |
77-
| `manager.webhook.cert.secret.name` | The name of the secret storing the webhook server certificate. | `gko-webhook-cert` |
57+
| Name | Description | Value |
58+
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
59+
| `manager.image.repository` | Specifies the docker registry and image name to use. | `graviteeio/kubernetes-operator` |
60+
| `manager.image.tag` | Specifies the docker image tag to use. If no value is set, the chart version will be used. | `""` |
61+
| `manager.image.pullPolicy` | Specifies the pullPolicy to use when starting a new container | `IfNotPresent` |
62+
| `manager.logs.json` | Whether to output manager logs in JSON format. | `true` |
63+
| `manager.configMap.name` | The name of the config map used to set the manager config from this values. | `gko-config` |
64+
| `manager.resources.limits.cpu` | The CPU resources limits for the GKO Manager container | `500m` |
65+
| `manager.resources.limits.memory` | The memory resources limits for the GKO Manager container | `128Mi` |
66+
| `manager.resources.requests.cpu` | The requested CPU for the GKO Manager container | `5m` |
67+
| `manager.resources.requests.memory` | The requested memory for the GKO Manager container | `64Mi` |
68+
| `manager.scope.cluster` | Use false to listen only in the release namespace. | `true` |
69+
| `manager.applyCRDs` | 👎 This feature is deprecated and will be replaced in a future release. If true, the manager will patch Custom Resource Definitions on startup. | `true` |
70+
| `manager.metrics.enabled` | If true, a metrics server will be created so that metrics can be scraped using prometheus. | `true` |
71+
| `manager.httpClient.insecureSkipCertVerify` | If true, the manager HTTP client will not verify the certificate used by the Management API. | `false` |
72+
| `manager.httpClient.timeoutSeconds` | he timeout (in seconds) used when issuing request to the Management API. | `5` |
73+
| `manager.webhook.enabled` | If true, the manager will register a webhook server operating on custom resources. | `true` |
74+
| `manager.webhook.service.name` | The service used to expose the webhook server. | `gko-webhook` |
75+
| `manager.webhook.service.port` | Which port the webhook server will listen to. | `9443` |
76+
| `manager.webhook.cert.create` | If true, a secret will be created to store the webhook server certificate. | `true` |
77+
| `manager.webhook.cert.secret.name` | The name of the secret storing the webhook server certificate. | `gko-webhook-cert` |
78+
| `manager.webhook.admission.checkApiContextPathConflictInCluster` | check if the same API context path exists in the whole cluster. | `false` |
7879

7980
### ingress
8081

helm/gko/templates/manager/config.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
kind: ConfigMap
16-
apiVersion: v1
15+
kind: ConfigMap
16+
apiVersion: v1
1717
metadata:
1818
name: {{ .Values.manager.configMap.name }}
1919
namespace: {{ .Release.Namespace }}
@@ -56,4 +56,7 @@ data:
5656
WEBHOOK_NAMESPACE: {{ .Release.Namespace }}
5757
WEBHOOK_SERVICE_NAME: {{ .Values.manager.webhook.service.name }}
5858
WEBHOOK_SERVICE_PORT: {{ quote .Values.manager.webhook.service.port }}
59+
{{- if .Values.manager.webhook.admission.checkApiContextPathConflictInCluster }}
60+
CHECK_API_CONTEXT_PATH_CONFLICT_IN_CLUSTER: "true"
61+
{{- end }}
5962
{{- end }}

helm/gko/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ manager:
107107
secret:
108108
## @param manager.webhook.cert.secret.name The name of the secret storing the webhook server certificate.
109109
name: gko-webhook-cert
110+
admission:
111+
## @param manager.webhook.admission.checkApiContextPathConflictInCluster check if the same API context path exists in the whole cluster.
112+
checkApiContextPathConflictInCluster: false
113+
110114
## @section ingress
111115
## @descriptionStart
112116
## Configure the behavior of the ingress controller.

internal/env/env.go

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,44 @@ import (
2323
)
2424

2525
const (
26-
CMTemplate404Name = "TEMPLATE_404_CONFIG_MAP_NAME"
27-
CMTemplate404NS = "TEMPLATE_404_CONFIG_MAP_NAMESPACE"
28-
Development = "DEV_MODE"
29-
NS = "NAMESPACE"
30-
ApplyCRDs = "APPLY_CRDS"
31-
EnableMetrics = "ENABLE_METRICS"
32-
EnableWebhook = "ENABLE_WEBHOOK"
33-
WebhookNS = "WEBHOOK_NAMESPACE"
34-
WebhookServiceName = "WEBHOOK_SERVICE_NAME"
35-
WebhookPort = "WEBHOOK_SERVICE_PORT"
36-
WebhookCertSecret = "WEBHOOK_CERT_SECRET_NAME" //nolint:gosec // This is not a hardcoded secret
37-
HttpCLientInsecureSkipCertVerify = "HTTP_CLIENT_INSECURE_SKIP_CERT_VERIFY"
38-
HttpClientTimeoutSeconds = "HTTP_CLIENT_TIMEOUT_SECONDS"
39-
TrueString = "true"
40-
IngressClasses = "INGRESS_CLASSES"
26+
CMTemplate404Name = "TEMPLATE_404_CONFIG_MAP_NAME"
27+
CMTemplate404NS = "TEMPLATE_404_CONFIG_MAP_NAMESPACE"
28+
Development = "DEV_MODE"
29+
NS = "NAMESPACE"
30+
ApplyCRDs = "APPLY_CRDS"
31+
EnableMetrics = "ENABLE_METRICS"
32+
EnableWebhook = "ENABLE_WEBHOOK"
33+
WebhookNS = "WEBHOOK_NAMESPACE"
34+
WebhookServiceName = "WEBHOOK_SERVICE_NAME"
35+
WebhookPort = "WEBHOOK_SERVICE_PORT"
36+
WebhookCertSecret = "WEBHOOK_CERT_SECRET_NAME" //nolint:gosec // This is not a hardcoded secret
37+
HttpCLientInsecureSkipCertVerify = "HTTP_CLIENT_INSECURE_SKIP_CERT_VERIFY"
38+
HttpClientTimeoutSeconds = "HTTP_CLIENT_TIMEOUT_SECONDS"
39+
TrueString = "true"
40+
IngressClasses = "INGRESS_CLASSES"
41+
CheckApiContextPathConflictInCluster = "CHECK_API_CONTEXT_PATH_CONFLICT_IN_CLUSTER"
4142

4243
// This default are applied when running the app locally.
4344
defaultWebhookPort = 9443
44-
defaultHttpCLientTimeout = 5
45+
defaultHttpClientTimeout = 5
4546
)
4647

4748
var Config = struct {
48-
NS string
49-
ApplyCRDs bool
50-
EnableMetrics bool
51-
EnableWebhook bool
52-
WebhookNS string
53-
WebhookService string
54-
WebhookPort int
55-
WebhookCertSecret string
56-
Development bool
57-
CMTemplate404Name string
58-
CMTemplate404NS string
59-
HTTPClientInsecureSkipVerify bool
60-
HTTPClientTimeoutSeconds int
61-
IngressClasses []string
49+
NS string
50+
ApplyCRDs bool
51+
EnableMetrics bool
52+
EnableWebhook bool
53+
WebhookNS string
54+
WebhookService string
55+
WebhookPort int
56+
WebhookCertSecret string
57+
Development bool
58+
CMTemplate404Name string
59+
CMTemplate404NS string
60+
HTTPClientInsecureSkipVerify bool
61+
HTTPClientTimeoutSeconds int
62+
IngressClasses []string
63+
CheckApiContextPathConflictInCluster bool
6264
}{}
6365

6466
func init() {
@@ -68,13 +70,14 @@ func init() {
6870
Config.CMTemplate404Name = os.Getenv(CMTemplate404Name)
6971
Config.CMTemplate404NS = os.Getenv(CMTemplate404NS)
7072
Config.HTTPClientInsecureSkipVerify = os.Getenv(HttpCLientInsecureSkipCertVerify) == TrueString
71-
Config.HTTPClientTimeoutSeconds = parseInt(HttpClientTimeoutSeconds, defaultHttpCLientTimeout)
73+
Config.HTTPClientTimeoutSeconds = parseInt(HttpClientTimeoutSeconds, defaultHttpClientTimeout)
7274
Config.EnableMetrics = os.Getenv(EnableMetrics) == TrueString
7375
Config.EnableWebhook = os.Getenv(EnableWebhook) == TrueString
7476
Config.WebhookNS = os.Getenv(WebhookNS)
7577
Config.WebhookService = os.Getenv(WebhookServiceName)
7678
Config.WebhookCertSecret = os.Getenv(WebhookCertSecret)
7779
Config.WebhookPort = parseInt(WebhookPort, defaultWebhookPort)
80+
Config.CheckApiContextPathConflictInCluster = os.Getenv(CheckApiContextPathConflictInCluster) == TrueString
7881
var ingressClass string
7982
if ingressClass = keys.IngressClassAnnotationValue; os.Getenv(IngressClasses) != "" {
8083
ingressClass = os.Getenv(IngressClasses)

test/integration/admissionwebhook/api_v4_create_withoutContext_invalid_path_webhook_test.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ package admissionwebhook
1717
import (
1818
"context"
1919

20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
2022
"github.com/gravitee-io/gravitee-kubernetes-operator/api/v1alpha1"
2123
"github.com/gravitee-io/gravitee-kubernetes-operator/test/internal/integration/constants"
2224
"github.com/gravitee-io/gravitee-kubernetes-operator/test/internal/integration/fixture"
2325
"github.com/gravitee-io/gravitee-kubernetes-operator/test/internal/integration/labels"
2426
"github.com/gravitee-io/gravitee-kubernetes-operator/test/internal/integration/manager"
2527
. "github.com/onsi/ginkgo/v2"
2628
. "github.com/onsi/gomega"
27-
"k8s.io/apimachinery/pkg/types"
2829
)
2930

3031
var _ = Describe("Webhook", labels.WithContext, func() {
@@ -42,11 +43,16 @@ var _ = Describe("Webhook", labels.WithContext, func() {
4243

4344
By("Check API creation validation")
4445
Eventually(func() error {
45-
api := new(v1alpha1.ApiV4Definition)
46-
if err := manager.Client().Get(ctx, types.NamespacedName{
47-
Name: fixtures.APIv4.Name,
48-
Namespace: fixtures.APIv4.Namespace,
49-
}, api); err != nil {
46+
api := &v1alpha1.ApiV4Definition{
47+
ObjectMeta: metav1.ObjectMeta{
48+
Name: fixtures.APIv4.Name + "-duplicate",
49+
Namespace: fixtures.APIv4.Namespace,
50+
},
51+
}
52+
53+
fixtures.APIv4.Spec.DeepCopyInto(&api.Spec)
54+
55+
if err := manager.Client().Create(ctx, api); err != nil {
5056
return err
5157
}
5258

0 commit comments

Comments
 (0)