commit
9c73dcfcb4
3 changed files with 360 additions and 0 deletions
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
**service-updater** - Script for upgrading java/play application from git |
||||
|
||||
## Description |
||||
|
||||
Scenario upgrade java/play application in production directory |
||||
|
||||
## Requirements |
||||
|
||||
CentOS: yum -y install python-pip |
||||
Debian: apt-get install python-pip |
||||
|
||||
pip install configparser |
||||
|
||||
## Usage |
||||
|
||||
service.py [service] <start|stop|restart|build|update|upgrade> |
||||
|
||||
start - Start service |
||||
stop - Stop service |
||||
restart - Restart service |
||||
build - Build service. [stand|modules|all] |
||||
update - Update current service from repository |
||||
upgrade - Update developing service from repository |
||||
|
||||
To build a specific service you need to pass a parameter [service]: |
||||
./service.py application build all |
||||
|
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
[service] |
||||
|
||||
projects: {'application': 'app', 'daemon': 'srv'} |
||||
|
||||
default: application |
||||
|
||||
#Default parameters can be used in other sections. |
||||
[DEFAULT] |
||||
|
||||
java_options: -Xmx2g |
||||
|
||||
path: ${home}/$$SERVICE |
||||
bin: ${path}/target/universal/stage/bin/$$SERVICE |
||||
pid: ${path}/target/universal/stage/RUNNING_PID |
||||
|
||||
modules_dir: ${home}/modules/ |
||||
modules_list: ${modules_dir}/modules.list |
||||
|
||||
class_path: ${path}/target/universal/stage/lib/ |
||||
git_path: ${home}/git/ |
||||
|
||||
#clean all |
||||
targets: ${path}/modules/*/target |
||||
|
||||
config_file_path: ${path}/conf/application.conf |
||||
|
||||
restarts_log: ${home}/restarts.log |
||||
update_log: ${home}/update.log |
||||
build_log_file: ${home}/build.log |
||||
|
||||
server: play.core.server.ServerStart |
||||
|
||||
http_port: 10000 |
||||
|
||||
#Java options |
||||
play: activator -Duser.home=${home}/user_home -Dsbt.ivy.home=${home}/user_home/repository -Divy-home=${home}/user_home/repository |
||||
|
||||
modules_log: ${home}/modules.updated |
||||
sbt_config: @${home}/sbt.boot.properties |
||||
sbt_opts: -Dsbt.boot.directory=${home}/user_home/.sbt |
||||
|
||||
[build] |
||||
|
||||
java_options: -J-Xms2g -J-Xmx4g |
||||
|
||||
git_branch: dev |
||||
|
||||
#Current directory |
||||
[develop] |
||||
|
||||
home: PATH/TO/DIRECTORY |
||||
git_path: ${home} |
||||
|
||||
[app] |
||||
|
||||
home: PATH |
||||
path: ${home}/git/app |
||||
|
||||
http_port: 10001 |
||||
|
||||
[srv] |
||||
|
||||
home: PATH |
||||
path: ${home}/git/srv |
||||
class_path: ${path}/target/universal/stage/lib/ |
||||
|
||||
http_port: 10002 |
||||
|
@ -0,0 +1,265 @@
@@ -0,0 +1,265 @@
|
||||
#!/usr/bin/env python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
# |
||||
# Script for upgrading java/play application from git |
||||
# |
||||
# (c) envrm |
||||
# |
||||
|
||||
#Requirements |
||||
# |
||||
# CentOS: yum -y install python-pip |
||||
# Debian: apt-get install python-pip |
||||
# |
||||
# pip install configparser |
||||
# |
||||
|
||||
import re |
||||
import os |
||||
import ast |
||||
import sys |
||||
import shutil |
||||
import signal |
||||
import datetime |
||||
import subprocess |
||||
import configparser |
||||
|
||||
from string import Template |
||||
from contextlib import contextmanager |
||||
|
||||
@contextmanager |
||||
def if_needed(): |
||||
'''Execute with error ignoring''' |
||||
try: |
||||
yield |
||||
except: |
||||
pass |
||||
|
||||
class Dir: |
||||
'''Execute procedures in directory''' |
||||
def __init__(self, directory): |
||||
self.current_dir = directory |
||||
|
||||
def __enter__(self): |
||||
self.previous_dir = os.getcwd() |
||||
os.chdir(self.current_dir) |
||||
|
||||
def __exit__(self, type, value, traceback): |
||||
os.chdir(self.previous_dir) |
||||
|
||||
#----------------------------------------------------------------------- |
||||
|
||||
def readConfig(config_file): |
||||
'''Loading configuration file''' |
||||
global settings |
||||
settings = configparser.ConfigParser() |
||||
settings._interpolation = configparser.ExtendedInterpolation() |
||||
settings.read(config_file) |
||||
return settings |
||||
|
||||
def opt(parameter): |
||||
'''Getting parameters from file''' |
||||
setting = parameter.split(":") |
||||
value = settings.get(setting[0], setting[1]) |
||||
|
||||
variables = re.findall(r"\$(\w+)", value) |
||||
|
||||
substr = {v: globals()[v] for v in variables if v in globals()} |
||||
|
||||
return Template(value).safe_substitute(**substr) |
||||
|
||||
def saveTimestamp(outfile, mode="a"): |
||||
'''Saving timestamt to file''' |
||||
with open(outfile, mode) as log: |
||||
now = datetime.datetime.now() |
||||
log.write(now.strftime("%Y-%m-%d %H:%M:%S\n")) |
||||
|
||||
#----------------------------------------------------------------------- |
||||
|
||||
def git(command, stand="develop"): |
||||
'''Executing git command''' |
||||
with Dir(opt(stand + ':git_path')): |
||||
git_output = subprocess.check_output('git ' + command, shell=True) |
||||
|
||||
return git_output |
||||
|
||||
def stop(stand="develop"): |
||||
'''Stop service''' |
||||
if os.path.isfile(opt(stand + ':pid')): |
||||
pid = opt(stand + ':pid') |
||||
else: |
||||
pid = os.path.join(opt(stand + ':path'), 'RUNNING_PID') |
||||
|
||||
print pid |
||||
with if_needed(): |
||||
with open(pid, 'r') as pid_file: |
||||
os.kill(int(pid_file.read()), signal.SIGTERM) |
||||
os.remove(pid) |
||||
print "#### Application stopped" |
||||
|
||||
def start(stand): |
||||
'''Start service''' |
||||
service_dir = opt(stand + ':path') |
||||
server = opt(stand + ':server') |
||||
|
||||
start_cmd = 'nohup java ' + opt(stand + ':java_options') \ |
||||
+ ' -Dfile.encoding=UTF-8 -Dconfig.file=' + service_dir + '/conf/application.conf ' \ |
||||
+ ' -Dhttp.port=' + opt(stand + ':http_port') + ' -cp "' + service_dir + '/conf/:' + opt(stand + ':class_path') + '/*" ' \ |
||||
+ server + ' ' + service_dir + ' | tee -a ' + opt(stand + ':home') + '/nohup.out &' |
||||
|
||||
print start_cmd |
||||
|
||||
with Dir(service_dir): |
||||
return_code = os.system(start_cmd) |
||||
if return_code == 0: |
||||
print "#### Application started" |
||||
else: |
||||
print return_code |
||||
exit(1) |
||||
|
||||
def restart(stand="develop"): |
||||
'''Restart service''' |
||||
stop(stand) |
||||
start(stand) |
||||
saveTimestamp(opt(stand + ':restarts_log')) |
||||
|
||||
def clean_all(): |
||||
'''Remove artefacts''' |
||||
os.system("rm -rfv " + opt('develop:targets')) |
||||
|
||||
def build(target="stand", modules=None): |
||||
'''Build service. [stand|modules|all]''' |
||||
play_cmd = opt(SERVICE + ':play') + " " + opt(SERVICE + ':sbt_config') |
||||
|
||||
print "OK" |
||||
|
||||
if target == "modules" or target == "all": |
||||
with Dir(opt('develop:modules_dir')): |
||||
if modules == None: |
||||
modules = os.walk(".").next()[1] |
||||
|
||||
modules = filter(None, set(modules)) |
||||
|
||||
with open(opt('develop:modules_list')) as f: |
||||
modules_deps = f.read().splitlines() |
||||
|
||||
for mod in modules_deps: |
||||
if mod in modules: |
||||
with Dir(os.path.join(opt('develop:modules_dir'), mod)): |
||||
print "#### Update module " + mod |
||||
return_code = os.system(play_cmd + " publishLocal") |
||||
|
||||
if return_code != 0: |
||||
exit(1) |
||||
|
||||
if target == "stand" or target == "all": |
||||
print "#### Update application" |
||||
with Dir(opt('develop:path')): |
||||
with if_needed(): |
||||
shutil.rmtree("target") |
||||
print play_cmd + " " + opt('build:java_options') + " stage | tee " + opt('develop:build_log_file') |
||||
return_code = os.system(play_cmd + " " + opt('build:java_options') + " stage | tee " + opt('develop:build_log_file')) |
||||
|
||||
if return_code != 0: |
||||
exit(1) |
||||
|
||||
def update_from_git(): |
||||
'''Update app with modules''' |
||||
git('checkout ' + opt('build:git_branch')) |
||||
git('branch --set-upstream-to=origin/' + opt('build:git_branch') + ' ' + opt('build:git_branch')) |
||||
print git('fetch') |
||||
git_log = git('diff --name-only HEAD..origin/' + opt('build:git_branch')) |
||||
git('pull') |
||||
|
||||
modules = [] |
||||
for line in git_log.splitlines(): |
||||
module = re.findall(r'commonmodules/([^/]*)/.*', line) |
||||
if module: |
||||
modules.extend(module) |
||||
|
||||
build("all", modules) |
||||
|
||||
def copy_libs(): |
||||
'''Copy libraries''' |
||||
with if_needed(): |
||||
shutil.rmtree(opt(SERVICE + ':class_path')) |
||||
shutil.copytree(opt('develop:class_path'), opt(SERVICE + ':class_path')) |
||||
|
||||
def update(): |
||||
'''Update current service from repository''' |
||||
saveTimestamp(opt('develop:restarts_log')) |
||||
stop() |
||||
update_from_git() |
||||
start() |
||||
saveTimestamp(opt('develop:update_log'), 'w') |
||||
|
||||
def upgrade(): |
||||
'''Update developing service from repository''' |
||||
update_from_git() |
||||
saveTimestamp(opt(SERVICE + ':restarts_log')) |
||||
stop(SERVICE) |
||||
git("pull", SERVICE) |
||||
copy_libs() |
||||
start(SERVICE) |
||||
saveTimestamp(opt(SERVICE + ':update_log'), 'w') |
||||
|
||||
#----------------------------------------------------------------------- |
||||
|
||||
def show_help(): |
||||
exe = os.path.basename(sys.argv[0]) |
||||
|
||||
'''Show help''' |
||||
print "USAGE: " + exe + " [service] <" + "|".join(allowed_tasks) + ">" |
||||
|
||||
for task in allowed_tasks: |
||||
print "\t" + task + "\t- " + globals()[task].__doc__ |
||||
|
||||
print "\nTo build a specific service you need to pass a parameter [service]:" |
||||
print "\t./" + exe, opt('service:default'), "\b build all" |
||||
print "\n[service] can be one of «" + "», «".join(ast.literal_eval(opt('service:projects')).keys()) + "»." |
||||
print "\nDefault value of [service] is", opt('service:default'), "\n" |
||||
|
||||
settings = [] |
||||
|
||||
readConfig('config.ini') |
||||
|
||||
allowed_tasks = ['start', 'stop', 'restart', 'build', 'update', 'upgrade'] |
||||
|
||||
#Services allowed for building |
||||
services = ast.literal_eval(opt('service:projects')) |
||||
|
||||
#Default service |
||||
SERVICE = ast.literal_eval(opt('service:projects'))[opt('service:default')] |
||||
|
||||
#Command line arguments parsing |
||||
if len(sys.argv) > 2 and sys.argv[2] in allowed_tasks: |
||||
arg_index = 2 |
||||
if sys.argv[1] in services: |
||||
SERVICE = ast.literal_eval(opt('service:projects'))[sys.argv[1]] |
||||
elif len(sys.argv) > 1 and sys.argv[1] in allowed_tasks: |
||||
arg_index = 1 |
||||
else: |
||||
show_help() |
||||
exit(1) |
||||
|
||||
#Procedure for execution |
||||
task = globals()[sys.argv[arg_index]] |
||||
|
||||
if task: |
||||
target = { |
||||
'update' : 'develop', |
||||
'upgrade': 'mroot' |
||||
}.get(sys.argv[1], "develop") |
||||
|
||||
if len(sys.argv) > 2 and sys.argv[2] in ['start','stop','restart']: |
||||
SERVICE = ast.literal_eval(opt('service:projects'))[sys.argv[1]] |
||||
print "CMD: " + sys.argv[1] + " " + sys.argv[2], "| SERVICE: ", SERVICE |
||||
task(SERVICE) |
||||
elif len(sys.argv) > (arg_index + 1): |
||||
print "CMD: " + sys.argv[arg_index] + " " + sys.argv[arg_index + 1] |
||||
task(sys.argv[arg_index + 1]) |
||||
else: |
||||
print "CMD: " + sys.argv[arg_index] |
||||
task() |
||||
|
Loading…
Reference in new issue