Skip to content

Commit

Permalink
adds add_auto_holidays, config and cronjob
Browse files Browse the repository at this point in the history
  • Loading branch information
gurubert committed Dec 7, 2023
1 parent 427e85a commit 6c97fd7
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 100 deletions.
225 changes: 125 additions & 100 deletions holidays/bin/holidays.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
# -*- encoding: utf-8; py-indent-offset: 4 -*-

#
# (C) 2023 Heinlein Support GmbH - License: GNU General Public License v2
Expand All @@ -19,7 +20,8 @@
#
# defaults
#
country = "de"
countries = ["de"]
default_country = "de"
states = {
'de': {
'bb': 'Brandenburg',
Expand All @@ -42,26 +44,12 @@
}
always = [{'day': 'all', 'time_ranges': [{'start': '00:00', 'end': '24:00'}]}]

def exclude_in(name, exclude_in_tp):
etp, etag = cmk.get_timeperiod(exclude_in_tp)

if args.debug:
pprint(etp)
pprint(etag)

exclude = etp['extensions']['exclude']
exclude.append(name)

if args.debug:
pprint(exclude)

cmk.edit_timeperiod(exclude_in_tp, etag, exclude=exclude)

parser = argparse.ArgumentParser()
parser.add_argument('-s', '--url', help='URL to Check_MK site')
parser.add_argument('-u', '--username', help='name of the automation user')
parser.add_argument('-p', '--password', help='secret of the automation user')
parser.add_argument('-c', '--config-file', help='config file',
parser.add_argument('-c', '--config-file', help='config file (JSON)',
default=os.path.join(os.environ.get('OMD_ROOT'), 'etc', 'holidays'))
parser.add_argument('-D', '--debug', action='store_true')
subparsers = parser.add_subparsers(title='available commands', help='call "subcommand --help" for more information')
Expand All @@ -72,109 +60,71 @@ def exclude_in(name, exclude_in_tp):
delete_old.set_defaults(func='delete_old')
dump_timeperiods = subparsers.add_parser('dump', help='dump timeperiods')
dump_timeperiods.set_defaults(func='dump_timeperiods')
create_timeperiod = subparsers.add_parser('create', help='create timeperiod from api-feiertage.de')
create_timeperiod.set_defaults(func='create_timeperiod')
create_timeperiod.add_argument('-a', '--all-states', action='store_true', help='Nur bundesweite Feiertage')
create_timeperiod.add_argument('-l', '--country', default=country, help='Land')
create_timeperiod.add_argument('-s', '--state', choices=states['de'].keys(), help='Bundesland')
create_timeperiod.add_argument('-y', '--year')
create_timeperiod.add_argument('-c', '--current-year', action='store_true')
create_timeperiod.add_argument('-e', '--exclude-in-default', action='store_true', help='Exclude in passender Standard-Timeperiod')
create_timeperiod.add_argument('-E', '--exclude-in', help='Exclude in anderer Timeperiod')
add_region = subparsers.add_parser('addregion', help='add a new region to the configuration (base timeperiods and tag)')
add_holidays = subparsers.add_parser('add_holidays', help='add timeperiod from api-feiertage.de')
add_holidays.set_defaults(func='add_holidays')
add_holidays.add_argument('-a', '--all-states', action='store_true', help='Nur bundesweite Feiertage')
add_holidays.add_argument('-l', '--country', choices=countries, default=default_country, help='Land (default=de)')
add_holidays.add_argument('-s', '--state', choices=states[default_country].keys(), help='Bundesland')
add_holidays.add_argument('-y', '--year')
add_holidays.add_argument('-Y', '--current-year', action='store_true')
add_holidays.add_argument('-e', '--exclude-in-default', action='store_true', help='Exclude in passender Standard-Timeperiod')
add_holidays.add_argument('-E', '--exclude-in', help='Exclude in anderer Timeperiod')
add_region = subparsers.add_parser('add_region', help='add a new region to the configuration (base timeperiods and tag)')
add_region.set_defaults(func='add_region')
add_region.add_argument('-l', '--country', default=country, help='Land')
add_region.add_argument('-l', '--country', choices=countries, default=default_country, help='Land')
add_region.add_argument('-s', '--state', choices=states['de'].keys(), help='Bundesland', required=True)
add_auto_holidays = subparsers.add_parser('add_auto_holidays', help='add timeperiods from api-feiertage.de for all regions')
add_auto_holidays.set_defaults(func='add_auto_holidays')
add_auto_holidays.add_argument('-y', '--year')
add_auto_holidays.add_argument('-Y', '--current-year', action='store_true')
cleanup = subparsers.add_parser('cleanup', help='remove timeperiods and tag group. Use with caution!')
cleanup.set_defaults(func='cleanup')

args = parser.parse_args()
if 'func' not in args:
parser.print_help()
sys.exit(1)
if args.debug:
pprint(args)

config = json.load(open(args.config_file))

if args.debug:
pprint(config)

cmk = checkmkapi.CMKRESTAPI(args.url, args.username, args.password)

if args.func == 'dump_timeperiods':
pprint(cmk.get_timeperiods()[0])

if args.func == 'delete_timeperiod':
cmk.delete_timeperiod(args.name, '*')
cmk.activate()

if args.func == 'delete_old':
tps, etag = cmk.get_timeperiods()

to_delete = []
thisyear = str(date.today().year)
def exclude_in_timeperiod(name, exclude_in_tp):
etp, etag = cmk.get_timeperiod(exclude_in_tp)

if args.debug:
print(f"Removing each timeperiod starting with \"{config['timeperiods']['holidays']['name']}_\" up to but not including {thisyear}")
pprint(etp)
pprint(etag)

tps, etag = cmk.get_timeperiods()
exclude = etp['extensions']['exclude']
exclude.append(name)

for tp in tps['value']:
if tp['id'].startswith(config['timeperiods']['holidays']['name'] + '_'):
year = tp['id'].split('_')[1]
if year < thisyear:
to_delete.append(tp['id'])
if args.debug:
pprint(exclude)

for tp in tps['value']:
excludes = tp['extensions'].get('exclude', [])
changes = False
for td in to_delete:
if td in excludes:
if args.debug:
print(f"Removing {td} from {tp['id']}")
excludes.remove(td)
changes = True
if changes:
te, etag = cmk.get_timeperiod(tp['id'])
cmk.edit_timeperiod(tp['id'], etag, exclude=excludes)
for td in to_delete:
if args.debug:
print(f"Removing {td}")
cmk.delete_timeperiod(td, '*')
if to_delete:
cmk.activate()
cmk.edit_timeperiod(exclude_in_tp, etag, exclude=exclude)

if args.func == 'create_timeperiod':
def add_holiday_timeperiod(country=default_country, state=None, all_states=False, current_year=False, set_year=None, exclude_in_default=True, exclude_in=None):
params = {}
name = config['timeperiods']['holidays']['name'] + '_'
alias = config['timeperiods']['holidays']['title'] + ' '
year = None
if args.current_year:
if current_year:
year = str(date.today().year)
elif args.year:
year = args.year
elif set_year:
year = set_year
if year:
params['years'] = year
name += year
alias += year
name += "_" + args.country
alias += " " + args.country.upper()
if args.all_states:
name += "_" + country
alias += " " + country.upper()
if all_states:
params['all_states'] = "true"
name += '_bundeseinheitlich'
alias += ' bundeseinheitlich'
elif args.state:
params['states'] = args.state
name += '_%s' % args.state
alias += ' %s' % states[args.country][args.state]
elif state:
params['states'] = state
name += '_%s' % state
alias += ' %s' % states[country][state]

if args.debug:
pprint(params)

if not params:
print('Please give at least a year or a state.\n')
create_timeperiod.print_help()
add_holidays.print_help()
sys.exit(1)

resp = requests.get(apifeiertage, params=params)
Expand All @@ -188,10 +138,7 @@ def exclude_in(name, exclude_in_tp):
if resp.status_code >= 400:
sys.stderr.write("%r\n" % data)

if not data.get('feiertage'):
print('Error: %s' % data.get('additional_note'))
sys.exit(1)
else:
if data.get('feiertage'):
exceptions = []
for feiertag in data['feiertage']:
exceptions.append({
Expand All @@ -210,13 +157,75 @@ def exclude_in(name, exclude_in_tp):
if args.debug:
pprint(tp)

if args.exclude_in_default:
exclude_in(name, config['timeperiods']['workhours']['name'] + "_" + args.country + "_" + args.state)
if exclude_in_default:
exclude_in_timeperiod(name, config['timeperiods']['workhours']['name'] + "_" + country + "_" + state)

if args.exclude_in:
exclude_in(name, args.exclude_in)
if exclude_in:
exclude_in_timeperiod(name, exclude_in)
else:
print('Error: %s' % data.get('additional_note'))
sys.exit(1)

args = parser.parse_args()
if 'func' not in args:
parser.print_help()
sys.exit(1)
if args.debug:
pprint(args)

config = json.load(open(args.config_file))

if args.debug:
pprint(config)

cmk = checkmkapi.CMKRESTAPI(args.url, args.username, args.password)

if args.func == 'dump_timeperiods':
pprint(cmk.get_timeperiods()[0])

if args.func == 'delete_timeperiod':
cmk.delete_timeperiod(args.name, '*')
cmk.activate()

if args.func == 'delete_old':
tps, etag = cmk.get_timeperiods()

to_delete = []
thisyear = str(date.today().year)

if args.debug:
print(f"Removing each timeperiod starting with \"{config['timeperiods']['holidays']['name']}_\" up to but not including {thisyear}")

tps, etag = cmk.get_timeperiods()

for tp in tps['value']:
if tp['id'].startswith(config['timeperiods']['holidays']['name'] + '_'):
year = tp['id'].split('_')[1]
if year < thisyear:
to_delete.append(tp['id'])

for tp in tps['value']:
excludes = tp['extensions'].get('exclude', [])
changes = False
for td in to_delete:
if td in excludes:
if args.debug:
print(f"Removing {td} from {tp['id']}")
excludes.remove(td)
changes = True
if changes:
te, etag = cmk.get_timeperiod(tp['id'])
cmk.edit_timeperiod(tp['id'], etag, exclude=excludes)
for td in to_delete:
if args.debug:
print(f"Removing {td}")
cmk.delete_timeperiod(td, '*')
if to_delete:
cmk.activate()

cmk.activate()
if args.func == 'add_holidays':
add_holiday_timeperiod(args.country, args.state, args.all_states, args.current_year, args.year, args.exclude_in_default, args.exclude_in)
cmk.activate()

if args.func == "add_region":
workhoursname = '%s_%s_%s' % ( config['timeperiods']['workhours']['name'],
Expand All @@ -241,6 +250,8 @@ def exclude_in(name, exclude_in_tp):
if args.debug:
pprint(tp)

add_holiday_timeperiod(country=args.country, state=args.state, current_year=True)

tg = None
try:
tg, etag = cmk.get_host_tag_group(config['taggroup']['name'])
Expand Down Expand Up @@ -275,6 +286,19 @@ def exclude_in(name, exclude_in_tp):
)
cmk.activate()

if args.func == 'add_auto_holidays':
tps, etag = cmk.get_timeperiods()
changes = False
for tp in tps['value']:
if tp['id'].startswith(config['timeperiods']['workhours']['name']):
if args.debug:
print(f"found {tp['id']}")
_, country, state = tp['id'].split('_')
add_holiday_timeperiod(country=country, state=state, current_year=args.current_year, set_year=args.year)
changes = True
if changes:
cmk.activate()

if args.func == "cleanup":
tps, etag = cmk.get_timeperiods()

Expand All @@ -294,7 +318,8 @@ def exclude_in(name, exclude_in_tp):

try:
cmk.delete_host_tag_group(config['taggroup']['name'])
print(f"remove host tag group {config['taggroup']['name']}")
if args.debug:
print(f"remove host tag group {config['taggroup']['name']}")
changes = True
except:
pass
Expand Down
8 changes: 8 additions & 0 deletions holidays/etc/cron.d/holidays
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Remove old holiday timeperiods in February
#
1 1 12 2 * $OMD_ROOT/local/bin/holidays.py delete_old
#
# Automatically add new holiday timeperiods in November
#
1 1 12 11 * $OMD_ROOT/local/bin/holidays.py add_auto_holidays
33 changes: 33 additions & 0 deletions holidays/etc/holidays
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"comment": "Configuration for ~/local/bin/holidays.py",

"workdays": [
{"day": "monday", "time_ranges": [{"start": "09:00", "end": "18:00"}]},
{"day": "tuesday", "time_ranges": [{"start": "09:00", "end": "18:00"}]},
{"day": "wednesday", "time_ranges": [{"start": "09:00", "end": "18:00"}]},
{"day": "thursday", "time_ranges": [{"start": "09:00", "end": "18:00"}]},
{"day": "friday", "time_ranges": [{"start": "09:00", "end": "15:00"}]}
],

"taggroup": {
"name": "holidays",
"title": "Feiertage",
"empty_title": "Keine Feiertage",
"topic": "Notifications"
},

"timeperiods": {
"oncall": {
"name": "oncall",
"title": "Bereitschaft"
},
"workhours": {
"name": "workhours",
"title": "Arbeitszeit"
},
"holidays": {
"name": "holidays",
"title": "Feiertage"
}
}
}
Binary file removed holidays/holidays-2.0.0.mkp
Binary file not shown.
Binary file added holidays/holidays-2.1.0.mkp
Binary file not shown.

0 comments on commit 6c97fd7

Please sign in to comment.