Network Primitives

The 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:

  1. What address to bind to
  2. What address to advertise for external access to the workload (ingress)

For remote units, a charm needs to know:

  1. What address to use connect to the workload from an external source
  2. 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 is relevant. Juju will take this into account when populating the address information below.

network-get

The 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.

Usage:

network-get [options] <binding-name> [--ingress-address] [--bind-address] [--egress-subnets]

Summary:

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

Details:

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.

Examples

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"

Output:

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 69.192.151.51/32

In the mysql model, we can see the offer connections.

juju switch ianaws:default
juju offers 

Output:

Offer  User   Relation id  Status  Endpoint  Interface  Role      Ingress subnets
mysql  admin  2            joined  db        mysql      provider  69.193.151.51/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"

Output:

bind-addresses:
- macaddress: ""
  interfacename: ""
  addresses:
  - address: 10.136.107.33
    cidr: ""
ingress-addresses:
- 54.237.63.211

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"

Output:

54.237.63.211

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\`"

Output:

69.193.151.51/32

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\`"

Output:

10.200.103.121

On the model hosting mediawiki:

juju run --unit mediawiki/0 "relation-get -r 0 - mysql/1"

Output:

database: remote-8193c748ad3c4f6382c7baeb44dcb2f3
egress-subnets: 54.237.63.211/32
host: 10.136.107.33
ingress-address: 54.237.63.211
password: dahlahbouchoose
private-address: 54.237.63.211
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.