Things often run on other things or need other things to run. In Escape we can express this idea using providers and consumers. A provider provides a certain service or platform and a consumer makes use of it.
In practical terms Providers and Consumers are regular Escape packages. A provider defines what kind of interface it implements and usually has a few outputs:
name: quickstart/my-provider version: [email protected] provides: - introduction outputs: - id: credentials default: "My platform specific configuration output"
A consumer defines what kind of provider it consumes, and will usually use the outputs to configure itself:
name: quickstart/my-consumer version: [email protected] consumes: - introduction inputs: - id: credentials default: $introduction.outputs.credentials
When we try to
escape run build or
escape run deploy this package that
requires a provider we get an error:
$ escape run build --plan escape-consumer.yml Build: Starting build. Build: Error: Missing provider of type 'introduction'. This can be configured using the -p / --extra-provider flag.
Which is Escape complaining that it can’t find a provider of type ‘introduction’, because we haven’t deployed one. We can fix this by releasing and deploying the provider:
$ escape run release --plan escape-provider.yml Release: Releasing quickstart/my-provider-v0.0.0 Build: ✔️ Completed build Test: ✔️ Tests passed. Destroy: ✔️ Destruction complete Deploy: ✔️ Successfully deployed my-provider-v0.0.0 with deployment name quickstart/my-provider in the dev environment. Smoke tests: ✔️ Smoke tests passed. Destroy: ✔️ Destruction complete Package: ✔️ Packaged quickstart/my-provider-v0.0.0 at /home/user/workspace/.escape/target/my-provider-v0.0.0.tgz Push: ✔️ Push successful. Release: ✔️ Successfully released quickstart/my-provider-v0.0.0 $ escape run deploy quickstart/my-provider-latest Deploy: ✔️ Successfully deployed my-provider-v0.0.0 with deployment name quickstart/my-provider in the dev environment. $ escape run build --plan escape-consumer.yml Build: ✔️ Completed build
In a previous section we have seen dependencies. Dependencies are resolved at build time and provide a tight coupling between parents and their children. Providers and consumers provide a much looser coupling due to interface typing. This makes it possible to implement multiple implementations for a provider without having to change consumers; for example: we can provide a different provider for testing or local development purposes.
We can configure dependency inputs from the parent package and/or use their outputs. Consumers, on the other hand, are unable to configure the providers and solely have access to their outputs.
Another difference is that a provider can be consumed by multiple deployments in the same environment, whereas a dependency only works as part of a parent release. In practical terms this means that a platform or shared service (e.g. a Kubernetes cluster, a message queue, etc.) is usually much more appropriate to implement as a provider than a dependency.