package au.com.dius.pact.provider.junit.loader;
import au.com.dius.pact.model.Pact;
import au.com.dius.pact.model.PactReader;
import au.com.dius.pact.provider.ConsumerInfo;
import au.com.dius.pact.provider.broker.PactBrokerClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import static au.com.dius.pact.provider.junit.sysprops.PactRunnerExpressionParser.parseExpressions;
import static au.com.dius.pact.provider.junit.sysprops.PactRunnerTagListExpressionParser.parseTagListExpressions;
import static java.util.stream.Collectors.toList;
/**
* Out-of-the-box implementation of {@link PactLoader} that downloads pacts from Pact broker
*/
public class PactBrokerLoader implements PactLoader {
private static final Logger LOGGER = LoggerFactory.getLogger(PactBrokerLoader.class);
private static final String LATEST = "latest";
private final String pactBrokerHost;
private final String pactBrokerPort;
private final String pactBrokerProtocol;
private final List<String> pactBrokerTags;
private boolean failIfNoPactsFound;
private PactBrokerAuth authentication;
public PactBrokerLoader(final String pactBrokerHost, final String pactBrokerPort, final String pactBrokerProtocol) {
this(pactBrokerHost, pactBrokerPort, pactBrokerProtocol, Collections.singletonList(LATEST));
}
public PactBrokerLoader(final String pactBrokerHost, final String pactBrokerPort, final String pactBrokerProtocol,
final List<String> tags) {
this.pactBrokerHost = pactBrokerHost;
this.pactBrokerPort = pactBrokerPort;
this.pactBrokerProtocol = pactBrokerProtocol;
this.pactBrokerTags = parseTagListExpressions(tags);
this.failIfNoPactsFound = true;
}
public PactBrokerLoader(final PactBroker pactBroker) {
this(pactBroker.host(), pactBroker.port(), pactBroker.protocol(), Arrays.asList(pactBroker.tags()));
this.failIfNoPactsFound = pactBroker.failIfNoPactsFound();
this.authentication = pactBroker.authentication();
}
public List<Pact> load(final String providerName) throws IOException {
List<Pact> pacts = new ArrayList<>();
if (pactBrokerTags == null || pactBrokerTags.isEmpty() || pactBrokerTags.size() == 1 &&
pactBrokerTags.contains(LATEST)) {
pacts.addAll(loadPactsForProvider(providerName, null));
} else {
for (String tag : pactBrokerTags) {
pacts.addAll(loadPactsForProvider(providerName, tag));
}
}
return pacts;
}
private List<Pact> loadPactsForProvider(final String providerName, final String tag) throws IOException {
LOGGER.debug("Loading pacts from pact broker for provider " + providerName + " and tag " + tag);
URIBuilder uriBuilder = new URIBuilder().setScheme(parseExpressions(pactBrokerProtocol))
.setHost(parseExpressions(pactBrokerHost))
.setPort(Integer.parseInt(parseExpressions(pactBrokerPort)));
try {
List<ConsumerInfo> consumers;
PactBrokerClient pactBrokerClient = newPactBrokerClient(uriBuilder.build());
if (StringUtils.isEmpty(tag)) {
consumers = pactBrokerClient.fetchConsumers(providerName);
} else {
consumers = pactBrokerClient.fetchConsumersWithTag(providerName, tag);
}
if (failIfNoPactsFound && consumers.isEmpty()) {
throw new NoPactsFoundException("No consumer pacts were found for provider '" + providerName + "' and tag '" +
tag + "'. (URL " + pactBrokerClient.getUrlForProvider(providerName, tag) + ")");
}
return consumers.stream()
.map(consumer -> this.loadPact(consumer, pactBrokerClient.getOptions()))
.collect(toList());
} catch (URISyntaxException e) {
throw new IOException("Was not able load pacts from broker as the broker URL was invalid", e);
}
}
Pact loadPact(ConsumerInfo consumer, Map options) {
return PactReader.loadPact(options, consumer.getPactFile());
}
PactBrokerClient newPactBrokerClient(URI url) throws URISyntaxException {
HashMap options = new HashMap();
if (this.authentication != null && !this.authentication.scheme().equalsIgnoreCase("none")) {
options.put("authentication", Arrays.asList(parseExpressions(this.authentication.scheme()),
parseExpressions(this.authentication.username()), parseExpressions(this.authentication.password())));
}
return new PactBrokerClient(url, options);
}
public boolean isFailIfNoPactsFound() {
return failIfNoPactsFound;
}
public void setFailIfNoPactsFound(boolean failIfNoPactsFound) {
this.failIfNoPactsFound = failIfNoPactsFound;
}
}