Disable Spring Cloud Sleuth when running Integration Tests? - java

When using org.springframework.cloud:spring-cloud-gcp-starter-trace:1.0.0.RELEASE and running my integration tests locally I get this error message:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'stackdriverSender' defined in class path
resource
[org/springframework/cloud/gcp/autoconfigure/trace/StackdriverTraceAutoConfiguration.class]:
Bean instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [zipkin2.reporter.Sender]: Factory method
'stackdriverSender' threw exception; nested exception is
java.io.IOException: The Application Default Credentials are not
available. They are available if running in Google Compute Engine.
Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS
must be defined pointing to a file defining the credentials. See
https://developers.google.com/accounts/docs/application-default-credentials
for more information.
This is totally understandable since this environment variable is not present locally and I don't want to use Sleuth/Stackdriver tracing when running the tests. I've looked in the reference documentation but I can only seem to find information on how to disable Sleuth for specific integration points such as RxJava, RestTemplate etc. But how can I disable Sleuth entirely?
I've tried setting spring.sleuth.enabled=false but this doesn't seem to make any difference.

HowTo: Disable all tests for a Webflux Sleuth implementation with Zipkin
If, you have these dependencies:
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
Then, fully disable Sleuth/Zipkin for your integration tests by adding an application.yml to your test/resources folder with:
spring:
sleuth: # All sleuth features disabled for integration tests
enabled: false
reactor:
enabled: false
web:
enabled: false
async:
enabled: false
client:
template:
enabled: false
zipkin: # All zipkin features disabled for integration tests
enabled: false

I actually found the answer by looking at the source for the StackdriverTraceAutoConfiguration class. The way to solve it if using GCP is to set spring.cloud.gcp.trace.enabled=false. This disables tracing for all integration points.

You can disable tracing, logging and set a fake project id as follow:
spring.cloud.gcp.project-id=fake-project-id
spring.cloud.gcp.logging.enabled=false
spring.cloud.gcp.trace.enabled=false

Related

How to disable DataSourceHealthIndicator bean in Spring Boot?

I have application with spring-boot-starter-actuator dependency. When I add my error handling library as dependency, application fails to start with the following message
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
After a bit research, I found out the error handling library introduces transitive dependency of spring-boot-starter-data-jpa which in turn causes actuator autoconfiguration to automatically introduce DataSourceHealthIndicator bean. This bean fails on missing database connection, but the application actually doesn't use database at all. However, the logging library requires the JPA dependency at runtime, so I can't exclude it.
I tried to set the following application property: management.health.db.enabled=false, but I still get the same error on startup. I can't find any documentation how to disable DataSourceHealthIndicator bean and leaving other autoconfiguration intact.

Custom DiscoveryClient for to discover Spring Cloud Config server

I am trying to build my own DiscoveryClient that would use Docker Swarm as the service source. I got it working with Spring Cloud Gateway and Spring Cloud Loadbalancer already. However, when I tried to use it to do discovery for the configserver by setting spring.cloud.config.discovery.enabled=true I get the following error
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.client.discovery.DiscoveryClient' available: expected at l
east 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I have created AutoConfigure classes as well but no luck. The project is here https://github.com/trajano/spring-cloud-demo.
When looking at the debug logs, with and without the discovery, it appears that the AutoConfiguration beans do not load up in the CONDITIONS EVALUATION REPORT specifically the ones in other libraries.
Similar to Spring cloud discovery first does not work at all but they are using Eureka, whereas I am trying to determine how to build my own DiscoveryClient.
I see your Configuration class for the DiscoveryClient has these annotations:
#ConditionalOnDiscoveryEnabled
#ConditionalOnBlockingDiscoveryEnabled
#ConditionalOnDockerSwarmDiscoveryEnabled
#AutoConfigureAfter({
DockerSwarmDiscoveryAutoConfiguration.class
})
#AutoConfigureBefore({
SimpleDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class
})
Could it be those settings are not enabled?
You mention you enabled discovery, but you do not mention the other ConditionOnX configurations.
If they are not enabled, the bean would not load.
There was a separate set of org.springframework.boot.autoconfigure.EnableAutoConfiguratio elements in spring.factory called org.springframework.cloud.bootstrap.BootstrapConfiguration
So I added this
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
net.trajano.spring.swarm.discovery.DockerSwarmDiscoveryClientConfigServiceBootstrapConfiguration
And this class
#ConditionalOnClass(ConfigServicePropertySourceLocator.class)
#ConditionalOnProperty("spring.cloud.config.discovery.enabled")
#Configuration(proxyBeanMethods = false)
#Import({
DockerSwarmDiscoveryClientAutoConfiguration.class,
// this emulates
// #EnableDiscoveryClient, the import
// selector doesn't run before the
// bootstrap phase
DockerClientConfiguration.class,
DockerSwarmDiscoveryAutoConfiguration.class,
DockerSwarmReactiveDiscoveryClientAutoConfiguration.class,
ReactiveCommonsClientAutoConfiguration.class
})
public class DockerSwarmDiscoveryClientConfigServiceBootstrapConfiguration {
}

Spring Cloud AWS SQS fails to connect to service endpoint locally

I'm trying to use Spring Cloud's AWS SQS in a project I'm working on. At this time, I'm only running the application locally on my dev machine. Thus, what I want is to connect to the SQS on AWS without having to deploy my app to an EC2 instance.
However, it seems like the AWS SDK used in Spring Cloud's AWS package will attempt to authenticate through metadata and wants to resolve 169.254.169.254/latest/meta-data/instance-id. Since I'm still the running the app locally, the endpoint cannot be resolved and an error is thrown:
2019-12-29 16:38:27.420 WARN 22462 --- [ restartedMain] com.amazonaws.util.EC2MetadataUtils : Unable to retrieve the requested metadata (/latest/meta-data/instance-id). Failed to connect to service endpoint:
com.amazonaws.SdkClientException: Failed to connect to service endpoint:
at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:100) ~[aws-java-sdk-core-1.11.699.jar:na]
at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:70) ~[aws-java-sdk-core-1.11.699.jar:na]
at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.readResource(InstanceMetadataServiceResourceFetcher.java:75) ~[aws-java-sdk-core-1.11.699.jar:na]
at com.amazonaws.internal.EC2ResourceFetcher.readResource(EC2ResourceFetcher.java:62) ~[aws-java-sdk-core-1.11.699.jar:na]
at com.amazonaws.util.EC2MetadataUtils.getItems(EC2MetadataUtils.java:400) ~[aws-java-sdk-core-1.11.699.jar:na]
at com.amazonaws.util.EC2MetadataUtils.getData(EC2MetadataUtils.java:369) ~[aws-java-sdk-core-1.11.699.jar:na]
at org.springframework.cloud.aws.context.support.env.AwsCloudEnvironmentCheckUtils.isRunningOnCloudEnvironment(AwsCloudEnvironmentCheckUtils.java:38) ~[spring-cloud-aws-context-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.cloud.aws.context.annotation.OnAwsCloudEnvironmentCondition.matches(OnAwsCloudEnvironmentCondition.java:37) ~[spring-cloud-aws-context-2.2.1.RELEASE.jar:2.2.1.RELEASE]
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:221) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:587) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
...
I've tried to explicitly supply an SQS endpoint in my bean, but it still attempts to connect to 169.254.169.254 resulting in the error above:
public AmazonSQSAsync sqsClient() {
EndpointConfiguration endpointConfig = new AwsClientBuilder.EndpointConfiguration(
"sqs.us-east-1.amazonaws.com",
"us-east-1"
);
return AmazonSQSAsyncClientBuilder
.standard()
.withEndpointConfiguration(endpointConfig)
.withCredentials(new AWSStaticCredentialsProvider(new DefaultAWSCredentialsProviderChain().getCredentials()))
.build();
}
Although I'm not certain about this, I suspect that the error is occurring because I'm running the app locally on my dev machine and so it couldn't resolve to the endpoint. But I'm not entirely sure about this too because I'm running other AWS services in the same app using the AWS SDK and I don't have this error.
I've the following dependencies in my pom.xml and it appears that having any one of them will cause the error to occur. That's, I don't even have to create the beans to have that error. Adding these dependencies will immediately, for some reason, causes the SDK to attempt to resolve that endpoint and fail with that error.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws-messaging</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
What else should I do to fix the error that it failed to connect to service endpoint?
I have received below errors when running Spring Boot Project for AWS SNS
i.InstanceMetadataServiceResourceFetcher : Fail to retrieve token
com.amazonaws.util.EC2MetadataUtils : Unable to retrieve the requested metadata (/latest/dynamic/instance-identity/document). Failed to connect to service endpoint:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'stackResourceRegistryFactoryBean' defined in class path resource [org/springframework/cloud/aws/autoconfigure/context/ContextStackAutoConfiguration.class]: Unsatisfied dependency expressed through method 'stackResourceRegistryFactoryBean' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'amazonCloudFormation' defined in class path resource [org/springframework/cloud/aws/autoconfigure/context/ContextStackAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: There is no EC2 meta data available, because the application is not running in the EC2 environment. Region detection is only possible if the application is running on a EC2 instance
Error creating bean with name 'org.springframework.cloud.aws.core.env.ResourceIdResolver.BEAN_NAME': Invocation of init method failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'stackResourceRegistryFactoryBean' defined in class path resource [org/springframework/cloud/aws/autoconfigure/context/ContextStackAutoConfiguration.class]: Unsatisfied dependency expressed through method 'stackResourceRegistryFactoryBean' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'amazonCloudFormation' defined in class path resource [org/springframework/cloud/aws/autoconfigure/context/ContextStackAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: There is no EC2 meta data available, because the application is not running in the EC2 environment. Region detection is only possible if the application is running on a EC2 instance
Resolution applied:
Add below code snippet to SpringBootApplication & Click on Run Button in the IDE
#SpringBootApplication(
exclude = {
org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration.class
}
)
I know many people have already explained what's issue and how to skip this error. But, all the above method didn't work for me. Finally after lot of search I set following aws configuration property and it worked for me.
cloud.aws.region.use-default-aws-region-chain=true
cloud.aws.stack.auto=false
cloud.aws.credentials.access-key=
cloud.aws.credentials.secret-key=
cloud.aws.region.auto=false
cloud.aws.region.static=
cloud.aws.stack=false
logging.level.com.amazonaws.util.EC2MetadataUtils=error
logging.level.com.amazonaws.internal.InstanceMetadataServiceResourceFetcher=error
The following configuration worked for me:
cloud:
aws:
region:
auto: false
static: eu-west-1
use-default-aws-region-chain: true
stack: false
stack.auto: false
logging:
level:
com:
amazonaws:
internal:
InstanceMetadataServiceResourceFetcher: error
util:
EC2MetadataUtils: error
When using the AWS Java SDK outside of an EC2 instance, you can disable loading credentials or regions from EC2 Metadata instance service with a System property or an Environment variable.
System Property : com.amazonaws.sdk.disableEc2Metadata
Environment variable : AWS_EC2_METADATA_DISABLED
However, you will still get a warning at application startup, it tells you the EC2Metadata is disabled by configuration : "EC2 Instance Metadata Service is disabled"
2020-03-27 18:10:42.483 WARN 71123 --- [main] com.amazonaws.util.EC2MetadataUtils : Unable to retrieve the requested metadata (/latest/meta-data/instance-id). EC2 Instance Metadata Service is disabled
com.amazonaws.AmazonClientException: EC2 Instance Metadata Service is disabled
at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.readResource(InstanceMetadataServiceResourceFetcher.java:65)
at com.amazonaws.internal.EC2ResourceFetcher.readResource(EC2ResourceFetcher.java:66)
at com.amazonaws.util.EC2MetadataUtils.getItems(EC2MetadataUtils.java:402)
at com.amazonaws.util.EC2MetadataUtils.getData(EC2MetadataUtils.java:371)
at org.springframework.cloud.aws.context.support.env.AwsCloudEnvironmentCheckUtils.isRunningOnCloudEnvironment(AwsCloudEnvironmentCheckUtils.java:38)
...
Fix the problem adding in the application.yaml file:
logging:
level:
com:
amazonaws:
util:
EC2MetadataUtils: error
As far as I understand its trying to check if your application is running on cloud environment, from the 5th last line of the stacktrace
org.springframework.cloud.aws.context.support.env.AwsCloudEnvironmentCheckUtils.isRunningOnCloudEnvironment(AwsCloudEnvironmentCheckUtils.java:38)
I checked out the the repo and here is the code snippet -
public static boolean isRunningOnCloudEnvironment() {
if (isCloudEnvironment == null) {
try {
isCloudEnvironment = EC2MetadataUtils
.getData(EC2_METADATA_ROOT + "/instance-id", 1) != null;
}
catch (AmazonClientException e) {
isCloudEnvironment = false;
}
}
return isCloudEnvironment;
}
As per the snippet it tried to fetch instance metadata and if it fails it return false, which means you are not on the Cloud Environment. However this code is expected to Catch AmazonClientException but the stacktrace you shared is throwing SdkClientException exception, which this part of the snippet can't catch and hence can't return false that you are not on a cloud environment.
Seems like some issue with this build of the library, As per the stacktrace you are using 2.2.1.RELEASE1 which was released 9 days back only. Could you please try to use one of the older version and then report if you are still facing the same issue.
Or as a temporary fix you can try tunnelling to your VPC's entry server. You can use sshuttle for tunnelling purpose if you want. This will mostly make that IP reachable from local machine as well.
I was getting same kind of error when running s3 bucket in spring boot i solved using different location used while creating bucket:
return AmazonS3ClientBuilder
.standard()
.withRegion("us-east-1") //This is the code i added to fix
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
Set cloud.aws.region.auto property to false in Spring application properties (or via environment variables etc.).
Define cloud.aws.region.static property.
This will tell Spring not to use automatic detection based EC2 meta data. Some details.
You may need to configure credentials similarly, you can find related info in the same doc.
The issue is with the spring-cloud version Hoxton.SR8. Replace your spring-cloud version in your pom.xml with Finchley.SR1.
I also faced similar error but not from the Spring cloud. When i added below configuration in application.properties, error went away.
logging.level.com.amazonaws.util.EC2MetadataUtils=error
logging.level.com.amazonaws.internal.InstanceMetadataServiceResourceFetcher=error
But i'm facing some other issues while opening s3a path. Then i printed the stacktrace of the exception and then i got below error
Caused by: com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [BasicAWSCredentialsProvider: Access key or secret key is null, WebIdentityTokenCredentialsProvider: You must specify a value for roleArn and roleSessionName, EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), com.amazonaws.auth.InstanceProfileCredentialsProvider#7700439a: Failed to connect to service endpoint: ]
Already credentials are there /.aws folder but not sure why application still giving the error. Fixed by creating environment variables AWS_ACCESS_KEY_ID, AWS_SECRET_KEY and AWS_SESSION_TOKEN
This was coming from an internal dependency at my company, so I couldn't get any of the previously posted solutions to work. What worked for me was to simply set in my environment variables AWS_REGION = 'us-east-1'.

Zipkin using Consul service name

For some reason Zipkin is using the Consul discovery name instead of the base spring.application.name property.
spring:
consul:
discovery:
prefer-ip-address: true
instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
But I want it to use the non-randomized application name (so myservice instead of myservice-67gg8d368).
If I set the Zipkin property zipkin.service.name then Consul throws errors saying it cannot find the service.
I'm unsure why the two are even sharing properties and not just adhering to their own. I'd like the service to use it's base application name because otherwise Zipkin is hard to use, as it lists every new container as a completely new service, making it very difficult to see over time how code changes have changed timing.
UPDATE:
This is the error I get in my logs if I set the zipkin.service.name
[o.s.c.c.d.ConsulDiscoveryClient] : Unable to locate service in consul agent: my-service-91828f2f88f18c3fadf193bfa3ad6d1f

Disable Redis AutoConfig in spring boot when testing

I am trying to disable Redis when I am testing with spring boot. I have disabled my configuration but the auto config created a default connection and fails because it can't connect to a non-existent service. For testing I am content to just use a basic in-memory cache or a no-op cache. That doesn't work either. Here is what I have tried:
per this issue I added said configuration to my test app properties
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
But. That gets me a bit further. But ultimately I get a NoSuchBeanDefinitionException redisTemplate - this is because redisReferenceResolver is trying to look that up.
Looking at my debugger right now, the bean it's trying to hydrate is:
org.springframework.data.redis.core.convert.ReferenceResolverImpl which is coming from spring-data-redis:1.8.0.RELEASE which is coming from this dependency: compile('org.springframework.boot:spring-boot-starter-data-redis') . I admit, the bean name is a bit misleading. The type it actually resolves to is not
The only other reference to redis is in our hibernate support.
Can someone explain how to turn this off for testing?
Try excluding this two auto-configuration classes in your test properties file:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
or
exclude
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
and set: spring.data.redis.repositories.enabled=false
With YAML syntax (& Spring Boot):
spring.autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
- org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
If you have SystemEnvironmentPropertySource in you app context you can use environment variable SPRING_AUTOCONFIGURE_EXCLUDE separating items with comma:
SPRING_AUTOCONFIGURE_EXCLUDE=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
Also try #EnableAutoConfiguration(exclude = {...}) on a #TestConfiguration annotated class.
If you dont want to change any files/code, you can also do this with an environment variable:
SPRING_AUTOCONFIGURE_EXCLUDE=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration

Categories

Resources