Skip to content

Commit

Permalink
Update azure service proxy configuration in Spring tier (#24810)
Browse files Browse the repository at this point in the history
Update azure proxy configuration properties and configure Azure SDK service builder
  • Loading branch information
Moary Chen authored Oct 28, 2021
1 parent e49b5a6 commit 876e9af
Show file tree
Hide file tree
Showing 16 changed files with 867 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.azure.spring.cloud.autoconfigure.properties.AbstractAzureServiceConfigurationProperties;
import com.azure.spring.core.properties.client.ClientProperties;
import com.azure.spring.service.cosmos.CosmosProperties;
import com.azure.spring.core.properties.proxy.HttpProxyProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotEmpty;
Expand All @@ -27,6 +29,9 @@ public class AzureCosmosProperties extends AbstractAzureServiceConfigurationProp

public static final String PREFIX = "spring.cloud.azure.cosmos";

@NestedConfigurationProperty
private final HttpProxyProperties proxy = new HttpProxyProperties();

@NotEmpty
@Pattern(regexp = "http[s]{0,1}://.*.documents.azure.com.*")
private String endpoint;
Expand Down Expand Up @@ -64,6 +69,10 @@ public class AzureCosmosProperties extends AbstractAzureServiceConfigurationProp
*/
private boolean populateQueryMetrics;

@Override
public HttpProxyProperties getProxy() {
return proxy;
}

@Override
public ClientProperties getClient() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.azure.spring.cloud.autoconfigure.properties;

import com.azure.spring.core.properties.proxy.ProxyProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

/**
Expand All @@ -13,8 +14,16 @@ public abstract class AbstractAzureAmqpConfigurationProperties extends AbstractA
@NestedConfigurationProperty
protected final AmqpClientConfigurationProperties client = new AmqpClientConfigurationProperties();

@NestedConfigurationProperty
protected final ProxyProperties proxy = new ProxyProperties();

@Override
public AmqpClientConfigurationProperties getClient() {
return client;
}

@Override
public ProxyProperties getProxy() {
return proxy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.azure.spring.cloud.autoconfigure.properties;

import com.azure.spring.core.properties.proxy.HttpProxyProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

/**
Expand All @@ -13,8 +14,16 @@ public abstract class AbstractAzureHttpConfigurationProperties extends AbstractA
@NestedConfigurationProperty
protected final HttpClientConfigurationProperties client = new HttpClientConfigurationProperties();

@NestedConfigurationProperty
protected final HttpProxyProperties proxy = new HttpProxyProperties();

@Override
public HttpClientConfigurationProperties getClient() {
return client;
}

@Override
public HttpProxyProperties getProxy() {
return proxy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.azure.spring.core.properties.AzureProperties;
import com.azure.spring.core.properties.credential.TokenCredentialProperties;
import com.azure.spring.core.properties.profile.AzureProfile;
import com.azure.spring.core.properties.proxy.ProxyProperties;
import com.azure.spring.core.properties.resource.AzureResourceMetadata;
import com.azure.spring.core.properties.retry.RetryProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
Expand All @@ -18,9 +17,6 @@ public abstract class AbstractAzureServiceConfigurationProperties implements Azu

protected boolean enabled = true;

@NestedConfigurationProperty
protected final ProxyProperties proxy = new ProxyProperties();

@NestedConfigurationProperty
protected final RetryProperties retry = new RetryProperties();

Expand All @@ -41,11 +37,6 @@ public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

@Override
public ProxyProperties getProxy() {
return proxy;
}

@Override
public RetryProperties getRetry() {
return retry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
package com.azure.spring.core.converter;

import com.azure.core.http.ProxyOptions;
import com.azure.spring.core.properties.proxy.ProxyProperties;
import com.azure.spring.core.properties.proxy.HttpProxyProperties;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;

import java.net.InetSocketAddress;

/**
* Converts a {@link ProxyProperties} to a {@link ProxyOptions}.
* Converts a {@link HttpProxyProperties} to a {@link ProxyOptions}.
*/
public final class AzureHttpProxyOptionsConverter implements Converter<ProxyProperties, ProxyOptions> {
public final class AzureHttpProxyOptionsConverter implements Converter<HttpProxyProperties, ProxyOptions> {

@Override
public ProxyOptions convert(ProxyProperties proxyProperties) {
public ProxyOptions convert(HttpProxyProperties proxyProperties) {
if (!StringUtils.hasText(proxyProperties.getHostname())) {
return null;
}
Expand All @@ -34,8 +34,9 @@ public ProxyOptions convert(ProxyProperties proxyProperties) {
if (StringUtils.hasText(proxyProperties.getUsername()) && StringUtils.hasText(proxyProperties.getPassword())) {
proxyOptions.setCredentials(proxyProperties.getUsername(), proxyProperties.getPassword());
}
// TODO (xiada) non proxy hosts
if (StringUtils.hasText(proxyProperties.getNonProxyHosts())) {
proxyOptions.setNonProxyHosts(proxyProperties.getNonProxyHosts());
}
return proxyOptions;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.azure.spring.core.properties.client.AmqpClientProperties;
import com.azure.spring.core.properties.client.ClientProperties;
import com.azure.spring.core.properties.retry.RetryProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.BiConsumer;

Expand All @@ -22,6 +24,7 @@
*/
public abstract class AbstractAzureAmqpClientBuilderFactory<T> extends AbstractAzureServiceClientBuilderFactory<T> {

private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAzureAmqpClientBuilderFactory.class);
private ClientOptions clientOptions = new ClientOptions();
private final AzureAmqpProxyOptionsConverter proxyOptionsConverter = new AzureAmqpProxyOptionsConverter();
private final AzureAmqpRetryOptionsConverter retryOptionsConverter = new AzureAmqpRetryOptionsConverter();
Expand Down Expand Up @@ -78,8 +81,13 @@ protected void configureProxy(T builder) {
if (getAzureProperties().getProxy() == null) {
return;
}

final ProxyOptions proxyOptions = proxyOptionsConverter.convert(getAzureProperties().getProxy());
consumeProxyOptions().accept(builder, proxyOptions);
if (proxyOptions != null) {
consumeProxyOptions().accept(builder, proxyOptions);
} else {
LOGGER.debug("No AMQP proxy properties available.");
}
}

protected ClientOptions getClientOptions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpClientProvider;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.ProxyOptions;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.core.http.policy.HttpPipelinePolicy;
import com.azure.core.util.Header;
Expand All @@ -15,7 +16,10 @@
import com.azure.spring.core.http.DefaultHttpProvider;
import com.azure.spring.core.properties.client.ClientProperties;
import com.azure.spring.core.properties.client.HttpClientProperties;
import com.azure.spring.core.properties.proxy.HttpProxyProperties;
import com.azure.spring.core.properties.proxy.ProxyProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -30,6 +34,7 @@
*/
public abstract class AbstractAzureHttpClientBuilderFactory<T> extends AbstractAzureServiceClientBuilderFactory<T> {

private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAzureHttpClientBuilderFactory.class);
private final HttpClientOptions httpClientOptions = new HttpClientOptions();
private HttpClientProvider httpClientProvider = new DefaultHttpProvider();
private final List<HttpPipelinePolicy> httpPipelinePolicies = new ArrayList<>();
Expand Down Expand Up @@ -66,9 +71,20 @@ protected void configureHttpClient(T builder) {

@Override
protected void configureProxy(T builder) {
final ProxyProperties proxy = getAzureProperties().getProxy();
if (proxy != null) {
this.httpClientOptions.setProxyOptions(proxyOptionsConverter.convert(proxy));
final ProxyProperties proxyProperties = getAzureProperties().getProxy();
if (proxyProperties == null) {
return;
}

if (proxyProperties instanceof HttpProxyProperties) {
ProxyOptions proxyOptions = proxyOptionsConverter.convert((HttpProxyProperties) proxyProperties);
if (proxyOptions != null) {
this.httpClientOptions.setProxyOptions(proxyOptions);
} else {
LOGGER.debug("No HTTP proxy properties available.");
}
} else {
LOGGER.warn("Non-http proxy configuration will not be applied.");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.spring.core.properties.proxy;

/**
* Extend the proxy properties for HTTP connection
*/
public class HttpProxyProperties extends ProxyProperties {
private String nonProxyHosts;

public String getNonProxyHosts() {
return nonProxyHosts;
}

public void setNonProxyHosts(String nonProxyHosts) {
this.nonProxyHosts = nonProxyHosts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,10 @@ protected void configureService(CosmosClientBuilder builder) {
// TODO (xiada): should we count this as authentication
map.from(this.cosmosProperties.getResourceToken()).to(builder::resourceToken);
map.from(this.cosmosProperties.getPermissions()).whenNot(List::isEmpty).to(builder::permissions);

if (ConnectionMode.GATEWAY.equals(this.cosmosProperties.getConnectionMode())) {
if (ConnectionMode.DIRECT.equals(this.cosmosProperties.getConnectionMode())) {
builder.directMode(this.cosmosProperties.getDirectConnection(), this.cosmosProperties.getGatewayConnection());
} else if (ConnectionMode.GATEWAY.equals(this.cosmosProperties.getConnectionMode())) {
builder.gatewayMode(this.cosmosProperties.getGatewayConnection());
} else if (ConnectionMode.DIRECT.equals(this.cosmosProperties.getConnectionMode())) {
// TODO (xiada): public CosmosClientBuilder directMode(DirectConnectionConfig directConnectionConfig, GatewayConnectionConfig gatewayConnectionConfig) {
builder.directMode(this.cosmosProperties.getDirectConnection());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.spring.service.cosmos;

import com.azure.cosmos.ConnectionMode;
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.DirectConnectionConfig;
import com.azure.cosmos.GatewayConnectionConfig;
import com.azure.spring.service.AzureServiceClientBuilderFactoryTestBase;
import org.junit.jupiter.api.Test;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.mock;

public class CosmosClientBuilderFactoryTest extends AzureServiceClientBuilderFactoryTestBase<CosmosClientBuilder,
TestAzureCosmosProperties, CosmosClientBuilderFactory> {

private static final String ENDPOINT = "https://test.documents.azure.com:443/";

@Test
void testGatewayConnectionModeConfigured() {
TestAzureCosmosProperties properties = createMinimalServiceProperties();
properties.setConnectionMode(ConnectionMode.GATEWAY);
final CosmosClientBuilderFactoryExt factoryExt = new CosmosClientBuilderFactoryExt(properties);
final CosmosClientBuilder builder = factoryExt.build();
verify(builder, times(1)).gatewayMode(any(GatewayConnectionConfig.class));
verify(builder, times(0)).directMode(any(DirectConnectionConfig.class));
}

@Test
void testDirectConnectionModeConfigured() {
TestAzureCosmosProperties properties = createMinimalServiceProperties();
properties.setConnectionMode(ConnectionMode.DIRECT);
final CosmosClientBuilderFactoryExt factoryExt = new CosmosClientBuilderFactoryExt(properties);
final CosmosClientBuilder builder = factoryExt.build();
verify(builder, times(0)).gatewayMode(any(GatewayConnectionConfig.class));
verify(builder, times(1)).directMode(any(DirectConnectionConfig.class), any(GatewayConnectionConfig.class));
}

@Override
protected TestAzureCosmosProperties createMinimalServiceProperties() {
TestAzureCosmosProperties cosmosProperties = new TestAzureCosmosProperties();
cosmosProperties.setEndpoint(ENDPOINT);
return cosmosProperties;
}

static class CosmosClientBuilderFactoryExt extends CosmosClientBuilderFactory {

CosmosClientBuilderFactoryExt(TestAzureCosmosProperties cosmosProperties) {
super(cosmosProperties);
}

@Override
protected CosmosClientBuilder createBuilderInstance() {
return mock(CosmosClientBuilder.class);
}
}
}
Loading

0 comments on commit 876e9af

Please sign in to comment.