API endpoint for retrieving bundle changes. #3035

Merged
merged 2 commits into from Aug 24, 2015

Conversation

Projects
None yet
4 participants
Member

frankban commented Aug 19, 2015

Implement the GetBundleChanges API endpoint on the Client.
This is used to generate end return the list of changes
required to deploy a bundle (from the GUI perspective),
given a bundle YAML content.

(Review request: http://reviews.vapour.ws/r/2416/)

API endpoint for retrieving bundle changes.
Implement the GetBundleChanges API endpoint on the Client.
This is used to generate end return the list of changes
required to deploy a bundle (from the GUI perspective),
given a bundle YAML content.
Member

frankban commented Aug 19, 2015

QA:

  • juju bootstrap an environment with this branch;
  • run the script at http://pastebin.ubuntu.com/12124421/ : you should
    see three Client:GetBundleChanges requests, the first one succeeding
    and returning the changes, the second one failing with verification
    errors, the third one failing with a more global yaml error;
  • destroy the environment.

I am copy/pasting the script in a comment below for future reference.

Member

frankban commented Aug 19, 2015

#!/usr/bin/env python

# Dependencies:
# sudo apt-get install python-pip
# python-dev and libevent-dev may be needed.
# sudo pip install websocket-client pyyaml

# Usage:
# run this script passing the environment name, or nothing to connect to the
# default environment.

from __future__ import (
    print_function,
    unicode_literals,
)

import itertools
import json
import os
import pprint
import ssl
import subprocess
import sys

import websocket
import yaml


SSLOPT = {
    'cert_reqs': ssl.CERT_NONE,
    'ssl_version': ssl.PROTOCOL_TLSv1,
}


BUNDLE_VALID = """
services:
  ganglia:
    charm: cs:precise/ganglia-7
    num_units: 1
    to:
    - nfs
    annotations:
      gui-x: "1107"
      gui-y: "526"
  nfs:
    charm: cs:precise/nfs-4
    num_units: 1
relations:
- - ganglia:juju-info
  - nfs:juju-info
"""
BUNDLE_INVALID = """
    services:
        django:
            charm: django
            num_units: 0
            to:
                - 42
"""
BUNDLE_INVALID_YAML = ':'


def start(ws, password):
    counter = itertools.count()

    def send(request):
        request['RequestId'] = counter.next()
        print(red('\n--> #{RequestId} {Type}:{Request}'.format(**request)))
        pprint.pprint(request)
        ws.send(json.dumps(request))
        response = json.loads(ws.recv())
        print(blue('<-- #{RequestId} Response'.format(**response)))
        pprint.pprint(response)
        print('\n{}'.format('-' * 80))
        return response

    # Log in.
    send({
        'Type': 'Admin',
        'Request': 'Login',
        'Params': {'AuthTag': 'user-admin', 'Password': password},
    })

    # Get bundle changes.
    for bundle in (BUNDLE_VALID, BUNDLE_INVALID, BUNDLE_INVALID_YAML):
        send({
            'Type': 'Client',
            'Request': 'GetBundleChanges',
            'Params': {'YAML': bundle},
        })


def blue(text):
    return '\033[01;34m{}\033[00m'.format(text)


def red(text):
    return '\033[01;31m{}\033[00m'.format(text)


def green(text):
    return '\033[01;32m{}\033[00m'.format(text)


def get_default_env_name():
    return subprocess.check_output(['juju', 'switch']).strip()


def get_env_info(env_name):
    jenv_path = os.path.expanduser(
        os.path.join('~', '.juju', 'environments', '{}.jenv'.format(env_name)))
    while True:
        with open(jenv_path) as stream:
            data = yaml.safe_load(stream)
        state_servers = data['state-servers']
        if state_servers:
            for state_server in state_servers:
                if not state_server.startswith(':'):
                    return (state_server,
                            data['bootstrap-config']['admin-secret'])
            raise ValueError('invalid state servers: {}'.format(state_servers))
        print('State server not ready, retrying.')
        # Calling status seems to set the state server info in the jenv.
        subprocess.check_output(['juju', 'status', '-e', env_name])


def connect(url):
    print(green('Connecting to {}.'.format(url)))
    return websocket.create_connection(url, sslopt=SSLOPT)


def main(args):
    env_name = args[0] if args else get_default_env_name()
    host, password = get_env_info(env_name)
    ws = connect('wss://{}'.format(host))
    try:
        start(ws, password)
    finally:
        print(green('\nClosing connection.'))
        ws.close()


if __name__ == '__main__':
    main(sys.argv[1:])
Owner

hatched commented Aug 20, 2015

👍 No QA yet

Member

makyo commented Aug 20, 2015

Awesome work. 👍 QA okay! Got the expected output from the python script.

Contributor

jujubot commented Aug 24, 2015

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju

jujubot added a commit that referenced this pull request Aug 24, 2015

Merge pull request #3035 from frankban/changes-endpoint
API endpoint for retrieving bundle changes.

Implement the GetBundleChanges API endpoint on the Client.
This is used to generate end return the list of changes
required to deploy a bundle (from the GUI perspective),
given a bundle YAML content.

(Review request: http://reviews.vapour.ws/r/2416/)

@jujubot jujubot merged commit 0eb685e into juju:guibundles Aug 24, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment