Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I am new to juju. So far I have created and started deploying one application charm and sever charm separately.

But now from the application I need to add relationship to server charm and get details from server charm.

Details like public address and private address. I researched about how to add relations between two charms. But I am not clear about how to add relations and get details. I only know I want to add some parameter in metadata.yaml file.

Can anyone tell me how to add relation and get details from server charm? Basically I need to provide IP address by server charm and after adding relationship from application charm need to read this IP address.

share|improve this question

1 Answer 1

up vote 5 down vote accepted

How do I define a relationship?

So, in order to define a relationship between two charms you must first, as you have alluded to, define the relation in each charms metadata.yaml file. Since you've defined a server/client role I'm going to stick to that in my examples below with foo-server and foo-client charms. Since it's likely the server providing the majority of the data to the client their metadata.yaml files would look as such:

foo-server

name: foo-server
description: Something more than this
provides:
  server:
    interface: foo

foo-client

name: foo-client
description: Something more than this
requires:
  backend:
    interface: foo

Juju has two primary relation types. Provides and Requires. In this case the server charm is providing "foo" as an interface. The client charm requires the "foo" interface to operate. This provides/requires lets juju know which charms can talk to which other charms.

The interface is an arbitrary name, in this case foo, but could be anything. There's a large list of already defined interfaces, such as: mysql, http, mongodb, etc. If your service provides one of these existing interfaces you'd want to consider implementing it. If not feel free to create a new one.

How do I get/send data?

Once you've defined your metadata, you'll need to create a few new hooks the hook names are defined in the linked documentation, but since you're just sending the address information we'll keep with a simple bash example of the implementation of each hook.

So, we have two charms, foo-server and foo-client. foo-server provides a "server" relation with the foo interface. foo-client requires a "backend" relation with the foo interface. Relation hooks are named based on the relation-name (not the interface name). These could both be called server, but to illustrate that juju matches on interface and not relation, I've made the foo-client relation name "backend".

foo-server/hooks/server-relation-joined

#!/bin/bash

set -eux

relation-set hostname=`unit-get private-address`

This is a very basic example, where we're creating a relation key called hostname and setting the value, using unit-get command, to the private-address of the unit the charm is deployed to. This address will vary from provider to provider, but it will always be reachable within a juju environment. You can set multiple keys by adding a space between keys, for example:

relation-set hostname=`unit-get private-address` public-address=`unit-get public-address`

This will send two keys, hostname and public-address to whatever service it's connected to.

foo-client/hooks/backend-relation-changed

Notice the difference in file name, this is invoking the relation-changed hook instead of relation-joined. Presumably the server is just giving the details of where it lives, so the client charm needs to know where that address is. By putting this in the relation-changed hook every time data on the relation is updated the hook is called again.

#!/bin/bash

set -eux

server_address=`relation-get hostname`

if [ -z "$server_address" ]; then
  juju-log "No data sent yet"
  exit 0
fi

# If you've gotten this far, you have a $server_address, configure as you see fit

Now, there's a little more involved in this hook. Taking it line by line, the first three are just standard stuff. It's a bash charm and set -eux is there to make sure the hook behaves as it should. The next line uses relation-get which will read relation data from the connection. Now, everything in a juju environment is orchestrated asynchronously. So you're never 100% certain you'll have data when you call relation-get. This is where the if block helps resolve that. If there's nothing in "$server_address", ie we didn't get a return value, the hook will simple exit. However, it's exiting with a zero status so it won't crop up as an error in juju.

I know this seems counter intuitive, we technically have a problem because we don't have data. Yes, but, it's more along the lines of "We don't have data, yet". By exiting zero, once the corresponding service actually sets the value, it'll trigger the relation-changed hook again and we'll be able to read the value. This is considered an example of an idempotency guard which are crucial as you write hooks.

share|improve this answer
1  
Thanks Marco.This what i wanted.You gave me clear idea about add relationship server and client. –  Sajith4U Jul 31 at 11:36
    
Hi i have done the same steps.But i can't identify the relations.when i try to add relation it gives this error.juju add-relation Server:website application:backend --show-log ERROR juju.cmd supercommand.go:323 no relations found –  Sajith4U Aug 1 at 5:38
    
@Sajith4U Please paste both of your metadata.yaml files in to paste.ubuntu.com and link that here –  Marco Ceppi Aug 1 at 11:37
    
Thanks This is the link paste.ubuntu.com/7923431 –  Sajith4U Aug 1 at 12:10
    
Make sure you've upgraded or redeployed since you added that to the metadata, otherwise that is the correct format –  Marco Ceppi Aug 1 at 12:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.