-
Notifications
You must be signed in to change notification settings - Fork 23
/
schedule.rego
140 lines (127 loc) · 4.55 KB
/
schedule.rego
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
#
# METADATA
# title: Schedule related checks
# description: >-
# Rules that verify the current date conform to a given schedule.
#
package policy.release.schedule
import rego.v1
import data.lib
# METADATA
# title: Weekday Restriction
# description: >-
# Check if the current weekday is allowed based on the rule data value from the key
# `disallowed_weekdays`. By default, the list is empty in which case *any* weekday is
# allowed. This check is enforced only for a "release" pipeline, as determined by
# the value of the `pipeline_intention` rule data.
# custom:
# short_name: weekday_restriction
# failure_msg: '%s is a disallowed weekday: %s'
# solution: Try again on a different weekday.
# collections:
# - redhat
#
deny contains result if {
_schedule_restrictions_apply
today := lower(time.weekday(lib.time.effective_current_time_ns))
disallowed := {lower(w) | some w in lib.rule_data("disallowed_weekdays")}
count(disallowed) > 0
today in disallowed
result := lib.result_helper(rego.metadata.chain(), [today, concat(", ", disallowed)])
}
# METADATA
# title: Date Restriction
# description: >-
# Check if the current date is not allowed based on the rule data value
# from the key `disallowed_dates`. By default, the list is empty in which
# case *any* day is allowed. This check is enforced only for a "release" pipeline,
# as determined by the value of the `pipeline_intention` rule data.
# custom:
# short_name: date_restriction
# failure_msg: '%s is a disallowed date: %s'
# solution: Try again on a different day.
# collections:
# - redhat
#
deny contains result if {
_schedule_restrictions_apply
today := time.format([lib.time.effective_current_time_ns, "UTC", "2006-01-02"])
disallowed := lib.rule_data("disallowed_dates")
today in disallowed
result := lib.result_helper(rego.metadata.chain(), [today, concat(", ", disallowed)])
}
# METADATA
# title: Rule data provided
# description: >-
# Confirm the expected rule data keys have been provided in the expected format. The keys are
# `disallowed_weekdays` and `disallowed_dates`.
# custom:
# short_name: rule_data_provided
# failure_msg: '%s'
# solution: If provided, ensure the rule data is in the expected format.
# collections:
# - redhat
# - policy_data
#
deny contains result if {
# (For this one let's do it always)
some error in _rule_data_errors
result := lib.result_helper(rego.metadata.chain(), [error])
}
# We want these checks to apply only if we're doing a release. Detect that by checking
# the `pipeline_intention` value which is set to "release" for Konflux release pipelines.
default _schedule_restrictions_apply := false
_schedule_restrictions_apply if {
lib.rule_data("pipeline_intention") == "release"
}
_rule_data_errors contains msg if {
key := "disallowed_weekdays"
# JSON Schema doesn't allow case insensitive enum types. So here we define a list of all the
# weekdays as "title-case", lower case, and upper case.
titled_weekdays := ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
weekdays := array.concat(
array.concat(
titled_weekdays,
[lower(d) | some d in titled_weekdays],
),
[upper(d) | some d in titled_weekdays],
)
# match_schema expects either a marshaled JSON resource (String) or an Object. It doesn't
# handle an Array directly.
value := json.marshal(lib.rule_data(key))
some violation in json.match_schema(
value,
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"enum": weekdays},
"uniqueItems": true,
},
)[1]
msg := sprintf("Rule data %s has unexpected format: %s", [key, violation.error])
}
_rule_data_errors contains msg if {
# IMPORTANT: Although the JSON schema spec does allow specifying a regular expression to match
# values, via the "pattern" attribute, rego's JSON schema validator does not:
# https://github.com/open-policy-agent/opa/issues/6089
key := "disallowed_dates"
# match_schema expects either a marshaled JSON resource (String) or an Object. It doesn't
# handle an Array directly.
value := json.marshal(lib.rule_data(key))
some violation in json.match_schema(
value,
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"},
"uniqueItems": true,
},
)[1]
msg := sprintf("Rule data %s has unexpected format: %s", [key, violation.error])
}
_rule_data_errors contains msg if {
key := "disallowed_dates"
some index, date in lib.rule_data(key)
not time.parse_ns("2006-01-02", date)
msg := sprintf("Rule data %s has unexpected format: %d: Invalid date %q", [key, index, date])
}