grepsr-cli 0.7.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ from typing import final
2
+ from cement import Controller, ex
3
+ import itertools;
4
+ from ..core.config import load_config, generate_autocomplete_script
5
+
6
+ class GenerateBase(Controller):
7
+ class Meta:
8
+ label = 'generate_base'
9
+
10
+
11
+ class Generate(Controller):
12
+ config = load_config('config.yml')
13
+
14
+ class Meta:
15
+ label = 'generate'
16
+ stacked_on = 'generate_base'
17
+ stacked_type = 'nested'
18
+
19
+ @ex(
20
+ help="Make and integrate tab autocompletion script",
21
+ )
22
+ def tab_completion(self):
23
+ config = self.config
24
+
25
+ base_paths_list = [
26
+ config['php']['paths'] if 'php' in config else [],
27
+ config['node']['paths'] if 'node' in config else [],
28
+ config['python']['paths'] if 'python' in config else [],
29
+ config['php_next']['paths'] if 'php_next' in config else []
30
+ ]
31
+
32
+ final_list = list(itertools.chain.from_iterable(base_paths_list))
33
+
34
+ generate_autocomplete_script(final_list)
@@ -0,0 +1,63 @@
1
+ from cement import Controller, ex
2
+ from webbrowser import open_new_tab
3
+ from ..core.config import load_config
4
+ from ..core.utils import get_plugin_path, get_plugin_info
5
+ from ..core.report_api import get_report_from_pid, run_report_by_rid
6
+
7
+
8
+ class ReportBase(Controller):
9
+ class Meta:
10
+ label = 'report_base'
11
+
12
+
13
+ class Report(Controller):
14
+ config = load_config('config.yml')
15
+
16
+ class Meta:
17
+ label = 'report'
18
+ stacked_on = 'report_base'
19
+ stacked_type = 'nested'
20
+
21
+ @ex(
22
+ help="run report to live",
23
+ arguments=[
24
+ (['-rid', '--report-id'], {
25
+ "action": "store",
26
+ "dest": "report_id"
27
+ }),
28
+ (['-s', '--service'], {
29
+ "action": "store",
30
+ "dest": "service_code"
31
+ })
32
+ ]
33
+ )
34
+ def run(self):
35
+
36
+ if(self.app.pargs.service_code is not None):
37
+ service_code = self.app.pargs.service_code
38
+ plugin_info = get_plugin_info(
39
+ get_plugin_path(service_code, all_types=True))
40
+
41
+ rid = get_report_from_pid(
42
+ plugin_info['pid'], plugin_info['report_name'])
43
+
44
+ if(rid):
45
+ run_api_message = run_report_by_rid(rid)
46
+ self.app.log.info("Report: {}, message: {}".format(
47
+ service_code, run_api_message))
48
+ open_new_tab(
49
+ f'https://appnext.grepsr.com/projects/{plugin_info["pid"]}')
50
+ else:
51
+ self.app.log.warning(
52
+ "We couldn't run report via report name, please try running it manually via the url")
53
+
54
+ self.app.log.info(
55
+ f'App Url: https://appnext.grepsr.com/projects/{plugin_info["pid"]}')
56
+
57
+ elif (self.app.pargs.report_id is not None):
58
+ report_id = self.app.pargs.report_id
59
+ run_api_message = run_report_by_rid(report_id)
60
+ self.app.log.info("Report ID: {}, message: {}".format(
61
+ report_id, run_api_message))
62
+ else:
63
+ self.app.log.error("please use a valid syntax")
File without changes
@@ -0,0 +1,39 @@
1
+ from base64 import b64decode
2
+ from boto3.session import Session
3
+
4
+ class S3():
5
+
6
+ def __init__(self, aws_id, aws_sec_key):
7
+ self.aws_id = aws_id
8
+ self.secret_key = aws_sec_key
9
+
10
+ self.aws_session = Session(
11
+ region_name='eu-central-1',
12
+ aws_access_key_id=self.aws_id,
13
+ aws_secret_access_key=self.secret_key
14
+ )
15
+
16
+ def get_decoded_auth_creds(self):
17
+ resp = self.aws_session.client('ecr').get_authorization_token()
18
+ encoded = resp.get('authorizationData')[0].get('authorizationToken')
19
+ return b64decode(encoded).decode('UTF-8')
20
+
21
+ def get_secure_url(self, bucket, filename, expires_in=7200, insecure=False):
22
+
23
+ # max is 7 days
24
+ if not expires_in:
25
+ expires_in = 7200
26
+ elif expires_in > 604800:
27
+ expires_in = 604800
28
+
29
+ url = self.aws_session.client('s3').generate_presigned_url(
30
+ 'get_object',
31
+ Params={
32
+ 'Bucket': bucket, 'Key': filename},
33
+ ExpiresIn=expires_in
34
+ )
35
+
36
+ if insecure:
37
+ return url.split("?")[0]
38
+ else:
39
+ return url
@@ -0,0 +1,191 @@
1
+ import yaml
2
+ from os import path, remove, system
3
+ from pathlib import Path
4
+ from .message_log import Log
5
+ from jinja2 import Template
6
+ import platform
7
+
8
+
9
+ config_path = path.expanduser('~/.grepsr')
10
+
11
+
12
+ def load_config(file_name, file_path=None):
13
+ """Loads yml config file for user configuration
14
+
15
+ Args:
16
+ file_name (str): the name of file in the path gcli/config
17
+ """
18
+
19
+ if file_path is None:
20
+ file_path = config_path
21
+ try:
22
+ file = f'{file_path}/{file_name}'
23
+ with open(file, 'r') as f:
24
+ file_content = f.read()
25
+ return yaml.full_load(file_content)
26
+ except:
27
+ Log.error("{} not found in Path {}".format(file_name, file_path))
28
+
29
+
30
+ def save_config(update=False):
31
+
32
+ if update == False:
33
+ setup_config = {}
34
+ else:
35
+ setup_config = load_config('config.yml')
36
+
37
+ platforms = ['php', 'node', 'python', 'php_next']
38
+ crawler_paths = []
39
+
40
+ for plat in platforms:
41
+ if yes_no_prompt(f"\nProcess configuration for {Log.OKCYAN + plat + Log.ENDC} platform?"):
42
+ if update == False:
43
+ setup_config[plat] = {}
44
+ setup_config[plat]['paths'] = []
45
+
46
+ if(plat == 'php'):
47
+ setup_config[plat]['sdk_image'] = '486559570021.dkr.ecr.eu-central-1.amazonaws.com/vortex/sdk:stable'
48
+ elif(plat == 'php_next'):
49
+ setup_config[plat]['sdk_image'] = '486559570021.dkr.ecr.eu-central-1.amazonaws.com/vortex/backend-next:latest'
50
+ else:
51
+ setup_config[plat]['sdk_image'] = ''
52
+
53
+ setup_config[plat]['env'] = {}
54
+ Log.heading("\nStep 1: Path Configuration")
55
+
56
+ if update == True:
57
+ if yes_no_prompt("Do you want to update crawler paths?") == True:
58
+ setup_config[plat]['paths'] = []
59
+ while True:
60
+ base_path = prompt_for(
61
+ prompt="Enter path for your plugin directory: ")
62
+ base_path = path.expanduser(base_path.rstrip('/'))
63
+ setup_config[plat]['paths'].append(base_path)
64
+ crawler_paths.append(base_path)
65
+ if(yes_no_prompt("Do you want to another path?") == False):
66
+ break
67
+ elif update == False:
68
+ while True:
69
+ base_path = prompt_for(
70
+ prompt="Enter path for your plugin directory: ")
71
+ base_path = path.expanduser(base_path.rstrip('/'))
72
+ setup_config[plat]['paths'].append(base_path)
73
+ crawler_paths.append(base_path)
74
+ if(yes_no_prompt("Do you want to another path?") == False):
75
+ break
76
+ else:
77
+ pass
78
+
79
+ Log.heading("\nStep 2: SDK Configuration")
80
+ if update == True:
81
+ if yes_no_prompt("Do you want to update SDK image ?") == True:
82
+ if plat == 'php':
83
+ setup_config[plat]['sdk_image'] = '486559570021.dkr.ecr.eu-central-1.amazonaws.com/vortex/sdk:stable'
84
+ elif plat == 'php_next':
85
+ setup_config[plat]['sdk_image'] = '486559570021.dkr.ecr.eu-central-1.amazonaws.com/vortex/backend-next:latest'
86
+ else:
87
+ setup_config[plat]['sdk_image'] = ''
88
+
89
+ sdk_image = prompt_for(
90
+ prompt=f"Enter SDK image for {Log.OKCYAN + plat + Log.ENDC} (defaults to stable sdk if empty): ", empty=True)
91
+ if sdk_image is not None:
92
+ setup_config[plat]['sdk_image'] = sdk_image
93
+ elif update == False:
94
+ sdk_image = prompt_for(
95
+ prompt=f"Enter SDK image for {Log.OKCYAN + plat + Log.ENDC} (defaults to stable sdk if empty): ", empty=True)
96
+ if sdk_image is not None:
97
+ setup_config[plat]['sdk_image'] = sdk_image
98
+ else:
99
+ pass
100
+
101
+ Log.heading("\nStep 3: Environment variable Coniguration")
102
+ if yes_no_prompt("Do you want to add environment variables?") == True:
103
+ while True:
104
+ env_key_val = prompt_for(
105
+ f"Enter env variable for {Log.OKCYAN + plat + Log.ENDC} (Eg:- CFG_PARAMS_SELENIUM_HOST: 192.168.90.64) \n")
106
+ try:
107
+ env_key_val = env_key_val.split(':')
108
+ setup_config[plat]['env'][env_key_val[0].strip()
109
+ ] = env_key_val[1].strip()
110
+ except:
111
+ Log.error("Please follow the correct format")
112
+ if yes_no_prompt("Do you want to another env variable?") == False:
113
+ break
114
+
115
+ if update == True:
116
+ if yes_no_prompt("Do you want to update your aws keys?") == True:
117
+ setup_config['aws_access_key_id'] = prompt_for(
118
+ f"Enter aws id \n")
119
+ setup_config['aws_secret_access_key'] = prompt_for(
120
+ f"Enter aws secret key \n")
121
+ else:
122
+ setup_config['aws_access_key_id'] = prompt_for(
123
+ f"Enter aws id \n")
124
+ setup_config['aws_secret_access_key'] = prompt_for(
125
+ f"Enter aws secret key \n")
126
+
127
+ setup_config['app_env'] = 'tst'
128
+
129
+ with open(config_path + '/config.yml', 'w') as w:
130
+ w.write(yaml.dump(setup_config))
131
+
132
+ generate_autocomplete_script(crawler_paths)
133
+
134
+ def prompt_for(prompt, empty=True):
135
+ while True:
136
+ ans = input(prompt)
137
+ if not empty and ans == '':
138
+ continue
139
+ break
140
+
141
+ return ans
142
+
143
+ def yes_no_prompt(ques):
144
+ answer = input(f'{ques} (y/n) ')
145
+ if(answer in ['y', '']):
146
+ return True
147
+ else:
148
+ return False
149
+
150
+
151
+ def generate_autocomplete_script(crawler_paths):
152
+
153
+ data = {}
154
+ data['paths'] = []
155
+ for p in range(len(crawler_paths)):
156
+ d = {}
157
+ d['ind'] = p
158
+ d['dest_path'] = crawler_paths[p]
159
+ data['paths'].append(d)
160
+
161
+ template_dir = Path(__file__).parent.parent.absolute()
162
+
163
+ # generate autocomplete file for zsh and bash
164
+ for auto_script in ['autocomplete', 'autocomplete_zsh']:
165
+
166
+ if path.exists(config_path + f'/{auto_script}.sh'):
167
+ remove(config_path +
168
+ f'/{auto_script}.sh')
169
+
170
+ template_file = '{}/templates/{}'.format(
171
+ template_dir, f'{auto_script}.jinja2')
172
+
173
+ with open(template_file) as file:
174
+ template = Template(file.read())
175
+
176
+ with open(config_path + f'/{auto_script}.sh', 'w') as dest_file:
177
+ dest_file.write(template.render(data))
178
+ Log.info(f"Generating Autocomplete Script for {platform.system()}")
179
+ if platform.system() == 'Linux':
180
+
181
+ with open(path.expanduser('~/.bashrc')) as rc_file:
182
+ rc_file = rc_file.read()
183
+ if ".grepsr/autocomplete.sh" not in rc_file:
184
+ system(
185
+ '''echo "source $HOME/.grepsr/autocomplete.sh" >> ~/.bashrc''')
186
+ elif platform.system() == 'Darwin':
187
+ with open(path.expanduser(path.expanduser('~/.zshrc'))) as rc_file:
188
+ rc_file = rc_file.read()
189
+ if ".grepsr/autocomplete_zsh.sh" not in rc_file:
190
+ system(
191
+ '''echo "source $HOME/.grepsr/autocomplete_zsh.sh" >> ~/.zshrc''')
grepsrcli/core/exc.py ADDED
@@ -0,0 +1,4 @@
1
+
2
+ class GrepsrCliError(Exception):
3
+ """Generic errors."""
4
+ pass
File without changes
@@ -0,0 +1,34 @@
1
+ class Log:
2
+ HEADER = '\033[95m'
3
+ OKBLUE = '\033[94m'
4
+ OKCYAN = '\033[96m'
5
+ OKGREEN = '\033[92m'
6
+ WARNING = '\033[93m'
7
+ FAIL = '\033[91m'
8
+ ENDC = '\033[0m'
9
+ BOLD = '\033[1m'
10
+ UNDERLINE = '\033[4m'
11
+
12
+ @staticmethod
13
+ def info(message):
14
+ print(f'{Log.OKGREEN}INFO: {message}{Log.ENDC}')
15
+
16
+ @staticmethod
17
+ def error(message):
18
+ print(f'{Log.BOLD}{Log.FAIL}ERR: {message}{Log.ENDC}')
19
+
20
+ @staticmethod
21
+ def standout(message):
22
+ print(f'{Log.HEADER}{message}{Log.ENDC}')
23
+
24
+ @staticmethod
25
+ def success(message):
26
+ print(f'{Log.OKGREEN}SUCCESS: {message}{Log.ENDC}')
27
+
28
+ @staticmethod
29
+ def warn(message):
30
+ print(f'{Log.WARNING}WARNING: {message}{Log.ENDC}')
31
+
32
+ @staticmethod
33
+ def heading(message):
34
+ print(f'{Log.OKBLUE}{message}{Log.ENDC}')
@@ -0,0 +1,126 @@
1
+ from http.server import BaseHTTPRequestHandler, HTTPServer
2
+ import json
3
+ import os
4
+ import subprocess
5
+ import time
6
+ import platform
7
+
8
+ PORT = 8848
9
+ PROC_TITLE = 'gcli_multiproc_procnum'
10
+ CHILD_PROC_ENV_IDENTIFIER = 'GCLI_CHILD_PROC_NUM'
11
+ PROCS = {}
12
+
13
+ """
14
+ def kill(proc_title, proc):
15
+ proc_pid = proc.pid
16
+ if platform.system() == 'Windows':
17
+ subprocess.run(
18
+ f'TASKKILL /F /T /FI "WINDOWTITLE eq {proc_title}*"', shell=True)
19
+ elif platform.system() == 'Linux':
20
+ os.killpg(proc_pid, signal.SIGINT)
21
+ """
22
+
23
+
24
+ def spawn_gcli_terminal(proc_num, service_code, params):
25
+ params_str = json.dumps(params, separators=[',', ':'])
26
+ '''
27
+ win_title = f'{PROC_TITLE}_{proc_num}'
28
+ if platform.system() == 'Windows':
29
+ cmd = f'start "{win_title}" cmd /k "sleep 1 && echo {service_code} && sleep 15 && echo {params_str}"'
30
+ proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
31
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
32
+ PROCS[win_title] = proc
33
+ elif platform.system() == 'Linux':
34
+ '''
35
+
36
+ win_title = f'{proc_num}.gcli'
37
+ output_logs_dir = os.path.join(os.path.expanduser('~'), '.grepsr-experiments', 'multi_proc')
38
+ os.makedirs(output_logs_dir, exist_ok=True)
39
+ # turn multiprocess flag off to prevent infinite recursion.
40
+ cmds = ["gcli", "crawler", "test", "-m", "0", "-s", service_code, "-p", params_str]
41
+ # if platform.system() == 'Windows':
42
+ # cmds[0] = 'C:\\Users\\DELL\\bin\\gcli.cmd'
43
+ with open(os.path.join(output_logs_dir, f'{win_title}.mp.out'), 'w') as fd:
44
+ # this env var tells that the current crawler is a child process initiated by main parent.
45
+ # this information might be needed somewhere
46
+ os.environ[CHILD_PROC_ENV_IDENTIFIER] = str(proc_num)
47
+ proc = subprocess.Popen(cmds, stdin=subprocess.PIPE, stdout=fd, stderr=subprocess.STDOUT)
48
+ # wait a little so that there is less chance of race condition when gcli starts processing.
49
+ time.sleep(2)
50
+ PROCS[win_title] = proc
51
+
52
+
53
+ class ProcessHandler(BaseHTTPRequestHandler):
54
+ def do_POST(self):
55
+ content_length = None
56
+ respo = {'success': False, 'message': ''}
57
+ try:
58
+ content_length = int(self.headers['content-length'])
59
+ except TypeError:
60
+ respo = {'success': False,
61
+ 'message': 'Could not convert content-length header to integer'}
62
+ if content_length is not None:
63
+ if self.headers['content-type'].split(';')[0] == 'application/json':
64
+ body = self.rfile.read(content_length).decode('UTF-8')
65
+ try:
66
+ data = json.loads(body)
67
+ service_code = data.get('service_code')
68
+ params = data.get('params')
69
+ proc_num = data.get('proc_num')
70
+ if (service_code is None) or (params is None) or (proc_num is None):
71
+ respo = {
72
+ 'success': False, 'message': 'No service code or params or proc number found'}
73
+ else:
74
+ spawn_gcli_terminal(proc_num, service_code, params)
75
+ respo = {'success': True, 'data': {'message': 'Spawned a process successfully!'}}
76
+ except json.JSONDecodeError:
77
+ respo = {'success': False,
78
+ 'message': 'request body is not JSON.'}
79
+
80
+ self.send_response(200)
81
+ self.send_header('content-type', 'application/json')
82
+ self.end_headers()
83
+
84
+ self.wfile.write(bytes(json.dumps(respo), "utf8"))
85
+
86
+ def start():
87
+ with HTTPServer(('127.0.0.1', PORT), ProcessHandler) as server:
88
+ try:
89
+ print('C&C: MultiProcess facillitation Python Server started', flush=True)
90
+ server.serve_forever()
91
+ except (Exception, KeyboardInterrupt) as e:
92
+ if not isinstance(e, KeyboardInterrupt):
93
+ print('\n', flush=True)
94
+ print(f'Do not Panic. Caught Exception. `{e}`', flush=True)
95
+ # print('', flush=True)
96
+ # print('Force Exit. Cleaning server and child processes.', flush=True)
97
+ server.server_close()
98
+
99
+ for i, proc in PROCS.items():
100
+ # print('Terminating Child process:: ', i, flush=True)
101
+ proc.terminate()
102
+ proc.communicate()
103
+ proc.kill()
104
+ print('Terminated Child process:: ', i, flush=True)
105
+ # kill(i, proc)
106
+
107
+
108
+ # outs, errs = proc.communicate(signal.CTRL_BREAK_EVENT)
109
+ # outs, errs = proc.communicate(signal.CTRL_C_EVENT)
110
+
111
+ # if hasattr(signal, 'CTRL_C_EVENT'):
112
+ # # windows. Need CTRL_C_EVENT to raise the signal in the whole process group
113
+ # print('using win method to kill whole process group', flush=True)
114
+ # os.kill(os.getpid(), signal.CTRL_C_EVENT)
115
+ # # os.kill(os.getpid(), signal.CTRL_BREAK_EVENT)
116
+ # else:
117
+ # print('using unix method to kill whole process group', flush=True)
118
+ # # unix.
119
+ # pgid = os.getpgid(os.getpid())
120
+ # if pgid == 1:
121
+ # os.kill(os.getpid(), signal.SIGINT)
122
+ # else:
123
+ # os.killpg(os.getpgid(os.getpid()), signal.SIGINT)
124
+
125
+ if __name__ == '__main__':
126
+ pass
@@ -0,0 +1,39 @@
1
+ from ..core.config import load_config
2
+ import requests as req
3
+ import json
4
+
5
+
6
+ config = load_config('config.yml')
7
+
8
+
9
+ def get_report_from_pid(pid, report_name):
10
+ """[summary]
11
+
12
+ Args:
13
+ pid ([type]): [description]
14
+ report_id ([type]): [description]
15
+ """
16
+
17
+ res = req.get(
18
+ 'https://api.grepsr.com/v1/report/list?project_id={}&x-api-key={}'.format(pid, config['api_key']))
19
+
20
+ res_json = json.loads(res.text)
21
+ reports = res_json['payload']
22
+ for report in reports:
23
+ if report['name'].strip() == report_name.strip():
24
+ return report['report_id']
25
+
26
+ return False
27
+
28
+
29
+ def run_report_by_rid(rid):
30
+ """[summary]
31
+
32
+ Args:
33
+ rid ([type]): [description]
34
+ """
35
+
36
+ run_api = req.get(
37
+ 'https://api.grep.sr/v1/report/run?report_id={}&x-api-key={}'.format(rid, config['api_key']))
38
+
39
+ return json.loads(run_api.text)['message']
@@ -0,0 +1,84 @@
1
+ from os import path
2
+ import os
3
+ import shutil
4
+ import subprocess
5
+ import yaml
6
+ from .message_log import Log
7
+ from .config import load_config
8
+ from .aws_s3 import S3
9
+
10
+
11
+ class SDKSetup:
12
+ config = load_config('config.yml')
13
+ home_path = path.expanduser('~')
14
+ config_path = path.expanduser('~/.grepsr/config.yml')
15
+
16
+ def __init__(self, type, dryrun, sdk_image):
17
+ self.type_dict = self.config[type]
18
+ self.type_name = type
19
+ self.dryrun = dryrun
20
+ self.sdk_image = sdk_image
21
+
22
+ self.do_setup()
23
+
24
+ def check_path(self):
25
+ for service_dir in self.type_dict.get('paths') or []:
26
+ service_dir = path.expanduser(service_dir)
27
+ if not path.exists(service_dir):
28
+ Log.error(
29
+ f'Directory {service_dir} was not found')
30
+ Log.error(
31
+ "Please check ~/.grepsr/config.yml to check if paths are correctly added")
32
+ return False
33
+ return True
34
+
35
+ def generate_autocomplete_directory(self, docker_id, dir_name):
36
+ for service_dir in self.type_dict.get('paths') or []:
37
+ Log.info(
38
+ f"Adding autocomplete modules in {service_dir}. This could take some time...")
39
+
40
+ autocomplete_dir = path.join(service_dir, '.autocomplete')
41
+ if os.path.exists(autocomplete_dir):
42
+ shutil.rmtree(autocomplete_dir)
43
+ os.makedirs(autocomplete_dir, exist_ok=True)
44
+
45
+ command = f"""docker cp -L {docker_id}:/home/grepsr/{dir_name}/lib {autocomplete_dir} && docker cp -L {docker_id}:/home/grepsr/{dir_name}/vendor {autocomplete_dir}
46
+ """
47
+ os.system(command)
48
+
49
+ def do_setup(self):
50
+ if self.sdk_image is not None:
51
+ with open(self.config_path, 'w') as w:
52
+ self.config[self.type_name]['sdk_image'] = self.sdk_image
53
+ w.write(yaml.dump(self.config))
54
+
55
+ if not self.check_path():
56
+ return False
57
+ if not self.dryrun:
58
+ Log.info("Logging in to AWS service")
59
+
60
+ s3 = S3(self.config['aws_access_key_id'], self.config['aws_secret_access_key'])
61
+ username, auth_token = s3.get_decoded_auth_creds().split(':')
62
+ sdk_image = self.sdk_image or self.type_dict['sdk_image']
63
+ hostname = sdk_image.split('/', 2)[0]
64
+ out = subprocess.run([
65
+ 'docker', 'login', '--username', username, '--password-stdin', hostname
66
+ ], input=auth_token, text=True, stdout=subprocess.PIPE)
67
+ Log.info(out.stdout)
68
+
69
+ Log.info("Getting the SDK")
70
+ os.system(f"docker pull {sdk_image}")
71
+
72
+ docker_id = subprocess.run(
73
+ ['docker', 'create', self.type_dict['sdk_image']], stdout=subprocess.PIPE).stdout
74
+ docker_id = docker_id.decode('utf-8').rstrip()
75
+
76
+ if self.type_name == 'php':
77
+ self.generate_autocomplete_directory(
78
+ docker_id, 'vortex-backend')
79
+ elif self.type_name == 'php_next':
80
+ self.generate_autocomplete_directory(
81
+ docker_id, 'vortex-backend-next')
82
+
83
+ os.system(f'docker rm {docker_id}')
84
+ Log.info("SDK has been installed successfully")