Source code for crossbar.quickstart.main

###############################################################################
#
# Crossbar.io Quickstart
# Copyright (c) typedef int GmbH. Licensed under EUPLv1.2.
#
###############################################################################

import os
import uuid

import click
import six
import yaml
from autobahn import util
from cookiecutter.main import cookiecutter

[docs] README = """# Crossbar.io Quickstart Project This project was generated using quickstart templates for Crossbar.io based services. The services are [Docker](https://www.docker.com/) based, and the service bundling is using [Docker Compose](https://docs.docker.com/compose/). To build your services: ```console make build ``` To check the service versions: ```console make version ``` To start your services: ```console make start ``` > Note: the latter is simply starting all services with `docker-compose up`. To start the services in the background, type `docker-compose up --detach`. """
[docs] MAKEFILE = """ SUBDIRS = $(shell ls -d */) default: start version: \tfor dir in $(SUBDIRS) ; do \ \t\techo "$$dir" ; \ \t\tcat $$dir/service.json ; \ \t\tmake -C $$dir version ; \ \tdone build: \tdocker-compose build # the following will automatically build the images from the Dockerfiles # references in docker-compose.yml, and it will also rebuild those images # and recreate containers as needed (eg when the Dockerfile or again a file # referenced therein, such as your actual application source code files, changes) # start: \tdocker-compose up --build """
[docs] readme_filename = "README.md"
[docs] makefile_filename = "Makefile"
[docs] docker_compose_filename = "docker-compose.yml"
[docs] DEVMODE = False
if DEVMODE:
[docs] CC1 = "/home/oberstet/scm/crossbario"
CC2 = "/home/oberstet/scm/xbr" else: CC1 = "gh:crossbario" CC2 = "gh:xbr" # built-in cookiecutters. #
[docs] _cookiecutters = [ # Crossbar.io (None, "Crossbar.io"), ("{}/cookiecutter-crossbar".format(CC1), "Create a Crossbar.io OSS app router"), ("{}/cookiecutter-crossbar-fabric".format(CC1), "Create a Crossbar.io app router"), ("{}/cookiecutter-crossbar-fabric-center".format(CC1), "Create a Crossbar.io cluster controller"), # XBR (None, "XBR"), ("{}/cookiecutter-xbr-api".format(CC2), "Create a XBR API bundle"), ("{}/cookiecutter-crossbar-fabric-xbr".format(CC1), "Create a Crossbar.io XBR data market"), # Autobahn (None, "Autobahn"), ("{}/cookiecutter-autobahn-python".format(CC1), "Create a Python based app or XBR service"), ("{}/cookiecutter-autobahn-js".format(CC1), "Create a JavaScript based app or XBR service"), ("{}/cookiecutter-autobahn-java".format(CC1), "Create a Java based app or XBR service"), ("{}/cookiecutter-autobahn-cpp".format(CC1), "Create a C++ based app or XBR service"), # Community project (None, "Community"), ("{}/cookiecutter-wampsharp".format(CC1), "Create a WampSharp/C# based app service"), ("{}/cookiecutter-nexus-go".format(CC1), "Create a Nexus/Go based app service"), ]
[docs] def hl(text, color="yellow", bold=True): if not isinstance(text, six.text_type): text = "{}".format(text) return click.style(text, fg=color, bold=bold)
[docs] def _initialize(): if not os.path.isfile(readme_filename): with open(readme_filename, "w") as fd: fd.write(README) click.echo("{} created".format(readme_filename)) if not os.path.isfile(makefile_filename): with open(makefile_filename, "w") as fd: fd.write(MAKEFILE) click.echo("{} created".format(makefile_filename)) docker_compose_filename = "docker-compose.yml" if not os.path.isfile(docker_compose_filename): docker_compose = {"version": "3.0", "services": {}} with open(docker_compose_filename, "w") as fd: fd.write(yaml.safe_dump(docker_compose)) click.echo("{} created".format(docker_compose_filename)) docker_compose = None with open(docker_compose_filename) as fd: data = fd.read() docker_compose = yaml.safe_load(data) if not isinstance(docker_compose, dict): raise click.ClickException( "invalid type {} found in {} for top level object".format(type(docker_compose), docker_compose_filename) ) if "services" not in docker_compose: raise click.ClickException( "no services attribute found in top level object for {}".format(docker_compose_filename) ) return docker_compose
[docs] def run(): click.echo("\n{cb} Project Quickstart\n".format(cb=hl("Crossbar.io / XBR"))) _templates = {} num = 0 click.echo(" {}: Exit".format(hl(num))) for template, desc in _cookiecutters: if template: num += 1 _templates[num] = template template_disp = hl(template, bold=False) click.echo( " {num}: {desc:46s} [{template}]".format(num=hl(str(num).ljust(3)), desc=desc, template=template_disp) ) else: click.echo("\n {}:\n".format(hl(desc))) click.echo("") select = None while select not in range(0, num + 1): select = click.prompt("Please select", type=int, default="0") if select > 0: template = _templates[select] click.echo("Initializing cookiecutter {} ...".format(template)) # initialize services root directory and return contents of # docker-compose.py as object docker_compose = _initialize() extra_context = { "uid": os.getuid(), "service_uuid": str(uuid.uuid4()), "generated": util.utcnow(), } output_dir = "." # cookiecutter returns the fully qualified path within which the template # was initialized. output_dir = cookiecutter(template, output_dir=output_dir, extra_context=extra_context) # the last part of the fully qualified output directory is the service name # that comes from "cookiecutter.json" service_name = os.path.basename(output_dir) # we expect the cookiecutter to produce a docker-compose-<service_name>.yml file service_docker_compose_filename = os.path.join(output_dir, "docker-compose-{}.yml".format(service_name)) if not os.path.isfile(service_docker_compose_filename): raise click.ClickException( "docker-compose fragment for service was not generated by cookiecutter. missing file:\n{}".format( service_docker_compose_filename ) ) # now load the docker-compose service fragment from the file generated by cookiecutter service_docker_compose = None with open(service_docker_compose_filename) as fd: data = fd.read() service_docker_compose = yaml.safe_load(data) # update the docker-compose object if service_name in docker_compose["services"]: click.echo('updating service "{}" existing in docker-compose.yml'.format(service_name)) else: click.echo('adding service "{}" to docker-compose.yml'.format(service_name)) docker_compose["services"][service_name] = service_docker_compose # write out the docker-compose object to the file with open(docker_compose_filename, "w") as fd: fd.write(yaml.safe_dump(docker_compose)) click.echo("{} written".format(docker_compose_filename))