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.
- grepsr_cli-0.7.4.dist-info/LICENSE.md +1 -0
- grepsr_cli-0.7.4.dist-info/METADATA +92 -0
- grepsr_cli-0.7.4.dist-info/RECORD +35 -0
- grepsr_cli-0.7.4.dist-info/WHEEL +5 -0
- grepsr_cli-0.7.4.dist-info/entry_points.txt +2 -0
- grepsr_cli-0.7.4.dist-info/top_level.txt +1 -0
- grepsrcli/__init__.py +0 -0
- grepsrcli/controllers/__init__.py +0 -0
- grepsrcli/controllers/base.py +55 -0
- grepsrcli/controllers/crawler.py +480 -0
- grepsrcli/controllers/generate.py +34 -0
- grepsrcli/controllers/report.py +63 -0
- grepsrcli/core/__init__.py +0 -0
- grepsrcli/core/aws_s3.py +39 -0
- grepsrcli/core/config.py +191 -0
- grepsrcli/core/exc.py +4 -0
- grepsrcli/core/input_prompts.py +0 -0
- grepsrcli/core/message_log.py +34 -0
- grepsrcli/core/multiproc_server.py +126 -0
- grepsrcli/core/report_api.py +39 -0
- grepsrcli/core/sdk_setup.py +84 -0
- grepsrcli/core/test_local.py +136 -0
- grepsrcli/core/utils.py +308 -0
- grepsrcli/ext/__init__.py +0 -0
- grepsrcli/main.py +91 -0
- grepsrcli/plugins/__init__.py +0 -0
- grepsrcli/templates/__init__.py +0 -0
- grepsrcli/templates/autocomplete.jinja2 +12 -0
- grepsrcli/templates/autocomplete_zsh.jinja2 +20 -0
- grepsrcli/templates/composer.jinja2 +21 -0
- grepsrcli/templates/node_boilerplate.jinja2 +100 -0
- grepsrcli/templates/php_boilerplate.jinja2 +63 -0
- grepsrcli/templates/php_brp_boilerplate.jinja2 +83 -0
- grepsrcli/templates/php_vc_boilerplate.jinja2 +65 -0
- grepsrcli/templates/py_boilerplate.jinja2 +56 -0
|
@@ -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
|
grepsrcli/core/aws_s3.py
ADDED
|
@@ -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
|
grepsrcli/core/config.py
ADDED
|
@@ -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
|
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")
|