Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
envsetup
Manage
Activity
Members
Plan
Redmine
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Analyze
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mediaserver
envsetup
Commits
c32f9657
Commit
c32f9657
authored
6 years ago
by
Nicolas KAROLAK
Browse files
Options
Downloads
Patches
Plain Diff
change(tests): formatting and functions documentation
parent
595578e7
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
tests/test_email.py
+133
-93
133 additions, 93 deletions
tests/test_email.py
tests/test_postgresql.py
+26
-71
26 additions, 71 deletions
tests/test_postgresql.py
utils.py
+195
-70
195 additions, 70 deletions
utils.py
with
354 additions
and
234 deletions
tests/test_email.py
+
133
−
93
View file @
c32f9657
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
"""
Criticality: High
Check that emails can be sent.
'''
"""
import
os
import
subprocess
import
sys
import
random
import
time
import
imp
# install spf lib if not present
try
:
import
spf
except
ImportError
:
subprocess
.
check_call
([
'
apt-get
'
,
'
-qq
'
,
'
-y
'
,
'
install
'
,
'
python3-spf
'
])
subprocess
.
check_call
([
"
apt-get
"
,
"
-qq
"
,
"
-y
"
,
"
install
"
,
"
python3-spf
"
])
import
spf
if
subprocess
.
call
([
'
which
'
,
'
netstat
'
])
!=
0
:
subprocess
.
check_call
([
'
apt-get
'
,
'
-qq
'
,
'
-y
'
,
'
install
'
,
'
net-tools
'
])
YELLOW
=
'
\033
[93m
'
GREEN
=
'
\033
[92m
'
RED
=
'
\033
[91m
'
DEF
=
'
\033
[0m
'
# install netstat if not present
if
subprocess
.
call
([
"
which
"
,
"
netstat
"
])
!=
0
:
subprocess
.
check_call
([
"
apt-get
"
,
"
-qq
"
,
"
-y
"
,
"
install
"
,
"
net-tools
"
])
os
.
chdir
(
os
.
path
.
dirname
(
__file__
))
if
not
os
.
path
.
isfile
(
'
../utils.py
'
):
print
(
'
The envsetup configuration was not found.
'
)
sys
.
exit
(
1
)
else
:
es_utils
=
imp
.
load_source
(
'
es_utils
'
,
'
../utils.py
'
)
conf
=
es_utils
.
load_conf
()
sys
.
path
.
append
(
"
..
"
)
# pylint: disable=wrong-import-position
from
envsetup
import
utils
as
u
# noqa: E402
def
print_color
(
txt
,
col
):
print
(
'
%s%s%s
'
%
(
col
,
txt
,
DEF
))
def
check_listen
()
->
int
:
"""
Check that Postfix is listening on 127.0.0.1:25.
def
print_yellow
(
txt
):
print_color
(
txt
,
YELLOW
)
:return: Exit return code
:rtype: int
"""
print
(
"
Checking that postfix is listening locally:
"
)
def
print_red
(
txt
):
print_color
(
txt
,
RED
)
# get listening state from netstat
status
,
out
=
subprocess
.
getstatusoutput
(
"
netstat -pant | grep master | grep
'
:25
'"
)
if
status
!=
0
or
"
127.0.0.1:25
"
not
in
out
:
u
.
error
(
"
Postfix is not listening on 127.0.0.1:25
"
)
return
1
def
print_green
(
txt
):
print_color
(
txt
,
GREEN
)
u
.
success
(
"
Postfix is listening on 127.0.0.1:25
"
)
def
check_listening_port
():
# check that postfix listens the port 25 correctly
status
,
out
=
subprocess
.
getstatusoutput
(
'
netstat -pant | grep master | grep
"
:25
"'
)
if
status
!=
0
:
print_red
(
'
The port 25 is not listened by postfix
"
master
"
process.
'
)
return
1
print_green
(
'
Postfix
"
master
"
process is listening port 25 correctly.
'
)
if
'
127.0.0.1:25
'
not
in
out
:
print_red
(
'
Postfix
"
master
"
process is not listening address 127.0.0.1, please check postfix configuration.
'
)
print
(
'
Postfix should listen address 127.0.0.1 to be sure that this server cannot be used as an SMTP relay by external services.
'
)
return
1
print_green
(
'
Postfix
"
master
"
process is listening address 127.0.0.1 correctly.
'
)
return
0
def
check_relay
():
print
(
'
Checking if SMTP relay conforms to conf.
'
)
status
,
out
=
subprocess
.
getstatusoutput
(
'
grep relayhost /etc/postfix/main.cf
'
)
def
check_relay
(
conf
:
dict
)
->
int
:
"""
Check that Postfix is not an open relay.
:param conf: EnvSetup configuration settings
:type conf: dict
:return: Exit return code
:rtype: int
"""
print
(
"
Checking that SMTP relay conforms to conf:
"
)
# get relayhost value from Postfix config
status
,
out
=
subprocess
.
getstatusoutput
(
"
grep relayhost /etc/postfix/main.cf
"
)
if
status
==
0
:
configured_relay
=
out
[
len
(
'
relayhost
'
):].
strip
(
'
\t
=
'
).
replace
(
'
[
'
,
''
).
replace
(
'
]
'
,
''
)
configured_relay
=
(
out
[
len
(
"
relayhost
"
)
:].
strip
(
"
\t
=
"
).
replace
(
"
[
"
,
""
).
replace
(
"
]
"
,
""
)
)
else
:
configured_relay
=
''
configured_relay
=
""
if
not
configured_relay
:
#
no relay configured, check relayless situation
s
ip
=
conf
.
get
(
'
NETWORK_IP_NAT
'
)
if
not
ip
:
ip
=
conf
.
get
(
'
NETWORK_IP
'
)
if
not
ip
:
print_yellow
(
'
Cannot determine public IP address
'
)
#
check public ip addres
s
ip
_addr
=
conf
.
get
(
"
NETWORK_IP_NAT
"
)
if
not
ip
_addr
:
ip
_addr
=
conf
.
get
(
"
NETWORK_IP
"
)
if
not
ip
_addr
:
u
.
warning
(
"
Cannot determine public IP address
"
)
return
3
with
open
(
'
/etc/mailname
'
,
'
r
'
)
as
f
:
d
=
f
.
read
().
strip
()
if
d
not
in
(
'
ubicast.tv
'
,
'
ubicast.eu
'
):
print_yellow
(
'
/etc/mailname does not contain ubicast.eu or ubicast.tv, mails will probably not be received on ubicast mailing lists
'
)
# check domain origin
with
open
(
"
/etc/mailname
"
,
"
r
"
)
as
mailname
:
data
=
mailname
.
read
().
strip
()
if
data
not
in
(
"
ubicast.tv
"
,
"
ubicast.eu
"
):
u
.
warning
(
"
/etc/mailname does not contain ubicast.eu or ubicast.tv
"
)
return
3
# check spf
result
,
explain
=
spf
.
check2
(
i
=
ip
,
s
=
'
support@ubicast.eu
'
,
h
=
''
)
if
result
!=
'
pass
'
:
print_red
(
'
ip %s is not in ubicast.eu SPF and emails sent from support@ubicast.eu may be treated as spam
'
%
ip
)
result
,
_
=
spf
.
check2
(
i
=
ip
_addr
,
s
=
"
support@ubicast.eu
"
,
h
=
""
)
if
result
!=
"
pass
"
:
u
.
error
(
"
SPF record for {} in ubicast.eu is missing
"
.
format
(
ip_addr
)
)
return
3
conf_relay
=
conf
.
get
(
'
EMAIL_SMTP_SERVER
'
,
''
).
replace
(
'
[
'
,
''
).
replace
(
'
]
'
,
''
)
# get relayhost value from envsetup config
conf_relay
=
conf
.
get
(
"
EMAIL_SMTP_SERVER
"
,
""
).
replace
(
"
[
"
,
""
).
replace
(
"
]
"
,
""
)
if
conf_relay
!=
configured_relay
:
print_red
(
'
Configured STMP relay (%s) does not match the expected value (%s).
'
%
(
configured_relay
,
conf_relay
))
u
.
error
(
"
STMP relay must be {}
"
.
format
(
conf_relay
))
return
3
else
:
print_green
(
'
STMP relay is properly set.
'
)
return
0
u
.
success
(
"
STMP relay is properly set
"
)
return
0
def
check_send_test_email
()
->
int
:
"""
Check that Postfix can send email.
:return: Exit return code
:rtype: int
"""
print
(
"
Checking Postfix can send email:
"
)
def
send_test_
email
():
email
=
'
noreply+
%s-%s
@ubicast.eu
'
%
(
time
.
time
(),
random
.
randint
(
0
,
1000
))
print
(
'
Sending test email to
"
%s
"
.
'
%
email
)
cmd
=
'
echo
"
This is a
test email
"
| mail -s
"
T
est email
from `cat /etc/hostname`
"
%s
'
%
email
# send
email
email
=
"
noreply+
{}-{}
@ubicast.eu
"
.
format
(
time
.
time
(),
random
.
randint
(
0
,
1000
))
u
.
info
(
"
Sending test email to
'
{}
'"
.
format
(
email
)
)
cmd
=
"
echo
'
test email
'
| mail -s
'
t
est email
'
{}
"
.
format
(
email
)
subprocess
.
getstatusoutput
(
cmd
)
# init vars
timeout
=
120
waited
=
1
delay
=
2
print
(
'
Timeout to find email sending log is set to %s seconds.
'
%
timeout
)
out
=
''
if
os
.
path
.
isfile
(
'
/var/log/mail.log
'
):
cmd
=
'
grep
"
%s
"
/var/log/mail.log
'
%
email
out
=
""
# find logs
if
os
.
path
.
isfile
(
"
/var/log/mail.log
"
):
cmd
=
"
grep
'
{}
'
/var/log/mail.log
"
.
format
(
email
)
else
:
print
(
'
/var/log/mail.log not found, trying journalctl
'
)
cmd
=
'
journalctl -u postfix | grep %s
'
%
email
u
.
info
(
"
/var/log/mail.log not found, trying journalctl
"
)
cmd
=
"
journalctl -u postfix | grep {}
"
.
format
(
email
)
# logs polling
time
.
sleep
(
1
)
while
True
:
status
,
out
=
subprocess
.
getstatusoutput
(
cmd
)
# found
if
status
==
0
:
out
=
out
.
strip
().
split
(
'
\n
'
)[
-
1
]
if
'
status=deferred
'
not
in
out
:
print
(
'
Log entry found after
%s
seconds
.
'
%
waited
)
out
=
out
.
strip
().
split
(
"
\n
"
)[
-
1
]
if
"
status=deferred
"
not
in
out
:
u
.
info
(
"
Log entry found after
{}
seconds
"
.
format
(
waited
)
)
break
# timeout
if
waited
>=
timeout
:
print_red
(
'
Failed to send email.
'
)
print
(
'
No log entry found after %s seconds using command: %s
'
%
(
waited
,
cmd
))
u
.
error
(
"
Failed to send email.
"
)
u
.
info
(
"
No log entry found after {} seconds using command: {}
"
.
format
(
waited
,
cmd
)
)
return
1
print
(
'
No log entry found after %s seconds, waiting %s more seconds...
'
%
(
waited
,
delay
))
# not found yet
u
.
info
(
"
No log entry found after {} seconds, waiting {} more seconds...
"
.
format
(
waited
,
delay
)
)
# wait before next iteration
time
.
sleep
(
delay
)
waited
+=
delay
delay
*=
2
if
'
bounced
'
not
in
out
or
'
The email account that you tried to reach does not exist.
'
in
out
:
print_green
(
'
Email sent.
'
)
return
0
else
:
print_red
(
'
Failed to send email.
'
)
print
(
'
Sending log line:
\n
%s
'
%
out
)
# check output for errors
if
"
bounced
"
in
out
or
"
you tried to reach does not exist
"
in
out
:
u
.
error
(
"
Failed to send email
"
)
u
.
info
(
"
Sending log line:
\n
{}
"
.
format
(
out
))
return
1
u
.
success
(
"
Email sent.
"
)
return
0
def
main
():
"""
Run all checks and exits with corresponding exit code.
"""
if
not
os
.
path
.
exists
(
"
/etc/postfix
"
):
u
.
error
(
"
Postfix dir does not exists, please install postfix
"
)
sys
.
exit
(
1
)
conf
=
u
.
load_conf
()
rcode
=
check_listen
()
if
rcode
==
0
:
rcode
=
check_relay
(
conf
)
if
check_send_test_email
()
==
1
:
rcode
=
1
if
not
os
.
path
.
exists
(
'
/etc/postfix
'
):
print_red
(
'
Postfix dir does not exists, please install postfix.
'
)
sys
.
exit
(
1
)
sys
.
exit
(
rcode
)
rc
=
check_listening_port
()
if
rc
==
0
:
rc
=
check_relay
()
if
send_test_email
()
==
1
:
rc
=
1
sys
.
exit
(
rc
)
if
__name__
==
"
__main__
"
:
main
()
This diff is collapsed.
Click to expand it.
tests/test_postgresql.py
+
26
−
71
View file @
c32f9657
...
...
@@ -4,8 +4,6 @@ Criticality: High
This test check the current state of the PostgreSQL database cluster.
"""
import
imp
import
os
import
re
import
socket
import
subprocess
...
...
@@ -13,45 +11,15 @@ import sys
import
time
import
uuid
sys
.
path
.
append
(
"
..
"
)
try
:
import
psycopg2
except
ImportError
:
sys
.
exit
(
2
)
GREEN
=
"
\033
[92m
"
YELLOW
=
"
\033
[93m
"
RED
=
"
\033
[91m
"
DEF
=
"
\033
[0m
"
def
success
(
message
:
str
):
"""
Print formatted success message.
:param message: Message to print
:type message: str
"""
print
(
"
{}✔{} {}
"
.
format
(
GREEN
,
DEF
,
message
))
def
warning
(
message
:
str
):
"""
Print formatted warning message.
:param message: Message to print
:type message: str
"""
print
(
"
{}⚠{} {}
"
.
format
(
YELLOW
,
DEF
,
message
))
def
error
(
message
:
str
):
"""
Print formatted error message.
:param message: Message to print
:type message: str
"""
print
(
"
{}✖{} {}
"
.
format
(
RED
,
DEF
,
message
))
# pylint: disable=wrong-import-position
from
envsetup
import
utils
as
u
# noqa: E402
def
is_ha
(
port
:
int
)
->
bool
:
...
...
@@ -254,7 +222,6 @@ def check_replication(primary: dict, standby: dict) -> tuple:
rand
=
uuid
.
uuid4
().
hex
write_query
=
"
CREATE TABLE es_test_{} (id serial PRIMARY KEY);
"
.
format
(
rand
)
read_query
=
"
SELECT * FROM es_test_{};
"
.
format
(
rand
)
del_query
=
"
DROP TABLE es_test_{};
"
.
format
(
rand
)
# write
try
:
...
...
@@ -281,7 +248,7 @@ def check_replication(primary: dict, standby: dict) -> tuple:
# delete
try
:
primary_psql
.
execute
(
del_query
)
primary_psql
.
execute
(
"
DROP TABLE es_test_{};
"
.
format
(
rand
)
)
except
psycopg2
.
Error
:
pass
...
...
@@ -314,15 +281,15 @@ def check_ha(db_conn: dict, errors: int = 0) -> int:
# check haproxy
print
(
"
Checking local HAProxy frontends:
"
)
if
not
check_listen
(
db_conn
[
"
host
"
],
54321
):
error
(
"
HAProxy pgsql-primary frontend is not listening
"
)
u
.
error
(
"
HAProxy pgsql-primary frontend is not listening
"
)
errors
+=
1
else
:
success
(
"
HAProxy pgsql-primary frontend is listening
"
)
u
.
success
(
"
HAProxy pgsql-primary frontend is listening
"
)
if
not
check_listen
(
db_conn
[
"
host
"
],
54322
):
error
(
"
HAProxy pgsql-standby frontend is not listening
"
)
u
.
error
(
"
HAProxy pgsql-standby frontend is not listening
"
)
errors
+=
1
else
:
success
(
"
HAProxy pgsql-standby frontend is listening
"
)
u
.
success
(
"
HAProxy pgsql-standby frontend is listening
"
)
# check remotes
print
(
"
Checking remote PostgreSQL nodes:
"
)
...
...
@@ -330,19 +297,19 @@ def check_ha(db_conn: dict, errors: int = 0) -> int:
node_host
=
nodes
[
node
][
"
host
"
]
node_port
=
nodes
[
node
][
"
port
"
]
if
not
check_listen
(
node_host
,
node_port
):
error
(
"
Cannot bind {}:{}
"
.
format
(
node_host
,
node_port
))
u
.
error
(
"
Cannot bind {}:{}
"
.
format
(
node_host
,
node_port
))
errors
+=
1
else
:
success
(
"
Can bind {}:{}
"
.
format
(
node_host
,
node_port
))
u
.
success
(
"
Can bind {}:{}
"
.
format
(
node_host
,
node_port
))
# check fenced
print
(
"
Checking cluster state:
"
)
fenced
,
node
=
check_fenced
(
nodes
)
if
fenced
:
error
(
"
Node `{}` is fenced
"
.
format
(
node
))
u
.
error
(
"
Node `{}` is fenced
"
.
format
(
node
))
errors
+=
1
else
:
success
(
"
No fenced node found
"
)
u
.
success
(
"
No fenced node found
"
)
# check replication
print
(
"
Checking replication state:
"
)
...
...
@@ -352,10 +319,10 @@ def check_ha(db_conn: dict, errors: int = 0) -> int:
standby
[
"
port
"
]
=
54322
status
,
info
=
check_replication
(
primary
,
standby
)
if
not
status
:
error
(
"
Cannot replicate between primary/standby ({})
"
.
format
(
info
))
u
.
error
(
"
Cannot replicate between primary/standby ({})
"
.
format
(
info
))
errors
+=
1
else
:
success
(
"
Can replicate between primary/standby ({})
"
.
format
(
info
))
u
.
success
(
"
Can replicate between primary/standby ({})
"
.
format
(
info
))
return
errors
...
...
@@ -371,27 +338,27 @@ def check_local(db_conn: dict, errors: int = 0) -> int:
:rtype: int
"""
db_
host
=
db_conn
[
"
host
"
]
db_
port
=
db_conn
[
"
port
"
]
db_
user
=
db_conn
[
"
user
"
]
host
=
db_conn
[
"
host
"
]
port
=
db_conn
[
"
port
"
]
user
=
db_conn
[
"
user
"
]
# check listen
print
(
"
Checking local PostgreSQL node:
"
)
if
not
check_listen
(
db_
host
,
db_
port
):
error
(
"
Cannot connect to {}:{}
"
.
format
(
db_
host
,
db_
port
))
if
not
check_listen
(
host
,
port
):
u
.
error
(
"
Cannot connect to {}:{}
"
.
format
(
host
,
port
))
errors
+=
1
else
:
success
(
"
Can connect to {}:{}
"
.
format
(
db_
host
,
db_
port
))
u
.
success
(
"
Can connect to {}:{}
"
.
format
(
host
,
port
))
# check read
print
(
"
Checking read operation:
"
)
read_query
=
"
SELECT 1;
"
status
,
info
=
check_psql
(
db_conn
,
read_query
)
if
not
status
:
error
(
"
Cannot read from {}@{}:{} ({})
"
.
format
(
db_
user
,
db_
host
,
db_
port
,
info
))
u
.
error
(
"
Cannot read from {}@{}:{} ({})
"
.
format
(
user
,
host
,
port
,
info
))
errors
+=
1
else
:
success
(
"
Can read from {}@{}:{}
"
.
format
(
db_
user
,
db_
host
,
db_
port
))
u
.
success
(
"
Can read from {}@{}:{}
"
.
format
(
user
,
host
,
port
))
# check write
print
(
"
Checking write operation:
"
)
...
...
@@ -399,10 +366,10 @@ def check_local(db_conn: dict, errors: int = 0) -> int:
write_query
=
"
CREATE TABLE es_test_{} (id serial PRIMARY KEY);
"
.
format
(
rand
)
status
,
info
=
check_psql
(
db_conn
,
write_query
)
if
not
status
:
error
(
"
Cannot write on {}@{}:{} ({})
"
.
format
(
db_
user
,
db_
host
,
db_
port
,
info
))
u
.
error
(
"
Cannot write on {}@{}:{} ({})
"
.
format
(
user
,
host
,
port
,
info
))
errors
+=
1
else
:
success
(
"
Can write on {}@{}:{}
"
.
format
(
db_
user
,
db_
host
,
db_
port
))
u
.
success
(
"
Can write on {}@{}:{}
"
.
format
(
user
,
host
,
port
))
# remove test table
check_psql
(
db_conn
,
"
DROP TABLE es_test_{};
"
.
format
(
rand
))
...
...
@@ -412,20 +379,8 @@ def check_local(db_conn: dict, errors: int = 0) -> int:
def
main
():
"""
Run all checks and exits with corresponding exit code.
"""
# envsetup utils path
cwd
=
os
.
path
.
dirname
(
__file__
)
utils
=
os
.
path
.
join
(
cwd
,
"
..
"
,
"
utils.py
"
)
# check envsetup utils presence
if
not
os
.
path
.
isfile
(
utils
):
error
(
"
{} not found.
"
.
format
(
utils
))
sys
.
exit
(
1
)
# load envsetup utils
es_utils
=
imp
.
load_source
(
"
es_utils
"
,
utils
)
# load configuration
conf
=
es_utils
.
load_conf
()
conf
=
u
.
load_conf
()
# get database configuration
db_host
=
conf
.
get
(
"
DB_HOST
"
)
if
conf
.
get
(
"
DB_HOST
"
)
else
"
127.0.0.1
"
...
...
This diff is collapsed.
Click to expand it.
utils.py
+
195
−
70
View file @
c32f9657
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
EnvSetup utilities.
"""
from
collections
import
OrderedDict
import
os
import
subprocess
import
sys
from
typing
import
Any
RED
=
"
\033
[91m
"
GREEN
=
"
\033
[92m
"
YELLOW
=
"
\033
[93m
"
BLUE
=
"
\033
[94m
"
DEF
=
"
\033
[0m
"
DEFAULT_CONF_PATH
=
"
global-conf.sh
"
AUTO_CONF_PATH
=
"
auto-generated-conf.sh
"
CONF_PATH
=
"
conf.sh
"
DEFAULT_CONF_PATH
=
'
global-conf.sh
'
AUTO_CONF_PATH
=
'
auto-generated-conf.sh
'
CONF_PATH
=
'
conf.sh
'
CONF
=
dict
()
def
log
(
text
:
str
,
error
:
bool
=
False
):
"""
Output log message to stout or stderr.
:param text: Message to log
:type text: str
:param error: Wether it should output to stderr or not, defaults to False
:param error: bool, optional
"""
def
log
(
text
,
error
=
False
):
fo
=
sys
.
stderr
if
error
else
sys
.
stdout
print
(
text
,
file
=
fo
)
fo
.
flush
()
def
get_dir
(
file_path
):
def
info
(
message
:
str
):
"""
Print formatted info message.
:param message: Message to print
:type message: str
"""
print
(
"
{}🛈{} {}
"
.
format
(
GREEN
,
DEF
,
message
))
def
success
(
message
:
str
):
"""
Print formatted success message.
:param message: Message to print
:type message: str
"""
print
(
"
{}✔{} {}
"
.
format
(
GREEN
,
DEF
,
message
))
def
warning
(
message
:
str
):
"""
Print formatted warning message.
:param message: Message to print
:type message: str
"""
print
(
"
{}⚠{} {}
"
.
format
(
YELLOW
,
DEF
,
message
))
def
error
(
message
:
str
):
"""
Print formatted error message.
:param message: Message to print
:type message: str
"""
print
(
"
{}✖{} {}
"
.
format
(
RED
,
DEF
,
message
))
def
get_dir
(
file_path
:
str
)
->
str
:
"""
Get the absolute directory path for the given file.
:param file_path: File path
:type file_path: str
:return: Absolute directory path
:rtype: str
"""
return
os
.
path
.
dirname
(
os
.
path
.
abspath
(
os
.
path
.
expanduser
(
file_path
)))
def
exec_cmd
(
cmd
,
log_output
=
True
,
get_output
=
True
):
def
exec_cmd
(
cmd
:
Any
,
log_output
:
bool
=
True
,
get_output
:
bool
=
True
)
->
tuple
:
"""
Execute the given command.
:param cmd: Command to run
:type cmd: Any
:param log_output: Wether to log output or not, defaults to True
:param log_output: bool, optional
:param get_output: Wether to return output or not, defaults to True
:param get_output: bool, optional
:return: Return code and output
:rtype: tuple
"""
shell
=
not
isinstance
(
cmd
,
(
tuple
,
list
))
stdout
=
subprocess
.
PIPE
if
get_output
or
not
log_output
else
sys
.
stdout
stderr
=
subprocess
.
PIPE
if
get_output
or
not
log_output
else
sys
.
stderr
p
=
subprocess
.
Popen
(
cmd
,
stdin
=
sys
.
stdin
,
stdout
=
stdout
,
stderr
=
stderr
,
shell
=
shell
)
# execute
p
=
subprocess
.
Popen
(
cmd
,
stdin
=
sys
.
stdin
,
stdout
=
stdout
,
stderr
=
stderr
,
shell
=
shell
)
out
,
err
=
p
.
communicate
()
# send to the correct output
if
get_output
:
out
=
out
.
decode
(
'
utf-8
'
).
strip
()
if
out
else
''
out
=
out
.
decode
(
"
utf-8
"
).
strip
()
if
out
else
""
if
err
:
if
out
:
out
+=
'
\n
'
out
+=
err
.
decode
(
'
utf-8
'
).
strip
()
out
+=
"
\n
"
out
+=
err
.
decode
(
"
utf-8
"
).
strip
()
out
=
out
.
strip
()
if
log_output
:
log
(
out
)
elif
log_output
:
sys
.
stdout
.
flush
()
sys
.
stderr
.
flush
()
return
p
.
returncode
,
out
def
check_cmd
(
cmd
,
log_output
=
False
):
code
,
out
=
exec_cmd
(
cmd
,
log_output
,
False
)
def
check_cmd
(
cmd
:
Any
,
log_output
:
bool
=
False
)
->
int
:
"""
Get the return code of the given command.
:param cmd: Command to execute
:type cmd: Any
:param log_output: Wether to log output or not, defaults to False
:param log_output: bool, optional
:return: Return code
:rtype: int
"""
code
,
_
=
exec_cmd
(
cmd
,
log_output
,
False
)
return
code
def
load_conf
():
def
load_conf
()
->
dict
:
"""
Load EnvSetup configuration settings.
:return: Configuration settings
:rtype: dict
"""
conf
=
{}
base_dir
=
get_dir
(
__file__
)
files
=
(
(
os
.
path
.
join
(
base_dir
,
DEFAULT_CONF_PATH
),
True
),
...
...
@@ -60,94 +160,119 @@ def load_conf():
for
path
,
is_default
in
files
:
if
not
os
.
path
.
exists
(
path
):
if
is_default
:
log
(
'
The configuration file for EnvSetup script does not exist.
\n
Path of configuration file: %s
'
%
path
,
error
=
True
)
log
(
"
The configuration file
'
{}
'
does not exist.
"
.
format
(
path
),
error
=
True
,
)
return
dict
()
continue
# Load conf
with
open
(
path
,
'
r
'
)
as
fo
:
with
open
(
path
,
"
r
"
)
as
fo
:
content
=
fo
.
read
()
# Parse conf
for
line
in
content
.
split
(
'
\n
'
):
for
line
in
content
.
split
(
"
\n
"
):
line
=
line
.
strip
()
if
line
and
not
line
.
startswith
(
'
#
'
)
and
'
=
'
in
line
:
name
,
*
val
=
line
.
split
(
'
=
'
)
name
=
name
.
strip
(
'
\t
\
'\"
'
)
val
=
(
'
=
'
.
join
(
val
)).
strip
(
'
\t
\
'\"
'
)
CONF
[
name
]
=
val
if
line
and
not
line
.
startswith
(
"
#
"
)
and
"
=
"
in
line
:
name
,
*
val
=
line
.
split
(
"
=
"
)
name
=
name
.
strip
(
"
\t
'
\"
"
)
val
=
(
"
=
"
.
join
(
val
)).
strip
(
"
\t
'
\"
"
)
conf
[
name
]
=
val
if
is_default
:
override
[
name
]
=
False
else
:
only_default
=
False
override
[
name
]
=
True
CONF
[
'
_override
'
]
=
override
conf
[
"
_override
"
]
=
override
# Check a value to know if the config file has been changed
if
only_default
:
log
(
'
\033
[93mWarning:
\033
[0m
'
)
log
(
'
The configuration is using only default values.
'
)
log
(
'
Perhaps you forget to change the configuration.
'
)
log
(
'
Path of configuration file: %s
'
%
os
.
path
.
join
(
base_dir
,
CONF_PATH
))
log
(
'
Perhaps you want to quit this script to change the configuration?
\n
'
)
return
CONF
log
(
"
\033
[93mWarning:
\033
[0m
"
)
log
(
"
The configuration is using only default values.
"
)
log
(
"
Perhaps you forget to change the configuration.
"
)
log
(
"
Path of configuration file: %s
"
%
os
.
path
.
join
(
base_dir
,
CONF_PATH
))
log
(
"
Perhaps you want to quit this script to change the configuration?
\n
"
)
return
conf
def
get_conf
(
name
:
str
,
default
:
str
=
None
)
->
str
:
"""
Get the given configuration parameter.
:param name: Parameter name
:type name: str
:param default: Default parameter value, defaults to None
:param default: str, optional
:return: Parameter value
:rtype: str
"""
conf
=
load_conf
()
return
conf
.
get
(
name
,
default
)
def
get_conf
(
name
,
default
=
None
):
if
not
CONF
:
load_conf
()
return
CONF
.
get
(
name
,
default
)
def
run_commands
(
cmds
:
list
):
"""
Run a serie of successive commands.
:param cmds: List of commands
:type cmds: list
:raises Exception: Houston we have a problem
"""
def
run_commands
(
cmds
):
# run a serie of successive commands
try
:
# Execute commands
for
cmd
in
cmds
:
if
not
isinstance
(
cmd
,
dict
):
cmd
=
dict
(
line
=
cmd
)
if
cmd
.
get
(
'
cond
'
):
cond
=
cmd
[
'
cond
'
]
negate
=
cmd
.
get
(
'
cond_neg
'
)
skip
=
cmd
.
get
(
'
cond_skip
'
)
if
cmd
.
get
(
"
cond
"
):
cond
=
cmd
[
"
cond
"
]
negate
=
cmd
.
get
(
"
cond_neg
"
)
skip
=
cmd
.
get
(
"
cond_skip
"
)
code
=
check_cmd
(
cond
)
success
=
code
!=
0
if
negate
else
code
==
0
if
not
success
:
msg
=
'
Condition for command
"
%s
"
not fullfilled.
'
%
cmd
[
'
line
'
]
valid
=
code
!=
0
if
negate
else
code
==
0
if
not
valid
:
msg
=
'
Condition for command
"
%s
"
not fullfilled.
'
%
cmd
[
"
line
"
]
if
skip
:
log
(
'
%s Command skipped.
'
%
msg
)
log
(
"
%s Command skipped.
"
%
msg
)
continue
raise
Exception
(
msg
)
if
cmd
[
'
line
'
]
==
'
write
'
:
if
not
cmd
.
get
(
'
target
'
):
raise
Exception
(
'
No target file to write in.
'
)
if
cmd
.
get
(
'
backup
'
)
and
os
.
path
.
exists
(
cmd
[
'
target
'
])
and
not
os
.
path
.
exists
(
cmd
[
'
target
'
]
+
'
.back
'
):
os
.
rename
(
cmd
[
'
target
'
],
cmd
[
'
target
'
]
+
'
.back
'
)
log
(
'
A backup file has been created for:
\n
%s
'
%
cmd
[
'
target
'
])
if
cmd
[
"
line
"
]
==
"
write
"
:
if
not
cmd
.
get
(
"
target
"
):
raise
Exception
(
"
No target file to write in.
"
)
if
(
cmd
.
get
(
"
backup
"
)
and
os
.
path
.
exists
(
cmd
[
"
target
"
])
and
not
os
.
path
.
exists
(
cmd
[
"
target
"
]
+
"
.back
"
)
):
os
.
rename
(
cmd
[
"
target
"
],
cmd
[
"
target
"
]
+
"
.back
"
)
log
(
"
A backup file has been created for:
\n
%s
"
%
cmd
[
"
target
"
])
# Load content from template if any
content
=
cmd
.
get
(
'
content
'
,
''
)
if
cmd
.
get
(
'
template
'
):
if
not
os
.
path
.
exists
(
cmd
[
'
template
'
]):
raise
Exception
(
'
Template file does not exist: %s.
'
%
cmd
[
'
template
'
])
with
open
(
cmd
[
'
template
'
],
'
r
'
)
as
fd
:
content
=
cmd
.
get
(
"
content
"
,
""
)
if
cmd
.
get
(
"
template
"
):
if
not
os
.
path
.
exists
(
cmd
[
"
template
"
]):
raise
Exception
(
"
Template file does not exist: %s.
"
%
cmd
[
"
template
"
]
)
with
open
(
cmd
[
"
template
"
],
"
r
"
)
as
fd
:
content
=
fd
.
read
()
if
cmd
.
get
(
'
params
'
):
for
k
,
v
in
cmd
[
'
params
'
]:
if
cmd
.
get
(
"
params
"
):
for
k
,
v
in
cmd
[
"
params
"
]:
content
=
content
.
replace
(
k
,
v
)
# Write target file
with
open
(
cmd
[
'
target
'
],
'
w+
'
)
as
fd
:
with
open
(
cmd
[
"
target
"
],
"
w+
"
)
as
fd
:
fd
.
write
(
content
)
log
(
'
File %s written
'
%
cmd
[
'
target
'
])
elif
cmd
[
'
line
'
]
==
'
backup
'
:
if
not
cmd
.
get
(
'
target
'
):
raise
Exception
(
'
No target file to backup.
'
)
if
not
os
.
path
.
exists
(
cmd
[
'
target
'
]
+
'
.back
'
):
os
.
rename
(
cmd
[
'
target
'
],
cmd
[
'
target
'
]
+
'
.back
'
)
log
(
'
A backup file has been created for:
\n
%s
'
%
cmd
[
'
target
'
])
log
(
"
File %s written
"
%
cmd
[
"
target
"
])
elif
cmd
[
"
line
"
]
==
"
backup
"
:
if
not
cmd
.
get
(
"
target
"
):
raise
Exception
(
"
No target file to backup.
"
)
if
not
os
.
path
.
exists
(
cmd
[
"
target
"
]
+
"
.back
"
):
os
.
rename
(
cmd
[
"
target
"
],
cmd
[
"
target
"
]
+
"
.back
"
)
log
(
"
A backup file has been created for:
\n
%s
"
%
cmd
[
"
target
"
])
else
:
log
(
'
A backup file already exist for:
\n
%s
'
%
cmd
[
'
target
'
])
log
(
"
A backup file already exist for:
\n
%s
"
%
cmd
[
"
target
"
])
else
:
log
(
'
>>>
'
+
cmd
[
'
line
'
])
code
=
check_cmd
(
cmd
[
'
line
'
],
log_output
=
True
)
log
(
"
>>>
"
+
cmd
[
"
line
"
])
code
=
check_cmd
(
cmd
[
"
line
"
],
log_output
=
True
)
if
code
!=
0
:
raise
Exception
(
'
Command exited with code %s.
'
%
code
)
raise
Exception
(
"
Command exited with code %s.
"
%
code
)
except
Exception
as
e
:
log
(
'
Command failed:
\n
%s
'
%
e
)
log
(
"
Command failed:
\n
%s
"
%
e
)
raise
This diff is collapsed.
Click to expand it.
Stéphane Diemer
@sdiemer
mentioned in commit
178de835
·
5 years ago
mentioned in commit
178de835
mentioned in commit 178de835f878e0646bc7c1f559afe34a909930ae
Toggle commit list
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment