spring-cloud-kubernetes icon indicating copy to clipboard operation
spring-cloud-kubernetes copied to clipboard

spring-cloud-kubernetes-discoveryserver: Null key for a Map not allowed in JSON for mssql service

Open agre1981 opened this issue 3 years ago • 5 comments

Describe the bug springcloud/spring-cloud-kubernetes-discoveryserver:2.1.1-SNAPSHOT (and 2.1.0 as well) "http://127.0.0.1:35795/apps" gives 500 "EncodingException: JSON encoding error: Null key for a Map not allowed in JSON " when deploy mssql image When i remove mssql service with next command it works fine. minikube kubectl -- delete service mssql2

Sample deployment scripts have been attached

minikube version: v1.24.0 commit: 76b94fb3c4e8ac5062daf70d60cf03ddcc0a741b Docker version 20.10.12, build e91ed57

NAME="Ubuntu" VERSION="20.04.3 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.3 LTS" VERSION_ID="20.04"

Exception: 2021-12-16 06:46:28.109 ERROR 1 --- [undedElastic-16] a.w.r.e.AbstractErrorWebExceptionHandler : [c379292a-1] 500 Server Error for HTTP GET "/apps"

org.springframework.core.codec.EncodingException: JSON encoding error: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?) (through reference chain: java.util.ArrayList[0]->org.springframewok.cloud.kubernetes.discoveryserver.DiscoveryServerController$Service["serviceInstances"]->java.util.ArrayList[0]->org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance["metadata"]) at org.springframework.http.codec.json.AbstractJackson2Encoder.encodeValue(AbstractJackson2Encoder.java:229) ~[spring-web-5.3.13.jar:5.3.13] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ? Handler org.springframewok.cloud.kubernetes.discoveryserver.DiscoveryServerController#apps() [DispatcherHandler] *__checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain] *__checkpoint ? HTTP GET "/apps" [ExceptionHandlingWebHandler]

mssql-deployment.zip

agre1981 avatar Dec 16 '21 07:12 agre1981

I'm getting the exact same exception with a simple Nginx deployment like the following:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx-deployment
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deployment
spec:
  ports:
  - port: 80
  selector:
    app: nginx-deployment

Calling the /apps endpoint on the discovery server yields HTTP 500 and the stack trace appears in the discover server's output. I have spring-cloud-kubernetes-discoveryserver:2.1.0 installed. Also, this is on Docker Desktop for Windows.

stacktrace.txt

pbloigu avatar Dec 19 '21 08:12 pbloigu

Alright, I did some more digging into this, and I think there is a bug here: https://github.com/spring-cloud/spring-cloud-kubernetes/blob/ff50c9c2dcfab281bd6c3df8cdd978299e73d165/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java#L151 It seems to assume a service port has a name defined like so ("default-http" in this example):

apiVersion: v1
kind: Service
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
spec:
  ports:
  - port: 80
    name: "default-http"
  selector:
    app: nginx-deployment

If the name is missing, a null key is inserted to the map, hence the exception.

So the workaround is to add names for service ports. Permanent fix might be to just skip adding a port to the metadata map if the name is missing?

pbloigu avatar Dec 21 '21 08:12 pbloigu

@pbloigu thank you! your workaround worked for me, regarding permanent fix we can probably use "default" if name does not exist

agre1981 avatar Dec 21 '21 10:12 agre1981

@pbloigu thank you! your workaround worked for me, regarding permanent fix we can probably use "default" if name does not exist

Yeah, well, I really don't have enough insight into what's the desired outcome in this case. Leave the unnamed ports out of the metadata map or make up some names for them?

pbloigu avatar Dec 21 '21 12:12 pbloigu

thank you both for triaging this, very helpful!

In theory, this is not complicated to "fix", but we need to think on either sensible defaults or a correct failure. I do not have an answer now, but will spent some time reflective on it.

wind57 avatar Dec 27 '21 19:12 wind57

I think maybe the best solution would be to just set the name to be <unset> as that is what the label is in k8s.

ryanjbaxter avatar Oct 13 '22 14:10 ryanjbaxter