pact4s.provider.PactSource.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2021 io.github.jbwheatley
*
* 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 pact4s
package provider
import java.io.File
import java.time.{Instant, LocalDate, OffsetDateTime}
import scala.annotation.nowarn
sealed trait PactSource
object PactSource {
/** It isn't necessary to use a pact broker to manage consumer pacts (though it is strongly recommended). The pacts
* can also be directly loaded from files by using this pactSource in [[ProviderInfoBuilder]]
*
* @param consumers
* A map of consumer names to the file where the pacts are written.
*/
final class FileSource private (val consumers: Map[String, File]) extends PactSource
object FileSource {
def apply(consumer: Map[String, File]): FileSource = new FileSource(consumer)
def apply(consumer: (String, File), others: (String, File)*) = new FileSource(others.toMap + consumer)
}
sealed trait PactBroker extends PactSource {
def brokerUrl: String
def auth: Option[Authentication]
def insecureTLS: Boolean
}
/** @param brokerUrl
* pact broker address
* @param auth
* authentication for accessing the pact broker. Can be token or basic auth.
* @param tags
* fetches all the latest pacts from the pact-broker for the provider with the given tags, all ignoring tags if
* [[tags]] is empty.
*/
final class PactBrokerWithTags private (
val brokerUrl: String,
val insecureTLS: Boolean,
val auth: Option[Authentication],
val tags: List[String]
) extends PactBroker {
private def copy(
brokerUrl: String = brokerUrl,
insecureTLS: Boolean = false,
auth: Option[Authentication] = None,
tags: List[String] = Nil
) = new PactBrokerWithTags(brokerUrl, insecureTLS, auth, tags)
def withAuth(auth: Authentication): PactBrokerWithTags = copy(auth = Some(auth))
def withoutAuth: PactBrokerWithTags = copy(auth = None)
def withTags(tags: List[String]): PactBrokerWithTags = copy(tags = tags)
def withTags(tags: String*): PactBrokerWithTags = copy(tags = tags.toList)
def withInsecureTLS(insecureTLS: Boolean): PactBrokerWithTags = copy(insecureTLS = insecureTLS)
private[pact4s] def toPactBrokerWithSelectors: PactBrokerWithSelectors = PactBrokerWithSelectors(
brokerUrl
)
.withOptionalAuth(auth)
.withConsumerVersionSelectors(tags.foldLeft(ConsumerVersionSelectors())(_.tag(_)))
.withInsecureTLS(insecureTLS)
}
object PactBrokerWithTags {
@deprecated("Use PactBrokerWithSelectors instead.", "0.3.0")
def apply(brokerUrl: String): PactBrokerWithTags =
new PactBrokerWithTags(brokerUrl, insecureTLS = false, auth = None, tags = Nil)
}
/** @param brokerUrl
* pact broker address
* @param auth
* authentication for accessing the pact broker. Can be token or basic auth.
*
* @see
* https://docs.pact.io/pact_broker/advanced_topics/pending_pacts for information on pending and WIP pacts
*
* @param enablePending
* enable pending pacts. Off by default. If enabled, you must provide a provider branch for verifications.
* @see
* also the master issue for pending pacts https://github.com/pact-foundation/pact_broker/issues/320
*
* @param includeWipPactsSince
* is a [[WipPactsSince]] which wraps an [[Option[java.time.Instant]]]. [[WipPactsSince]] also has constructors for
* using [[java.time.LocalDate]] and [[java.time.OffsetDateTime]] for convenience. All WIP pacts are pending pacts,
* so we enforce the setting of [[enablePending]] if this field is set.
* @see
* also the master issue for WIP pacts here for more discussion
* https://github.com/pact-foundation/pact_broker/issues/338
*
* @param providerTags
* deprecated in favour of provider branch. Any tags that are going to be applied to the provider version when the
* verification results are published. Only used in the pending pact calculation, so will get set to empty when
* passed to pact-jvm if [[enablePending]] is set to false.
*
* @param consumerVersionSelectors
* specifies which consumer pacts should be chosen for verification.
*
* Example:
* {{{
* PactBrokerWithSelectors(
* brokerUrl = "https://test.pact.dius.com.au"
* ).withPendingPactsEnabled
* .withAuth(BasicAuth("dXfltyFMgNOFZAxr8io9wJ37iUpY42M", "O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1"))
* .withWipPactsSince(WipPactsSince.instant(Instant.EPOCH))
* .withConsumerVersionSelectors(ConsumerVersionSelectors.mainBranch)
* }}}
*/
final class PactBrokerWithSelectors private (
val brokerUrl: String,
val insecureTLS: Boolean,
val auth: Option[Authentication],
val enablePending: Boolean,
val includeWipPactsSince: WipPactsSince,
@deprecated(
message = "Set a provider branch when verifying instead of using tags. Tags are deprecated.",
since = "0.11.0"
) val providerTags: Option[ProviderTags],
val consumerVersionSelectors: ConsumerVersionSelectors
) extends PactBroker {
@nowarn("cat=deprecation")
private def copy(
brokerUrl: String = brokerUrl,
insecureTLS: Boolean = insecureTLS,
auth: Option[Authentication] = auth,
enablePending: Boolean = enablePending,
includeWipPactsSince: WipPactsSince = includeWipPactsSince,
@deprecated(
message = "Set a provider branch when verifying instead of using tags. Tags are deprecated.",
since = "0.11.0"
) providerTags: Option[ProviderTags] = providerTags,
consumerVersionSelectors: ConsumerVersionSelectors = consumerVersionSelectors
): PactBrokerWithSelectors =
new PactBrokerWithSelectors(
brokerUrl,
insecureTLS,
auth,
enablePending,
includeWipPactsSince,
providerTags,
consumerVersionSelectors
)
private[pact4s] def withOptionalAuth(auth: Option[Authentication]): PactBrokerWithSelectors = copy(auth = auth)
def withAuth(auth: Authentication): PactBrokerWithSelectors = withOptionalAuth(Some(auth))
@deprecated(message = "Use withPendingPactsEnabled", since = "0.11.0")
def withPendingPactsEnabled(providerTags: ProviderTags): PactBrokerWithSelectors =
withPendingPacts(true).withProviderTags(providerTags)
def withPendingPactsEnabled: PactBrokerWithSelectors =
withPendingPacts(true)
def withPendingPactsDisabled: PactBrokerWithSelectors =
withPendingPacts(false)
def withPendingPacts(enabled: Boolean): PactBrokerWithSelectors =
copy(enablePending = enabled, includeWipPactsSince = if (enabled) includeWipPactsSince else WipPactsSince.never)
@deprecated(message = "Use withWipPactsSince(since: WipPactsSince)", since = "0.0.19")
def withWipPactsSince(since: Instant, providerTags: ProviderTags): PactBrokerWithSelectors =
withWipPactsSince(WipPactsSince.instant(since)).withProviderTags(providerTags)
@deprecated(message = "Use withWipPactsSince(since: WipPactsSince)", since = "0.0.19")
def withWipPactsSince(since: LocalDate, providerTags: ProviderTags): PactBrokerWithSelectors =
withWipPactsSince(WipPactsSince.localDate(since)).withProviderTags(providerTags)
@deprecated(message = "Use withWipPactsSince(since: WipPactsSince)", since = "0.0.19")
def withWipPactsSince(since: OffsetDateTime, providerTags: ProviderTags): PactBrokerWithSelectors =
withWipPactsSince(WipPactsSince.offsetDateTime(since)).withProviderTags(providerTags)
/** this method is somewhat unsafe, as it is illegal to enable pending pacts (of which WIP pacts are a subset)
* without provider tags being provided.
*/
def withWipPactsSince(since: WipPactsSince): PactBrokerWithSelectors =
copy(enablePending = true, includeWipPactsSince = since)
@deprecated(
message = "Set a provider branch when verifying instead of using tags. Tags are deprecated.",
since = "0.11.0"
)
def withProviderTags(providerTags: ProviderTags): PactBrokerWithSelectors = copy(providerTags = Some(providerTags))
@deprecated(
message = "Set a provider branch when verifying instead of using tags. Tags are deprecated.",
since = "0.11.0"
)
def withOptionalProviderTags(providerTags: Option[ProviderTags]): PactBrokerWithSelectors =
copy(providerTags = providerTags)
def withConsumerVersionSelectors(selectors: ConsumerVersionSelectors): PactBrokerWithSelectors =
copy(consumerVersionSelectors = selectors)
def withInsecureTLS(insecureTLS: Boolean): PactBrokerWithSelectors = copy(insecureTLS = insecureTLS)
@nowarn("cat=deprecation")
private[pact4s] def validate(providerBranch: Option[Branch]): Either[Throwable, Unit] =
if (enablePending && providerTags.isEmpty && providerBranch.isEmpty)
Left(
new IllegalArgumentException(
"Provider branch (or previously tags) must be provided if pending pacts are enabled"
)
)
else if (includeWipPactsSince.since.isDefined && providerTags.isEmpty && providerBranch.isEmpty)
Left(
new IllegalArgumentException("Provider branch (or previously tags) must be provided if WIP pacts are enabled")
)
else Right(())
}
object PactBrokerWithSelectors {
def apply(
brokerUrl: String
): PactBrokerWithSelectors =
new PactBrokerWithSelectors(
brokerUrl = brokerUrl,
insecureTLS = false,
auth = None,
enablePending = false,
includeWipPactsSince = WipPactsSince.never,
providerTags = None,
consumerVersionSelectors = ConsumerVersionSelectors()
)
}
}