Charm Network Primitives
network-get hook tool allows charms to discover important network related information. There are 2 key things a charm needs to know about its local units:
- What address to bind to
- What address to use to connect to the workload of an external source (i.e. the ingress address of that external source)
For remote units, a charm needs to know:
- What address to use connect to the workload from an external source
- The egress subnets for incoming traffic
Both ingress address and egress subnets may vary depending on the relation. This is because if the relation is cross model, the ingress address is the public / floating address of the unit to allow ingress from outside the model. And a given relation may see traffic originate from different egress subnets.
The space bindings for a given endpoint also affect that address information. Juju will take this into account when populating the address information below.
network-get hook tool is used to get networking information about the local unit.
network-get is relation aware. As with other hook tools, it is either run in a relation context or accepts a relation id passed using the
-r switch. It may also be run outside of a relation context, in which case only the binding address information is relevant.
By default it prints a block of YAML with the 3 pieces of address information:
- binding address(es)
- ingress address(es)
- egress subnets
Flags may be used to request only a specific address value.
network-get [options] <binding-name> [--ingress-address] [--bind-address] [--egress-subnets]
get network config Options: --bind-address (= false) get the address for the binding on which the unit should listen --egress-subnets (= false) get the egress subnets for the binding --format (= smart) Specify output format (json|smart|yaml) --ingress-address (= false) get the ingress address for the binding -o, --output (= "") Specify an output file --primary-address (= false) (deprecated) get the primary address for the binding -r, --relation (= ) specify a relation by id
network-get returns the network config for a given binding name. By default it returns the list of interfaces and associated addresses in the space for the binding, as well as the ingress address for the binding. If defined, any egress subnets are also returned. If one of the following flags are specified, just that value is returned. If more than one flag is specified, a map of values is returned. --bind-address: the address the local unit should listen on to serve connections, as well as the address that should be advertised to its peers. --ingress-address: the address the local unit should advertise as being used for incoming connections. --egress_subnets: subnets (in CIDR notation) from which traffic on this relation will originate.
Deploy MySQL in an AWS model with no relation context
To deploy MySQL in an AWS model with no relation context:
juju run --unit mysql/1 "network-get --format yaml db"
bind-addresses: - macaddress: "" interfacename: "" addresses: - address: 10.136.107.33 cidr: "" ingress-addresses: - 10.136.107.33
Deploy MediaWiki in a local cloud model
To deploy MediaWiki in a local cloud model. Relate to mysql using relation
--via to explicitly specify an egress subnet on the relation:
juju relate mediawiki:db ianaws:admin/default.mysql --via 126.96.36.199/32
In the mysql model, we can see the offer connections.
juju switch ianaws:default juju offers
Offer User Relation id Status Endpoint Interface Role Ingress subnets mysql admin 2 joined db mysql provider 188.8.131.52/32
On the AWS mysql model, the relation id is ‘db:2’, or simply just ‘2’, for the mediawiki relation.
Let’s get address information for a local unit:
juju run --unit mysql/1 "network-get --format yaml db -r db:2"
The endpoint prefix to relation id is optional, so this works as well:
juju run --unit mysql/1 "network-get --format yaml db -r 2"
bind-addresses: - macaddress: "" interfacename: "" addresses: - address: 10.136.107.33 cidr: "" ingress-addresses: - 184.108.40.206
Note that the ingress address is now set to the public address, since for this relation ingress will be from an external source:
juju run --unit mysql/1 "network-get --format yaml db -r db:2 --ingress-address"
The egress subnets for the remote unit are obtained using
relation-get. This takes the name of the remote unit for which to get the relation data. When run in a relation context, the remote unit is $JUJU_REMOTE_UNIT. Outside of a relation context, we can use
relation-list to get the remote unit (for this example there is only one):
juju run --unit mysql/1 "relation-get -r db:2 egress-subnets `relation-list -r db:2`"
To get the ingress address of the remote unit. Because the test model is using a local LXD cloud, we only get a 10.x.x.x address; ingress from an AWS cloud to a local LXD cloud isn’t supported in this case, but the example illustrates how a charm can get the ingress address of the remote unit:
juju run --unit mysql/1 "relation-get -r db:2 ingress-address `relation-list -r db:2`"
On the model hosting mediawiki:
juju run --unit mediawiki/0 "relation-get -r 0 - mysql/1"
database: remote-8193c748ad3c4f6382c7baeb44dcb2f3 egress-subnets: 220.127.116.11/32 host: 10.136.107.33 ingress-address: 18.104.22.168 password: dahlahbouchoose private-address: 22.214.171.124 slave: "False" user: sieyaijeediohie
Note the correct ingress-address is given to allow mediawiki to know how to reach mysql in the offering model. As we retain private-address for backwards compatibility.
So long as charms evolve to use these new primitives to access the key address values, they will work in both cross model and non cross model scenarios.