-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtask_api.py
157 lines (129 loc) · 5.88 KB
/
task_api.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from threading import Thread
from celery import Celery
from . import tasks
from .celery import app
__all__ = ('TaskApi', )
def watch_task(task, callback, kwargs=None):
"""
watch task until it ends and then execute callback:
callback(response, **kwargs)
where response is a result of task
:param task: task to watch
:param callback: function which is called when task finishes
:param kwargs: dict which is passed to callback
:return: None
"""
try:
response = task.wait()
except Exception as exc:
response = exc
if kwargs:
callback(response, **kwargs)
else:
callback(response)
class TaskApi(object):
""" universal API for tasks which are executed on celery workers """
def build_docker_image(self, build_image, git_url, local_tag, git_dockerfile_path=None, git_commit=None,
parent_registry=None, target_registries=None, tag=None, repos=None,
callback=None, lint_callback=None, kwargs=None):
"""
build docker image from supplied git repo
TODO:
DockerFile has to be in root of the gitrepo, path and commit are not implemented yet
yum repos
:param build_image: name of the build image (supplied docker image is built inside this image)
:param git_url: url to git repo
:param local_tag: image is known within the service with this tag
:param git_dockerfile_path: path to dockerfile within git repo (default is ./Dockerfile)
:param git_commit: which commit to checkout (master by default)
:param parent_registry: pull base image from this registry
:param target_registries: list of urls where built image will be pushed
:param tag: tag image with this tag (and push it to target_repo if specified)
:param repos: list of yum repos to enable in image
:param callback: function to call when task finishes, it has to accept at least
one argument: return value of task
:param kwargs: dict which is pass to callback, callback is called like this:
callback(task_response, **kwargs)
:return: task_id
"""
args = (build_image, git_url, local_tag)
task_kwargs = {'parent_registry': parent_registry,
'target_registries': target_registries,
'tag': tag,
'git_commit': git_commit,
'git_dockerfile_path': git_dockerfile_path,
'repos': repos}
# The linter task, which runs dockerfile_lint
linter_task = tasks.linter.s(git_url,
git_dockerfile_path,
git_commit)
# This task builds the image
build_image_task = tasks.build_image.subtask((build_image,
git_url,
local_tag),
**task_kwargs)
# This task submits the results
submit_results_task = tasks.submit_results.s()
# Chain the tasks together in the right order and start them
task_chain = (linter_task |
build_image_task |
submit_results_task).apply_async()
# Call lint_callback when the linter task is done
linter = task_chain.parent.parent # 3rd from last task
lint_watcher = Thread(target=watch_task,
args=(linter,
lint_callback,
kwargs))
lint_watcher.start()
# Call callback when the entire chain is done
chain_watcher = Thread(target=watch_task,
args=(task_chain,
callback,
kwargs))
chain_watcher.start()
# Return the celery task ID of the chain
return task_chain.task_id
def find_dockerfiles_in_git(self):
raise NotImplemented()
def push_docker_image(self, image_name, source_registry, target_registry, tags, callback=None, kwargs=None):
"""
pull docker image from source registry, tag it with multiple tags and push it to target registry
:param image_name: image to pull
:param source_registry: registry to pull from
:param target_registry: registry for pushing
:param tags: list of tags for image tagging
:param callback: function to call when task finishes, it has to accept at least
one argument: return value of task
:param kwargs: dict which is pass to callback, callback is called like this:
callback(task_response, **kwargs)
:return: task_id
"""
task_info = tasks.push_image.delay(image_name, source_registry, target_registry, tags)
task_id = task_info.task_id
if callback:
t = Thread(target=watch_task, args=(task_info, callback, kwargs))
#w.daemon = True
t.start()
return task_id
def desktop_callback(data):
""" show desktop notification when build finishes """
from pprint import pprint
pprint(data)
try:
from gi.repository import Notify
except ImportError:
pass
else:
Notify.init("Docker Build Service")
n = Notify.Notification.new(
"Docker Build Service",
"Docker Build of '%s' has finished." % data[0]['Id'],
"dialog-information"
)
n.show()
if __name__ == '__main__':
t = TaskApi()
t.build_docker_image(build_image="buildroot-fedora",
git_url="github.com/TomasTomecek/docker-hello-world.git",
local_tag="fedora-celery-build",
callback=desktop_callback)