Dependencies
In the Porter manifest you can define a dependency on another bundle. The dependent bundle is executed before the bundle is installed, updated, or a custom action is invoked. The dependent bundle is uninstalled after the root bundle is uninstalled.
Dependencies are an extension of the CNAB Spec. The Dependency specification is still evolving and we are using Porter to act as an initial implementation. So other CNAB tools may not support dependencies initially.
Here is a full example of a Porter manifest that uses dependencies.
Define a dependency
In the manifest, add entries for each dependency of your bundle. The name
field takes a short name for the dependent bundle that
you will use to reference the dependent bundle elsewhere in the bundle. For example you can reference the dependent bundle’s
outputs via ${ bundle.dependencies.NAME.outputs }
. The reference
field takes the bundle reference of the dependency.
Both name
and reference
are required fields.
dependencies:
requires:
- name: mysql
bundle:
reference: getporter/mysql:v0.1.3
Define dependencies v2 (Shared)
The second version of dependencies – also called “shared dependencies” or DependenciesV2 – is available under the experimental flag, and therefore an experimental feature. Please proceed with caution.
You can enable the experimental flag, thus enabling DependenciesV2, by setting an environment variable as follows:
PORTER_EXPERIMENTAL=dependencies-v2
The configuration for DependenciesV2 is similar to that of the first version, except there is now a “sharing” section with the following required fields: mode
, group.name
.
mode
is a boolean, and group.name
is the identifier that will allow for certain bundles to share parameters and outputs between each other.
dependencies:
requires:
- name: mysql
bundle:
reference: localhost:5000/mysql:v0.1.0
sharing:
mode: true
group:
name: myapp
parameters:
database-name: wordpress
mysql-user: wordpress
namespace: wordpress
If there is an existing dependency installed that the parent bundle should connect to, you must create a label for the existing dependency with the sh.porter.SharingGroup
key, with the value of the group name specified in the parent bundle.
The existing dependency must be successfully installed. If it is uninstalled this key must be deleted by the users before the operation can proceed.
porter install --label sh.porter.SharingGroup=myapp
There are some safeguards in place to make it so other bundles depending on the dependency cannot be broken, therefore on the following actions this will occur:
Install: For the parent bundle on existing dependency, the dependency arguments will be passed to the parent. No further changes.
Upgrade: The parent bundle will execute the upgrade action, but it will not change anything about the existing dependency.
Invoke: Any changes that happen here will change the existing dependency. It will be on the user to handle propagating those changes to other parent bundles if needed.
Uninstall: The parent bundle will be uninstalled, but the existing dependency will not be and needs to be uninstalled in a separate command.
Ordering of dependencies
If more than one dependency is declared, they will be installed in the order they are listed. For example, if both the mysql
and
nginx
bundles are required, but the mysql
bundle should be installed first, you would list them as such:
dependencies:
requires:
- name: mysql
bundle:
reference: getporter/mysql:v0.1.3
- name: nginx
bundle:
reference: my/nginx-bundle:v0.1.0
Defaulting Parameters
Parameters defined in a dependent bundle can be defaulted from the root bundle.
In the example below, the mysql bundle defines database_name
and
mysql_user
parameters, and the root bundle (Wordpress) has chosen to default those parameters
to specific values, so that the user isn’t required to provide values for those parameter.
dependencies:
requires:
- name: mysql
bundle:
reference: getporter/mysql:v0.1.3
parameters:
database_name: wordpress
mysql_user: wordpress
Specifying parameters
Command-line
You can specify parameters for a dependent bundle on the command-line using the following syntax
--param DEPENDENCY#PARAMETER=VALUE
For example, to override the default parameter database_name
when installing the wordpress bundle the comand would be
$ porter install --reference getporter/mysql:v0.1.3 --param mysql#database_name=mywordpress
DEPENDENCY
: The dependency name used in thedependencies
section of the porter manifest. From the example above, the name is “mysql”.PARAMETER
: The name of the parameter.VALUE
: The parameter value.
Parameter Set
The same syntax shown above can be used to specify dependency parameters in a Parameter Set file.
Here, the name
field should be set to the DEPENDENCY#PARAMETER
value, or mysql#database-name
from above.
{
"name": "wordpress",
"parameters": [
{
"name": "mysql#database-name",
"source": {
"value": "mywordpress"
}
}
]
}
Parameter Precedence
A parameter for a dependency can be set in a few places, here is the order of precedence:
- Parameters set directly on the command-line via
--param
- Parameters set in a Parameter Set file via
--parameter-set
- Parameters set using a dependency default, for example
dependencies: requires: - name: mysql bundle: reference: getporter/mysql:v0.1.3 parameters: database_name: wordpress
- Parameter defaults defined in a bundle, for example
parameters: - name: database_name type: string default: mydb
Dependency Registry Authentication
Porter support multiple registries. If you are pulling different dependencies from multiple registries, just make sure that you login into each registry before executing your bundle.
For example:
echo $(DOCKER_REGISTRY_TOKEN) | docker login $(DOCKER_REGISTRY_URL) --username $(DOCKER_REGISTRY_USERNAME) --password-stdin
echo $(PRIVATE_REGISTRY_TOKEN) | docker login $(PRIVATE_REGISTRY_URL) --username $(PRIVATE_REGISTRY_USERNAME) --password-stdin
echo $(SECOND_PRIVATE_REGISTRY_TOKEN) | docker login $(SECOND_PRIVATE_REGISTRY_URL) --username $(SECOND_PRIVATE_REGISTRY_USERNAME) --password-stdin
Dependency Graph
At this time Porter only supports direct dependencies. Dependencies of dependencies, a.k.a. transitive dependencies, are ignored. See Design: Dependency Graph Resolution for our backlog item tracking this feature. We do plan to support it!