Passed
Push — master ( e106c7...8d9a55 )
by Emmanuel
05:18
created

stakkr.setup._recipe_init_stakkr()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 0
dl 0
loc 5
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
# coding: utf-8
2
"""Setup post actions, used in main setup.py."""
3
4
import os
5
import shutil
6
import sys
7
import click
8
from stakkr import file_utils
9
from stakkr.actions import StakkrActions
10
from yaml import load, dump
11
12
13
@click.command(help="""Initialize for the first time stakkr by copying
14
templates and directory structure""")
15
@click.option('--force', '-f', help="Force recreate directories structure", is_flag=True)
16
@click.argument('recipe', required=False)
17
def init(force: bool, recipe: str = None):
18
    """CLI Entry point, when initializing stakkr manually."""
19
    config_file = os.getcwd() + '/stakkr.yml'
20
    if os.path.isfile(config_file) and force is False:
21
        click.secho('Config file (stakkr.yml) already present. Leaving.', fg='yellow')
22
        return
23
24
    if recipe is not None:
25
        install_recipe(recipe)
26
        msg = "Recipe has been installed"
27
    else:
28
        install_filetree(force)
29
        msg = "Config (stakkr.yml) not present, don't forget to create it"
30
31
    click.secho(msg, fg='yellow')
32
33
34
def install_filetree(force: bool = False):
35
    """Create templates (directories and files)."""
36
    print('Post Installation : create templates')
37
38
    project_dir = os.getcwd()
39
    # If already installed don't do anything
40
    if os.path.isfile(project_dir + '/stakkr.yml'):
41
        return
42
43
    required_dirs = [
44
        'conf/mysql-override',
45
        'conf/php-fpm-override',
46
        'conf/xhgui-override',
47
        'data',
48
        'home/www-data',
49
        'home/www-data/bin',
50
        'logs',
51
        'plugins',
52
        'services',
53
        'www'
54
    ]
55
    for required_dir in required_dirs:
56
        _create_dir(project_dir, required_dir, force)
57
58
    required_tpls = [
59
        # 'bash_completion', # How to do with a system wide installation ?
60
        'stakkr.yml.tpl',
61
        'conf/mysql-override/mysqld.cnf',
62
        'conf/php-fpm-override/example.conf',
63
        'conf/php-fpm-override/README',
64
        'conf/xhgui-override/config.php',
65
        'home/www-data/.bashrc'
66
    ]
67
    for required_tpl in required_tpls:
68
        _copy_file(project_dir, required_tpl, force)
69
70
71
def install_recipe(recipe: str):
72
    recipe_config = _recipe_get_config(recipe)
73
    with open(recipe_config, 'r') as stream:
74
        recipe = load(stream)
75
76
    click.secho('Installing services')
77
    _recipe_install_services(recipe['services'])
78
79
    click.secho('Creating config')
80
    _recipe_create_stakkr_config(recipe['config'])
81
82
    click.secho('Starting stakkr (can take a few minutes)')
83
    stakkr = _recipe_init_stakkr()
84
    res = stakkr.start(None, True, True, True)
85
86
    click.secho('Running commands')
87
    _recipe_run_commands(stakkr, recipe['commands'])
88
    _recipe_display_messages(stakkr)
89
90
def _create_dir(project_dir: str, dir_name: str, force: bool):
91
    dir_name = project_dir + '/' + dir_name.lstrip('/')
92
    if os.path.isdir(dir_name) and force is False:
93
        return
94
95
    if not os.path.isdir(dir_name):
96
        os.makedirs(dir_name)
97
98
99
def _copy_file(project_dir: str, source_file: str, force: bool):
100
    full_path = file_utils.get_file('tpls', source_file)
101
    dest_file = project_dir + '/' + source_file
102
    if os.path.isfile(dest_file) and force is False:
103
        print('  - {} exists, do not overwrite'.format(source_file))
104
        return
105
106
    print('  - {} written'.format(source_file))
107
    try:
108
        shutil.copy(full_path, dest_file)
109
    except Exception:
110
        msg = "Error trying to copy {} .. check that the file is there ...".format(full_path)
111
        print(msg, file=sys.stderr)
112
113
114
def _recipe_get_config(recipe: str):
115
    if recipe is None:
116
        return
117
118
    recipe_config = file_utils.get_file('static/recipes', '{}.yml'.format(recipe))
119
    if os.path.isfile(recipe_config) is False:
120
        click.secho('"{}" recipe does not exist'.format(recipe), fg='red')
121
        sys.exit(1)
122
123
    return recipe_config
124
125
126
def _recipe_create_stakkr_config(config: dict):
127
    with open('stakkr.yml', 'w') as outfile:
128
        dump(config, outfile, default_flow_style=False)
129
130
131
def _recipe_install_services(services: list):
132
    from stakkr.services import install
133
134
    for service in services:
135
        success, message = install('services', service)
136
        if success is False:
137
            click.echo(click.style(message, fg='red'))
138
            sys.exit(1)
139
140
141
def _recipe_init_stakkr():
142
    return StakkrActions({
143
        'CONFIG': '{}/stakkr.yml'.format(os.getcwd()),
144
        'VERBOSE': False,
145
        'DEBUG': False
146
    })
147
148
149
def _recipe_run_commands(stakkr: StakkrActions, commands: str):
150
    for title, cmd in commands.items():
151
        click.secho('  ↳ {}'.format(title))
152
        user = cmd['user'] if 'user' in cmd else 'root'
153
        stakkr.exec_cmd(cmd['container'], user, cmd['args'], True)
154
155
def _recipe_display_messages(stakkr: StakkrActions):
156
    services_ports = stakkr.get_services_urls()
157
    print('\nServices URLs :')
158
    print(services_ports)