stakkr.stakkr_compose   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Test Coverage

Coverage 93.88%

Importance

Changes 0
Metric Value
eloc 102
dl 0
loc 171
ccs 92
cts 98
cp 0.9388
rs 10
c 0
b 0
f 0
wmc 30

12 Functions

Rating   Name   Duplication   Size   Complexity  
A cli() 0 21 1
A _add_local_services() 0 9 3
A get_available_services() 0 12 2
A _get_base_command() 0 19 3
A _set_env_from_config() 0 16 3
A _get_enabled_services_files() 0 14 3
A _get_uid() 0 5 3
A _get_config() 0 9 2
A _set_env_for_services() 0 8 4
A _get_gid() 0 5 3
A _get_services_from_dir() 0 5 2
A _set_env_for_proxy() 0 4 1
1
#!/usr/bin/env python
2
# coding: utf-8
3 1
"""
4
CLI Main Entry Point.
5
6
Wraps docker-compose and build it from what has been taken from config.
7
"""
8
9 1
import glob
10 1
import os
11 1
import subprocess
12 1
import sys
13 1
import click
14 1
from stakkr import file_utils
15 1
from stakkr.configreader import Config
16
17
18 1
@click.command(help="Wrapper for docker-compose",
19
               context_settings=dict(ignore_unknown_options=True))
20 1
@click.option('--config-file', '-c', help="Set stakkr config file location (default stakkr.yml)")
21 1
@click.argument('command', nargs=-1, type=click.UNPROCESSED)
22 1
def cli(config_file: str, command: tuple = ()):
23
    """Command line entry point."""
24 1
    config, config_file = _get_config(config_file)
25
26
    # Set main config and services as env variables
27 1
    _set_env_from_config(config)
28
29
    # Register proxy env parameters
30 1
    _set_env_for_proxy(config['proxy'])
31
32
    # set the base command
33 1
    base_cmd = _get_base_command(config)
34
35 1
    msg = click.style('[VERBOSE] ', fg='green')
36 1
    msg += 'Compose command: ' + ' '.join(base_cmd + list(command))
37 1
    click.echo(msg, err=True)
38 1
    subprocess.call(base_cmd + list(command))
39
40
41 1
def _add_local_services(project_dir: str, available_services: list):
42
    """Get services in the virtualenv services/ directory, so specific to that stakkr."""
43 1
    services_dir = project_dir + '/services/*/docker-compose'
44 1
    for service_dir in glob.glob(services_dir):
45 1
        conf_files = _get_services_from_dir(service_dir)
46 1
        for conf_file in conf_files:
47 1
            available_services[conf_file[:-4]] = service_dir + '/' + conf_file
48
49 1
    return available_services
50
51
52 1
def get_available_services(project_dir: str):
53
    """Get standard services bundled with stakkr."""
54 1
    services_dir = file_utils.get_dir('static') + '/services/'
55 1
    conf_files = _get_services_from_dir(services_dir)
56
57 1
    services = dict()
58 1
    for conf_file in conf_files:
59 1
        services[conf_file[:-4]] = services_dir + conf_file
60
61 1
    services = _add_local_services(project_dir, services)
62
63 1
    return services
64
65
66 1
def _get_base_command(config: dict):
67
    """Build the docker-compose file to be run as a command."""
68 1
    main_file = 'docker-compose.yml'
69
    # Set the network subnet ?
70 1
    if config['subnet'] != '':
71 1
        main_file = 'docker-compose.subnet.yml'
72 1
    cmd = ['docker-compose', '-f', file_utils.get_file('static', main_file)]
73
74
    # What to load
75 1
    activated_services = _get_enabled_services_files(
76
        config['project_dir'],
77
        [svc for svc, opts in config['services'].items() if opts['enabled'] is True])
78
    # Create the command
79 1
    services = []
80 1
    for service in activated_services:
81 1
        services.append('-f')
82 1
        services.append(service)
83
84 1
    return cmd + services + ['-p', config['project_name']]
85
86
87 1
def _get_config(config_file: str):
88
    """Read main stakkr.yml file."""
89 1
    config_reader = Config(config_file)
90 1
    config = config_reader.read()
91 1
    if config is False:
92 1
        config_reader.display_errors()
93 1
        sys.exit(1)
94
95 1
    return config, config_reader.config_file
96
97
98 1
def _get_enabled_services_files(project_dir: str, configured_services: list):
99
    """Compile all available services : standard and local install."""
100 1
    available_services = get_available_services(project_dir)
101
102 1
    services_files = []
103 1
    for service in configured_services:
104 1
        if service not in available_services:
105
            msg = 'Error: service "{}" has no configuration file. '.format(service)
106
            msg += 'Check your config'
107
            click.secho(msg, fg='red')
108
            sys.exit(1)
109 1
        services_files.append(available_services[service])
110
111 1
    return services_files
112
113
114 1
def _get_gid(gid: int):
115 1
    if gid is not None:
116 1
        return str(gid)
117
118 1
    return '1000' if os.name == 'nt' else str(os.getgid())
119
120
121 1
def _get_services_from_dir(services_dir: str):
122 1
    if os.path.isdir(services_dir) is False:
123
        return []
124
125 1
    return [service for service in os.listdir(services_dir) if service.endswith('.yml')]
126
127
128 1
def _get_uid(uid: int):
129 1
    if uid is not None:
130 1
        return str(uid)
131
132 1
    return '1000' if os.name == 'nt' else str(os.getuid())
133
134
135 1
def _set_env_for_proxy(config: dict):
136
    """Define environment variables to be used in services yaml."""
137 1
    os.environ['PROXY_ENABLED'] = str(config['enabled'])
138 1
    os.environ['PROXY_DOMAIN'] = str(config['domain'])
139
140
141 1
def _set_env_for_services(services: dict):
142 1
    for service, params in services.items():
143 1
        if params['enabled'] is False:
144 1
            continue
145
146 1
        for param, value in params.items():
147 1
            env_var = 'DOCKER_{}_{}'.format(service, param).upper()
148 1
            os.environ[env_var] = str(value)
149
150
151 1
def _set_env_from_config(config: dict):
152
    """Define environment variables to be used in services yaml."""
153 1
    os.environ['COMPOSE_BASE_DIR'] = config['project_dir']
154 1
    os.environ['COMPOSE_PROJECT_NAME'] = config['project_name']
155
156 1
    for parameter, value in config.items():
157 1
        if parameter == 'services':
158 1
            _set_env_for_services(value)
159 1
            continue
160
161 1
        os.environ['DOCKER_{}'.format(parameter.upper())] = str(value)
162
163
    # Do that at the end, else the value in config will overwrite the possible
164
    # default value
165 1
    os.environ['DOCKER_UID'] = _get_uid(config['uid'])
166 1
    os.environ['DOCKER_GID'] = _get_gid(config['gid'])
167
168
169 1
if __name__ == '__main__':
170
    cli()
171