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

Throw Exception When A Repo In A Multi Git Configuration Fails - Do Not Fallback To Default Repo

Open tnaskali opened this issue 1 year ago • 7 comments

Describe the bug When on a multiple repository setup where one of the alternate repository contains unsupported legacy spring configuration, the exception NoSuchLabelException is thrown instead of the expected InvalidConfigDataPropertyException.

Spring Boot version : 3.0.5 Spring Cloud version : 2022.0.2

Sample Repository setup :

spring:
  cloud:
    config:
      server:
        git:
          clone-on-start: true
          default-label: master
          uri: ${application.repositories.default}
          search-paths: ${application.search-paths.default}
          repos:
            staging:
              pattern: "*/*staging*"
              uri: ${application.repositories.alternate}
              search-paths: ${application.search-paths.default}

invalid application.yml within the alternate repository :

---
spring:
  profiles: profile1
  datasource:
    username: john

actual error message when request matches the alternate "staging" repository :

2023.05.01 09:29:28.988 | [http-nio-8080-exec-1] | ERROR | [dispatcherServlet] | | | CORRELATION_ID=<nocor_id> | Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.cloud.config.server.environment.NoSuchLabelException: No such label: 1.0.0] with root cause org.eclipse.jgit.api.errors.RefNotFoundException: Ref 1.0.0 cannot be resolved at org.eclipse.jgit.api.CheckoutCommand.call(CheckoutCommand.java:224) at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.checkout(JGitEnvironmentRepository.java:467) at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.refresh(JGitEnvironmentRepository.java:306) at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.getLocations(JGitEnvironmentRepository.java:262) at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.getLocations(MultipleJGitEnvironmentRepository.java:144) at org.springframework.cloud.config.server.environment.SearchPathCompositeEnvironmentRepository.addForSearchPathLocators(SearchPathCompositeEnvironmentRepository.java:72) at org.springframework.cloud.config.server.environment.SearchPathCompositeEnvironmentRepository.getLocations(SearchPathCompositeEnvironmentRepository.java:55) at org.springframework.cloud.config.server.resource.GenericResourceRepository.findOne(GenericResourceRepository.java:67)

expected error message, as thrown when coming from the default repo :

2023.05.01 09:27:38.796 | [http-nio-8080-exec-6] | ERROR | [dispatcherServlet] | | | CORRELATION_ID=<nocor_id> | Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.cloud.config.server.environment.FailedToConstructEnvironmentException: Could not construct context for config=myapp profile=staging label= includeOrigin=false; nested exception is org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property 'spring.profiles' imported from location 'file [C:\Users\naskalit\AppData\Local\Temp\config-repo-2369028666792197659\staging\myapp\application.yml]' is invalid and should be replaced with 'spring.config.activate.on-profile' [origin: URL [file:/C:/Users/naskalit/AppData/Local/Temp/config-repo-2369028666792197659/staging/myapp/application.yml] - 10:13]] with root cause org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property 'spring.profiles' imported from location 'file [C:\Users\naskalit\AppData\Local\Temp\config-repo-2369028666792197659\staging\myapp\application.yml]' is invalid and should be replaced with 'spring.config.activate.on-profile' [origin: URL [file:/C:/Users/naskalit/AppData/Local/Temp/config-repo-2369028666792197659/staging/myapp/application.yml] - 10:13] at org.springframework.boot.context.config.InvalidConfigDataPropertyException.lambda$throwIfPropertyFound$0(InvalidConfigDataPropertyException.java:113) at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) at java.base/java.util.Collections$UnmodifiableMap.forEach(Collections.java:1553) at org.springframework.boot.context.config.InvalidConfigDataPropertyException.throwIfPropertyFound(InvalidConfigDataPropertyException.java:109) at org.springframework.boot.context.config.ConfigDataEnvironment.checkForInvalidProperties(ConfigDataEnvironment.java:364) at org.springframework.boot.context.config.ConfigDataEnvironment.applyToEnvironment(ConfigDataEnvironment.java:328) at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:235) at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:96) at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.applyTo(ConfigDataEnvironmentPostProcessor.java:169) at org.springframework.cloud.config.server.environment.NativeEnvironmentRepository.findOne(NativeEnvironmentRepository.java:145) at org.springframework.cloud.config.server.environment.AbstractScmEnvironmentRepository.findOne(AbstractScmEnvironmentRepository.java:64) at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.findOneFromCandidate(MultipleJGitEnvironmentRepository.java:195) at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.findOne(MultipleJGitEnvironmentRepository.java:178) at org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryWrapper.lambda$findOne$3(ObservationEnvironmentRepositoryWrapper.java:75)

tnaskali avatar May 01 '23 07:05 tnaskali

Does the label (aka branch) 1.0.0 exist in the default git repo?

I am guessing what is happening is you are requesting a label that exists in the staging repo but since that repo contains an invalid configuration file an exception is thrown and then the config server will try the default git repo. But since that git repo doesn't contain that label it throws the NoSuchLabelException.

If you set logging.level.org.springframework.cloud.config.server: DEBUG I think you would see the InvalidConfigDataPropertyException.

ryanjbaxter avatar May 03 '23 17:05 ryanjbaxter

You're absolutely right, indeed the 1.0.0 tag doesn't exist in the default repository. That explains the actual error message. Now let's assume it did exist, in my case this would be even worse because I might end up accidentally using configuration from the wrong repository at runtime. I couldn't find anything in the documentation, but is there an option to force the original error to be raised and prevent the fallback to the default repository to not silently present me with unwanted configuration ?

tnaskali avatar May 04 '23 09:05 tnaskali

In my opinion the notion of "default" repository in its current implementation can be ambiguous as it can either mean that no match has been found in any of the alternate repositories based on the application/profile pattern, or that a match has been found but that something has happened that prevented the repository to be used. This can lead to misinterpretations and unwanted results.

tnaskali avatar May 04 '23 10:05 tnaskali

We cannot change the way it behaves currently because that would be a breaking change for others relying on this functionality.

I couldn't find anything in the documentation, but is there an option to force the original error to be raised and prevent the fallback to the default repository to not silently present me with unwanted configuration ?

Why specify the default repo, if you don't want that to be tried?

ryanjbaxter avatar May 04 '23 19:05 ryanjbaxter

I want the default repo to be used if nothing matched any of the specified application/profile patterns. But I don't want it to be used if an error occurred while getting the configuration from a matched repository, I'd like the original exception (InvalidConfigDataPropertyException in my example) to be raised instead. Could you think of a setup that would grant me that behaviour ?

tnaskali avatar May 04 '23 19:05 tnaskali

So what you want is to specify multiple git repos, but if one matches but an exception is thrown you don't want it to try matching the rest of the repos correct?

ryanjbaxter avatar May 04 '23 20:05 ryanjbaxter

Yes that's correct

tnaskali avatar May 04 '23 20:05 tnaskali