Skip to content

Commit f26a3b9

Browse files
committed
dns: add batch mode to generate snippets script
* Allow to run the generate_dns_snippets script in non-interactive mode that will commit in the temporary directory but not push to its remote, allowing to manage the interactive part remotely via a cookbook. * This commit implements only the first part of the two-phase commit via cookbook. Bug: T233183 Change-Id: I8496efdffea24a47564026561db780f95b9beb70
1 parent aa781b9 commit f26a3b9

File tree

1 file changed

+35
-15
lines changed

1 file changed

+35
-15
lines changed

Diff for: dns/generate_dns_snippets.py

+35-15
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
"""
1010
import argparse
1111
import ipaddress
12+
import json
1213
import logging
1314
import os
15+
import shutil
1416
import sys
1517
import tempfile
1618

@@ -63,8 +65,12 @@ def parse_args(args: Optional[Sequence[str]] = None) -> argparse.Namespace:
6365
6466
"""
6567
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
66-
parser.add_argument('-c', '--config', help='The config file to load.', default='/etc/dns-snippets.cfg')
68+
parser.add_argument('-c', '--config', help='The config file to load.', default='/etc/dns-snippets.ini')
6769
parser.add_argument('-v', '--verbose', help='Verbose mode.', action='store_true')
70+
parser.add_argument('-b', '--batch', action='store_true',
71+
help=('Enable the non-interactive mode, the commit will not be pushed to its remote and the '
72+
'temporary directory will not be deleted. A JSON with the path of the temporary '
73+
'directory and the SHA1 of the commit will be printed to the last line of stdout.'))
6874
parser.add_argument('message', help='The commit message to use.')
6975

7076
return parser.parse_args(args)
@@ -208,18 +214,19 @@ def get_file_stats(tmpdir: str) -> Tuple[int, int]:
208214
return files, lines
209215

210216

211-
def commit_changes(args: argparse.Namespace, working_repo: git.Repo) -> Optional[Dict[str, int]]:
217+
def commit_changes(args: argparse.Namespace, working_repo: git.Repo) -> Optional[git.objects.commit.Commit]:
212218
"""Add local changes and commit them, if any."""
213219
working_repo.index.add('*')
214-
if not working_repo.index.diff(working_repo.head.commit):
220+
if working_repo.head.is_valid() and not working_repo.index.diff(working_repo.head.commit):
215221
logger.info('Nothing to commit!')
216222
return None
217223

218224
author = git.Actor(GIT_USER_NAME, GIT_USER_EMAIL)
219225
message = '{user}: {message}'.format(user=get_user_id(), message=args.message)
220226
commit = working_repo.index.commit(message, author=author, committer=author)
227+
logger.info('Committed changes: %s', commit.hexsha)
221228

222-
return commit.stats.total
229+
return commit
223230

224231

225232
def validate_delta(changed: int, existing: int, warning: int, error: int, what: str) -> None:
@@ -249,19 +256,27 @@ def run(args: argparse.Namespace, config: ConfigParser, tmpdir: str) -> int:
249256
records = generate_records(devices, config.getint('dns_snippets', 'min_records'))
250257
working_repo = setup_repo(config, tmpdir)
251258
files, lines = get_file_stats(tmpdir)
252-
working_repo.git.rm('.', r=True) # Delete all existing files to ensure removal of stale files
259+
working_repo.git.rm('.', r=True, ignore_unmatch=True) # Delete all existing files to ensure removal of stale files
253260
generate_snippets(records, tmpdir)
254-
delta = commit_changes(args, working_repo)
255-
if delta is None:
261+
commit = commit_changes(args, working_repo)
262+
263+
if commit is None:
264+
if args.batch:
265+
print(json.dumps({'no_changes': True}))
256266
return NO_CHANGES_RETURN_CODE
257267

258268
print(working_repo.git.show(['--color=always', 'HEAD']))
259-
validate(files, lines, delta)
269+
validate(files, lines, commit.stats.total)
270+
271+
if args.batch:
272+
print(json.dumps({'path': tmpdir, 'sha1': commit.hexsha}))
273+
return 0
274+
260275
answer = input('OK to push the changes to the {origin} repository? (y/n) '.format(
261276
origin=config.get('dns_snippets', 'repo_path')))
262277
if answer == 'y':
263278
push_info = working_repo.remote().push()[0]
264-
logger.info('Pushed with %d flags: %s %s', push_info.flags, push_info.summary.strip(), delta)
279+
logger.info('Pushed with bitflags %d: %s %s', push_info.flags, push_info.summary.strip(), commit.stats.total)
265280
exit_code = 0
266281
else:
267282
logger.error('Manually aborted.')
@@ -277,17 +292,22 @@ def main() -> int:
277292
config = ConfigParser()
278293
config.read(args.config)
279294

280-
with tempfile.TemporaryDirectory(prefix='dns-snippets-') as tmpdir:
281-
try:
282-
exit_code = run(args, config, tmpdir)
283-
except Exception:
284-
logger.exception('Failed to run')
285-
exit_code = 1
295+
tmpdir = tempfile.mkdtemp(prefix='dns-snippets-')
296+
try:
297+
exit_code = run(args, config, tmpdir)
286298

299+
except Exception:
300+
logger.exception('Failed to run')
301+
exit_code = 1
302+
303+
finally:
287304
if exit_code not in (0, NO_CHANGES_RETURN_CODE):
288305
print('An error occurred, the generated files can be inspected in {tmpdir}'.format(tmpdir=tmpdir))
289306
input('Press any key to cleanup the generated files and exit ')
290307

308+
if not args.batch or exit_code == NO_CHANGES_RETURN_CODE:
309+
shutil.rmtree(tmpdir, ignore_errors=True)
310+
291311
return exit_code
292312

293313

0 commit comments

Comments
 (0)