diff --git a/gradle.properties b/gradle.properties index 731482fd7..2706dc37d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ kotlinVersion=1.4.32 org.gradle.parallel=true spinnakerGradleVersion=8.25.0 targetJava11=true -includeRuntimes=actuator,core,eureka,retrofit,secrets-aws,secrets-gcp,stackdriver,swagger,tomcat,web +includeRuntimes=actuator,core,eureka,retrofit2,secrets-aws,secrets-gcp,stackdriver,swagger,tomcat,web diff --git a/kork-retrofit/kork-retrofit.gradle b/kork-retrofit/kork-retrofit.gradle deleted file mode 100644 index 8c30711b3..000000000 --- a/kork-retrofit/kork-retrofit.gradle +++ /dev/null @@ -1,24 +0,0 @@ -apply plugin: "java-library" -apply from: "$rootDir/gradle/kotlin-test.gradle" -apply from: "$rootDir/gradle/lombok.gradle" - -dependencies { - api(platform(project(":spinnaker-dependencies"))) - - implementation project(":kork-web") - - implementation "com.squareup.retrofit:retrofit" - implementation "com.jakewharton.retrofit:retrofit1-okhttp3-client" - implementation "com.squareup.retrofit:converter-jackson" - implementation "io.zipkin.brave:brave-instrumentation-okhttp3" - - testImplementation project(":kork-test") - testImplementation "org.spockframework:spock-core" - testImplementation "org.spockframework:spock-spring" - testImplementation "org.springframework.boot:spring-boot-starter-test" - testImplementation "com.netflix.spectator:spectator-reg-micrometer" - testImplementation "com.squareup.okhttp3:mockwebserver" - testRuntimeOnly "cglib:cglib-nodep" - testRuntimeOnly "org.objenesis:objenesis" - -} diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/RetrofitServiceFactory.java b/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/RetrofitServiceFactory.java deleted file mode 100644 index 40465bec5..000000000 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/RetrofitServiceFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020 Netflix, Inc. - * - * 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 com.netflix.spinnaker.kork.retrofit; - -import static retrofit.Endpoints.newFixedEndpoint; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.jakewharton.retrofit.Ok3Client; -import com.netflix.spinnaker.config.ServiceEndpoint; -import com.netflix.spinnaker.config.okhttp3.OkHttpClientProvider; -import com.netflix.spinnaker.kork.annotations.NonnullByDefault; -import com.netflix.spinnaker.kork.client.ServiceClientFactory; -import com.netflix.spinnaker.retrofit.Slf4jRetrofitLogger; -import retrofit.Endpoint; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; -import retrofit.converter.JacksonConverter; - -@NonnullByDefault -class RetrofitServiceFactory implements ServiceClientFactory { - - private final RestAdapter.LogLevel retrofitLogLevel; - private final OkHttpClientProvider clientProvider; - private final RequestInterceptor spinnakerRequestInterceptor; - - RetrofitServiceFactory( - RestAdapter.LogLevel retrofitLogLevel, - OkHttpClientProvider clientProvider, - RequestInterceptor spinnakerRequestInterceptor) { - this.retrofitLogLevel = retrofitLogLevel; - this.clientProvider = clientProvider; - this.spinnakerRequestInterceptor = spinnakerRequestInterceptor; - } - - @Override - public T create(Class type, ServiceEndpoint serviceEndpoint, ObjectMapper objectMapper) { - Endpoint endpoint = newFixedEndpoint(serviceEndpoint.getBaseUrl()); - return new RestAdapter.Builder() - .setRequestInterceptor(spinnakerRequestInterceptor) - .setConverter(new JacksonConverter(objectMapper)) - .setEndpoint(endpoint) - .setClient(new Ok3Client(clientProvider.getClient(serviceEndpoint))) - .setLogLevel(retrofitLogLevel) - .setLog(new Slf4jRetrofitLogger(type)) - .build() - .create(type); - } -} diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/RetrofitServiceFactoryAutoConfiguration.java b/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/RetrofitServiceFactoryAutoConfiguration.java deleted file mode 100644 index d9a93fb9e..000000000 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/RetrofitServiceFactoryAutoConfiguration.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2020 Netflix, Inc. - * - * 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 com.netflix.spinnaker.kork.retrofit; - -import com.netflix.spinnaker.config.okhttp3.OkHttpClientProvider; -import com.netflix.spinnaker.kork.client.ServiceClientFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; - -@Configuration -@ConditionalOnProperty(value = "retrofit.enabled", havingValue = "true", matchIfMissing = true) -public class RetrofitServiceFactoryAutoConfiguration { - - @Bean - @Order(Ordered.LOWEST_PRECEDENCE) - ServiceClientFactory serviceClientFactory( - RestAdapter.LogLevel retrofitLogLevel, - OkHttpClientProvider clientProvider, - RequestInterceptor spinnakerRequestInterceptor) { - return new RetrofitServiceFactory( - retrofitLogLevel, clientProvider, spinnakerRequestInterceptor); - } -} diff --git a/kork-retrofit/src/main/resources/META-INF/spring.factories b/kork-retrofit/src/main/resources/META-INF/spring.factories deleted file mode 100644 index bf79b5722..000000000 --- a/kork-retrofit/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.netflix.spinnaker.kork.retrofit.RetrofitServiceFactoryAutoConfiguration diff --git a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandlerTest.java b/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandlerTest.java deleted file mode 100644 index 5c15fc37b..000000000 --- a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandlerTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2020 Avast Software, Inc. - * - * 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 com.netflix.spinnaker.kork.retrofit.exceptions; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.Assert; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.http.HttpStatus; -import retrofit.RestAdapter; -import retrofit.RetrofitError; -import retrofit.client.Response; -import retrofit.converter.JacksonConverter; -import retrofit.http.GET; - -public class SpinnakerRetrofitErrorHandlerTest { - - private static RetrofitService retrofitService; - - private static final MockWebServer mockWebServer = new MockWebServer(); - - @BeforeAll - public static void setupOnce() throws Exception { - mockWebServer.start(); - retrofitService = - new RestAdapter.Builder() - .setEndpoint(mockWebServer.url("/").toString()) - .setErrorHandler(SpinnakerRetrofitErrorHandler.getInstance()) - .build() - .create(RetrofitService.class); - } - - @AfterAll - public static void shutdownOnce() throws Exception { - mockWebServer.shutdown(); - } - - @Test - public void testNotFoundIsNotRetryable() { - mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.NOT_FOUND.value())); - SpinnakerHttpException notFoundException = - assertThrows(SpinnakerHttpException.class, () -> retrofitService.getFoo()); - assertNotNull(notFoundException.getRetryable()); - assertFalse(notFoundException.getRetryable()); - } - - @ParameterizedTest(name = "Deserialize response using {0}") - // Test the different converters used to deserialize the response body to the - // SpinnakerServerException.RetrofitErrorResponseBody class: - // - // - the JacksonConverter constructed without an ObjectMapper is used in - // Clouddriver's RestAdapter to communicate with Front50Service - // - // - the JacksonConverter constructed with an ObjectMapper is used in Rosco's RestAdapter to - // communicate with Clouddriver - // - // - GSONConverter is the default converter used by Retrofit if no converter - // is set when building out the RestAdapter - @ValueSource( - strings = {"Default_GSONConverter", "JacksonConverter", "JacksonConverterWithObjectMapper"}) - public void testResponseWithExtraField(String retrofitConverter) throws Exception { - Map responseBodyMap = new HashMap<>(); - responseBodyMap.put("timestamp", "123123123123"); - responseBodyMap.put("message", "Not Found error Message"); - String responseBodyString = new ObjectMapper().writeValueAsString(responseBodyMap); - - RestAdapter.Builder restAdapter = - new RestAdapter.Builder() - .setEndpoint(mockWebServer.url("/").toString()) - .setErrorHandler(SpinnakerRetrofitErrorHandler.getInstance()); - - if (retrofitConverter.equals("JacksonConverter")) { - restAdapter.setConverter(new JacksonConverter()); - } else if (retrofitConverter.equals("JacksonConverterWithObjectMapper")) { - ObjectMapper objectMapper = - new ObjectMapper() - .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - - restAdapter.setConverter(new JacksonConverter(objectMapper)); - } - - RetrofitService retrofitServiceTestConverter = - restAdapter.build().create(RetrofitService.class); - - mockWebServer.enqueue( - new MockResponse() - .setBody(responseBodyString) - // an arbitrary response code -- one that - // SpinnakerRetrofitErrorHandler converts to a - // SpinnakerServerException (or one of its children). - .setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); - - // If the converter can not deserialize the response body to the - // SpinnakerServerException.RetrofitErrorResponseBody - // class, then a RuntimeException will be thrown with a ConversionException nested inside. - // - // java.lang.RuntimeException: - // retrofit.converter.ConversionException: - // com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field - // "..." - // - // so make sure we get a SpinnakerHttpException from calling getFoo - assertThrows(SpinnakerHttpException.class, retrofitServiceTestConverter::getFoo); - } - - @Test - public void testBadRequestIsNotRetryable() { - mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.BAD_REQUEST.value())); - SpinnakerHttpException spinnakerHttpException = - assertThrows(SpinnakerHttpException.class, () -> retrofitService.getFoo()); - assertNotNull(spinnakerHttpException.getRetryable()); - assertFalse(spinnakerHttpException.getRetryable()); - } - - @Test - public void testOtherClientErrorHasNullRetryable() { - // Arbitrarily choose GONE as an example of a client (e.g. 4xx) error that - // we expect to have null retryable - mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.GONE.value())); - SpinnakerHttpException spinnakerHttpException = - assertThrows(SpinnakerHttpException.class, () -> retrofitService.getFoo()); - assertNull(spinnakerHttpException.getRetryable()); - } - - @Test - public void testSimpleSpinnakerNetworkException() { - String message = "my custom message"; - IOException e = new IOException(message); - RetrofitError retrofitError = RetrofitError.networkError("http://localhost", e); - SpinnakerRetrofitErrorHandler handler = SpinnakerRetrofitErrorHandler.getInstance(); - Throwable throwable = handler.handleError(retrofitError); - Assert.assertEquals(message, throwable.getMessage()); - } - - interface RetrofitService { - @GET("/foo") - Response getFoo(); - } -} diff --git a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlersTest.java b/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlersTest.java deleted file mode 100644 index bcb03a734..000000000 --- a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlersTest.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2021 Salesforce, Inc. - * - * 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 com.netflix.spinnaker.kork.retrofit.exceptions; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import ch.qos.logback.classic.Level; -import com.netflix.spinnaker.config.ErrorConfiguration; -import com.netflix.spinnaker.config.RetrofitErrorConfiguration; -import com.netflix.spinnaker.kork.test.log.MemoryAppender; -import java.net.URI; -import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.test.context.TestPropertySource; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; -import retrofit.client.Response; -import retrofit.mime.TypedString; - -@SpringBootTest( - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { - ErrorConfiguration.class, - RetrofitErrorConfiguration.class, - SpinnakerRetrofitExceptionHandlersTest.TestControllerConfiguration.class - }) -@TestPropertySource(properties = {"retrofit.enabled = false"}) -class SpinnakerRetrofitExceptionHandlersTest { - - private static final String CUSTOM_MESSAGE = "custom message"; - - @LocalServerPort int port; - - @Autowired TestRestTemplate restTemplate; - - private MemoryAppender memoryAppender; - - @BeforeEach - private void setup(TestInfo testInfo) { - System.out.println("--------------- Test " + testInfo.getDisplayName()); - memoryAppender = new MemoryAppender(SpinnakerRetrofitExceptionHandlers.class); - } - - @Test - void testSpinnakerServerException() throws Exception { - URI uri = getUri("/spinnakerServerException"); - - ResponseEntity entity = restTemplate.getForEntity(uri, String.class); - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode()); - assertEquals(1, memoryAppender.countEventsForLevel(Level.ERROR)); - } - - @Test - void testChainedSpinnakerServerException() throws Exception { - URI uri = getUri("/chainedSpinnakerServerException"); - - ResponseEntity entity = restTemplate.getForEntity(uri, String.class); - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode()); - assertEquals(1, memoryAppender.countEventsForLevel(Level.ERROR)); - - // Make sure the message is what we expect. - assertEquals(1, memoryAppender.search(CUSTOM_MESSAGE, Level.ERROR).size()); - } - - @ParameterizedTest(name = "testSpinnakerHttpException status = {0}") - @ValueSource(ints = {403, 400, 500}) - void testSpinnakerHttpException(int status) throws Exception { - URI uri = getUri("/spinnakerHttpException/" + String.valueOf(status)); - - ResponseEntity entity = restTemplate.getForEntity(uri, String.class); - assertEquals(status, entity.getStatusCode().value()); - - // Only expect error logging for a server error, debug otherwise. No need - // to fill up logs with client errors assuming the server is doing the best - // it can. - assertEquals( - 1, - memoryAppender.countEventsForLevel( - HttpStatus.resolve(status).is5xxServerError() ? Level.ERROR : Level.DEBUG)); - } - - @ParameterizedTest(name = "testChainedSpinnakerHttpException status = {0}") - @ValueSource(ints = {403, 400, 500}) - void testChainedSpinnakerHttpException(int status) throws Exception { - URI uri = getUri("/chainedSpinnakerHttpException/" + String.valueOf(status)); - - ResponseEntity entity = restTemplate.getForEntity(uri, String.class); - assertEquals(status, entity.getStatusCode().value()); - - // Only expect error logging for a server error, debug otherwise. No need - // to fill up logs with client errors assuming the server is doing the best - // it can. - assertEquals( - 1, - memoryAppender.countEventsForLevel( - HttpStatus.resolve(status).is5xxServerError() ? Level.ERROR : Level.DEBUG)); - - // Make sure the message is what we expect. - assertEquals( - 1, - memoryAppender - .search( - CUSTOM_MESSAGE, - HttpStatus.resolve(status).is5xxServerError() ? Level.ERROR : Level.DEBUG) - .size()); - } - - private URI getUri(String path) { - return UriComponentsBuilder.fromHttpUrl("http://localhost/test-controller") - .port(port) - .path(path) - .build() - .toUri(); - } - - @Configuration - @EnableAutoConfiguration - static class TestControllerConfiguration { - @EnableWebSecurity - class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable().headers().disable().authorizeRequests().anyRequest().permitAll(); - } - } - - @Bean - TestController testController() { - return new TestController(); - } - } - - @RestController - @RequestMapping("/test-controller") - static class TestController { - - @GetMapping("/spinnakerServerException") - void spinnakerServerException() { - // Building a "real" RetrofitError object to pass to the - // SpinnakerServerException constructor isn't great, e.g.: - // - // String url = "https://some-url"; - // Response response = new Response(url, HttpStatus.BAD_GATEWAY.value(), "arbitrary reason", - // List.of(), new TypedString("{ message: \"message\" }")) - // RetrofitError retrofitError = RetrofitError.httpError(url, response, - // Platform.get().defaultConverter(), Response.class) - // - // and neither is a mock RetrofitError object since it means exposing - // SpinnakerServerException.RetrofitErrorResponseBody, e.g: - // - // RetrofitError retrofitError = mock(RetrofitError.class) - // String message = "message"; - // SpinnakerServerException.RetrofitErrorResponseBody retrofitErrorResponseBody = new - // SpinnakerServerException.RetrofitErrorResponseBody(message); - // when(retrofitError.getBodyAs(any())).thenReturn retrofitErrorResponseBody; - // throw new SpinnakerServerException(retrofitError) - // - // And in the end, the thing we care about is how SpinnakerServerException - // gets handled. This isn't a test of how the SpinnakerServerException - // class uses a RetrofitError to build its message. - SpinnakerServerException spinnakerServerException = mock(SpinnakerServerException.class); - when(spinnakerServerException.getMessage()).thenReturn("message"); - throw spinnakerServerException; - } - - @GetMapping("/chainedSpinnakerServerException") - void chainedSpinnakerServerException() { - SpinnakerServerException spinnakerServerException = mock(SpinnakerServerException.class); - when(spinnakerServerException.getMessage()).thenReturn("message"); - throw new SpinnakerServerException(CUSTOM_MESSAGE, spinnakerServerException); - } - - @GetMapping("/spinnakerHttpException/{status}") - void spinnakerHttpException(@PathVariable int status) { - throw makeSpinnakerHttpException(status); - } - - @GetMapping("/chainedSpinnakerHttpException/{status}") - void chainedSpinnakerHttpException(@PathVariable int status) { - throw new SpinnakerHttpException(CUSTOM_MESSAGE, makeSpinnakerHttpException(status)); - } - - SpinnakerHttpException makeSpinnakerHttpException(int status) { - SpinnakerHttpException spinnakerHttpException = mock(SpinnakerHttpException.class); - when(spinnakerHttpException.getMessage()).thenReturn("message"); - - // Response is a final class, so straightforward mocking fails. - String url = "https://some-url"; - Response response = - new Response( - url, - status, - "arbitrary reason", - List.of(), - new TypedString("{ message: \"unused message due to above mock\" }")); - - when(spinnakerHttpException.getResponse()).thenReturn(response); - return spinnakerHttpException; - } - } -} diff --git a/kork-retrofit/src/test/kotlin/com/netflix/spinnaker/kork/retrofit/RetrofitServiceProviderTest.kt b/kork-retrofit/src/test/kotlin/com/netflix/spinnaker/kork/retrofit/RetrofitServiceProviderTest.kt deleted file mode 100644 index 890edbd49..000000000 --- a/kork-retrofit/src/test/kotlin/com/netflix/spinnaker/kork/retrofit/RetrofitServiceProviderTest.kt +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2020 Netflix, Inc. - * - * 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 com.netflix.spinnaker.kork.retrofit - -import brave.Tracing -import brave.http.HttpTracing -import com.fasterxml.jackson.databind.ObjectMapper -import com.netflix.spinnaker.config.DefaultServiceEndpoint -import com.netflix.spinnaker.config.RetrofitConfiguration -import com.netflix.spinnaker.config.okhttp3.DefaultOkHttpClientBuilderProvider -import com.netflix.spinnaker.config.okhttp3.OkHttpClientProvider -import com.netflix.spinnaker.config.okhttp3.RawOkHttpClientFactory -import com.netflix.spinnaker.config.DefaultServiceClientProvider -import com.netflix.spinnaker.kork.client.ServiceClientFactory -import com.netflix.spinnaker.kork.client.ServiceClientProvider -import com.netflix.spinnaker.okhttp.OkHttpClientConfigurationProperties -import com.netflix.spinnaker.okhttp.SpinnakerRequestInterceptor -import dev.minutest.junit.JUnit5Minutests -import dev.minutest.rootContext -import okhttp3.OkHttpClient -import org.springframework.boot.autoconfigure.AutoConfigurations -import org.springframework.boot.test.context.assertj.AssertableApplicationContext -import org.springframework.boot.test.context.runner.ApplicationContextRunner -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import retrofit.Callback -import retrofit.http.GET -import retrofit.http.Path -import strikt.api.expect -import strikt.assertions.isA -import strikt.assertions.isEqualTo - -class RetrofitServiceProviderTest : JUnit5Minutests { - - fun tests() = rootContext { - derivedContext("no configuration") { - fixture { - ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of( - RetrofitServiceFactoryAutoConfiguration::class.java, - RetrofitConfiguration::class.java, - TestConfiguration::class.java - )) - } - - test("initializes service client provider") { - run { ctx: AssertableApplicationContext -> - expect { - that(ctx.getBeansOfType(ServiceClientProvider::class.java)).get { size }.isEqualTo(1) - that(ctx.getBean(ServiceClientProvider::class.java).getService(Retrofit1Service::class.java, DefaultServiceEndpoint("retrofit1", "https://www.test.com"))).isA() - } - } - } - - test("initializes service client factories") { - run { ctx: AssertableApplicationContext -> - expect { - that(ctx.getBeansOfType(ServiceClientFactory::class.java)).get { size }.isEqualTo(1) - } - } - } - - } - } - -} - -@Configuration -private open class TestConfiguration { - - @Bean - open fun httpTracing(): HttpTracing = - HttpTracing.newBuilder(Tracing.newBuilder().build()).build() - - @Bean - open fun okHttpClient(httpTracing: HttpTracing): OkHttpClient { - return RawOkHttpClientFactory().create(OkHttpClientConfigurationProperties(), emptyList(), httpTracing) - } - - @Bean - open fun okHttpClientProvider(okHttpClient: OkHttpClient): OkHttpClientProvider { - return OkHttpClientProvider(listOf(DefaultOkHttpClientBuilderProvider(okHttpClient, OkHttpClientConfigurationProperties()))) - } - - @Bean - open fun spinnakerRequestInterceptor(): SpinnakerRequestInterceptor { - return SpinnakerRequestInterceptor(OkHttpClientConfigurationProperties()) - } - - @Bean - open fun objectMapper(): ObjectMapper { - return ObjectMapper() - } - - @Bean - open fun serviceClientProvider( - serviceClientFactories: List, objectMapper: ObjectMapper): DefaultServiceClientProvider { - return DefaultServiceClientProvider(serviceClientFactories, objectMapper) - } - -} - -interface Retrofit1Service { - - @GET("/users/{user}/something") - fun getSomething(@Path("user") user: String?, callback: Callback?>?) - -} - - diff --git a/kork-retrofit2/kork-retrofit2.gradle b/kork-retrofit2/kork-retrofit2.gradle index f85d1f9b7..fd1c20f6d 100644 --- a/kork-retrofit2/kork-retrofit2.gradle +++ b/kork-retrofit2/kork-retrofit2.gradle @@ -1,5 +1,6 @@ apply plugin: "java-library" apply from: "$rootDir/gradle/kotlin-test.gradle" +apply from: "$rootDir/gradle/lombok.gradle" dependencies { api(platform(project(":spinnaker-dependencies"))) diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/config/RetrofitErrorConfiguration.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/config/RetrofitErrorConfiguration.java similarity index 93% rename from kork-retrofit/src/main/java/com/netflix/spinnaker/config/RetrofitErrorConfiguration.java rename to kork-retrofit2/src/main/java/com/netflix/spinnaker/config/RetrofitErrorConfiguration.java index 260bdd05d..775432c99 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/config/RetrofitErrorConfiguration.java +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/config/RetrofitErrorConfiguration.java @@ -1,11 +1,11 @@ /* - * Copyright 2021 Salesforce, Inc. + * Copyright 2022 Netflix, Inc. * * 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 + * 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, diff --git a/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitException.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitException.java new file mode 100644 index 000000000..d0ae30720 --- /dev/null +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitException.java @@ -0,0 +1,110 @@ +/* + * Copyright 2022 Netflix, Inc. + * + * 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 com.netflix.spinnaker.kork.retrofit.exceptions; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import okhttp3.ResponseBody; +import retrofit2.Converter; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class RetrofitException extends RuntimeException { + public static RetrofitException httpError(String url, Response response, Retrofit retrofit) { + String message = response.code() + " " + response.message(); + return new RetrofitException(message, url, response, Kind.HTTP, null, retrofit); + } + + public static RetrofitException networkError(IOException exception) { + return new RetrofitException(exception.getMessage(), null, null, Kind.NETWORK, exception, null); + } + + public static RetrofitException unexpectedError(Throwable exception) { + return new RetrofitException( + exception.getMessage(), null, null, Kind.UNEXPECTED, exception, null); + } + + /** Identifies the event kind which triggered a {@link RetrofitException}. */ + public enum Kind { + /** An {@link IOException} occurred while communicating to the server. */ + NETWORK, + /** A non-200 HTTP status code was received from the server. */ + HTTP, + /** + * An internal error occurred while attempting to execute a request. It is best practice to + * re-throw this exception so your application crashes. + */ + UNEXPECTED + } + + private final String url; + private final Response response; + private final Kind kind; + private final Retrofit retrofit; + + RetrofitException( + String message, + String url, + Response response, + Kind kind, + Throwable exception, + Retrofit retrofit) { + super(message, exception); + this.url = url; + this.response = response; + this.kind = kind; + this.retrofit = retrofit; + } + + /** The request URL which produced the error. */ + public String getUrl() { + return url; + } + + /** Response object containing status code, headers, body, etc. */ + public Response getResponse() { + return response; + } + + /** The event kind which triggered this error. */ + public Kind getKind() { + return kind; + } + + /** The Retrofit this request was executed on */ + public Retrofit getRetrofit() { + return retrofit; + } + + /** + * HTTP response body converted to specified {@code type}. {@code null} if there is no response. + * + * @throws IOException if unable to convert the body to the specified {@code type}. + */ + public T getBodyAs(Class type) { + if (response == null || response.errorBody() == null) { + return null; + } + try { + Converter converter = + retrofit.responseBodyConverter(type, new Annotation[0]); + return converter.convert(response.errorBody()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java similarity index 84% rename from kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java rename to kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java index 17963006e..6e106b921 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Google, Inc. + * Copyright 2022 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,19 +18,18 @@ import com.netflix.spinnaker.kork.annotations.NonnullByDefault; import lombok.Getter; -import retrofit.RetrofitError; -import retrofit.client.Response; +import retrofit2.Response; /** - * An exception that exposes the {@link Response} of a given HTTP {@link RetrofitError} and a detail - * message that extracts useful information from the {@link Response}. + * An exception that exposes the {@link Response} of a given HTTP {@link RetrofitException} and a + * detail message that extracts useful information from the {@link Response}. */ @Getter @NonnullByDefault public class SpinnakerHttpException extends SpinnakerServerException { private final Response response; - public SpinnakerHttpException(RetrofitError e) { + public SpinnakerHttpException(RetrofitException e) { super(e); this.response = e.getResponse(); } @@ -61,8 +60,6 @@ public String getMessage() { if (getRawMessage() == null) { return super.getMessage(); } - return String.format( - "Status: %s, URL: %s, Message: %s", - response.getStatus(), response.getUrl(), getRawMessage()); + return String.format("Status: %s, URL: %s, Message: %s", response.code(), getRawMessage()); } } diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerNetworkException.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerNetworkException.java similarity index 84% rename from kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerNetworkException.java rename to kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerNetworkException.java index 8a5364604..88eaba217 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerNetworkException.java +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerNetworkException.java @@ -17,12 +17,11 @@ package com.netflix.spinnaker.kork.retrofit.exceptions; import com.netflix.spinnaker.kork.annotations.NonnullByDefault; -import retrofit.RetrofitError; -/** Wraps an exception of kind {@link RetrofitError.Kind} NETWORK. */ +/** Wraps an exception of kind {@link RetrofitException.Kind} NETWORK. */ @NonnullByDefault public final class SpinnakerNetworkException extends SpinnakerServerException { - public SpinnakerNetworkException(RetrofitError e) { + public SpinnakerNetworkException(RetrofitException e) { super(e); } } diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandler.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandler.java similarity index 74% rename from kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandler.java rename to kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandler.java index b03c54582..e948de38b 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandler.java +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitErrorHandler.java @@ -18,16 +18,14 @@ import com.netflix.spinnaker.kork.annotations.NonnullByDefault; import org.springframework.http.HttpStatus; -import retrofit.ErrorHandler; -import retrofit.RetrofitError; /** - * An error handler to be registered with a {@link retrofit.RestAdapter}. Allows clients to catch a + * An error handler to be registered with a {@link retrofit2.Retrofit}. Allows clients to catch a * SpinnakerServerException or something more specific (e.g. {@link SpinnakerHttpException}, or - * {@link SpinnakerNetworkException}) depending on the properties of the {@link RetrofitError}. + * {@link SpinnakerNetworkException}) depending on the properties of the {@link RetrofitException}) */ @NonnullByDefault -public final class SpinnakerRetrofitErrorHandler implements ErrorHandler { +public final class SpinnakerRetrofitErrorHandler { private SpinnakerRetrofitErrorHandler() {} /** @@ -41,18 +39,18 @@ public static SpinnakerRetrofitErrorHandler getInstance() { /** * Returns a more specific {@link Throwable} depending on properties of the caught {@link - * RetrofitError}. + * RetrofitException}. * - * @param e The {@link RetrofitError} thrown by an invocation of the {@link retrofit.RestAdapter} + * @param e The {@link RetrofitException} thrown by an invocation of the {@link + * retrofit2.Retrofit} * @return A more informative {@link Throwable} */ - @Override - public Throwable handleError(RetrofitError e) { + public Throwable handleError(RetrofitException e) { switch (e.getKind()) { case HTTP: SpinnakerHttpException retval = new SpinnakerHttpException(e); - if ((e.getResponse().getStatus() == HttpStatus.NOT_FOUND.value()) - || (e.getResponse().getStatus() == HttpStatus.BAD_REQUEST.value())) { + if ((e.getResponse().code() == HttpStatus.NOT_FOUND.value()) + || (e.getResponse().code() == HttpStatus.BAD_REQUEST.value())) { retval.setRetryable(false); } return retval; diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlers.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlers.java similarity index 98% rename from kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlers.java rename to kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlers.java index 80ae4e8fb..14207a90b 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlers.java +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerRetrofitExceptionHandlers.java @@ -63,7 +63,7 @@ public void handleSpinnakerHttpException( // We made an http request that failed and nothing else handled that // failure, so generate our response based on the response we received. storeException(request, response, e); - int status = e.getResponse().getStatus(); + int status = e.getResponse().code(); // Log server errors as errors, but client errors as debug to avoid filling // up the logs with someone else's problem. HttpStatus httpStatus = HttpStatus.resolve(status); diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerException.java b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerException.java similarity index 90% rename from kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerException.java rename to kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerException.java index 9a7cc6e2d..c32b44c0a 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerException.java +++ b/kork-retrofit2/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerException.java @@ -23,9 +23,8 @@ import com.netflix.spinnaker.kork.exceptions.SpinnakerException; import java.util.Optional; import lombok.Getter; -import retrofit.RetrofitError; -/** An exception that exposes the message of a {@link RetrofitError}, or a custom message. */ +/** An exception that exposes the message of a {@link RetrofitException}, or a custom message. */ @NonnullByDefault public class SpinnakerServerException extends SpinnakerException { @@ -36,11 +35,12 @@ public class SpinnakerServerException extends SpinnakerException { private final String rawMessage; /** - * Parses the message from the {@link RetrofitErrorResponseBody} of a {@link RetrofitError}. + * Parses the message from the {@link RetrofitErrorResponseBody} of a {@link RetrofitException}. * - * @param e The {@link RetrofitError} thrown by an invocation of the {@link retrofit.RestAdapter} + * @param e The {@link RetrofitException} thrown by an invocation of the {@link + * retrofit2.Retrofit} */ - public SpinnakerServerException(RetrofitError e) { + public SpinnakerServerException(RetrofitException e) { super(e.getCause()); RetrofitErrorResponseBody body = (RetrofitErrorResponseBody) e.getBodyAs(RetrofitErrorResponseBody.class); diff --git a/kork-web/kork-web.gradle b/kork-web/kork-web.gradle index 90425424c..3232f79e7 100644 --- a/kork-web/kork-web.gradle +++ b/kork-web/kork-web.gradle @@ -22,7 +22,8 @@ dependencies { api "com.fasterxml.jackson.core:jackson-annotations" api "com.squareup.okhttp:okhttp" api "com.squareup.okhttp3:okhttp" - api "com.squareup.retrofit:retrofit" + implementation "com.squareup.retrofit2:retrofit" + implementation "com.squareup.okhttp3:logging-interceptor" implementation "com.google.guava:guava" implementation "javax.inject:javax.inject:1" diff --git a/kork-web/src/main/groovy/com/netflix/spinnaker/config/RetrofitConfiguration.groovy b/kork-web/src/main/groovy/com/netflix/spinnaker/config/RetrofitConfiguration.groovy index 63cdcf318..4429b27aa 100644 --- a/kork-web/src/main/groovy/com/netflix/spinnaker/config/RetrofitConfiguration.groovy +++ b/kork-web/src/main/groovy/com/netflix/spinnaker/config/RetrofitConfiguration.groovy @@ -17,16 +17,16 @@ package com.netflix.spinnaker.config import com.netflix.spinnaker.retrofit.RetrofitConfigurationProperties +import okhttp3.logging.HttpLoggingInterceptor import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import retrofit.RestAdapter @Configuration @EnableConfigurationProperties(RetrofitConfigurationProperties) class RetrofitConfiguration { @Bean - RestAdapter.LogLevel retrofitLogLevel(RetrofitConfigurationProperties retrofitConfigurationProperties) { + HttpLoggingInterceptor.Level retrofitLogLevel(RetrofitConfigurationProperties retrofitConfigurationProperties) { return retrofitConfigurationProperties.logLevel } } diff --git a/kork-web/src/main/groovy/com/netflix/spinnaker/okhttp/SpinnakerRequestInterceptor.groovy b/kork-web/src/main/groovy/com/netflix/spinnaker/okhttp/SpinnakerRequestInterceptor.groovy index 0e97ddc69..b270c5130 100644 --- a/kork-web/src/main/groovy/com/netflix/spinnaker/okhttp/SpinnakerRequestInterceptor.groovy +++ b/kork-web/src/main/groovy/com/netflix/spinnaker/okhttp/SpinnakerRequestInterceptor.groovy @@ -17,25 +17,30 @@ package com.netflix.spinnaker.okhttp import com.netflix.spinnaker.security.AuthenticatedRequest -import retrofit.RequestInterceptor +import okhttp3.Interceptor +import okhttp3.Request +import okhttp3.Response -class SpinnakerRequestInterceptor implements RequestInterceptor { +class SpinnakerRequestInterceptor implements Interceptor { private final OkHttpClientConfigurationProperties okHttpClientConfigurationProperties SpinnakerRequestInterceptor(OkHttpClientConfigurationProperties okHttpClientConfigurationProperties) { this.okHttpClientConfigurationProperties = okHttpClientConfigurationProperties } - void intercept(RequestInterceptor.RequestFacade request) { + @Override + Response intercept(Chain chain) throws IOException { + Request request = chain.request(); if (!okHttpClientConfigurationProperties.propagateSpinnakerHeaders) { - // noop - return + return chain.proceed(request); } AuthenticatedRequest.authenticationHeaders.each { String key, Optional value -> if (value.present) { - request.addHeader(key, value.get()) + request = request.newBuilder().addHeader(key, value.get()) } + return chain.proceed(request); } } } + diff --git a/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/RetrofitConfigurationProperties.java b/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/RetrofitConfigurationProperties.java index c07786da9..a905b2309 100644 --- a/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/RetrofitConfigurationProperties.java +++ b/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/RetrofitConfigurationProperties.java @@ -16,18 +16,19 @@ package com.netflix.spinnaker.retrofit; +import okhttp3.logging.HttpLoggingInterceptor; import org.springframework.boot.context.properties.ConfigurationProperties; -import retrofit.RestAdapter; -@ConfigurationProperties("retrofit") +@ConfigurationProperties("retrofit2") public class RetrofitConfigurationProperties { - RestAdapter.LogLevel logLevel = RestAdapter.LogLevel.BASIC; - public RestAdapter.LogLevel getLogLevel() { + private HttpLoggingInterceptor.Level logLevel = HttpLoggingInterceptor.Level.BASIC; + + public HttpLoggingInterceptor.Level getLogLevel() { return logLevel; } - public void setLogLevel(RestAdapter.LogLevel logLevel) { + public void setLogLevel(HttpLoggingInterceptor.Level logLevel) { this.logLevel = logLevel; } } diff --git a/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/Slf4jRetrofitLogger.java b/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/Slf4jRetrofitLogger.java deleted file mode 100644 index 7bc8df07a..000000000 --- a/kork-web/src/main/groovy/com/netflix/spinnaker/retrofit/Slf4jRetrofitLogger.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2016 Netflix, Inc. - * - * 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 com.netflix.spinnaker.retrofit; - -import java.util.Objects; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import retrofit.RestAdapter; - -public class Slf4jRetrofitLogger implements RestAdapter.Log { - private final Logger logger; - - public Slf4jRetrofitLogger(Class type) { - this(LoggerFactory.getLogger(type)); - } - - public Slf4jRetrofitLogger(Logger logger) { - this.logger = Objects.requireNonNull(logger); - } - - @Override - public void log(String message) { - logger.info(message); - } -} diff --git a/kork-web/src/main/java/com/netflix/spinnaker/kork/web/exceptions/GenericExceptionHandlers.java b/kork-web/src/main/java/com/netflix/spinnaker/kork/web/exceptions/GenericExceptionHandlers.java index 1f9a0cefa..2e940bde5 100644 --- a/kork-web/src/main/java/com/netflix/spinnaker/kork/web/exceptions/GenericExceptionHandlers.java +++ b/kork-web/src/main/java/com/netflix/spinnaker/kork/web/exceptions/GenericExceptionHandlers.java @@ -16,15 +16,8 @@ package com.netflix.spinnaker.kork.web.exceptions; -import com.google.common.base.Charsets; -import com.google.common.io.CharStreams; -import com.netflix.spinnaker.kork.exceptions.HasAdditionalAttributes; import com.netflix.spinnaker.kork.exceptions.UserException; import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; @@ -35,8 +28,6 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; -import retrofit.RetrofitError; -import retrofit.client.Header; @ControllerAdvice public class GenericExceptionHandlers extends BaseExceptionHandlers { @@ -89,42 +80,6 @@ public void handleIllegalStateException( handleResponseStatusAnnotatedException(e, response); } - @ExceptionHandler(RetrofitError.class) - public void handleRetrofitError( - RetrofitError e, HttpServletResponse response, HttpServletRequest request) - throws IOException { - if (e.getResponse() != null) { - Map additionalContext = new HashMap<>(); - additionalContext.put("url", e.getResponse().getUrl()); - - Header contentTypeHeader = - e.getResponse().getHeaders().stream() - .filter(h -> h.getName().equalsIgnoreCase("content-type")) - .findFirst() - .orElse(null); - - if (contentTypeHeader != null - && contentTypeHeader.getValue().toLowerCase().contains("application/json")) { - // include any json responses - additionalContext.put( - "body", - CharStreams.toString( - new InputStreamReader(e.getResponse().getBody().in(), Charsets.UTF_8))); - } - - RetrofitErrorWrapper retrofitErrorWrapper = - new RetrofitErrorWrapper(e.getMessage(), additionalContext); - storeException(request, response, retrofitErrorWrapper); - response.sendError( - e.getResponse().getStatus(), - exceptionMessageDecorator.decorate( - retrofitErrorWrapper, retrofitErrorWrapper.getMessage())); - } else { - // no retrofit response (likely) indicates a NETWORK error - handleException(e, response, request); - } - } - @ExceptionHandler(Exception.class) public void handleException(Exception e, HttpServletResponse response, HttpServletRequest request) throws IOException { @@ -165,19 +120,4 @@ private void handleResponseStatusAnnotatedException(Exception e, HttpServletResp exceptionMessageDecorator.decorate(e, e.getMessage())); } } - - private static class RetrofitErrorWrapper extends RuntimeException - implements HasAdditionalAttributes { - private final Map additionalAttributes; - - public RetrofitErrorWrapper(String message, Map additionalAttributes) { - super(message); - this.additionalAttributes = additionalAttributes; - } - - @Override - public Map getAdditionalAttributes() { - return additionalAttributes != null ? additionalAttributes : Collections.emptyMap(); - } - } } diff --git a/settings.gradle b/settings.gradle index c25bf9008..2250afaa8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -57,7 +57,6 @@ include( "kork-secrets-aws", "kork-secrets-gcp", "kork-security", - "kork-retrofit", "kork-retrofit2", "kork-sql", "kork-sql-test", diff --git a/spinnaker-dependencies/spinnaker-dependencies.gradle b/spinnaker-dependencies/spinnaker-dependencies.gradle index 02b34f8c6..36b0f2e29 100644 --- a/spinnaker-dependencies/spinnaker-dependencies.gradle +++ b/spinnaker-dependencies/spinnaker-dependencies.gradle @@ -19,7 +19,6 @@ ext { okhttp : "2.7.5", // CVE-2016-2402 okhttp3 : "3.14.9", openapi : "1.3.9", // this needs to be kept in sync with spring boot as it pulls in the spring-boot-dependencies BOM - retrofit : "1.9.0", retrofit2 : "2.8.1", spectator : "1.0.6", spek : "1.1.5", @@ -118,10 +117,6 @@ dependencies { api("com.squareup.retrofit2:converter-jackson:${versions.retrofit2}") api("com.squareup.retrofit2:retrofit-mock:${versions.retrofit2}") api("com.squareup.retrofit2:retrofit:${versions.retrofit2}") - api("com.squareup.retrofit:converter-jackson:${versions.retrofit}") - api("com.squareup.retrofit:converter-simplexml:${versions.retrofit}") - api("com.squareup.retrofit:retrofit-mock:${versions.retrofit}") - api("com.squareup.retrofit:retrofit:${versions.retrofit}") api("com.sun.xml.bind:jaxb-core:2.3.0.1") api("com.sun.xml.bind:jaxb-impl:2.3.2") api("com.vdurmont:semver4j:3.1.0")