Add support for command-line arguments and options

Previously, the YAML and iCal directories needed to be specified in
const.py. The locations specified in const.py have been modified to
represent the default locations, if no command-line options are
provided to override them.

In addition, parameters have provided to execute the script in one of
two modes:

  * To execute the script in Jenkins test job mode, the -t/--test
    parameters can be used. Valid values include 'check', 'gate',
    and 'post'.

  * To execute the script in YAML-iCal conversion mode, the
    -c/--convert parameter can be used. This can be combined with
    the -m/--meetings parameter, to specify a list of meetings
    to process. The meeting list file should contain the filenames
    of meetings that correspond to meeting files in the YAML
    directory, and should be separated by newlines.

Support for command line options was implemented using the argparse
module. This module has been added to requirements.txt.

Change-Id: I9e5e8f123d7a28997cbd8eb8e67b246d68c97260
This commit is contained in:
Josh Tan 2014-05-04 17:47:18 -05:00
parent 97ced8fa45
commit e6ec82a4c9
7 changed files with 152 additions and 60 deletions

View File

@ -31,4 +31,4 @@ DEFAULT_YAML_DIR = '../meetings'
DEFAULT_ICAL_DIR = '../icals'
# NOTE(jotan): The following publish URL is for testing purposes only.
# It should be later changed to the official OpenStack Meetings Wiki.
DEFAULT_PUBLISH_URL = 'https://wiki.openstack.org/wiki/Meetings_Autogenerated'
PUBLISH_URL = 'https://wiki.openstack.org/wiki/Meetings_Autogenerated'

View File

@ -16,11 +16,10 @@
# under the License.
import logging
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import os
import yaml
import const
from meeting import Meeting
import util
@ -29,22 +28,13 @@ logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',
level=logging.DEBUG)
def execute_check():
def execute_check(yaml_dir, ical_dir):
"""Execute check job."""
logging.info('Check job initiated.')
# NOTE(jotan): once a CLI parameter for YAML_DIR has been
# implemented, only use DEFAULT_YAML_DIR if the parameter has
# not been supplied
yaml_dir = const.DEFAULT_YAML_DIR
meetings = __load_meetings(yaml_dir)
# convert meetings to a list of ical
for m in meetings:
m.write_ical()
logging.info('Wrote %d meetings to iCal' % (len(meetings)))
util.convert_yaml_to_ical(yaml_dir, ical_dir)
os.chdir(const.SRC_DIR)
if util.check_uniqueness() == 0:
@ -55,7 +45,7 @@ def execute_check():
return 1
def execute_gate():
def execute_gate(yaml_dir):
"""Execute gate job."""
logging.info('Gate job initiated.')
@ -65,33 +55,109 @@ def execute_gate():
return result
def execute_post():
def execute_post(yaml_dir, ical_dir, publish_url):
"""Execute post job."""
logging.info('Post job initiated.')
yaml_dir = const.DEFAULT_YAML_DIR
meetings = __load_meetings(yaml_dir)
# convert meetings to a list of ical
for m in meetings:
m.write_ical()
logging.info('Wrote %d meetings to iCal' % (len(meetings)))
util.convert_yaml_to_ical(yaml_dir, ical_dir)
logging.info('Post job finished.')
def __load_meetings(yaml_dir):
"""Return a list of Meetings initialized from files in yaml_dir."""
os.chdir(yaml_dir)
meetings_yaml = [f for f in os.listdir()
if os.path.isfile(f) and
f.endswith(const.YAML_FILE_EXT)]
meetings = [Meeting(yaml.load(open(f, 'r')), f)
for f in meetings_yaml]
logging.info('Loaded %d meetings from YAML' % (len(meetings)))
os.chdir(const.SRC_DIR)
return meetings
# entry point
execute_check()
if __name__ == '__main__':
# build option parser:
description = """
A tool that automates the process for testing, integrating, and
publishing changes to OpenStack meetings using the existing OpenStack
project infrastructure.
"""
epilog = """
This program is meant to be invoked as a Jenkins job during check,
gate, and post tests. Depending on which test invokes the program,
it will perform different activites.
Check:
- Verify correct YAML syntax for proposed meeting changes.
- Verify YAML files can be converted to valid iCal files
- Test that proposed changes would not result in scheduling
conflicts
Gate:
- Test that proposed changes would not result in scheduling
conflicts (including conflicts with changes that have been
made since the inital check test).
Post:
- Convert YAML files to iCal files
- Publish meeting changes and associated iCal files to a
public wiki location
"""
parser = ArgumentParser(
formatter_class=RawDescriptionHelpFormatter,
description=description,
epilog=epilog)
parser.add_argument("-t", "--test",
help="test to execute. valid values are check,\
gate, and post.")
parser.add_argument("-c", "--convert",
action="store_true",
default=False,
help="convert meeting YAML to iCal format.")
parser.add_argument("-y", "--yamldir",
dest="yaml_dir",
default=const.DEFAULT_YAML_DIR,
help="directory containing YAML to process")
parser.add_argument("-m", "--meetings",
dest="meeting_list_file",
help="name of file containing meetings to \
process. meetings are specified by filename,\
which correspond to meeting filenames in\
yamldir. filenames should be separated by\
newlines.")
parser.add_argument("-i", "--icaldir",
dest="ical_dir",
default=const.DEFAULT_ICAL_DIR,
help="directory to store converted iCal")
# parse arguments:
args = parser.parse_args()
test = args.test
convert = args.convert
yaml_dir = args.yaml_dir
meeting_list_file = args.meeting_list_file
ical_dir = args.ical_dir
if (yaml_dir and not os.path.isdir(yaml_dir)):
parser.error("invalid YAML directory provided")
if (ical_dir and not os.path.isdir(ical_dir)):
parser.error("invalid iCal directory provided")
if not test and not convert:
parser.error(
"invalid arguments. must specify test or convert")
elif test:
if test == "check":
execute_check(yaml_dir, ical_dir)
elif test == "gate":
execute_gate(yaml_dir)
elif test == "post":
execute_post(yaml_dir, ical_dir, const.PUBLISH_URL)
else:
parser.error("invalid test provided")
elif convert:
# if file containing list of meetings provided
if meeting_list_file:
if not os.path.isfile(meeting_list_file):
parser.error("meeting list file does not exist")
util.convert_yaml_to_ical(yaml_dir,
ical_dir,
meeting_list_file)
else:
# convert all meetings in yaml_dir
util.convert_yaml_to_ical(yaml_dir, ical_dir)

View File

@ -43,7 +43,7 @@ class Meeting:
# create schedule objects
self.schedules = [Schedule(schedule) for schedule in yaml['schedule']]
def write_ical(self):
def write_ical(self, ical_dir):
"""Write this meeting to disk using the iCal format."""
cal = icalendar.Calendar()
@ -99,7 +99,6 @@ class Meeting:
cal.add_component(event)
# write ical files to disk
ical_dir = const.DEFAULT_ICAL_DIR
ical_filename = self.filename[:-4] + 'ics'
if not os.path.exists(ical_dir):

View File

@ -34,6 +34,52 @@ def publish(meeting, ical):
pass
def load_meetings(yaml_dir, meeting_list=None):
"""Return a list of Meetings initialized from files in yaml_dir."""
os.chdir(yaml_dir)
if meeting_list:
meetings_yaml = [f for f in os.listdir()
if os.path.isfile(f) and
f.endswith(const.YAML_FILE_EXT) and
f in meeting_list]
else:
meetings_yaml = [f for f in os.listdir()
if os.path.isfile(f) and
f.endswith(const.YAML_FILE_EXT)]
meetings = [Meeting(yaml.load(open(f, 'r')), f)
for f in meetings_yaml]
logging.info('Loaded %d meetings from YAML' % (len(meetings)))
return meetings
def convert_yaml_to_ical(yaml_dir, ical_dir, meeting_list_file=None):
"""Convert meeting YAML files to the iCal format and place
in ical_dir. If meeting_list is specified, only those meetings
in yaml_dir with filenames contained in meeting_list are
converted; otherwise, all meeting in yaml_dir are converted.
"""
meeting_list = None
if meeting_list_file:
meeting_list = open(meeting_list_file).read().splitlines()
meetings = load_meetings(yaml_dir,
meeting_list)
# convert meetings to a list of ical
for m in meetings:
m.write_ical(ical_dir)
# TODO(jotan): verify converted ical is valid
logging.info('Wrote %d meetings to iCal' % (len(meetings)))
def check_uniqueness():
"""Check for uniqueness in meeting room and time combination. During gate
job, we do not care about the meeting name.

View File

@ -1,7 +1,7 @@
project: Ironic team Meeting
schedule:
- time: '1900'
day: Mondays
day: Monday
irc: openstack-meeting
frequency: weekly
chair: Devananda van der Veen

View File

@ -1,20 +0,0 @@
project: Nova Team meeting
schedule:
- time: '1400'
day: Thursday
irc: openstack-meeting-alt
frequency: biweekly
- time: '2100'
day: Thursday
irc: openstack-meeting
frequency: biweekly
chair: Russell Bryant
description: >
This meeting is a weekly gathering of developers working on OpenStack Compute
(NOVA). We cover topics such as release and planning and status, bugs,
reviews, and other current topics worthy of real-time discussion
agenda: |
*Icehouse-rc
*other bugs
*blueprints
*Open Discussion

View File

@ -2,3 +2,4 @@ pbr
pyyaml
icalendar
argparse