[docs]def__virtual__():""" Only load if the pygerduty module is available in __salt__ """if"pagerduty_util.get_resource"in__salt__:return"pagerduty_schedule"return(False,"pagerduty_util module could not be loaded")
[docs]defpresent(profile="pagerduty",subdomain=None,api_key=None,**kwargs):""" Ensure that a pagerduty schedule exists. This method accepts as args everything defined in https://developer.pagerduty.com/documentation/rest/schedules/create. This means that most arguments are in a dict called "schedule." User id's can be pagerduty id, or name, or email address. """# for convenience, we accept id, name, or email as the user id.kwargs["schedule"]["name"]=kwargs["name"]# match PD API structureforschedule_layerinkwargs["schedule"]["schedule_layers"]:foruserinschedule_layer["users"]:u=__salt__["pagerduty_util.get_resource"]("users",user["user"]["id"],["email","name","id"],profile=profile,subdomain=subdomain,api_key=api_key,)ifuisNone:raiseCommandExecutionError(f"unknown user: {user}")user["user"]["id"]=u["id"]r=__salt__["pagerduty_util.resource_present"]("schedules",["name","id"],_diff,profile,subdomain,api_key,**kwargs)returnr
[docs]defabsent(profile="pagerduty",subdomain=None,api_key=None,**kwargs):""" Ensure that a pagerduty schedule does not exist. Name can be pagerduty schedule id or pagerduty schedule name. """r=__salt__["pagerduty_util.resource_absent"]("schedules",["name","id"],profile,subdomain,api_key,**kwargs)returnr
def_diff(state_data,resource_object):"""helper method to compare salt state info with the PagerDuty API json structure, and determine if we need to update. returns the dict to pass to the PD API to perform the update, or empty dict if no update. """state_data["id"]=resource_object["schedule"]["id"]objects_differ=None# first check all the easy top-level properties: everything except the schedule_layers.fork,vinstate_data["schedule"].items():ifk=="schedule_layers":continueifv!=resource_object["schedule"][k]:objects_differ=f"{k}{v}{resource_object['schedule'][k]}"break# check schedule_layersifnotobjects_differ:forlayerinstate_data["schedule"]["schedule_layers"]:# find matching layer nameresource_layer=Noneforresource_layerinresource_object["schedule"]["schedule_layers"]:found=Falseiflayer["name"]==resource_layer["name"]:found=Truebreakifnotfound:objects_differ=f"layer {layer['name']} missing"break# set the id, so that we will update this layer instead of creating a new onelayer["id"]=resource_layer["id"]# compare contents of layer and resource_layerfork,vinlayer.items():ifk=="users":continueifk=="start":continueifv!=resource_layer[k]:objects_differ=f"layer {layer['name']} key {k}{v} != {resource_layer[k]}"breakifobjects_differ:break# compare layer['users']iflen(layer["users"])!=len(resource_layer["users"]):objects_differ=(f"num users in layer {layer['name']}{len(layer['users'])} "f"!= {len(resource_layer['users'])}")breakforuser1inlayer["users"]:found=Falseuser2=Noneforuser2inresource_layer["users"]:# deal with PD API bug: when you submit member_order=N, you get back member_order=N+1ifuser1["member_order"]==user2["member_order"]-1:found=Truebreakifnotfound:objects_differ=(f"layer {layer['name']} no one with member_order {user1['member_order']}")breakifuser1["user"]["id"]!=user2["user"]["id"]:objects_differ=(f"layer {layer['name']} user at member_order {user1['member_order']} "f"{user1['user']['id']} != {user2['user']['id']}")breakifobjects_differ:returnstate_datareturn{}