-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathapp.py
103 lines (77 loc) · 3.43 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
import click
import re
from flask import Flask
from flask import request
from flask import jsonify
import docker
app = Flask(__name__)
client = docker.from_env()
@app.route('/')
def main():
return jsonify(success=True), 200
@app.route('/images/pull', methods=['POST'])
def image_puller():
if not request.form['token'] or not request.form['image']:
return jsonify(success=False, error="Missing parameters"), 400
image = request.form['image']
if request.form['token'] != os.environ['TOKEN']:
return jsonify(success=False, error="Invalid token"), 403
restart_containers = True if request.form['restart_containers'] == "true" else False
old_containers = []
for container in client.containers.list():
if re.match( r'.*' + re.escape(image) + r'$', container.attrs['Config']['Image']):
old_containers.append(container)
if len(old_containers) == 0:
return jsonify(success=False, error="No running containers found with the specified image"), 404
print ('Updating', str(len(old_containers)), 'containers with', image, 'image')
image = image.split(':')
image_name = image[0]
image_tag = image[1] if len(image) == 2 else 'latest'
print ('\tPulling new image...')
client.images.pull(image_name, tag=image_tag)
if restart_containers == False:
return jsonify(success=True, message=str(len(old_containers)) + " containers updated"), 200
print ('\tCreating new containers...')
new_containers = []
for container in old_containers:
if 'HOSTNAME' in os.environ and os.environ['HOSTNAME'] == container.attrs['Id']:
return jsonify(success=False, error="You can't restart the container where the puller script is running"), 403
new_cont = docker.APIClient().create_container(container.attrs['Config']['Image'], environment=container.attrs['Config']['Env'], host_config=container.attrs['HostConfig'])
new_containers.append(client.containers.get(new_cont['Id']))
print ('\tStopping old containers...')
for container in old_containers:
container.stop()
print ('\tStarting new containers...')
for container in new_containers:
container.start()
print ('\tRemoving old containers...')
for container in old_containers:
container.remove()
return jsonify(success=True, message=str(len(old_containers)) + " containers updated and restarted"), 200
@click.command()
@click.option('-h', default='0.0.0.0', help='Set the host')
@click.option('-p', default=8080, help='Set the listening port')
@click.option('--debug', default=False, help='Enable debug option')
def main(h, p, debug):
if not os.environ.get('TOKEN'):
print ('ERROR: Missing TOKEN env variable')
sys.exit(1)
registry_user = os.environ.get('REGISTRY_USER')
registry_passwd = os.environ.get('REGISTRY_PASSWD')
registry_url = os.environ.get('REGISTRY_URL', 'https://index.docker.io/v1/')
if registry_user and registry_passwd:
try:
client.login(username=registry_user, password=registry_passwd, registry=registry_url)
except Exception as e:
print(e)
sys.exit(1)
app.run(
host = os.environ.get('HOST', default=h),
port = os.environ.get('PORT', default=p),
debug = os.environ.get('DEBUG', default=debug)
)
if __name__ == "__main__":
main()