/* * Copyright 2018 the original author or authors. * * Licensed 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 de.codecentric.spring.boot.chaos.monkey.configuration; import de.codecentric.spring.boot.chaos.monkey.assaults.ChaosMonkeyAssault; import de.codecentric.spring.boot.chaos.monkey.assaults.ChaosMonkeyRequestAssault; import de.codecentric.spring.boot.chaos.monkey.assaults.ChaosMonkeyRuntimeAssault; import de.codecentric.spring.boot.chaos.monkey.assaults.ExceptionAssault; import de.codecentric.spring.boot.chaos.monkey.assaults.KillAppAssault; import de.codecentric.spring.boot.chaos.monkey.assaults.LatencyAssault; import de.codecentric.spring.boot.chaos.monkey.assaults.MemoryAssault; import de.codecentric.spring.boot.chaos.monkey.component.ChaosMonkeyRequestScope; import de.codecentric.spring.boot.chaos.monkey.component.ChaosMonkeyRuntimeScope; import de.codecentric.spring.boot.chaos.monkey.component.ChaosMonkeyScheduler; import de.codecentric.spring.boot.chaos.monkey.component.MetricEventPublisher; import de.codecentric.spring.boot.chaos.monkey.component.Metrics; import de.codecentric.spring.boot.chaos.monkey.endpoints.ChaosMonkeyJmxEndpoint; import de.codecentric.spring.boot.chaos.monkey.endpoints.ChaosMonkeyRestEndpoint; import de.codecentric.spring.boot.chaos.monkey.watcher.SpringComponentAspect; import de.codecentric.spring.boot.chaos.monkey.watcher.SpringControllerAspect; import de.codecentric.spring.boot.chaos.monkey.watcher.SpringRepositoryAspectJDBC; import de.codecentric.spring.boot.chaos.monkey.watcher.SpringRepositoryAspectJPA; import de.codecentric.spring.boot.chaos.monkey.watcher.SpringRestControllerAspect; import de.codecentric.spring.boot.chaos.monkey.watcher.SpringServiceAspect; import java.io.IOException; import java.nio.charset.Charset; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Profile; import org.springframework.core.io.ClassPathResource; import org.springframework.lang.Nullable; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.util.StreamUtils; /** @author Benjamin Wilms */ @Configuration @Profile("chaos-monkey") @EnableConfigurationProperties({ ChaosMonkeyProperties.class, AssaultProperties.class, WatcherProperties.class }) @EnableScheduling public class ChaosMonkeyConfiguration { private static final Logger Logger = LoggerFactory.getLogger(ChaosMonkeyConfiguration.class); private final ChaosMonkeyProperties chaosMonkeyProperties; private final WatcherProperties watcherProperties; private final AssaultProperties assaultProperties; public ChaosMonkeyConfiguration( ChaosMonkeyProperties chaosMonkeyProperties, WatcherProperties watcherProperties, AssaultProperties assaultProperties) { this.chaosMonkeyProperties = chaosMonkeyProperties; this.watcherProperties = watcherProperties; this.assaultProperties = assaultProperties; try { String chaosLogo = StreamUtils.copyToString( new ClassPathResource("chaos-logo.txt").getInputStream(), Charset.defaultCharset()); Logger.info(chaosLogo); } catch (IOException e) { Logger.info("Chaos Monkey - ready to do evil"); } } @Bean @ConditionalOnClass(name = "io.micrometer.core.instrument.MeterRegistry") public Metrics metrics() { return new Metrics(); } @Bean public MetricEventPublisher publisher() { return new MetricEventPublisher(); } @Bean public ChaosMonkeySettings settings() { return new ChaosMonkeySettings(chaosMonkeyProperties, assaultProperties, watcherProperties); } @Bean public LatencyAssault latencyAssault() { return new LatencyAssault(settings(), publisher()); } @Bean public ExceptionAssault exceptionAssault() { return new ExceptionAssault(settings(), publisher()); } @Bean public KillAppAssault killAppAssault() { return new KillAppAssault(settings(), publisher()); } @Bean public MemoryAssault memoryAssault() { return new MemoryAssault(Runtime.getRuntime(), settings(), publisher()); } @Bean public ChaosMonkeyRequestScope chaosMonkeyRequestScope( List<ChaosMonkeyRequestAssault> chaosMonkeyAssaults, List<ChaosMonkeyAssault> allAssaults) { return new ChaosMonkeyRequestScope(settings(), chaosMonkeyAssaults, allAssaults, publisher()); } @Bean public ChaosMonkeyScheduler scheduler( @Nullable TaskScheduler scheduler, ChaosMonkeyRuntimeScope runtimeScope) { ScheduledTaskRegistrar registrar = null; if (scheduler != null) { registrar = new ScheduledTaskRegistrar(); registrar.setTaskScheduler(scheduler); } return new ChaosMonkeyScheduler(registrar, assaultProperties, runtimeScope); } @Bean public ChaosMonkeyRuntimeScope chaosMonkeyRuntimeScope( List<ChaosMonkeyRuntimeAssault> chaosMonkeyAssaults) { return new ChaosMonkeyRuntimeScope(settings(), chaosMonkeyAssaults); } @Bean @DependsOn("chaosMonkeyRequestScope") public SpringControllerAspect controllerAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) { return new SpringControllerAspect(chaosMonkeyRequestScope, publisher(), watcherProperties); } @Bean @DependsOn("chaosMonkeyRequestScope") public SpringRestControllerAspect restControllerAspect( ChaosMonkeyRequestScope chaosMonkeyRequestScope) { return new SpringRestControllerAspect(chaosMonkeyRequestScope, publisher(), watcherProperties); } @Bean @DependsOn("chaosMonkeyRequestScope") public SpringServiceAspect serviceAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) { return new SpringServiceAspect(chaosMonkeyRequestScope, publisher(), watcherProperties); } @Bean @DependsOn("chaosMonkeyRequestScope") public SpringComponentAspect componentAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) { return new SpringComponentAspect(chaosMonkeyRequestScope, publisher(), watcherProperties); } @Bean @DependsOn("chaosMonkeyRequestScope") @ConditionalOnClass(name = "org.springframework.data.repository.Repository") // Creates aspects that match interfaces annotated with @Repository public SpringRepositoryAspectJPA repositoryAspectJpa( ChaosMonkeyRequestScope chaosMonkeyRequestScope) { return new SpringRepositoryAspectJPA(chaosMonkeyRequestScope, publisher(), watcherProperties); } @Bean @DependsOn("chaosMonkeyRequestScope") // creates aspects that match simple classes annotated with @repository public SpringRepositoryAspectJDBC repositoryAspectJdbc( ChaosMonkeyRequestScope chaosMonkeyRequestScope) { return new SpringRepositoryAspectJDBC(chaosMonkeyRequestScope, publisher(), watcherProperties); } @Bean @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint public ChaosMonkeyRestEndpoint chaosMonkeyRestEndpoint( ChaosMonkeyRuntimeScope runtimeScope, ChaosMonkeyScheduler scheduler) { return new ChaosMonkeyRestEndpoint(settings(), runtimeScope, scheduler); } @Bean @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint public ChaosMonkeyJmxEndpoint chaosMonkeyJmxEndpoint() { return new ChaosMonkeyJmxEndpoint(settings()); } }