-
Notifications
You must be signed in to change notification settings - Fork 174
/
Copy pathTiltfile
160 lines (131 loc) · 8.55 KB
/
Tiltfile
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
157
158
159
# -*- mode: Python -*-
krsync_path = os.path.join(os.getcwd(), 'krsync.sh')
MIN_LOCAL_RSYNC_VERSION = '3.0.0'
verify_rsync_path = os.path.join(os.getcwd(), 'verify_rsync.sh')
# Path on the remote container where the rsync binary is located
rsync_path = '/bin/rsync.tilt'
# if no local rsync/insufficient version, bail
print('-- syncback extension checking for local rsync --')
local([verify_rsync_path, MIN_LOCAL_RSYNC_VERSION])
DEFAULT_EXCLUDES = ['.git', '.gitignore', '.dockerignore', 'Dockerfile', '.tiltignore', 'Tiltfile', 'tilt_modules']
def syncback_command_args(k8s_object, src_dir, ignore=None, delete=False, paths=None, target_dir='.', container='', namespace='', verbose=False, rsync_path=rsync_path, rsync_options=None):
"""
Generate a list of command arguments to run that will sync the specified files from the given k8s object to the local filesystem.
:param k8s_object (str): a Kubernetes object identifier (e.g. deploy/my-deploy, job/my-job, or a pod ID) that Tilt
can use to select a pod. As per the behavior of `kubectl exec`, we will act on the first pod of the specified
object, using the first container by default.
:param src_dir (str): directory IN THE KUBERNETES CONTAINER to sync from. Any paths specified, if relative,
should be relative to this dir.
:param ignore (List[str], optional): files to ignore when syncing (relative to src_dir).
:param delete (bool, optional): run rsync with the --delete flag, i.e. delete files locally if not present in
the container. By default, False. THIS OPTION RISKS WIPING OUT FILES that exist locally but not in the
container. Tilt will protect some files automatically, but we recommend syncing specific paths (via `paths`
and/or using the `ignore` parameter to explicitly protect other files that exist locally but not on the container.
:param paths (List[str], optional): paths IN THE KUBERNETES CONTAINER to sync, relative to src_dir. May be files or dirs.
Note that these must not begin with `./`. If this arg is not passed, sync all of src_dir.
:param target_dir (str, optional): directory ON THE LOCAL FS to sync to. Defaults to '.'
:param container (str, optiona): name of the container to sync from (by default, the first container)
:param namespace (str, optiona): namespace of the desired k8s_object, if not `default`.
:param verbose (bool, optional): if true, print additional rsync information.
:param rsync_path (str, optional): A path where the remote containers `rsync` executable is located. Defaults to `/bin/rsync.tilt`.
:param rsync_options (List[str], optional): additional options passed to the `rsync` command.
"""
# Verify inputs
if not src_dir.endswith('/'):
fail('src_dir must be a directory and have a trailing slash (because of rsync syntax rules)')
if paths:
for p in paths:
if p.startswith('./'):
fail('Found illegal path "{}": paths may not begin with ./ (because of rsync syntax rules)'.format(p))
if p.startswith('/'):
fail('Found illegal path "{}": paths may not begin with / and must be relative to src_dir (because of rsync syntax rules)'.format(p))
filters = []
if paths and ignore:
fail('Paths and ignore are mutually exclusive.')
if not paths:
if not ignore:
ignore = []
# Sync the entire src_dir except ignored items. Danger, Will Robinson! Exclude some stuff
# that may exist locally but not in your container so it
# doesn't get wiped out locally on your first sync
to_exclude = DEFAULT_EXCLUDES + ignore
filters.extend(['--exclude={}***'.format(ex) for ex in to_exclude])
else:
# TODO: if you're rsync-savvy you might want to do the wildcarding manually--
# give an option to turn off automatic +'***'
filters.extend(['--include={}***'.format(p) for p in paths])
filters.append('--exclude=*')
# set remote name to a dummy name
remote_name = 'syncback'
# instead of wrestling with passing optional args to krsync.sh that do not
# then get passed to rsync, just bundle container and namespace flags with
# k8s object specifier (quoted 1st argument)
if container:
k8s_object = '{obj} -c {container}'.format(obj=k8s_object, container=container)
if namespace:
k8s_object = '{obj} -n {namespace}'.format(obj=k8s_object, namespace=namespace)
flags = '-aOv'
if verbose:
flags = '-aOvvi'
argv = [
krsync_path,
k8s_object,
rsync_path,
flags,
'--progress',
'--stats',
]
if delete:
argv.append('--delete')
argv.append('-T=/tmp/rsync.tilt')
argv.extend(filters)
if rsync_options:
argv.extend(rsync_options)
argv.append(remote_name + ':' + src_dir)
argv.append(target_dir)
return argv
def syncback_command(k8s_object, src_dir, ignore=None, delete=False, paths=None, target_dir='.', container='', namespace='', verbose=False, rsync_path=rsync_path, rsync_options=None):
"""
Generate a properly-quoted shell command string that will sync the specified files from the given k8s object to the local filesystem.
"""
argv = syncback_command_args(k8s_object, src_dir, ignore, delete, paths, target_dir, container, namespace, verbose, rsync_path, rsync_options)
return ' '.join([shlex.quote(arg) for arg in argv])
def syncback(name, k8s_object, src_dir, ignore=None, delete=False, paths=None, target_dir='.', container='', namespace='', verbose=False, labels=[], resource_deps=[], rsync_path=rsync_path, rsync_options=None):
"""
Create a local resource that will (via rsync) sync the specified files
from the specified k8s object to the local filesystem.
:param name (str): name of the created local resource.
:param k8s_object (str): a Kubernetes object identifier (e.g. deploy/my-deploy, job/my-job, or a pod ID) that Tilt
can use to select a pod. As per the behavior of `kubectl exec`, we will act on the first pod of the specified
object, using the first container by default.
:param src_dir (str): directory IN THE KUBERNETES CONTAINER to sync from. Any paths specified, if relative,
should be relative to this dir.
:param ignore (List[str], optional): files to ignore when syncing (relative to src_dir).
:param delete (bool, optional): run rsync with the --delete flag, i.e. delete files locally if not present in
the container. By default, False. THIS OPTION RISKS WIPING OUT FILES that exist locally but not in the
container. Tilt will protect some files automatically, but we recommend syncing specific paths (via `paths`
and/or using the `ignore` parameter to explicitly protect other files that exist locally but not on the container.
:param paths (List[str], optional): paths IN THE KUBERNETES CONTAINER to sync, relative to src_dir. May be files or dirs.
Note that these must not begin with `./`. If this arg is not passed, sync all of src_dir.
:param target_dir (str, optional): directory ON THE LOCAL FS to sync to. Defaults to '.'
:param container (str, optiona): name of the container to sync from (by default, the first container)
:param namespace (str, optiona): namespace of the desired k8s_object, if not `default`.
:param verbose (bool, optional): if true, print additional rsync information.
:param labels (Union[str, List[str]], optional): Used to group resources in the Web UI.
:param resource_deps (Union[str, List[str]], optional): Used to declare dependencies on other resources.
:param rsync_path (str, optional): A path where the remote containers `rsync` executable is located. Defaults to `/bin/rsync.tilt`.
:param rsync_options (List[str], optional): additional options passed to the `rsync` command.
"""
# Ensure extra kwargs are only passed to local_resource if specified to
# provide backward compatibility with older version of tilt.
command = syncback_command(k8s_object, src_dir,
ignore=ignore, delete=delete, paths=paths,
target_dir=target_dir,
container=container, namespace=namespace,
verbose=verbose, rsync_path=rsync_path, rsync_options=rsync_options)
extra_args = {}
if labels:
extra_args["labels"] = labels
if resource_deps:
extra_args["resource_deps"] = resource_deps
local_resource(name, command, trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False, **extra_args)