Skip to content

Commit 2621f69

Browse files
author
Liudmila Molkova
authored
Add annotation to exclude collisions on cloud.platform enum and add policies (#2477)
1 parent a413c6f commit 2621f69

File tree

6 files changed

+127
-2
lines changed

6 files changed

+127
-2
lines changed

.chloggen/2477.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
change_type: bug_fix
2+
component: cloud
3+
note: Exclude deprecated Azure members from code generation on the `cloud.platform` attribute
4+
issues: [2477, 2455]

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"editor.rulers": [80],
33
"yaml.schemas": {
4-
"https://raw.githubusercontent.com/open-telemetry/weaver/v0.15.0/schemas/semconv.schema.json": [
4+
"https://raw.githubusercontent.com/open-telemetry/weaver/v0.16.1/schemas/semconv.schema.json": [
55
"model/**/*.yaml"
66
]
77
},

dependencies.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Dependabot can keep this file up to date with latest containers.
44

55
# Weaver is used to generate markdown docs, and enforce policies on the model.
6-
FROM otel/weaver:v0.15.2@sha256:b13acea09f721774daba36344861f689ac4bb8d6ecd94c4600b4d590c8fb34b9 AS weaver
6+
FROM otel/weaver:v0.16.1@sha256:5ca4901b460217604ddb83feaca05238e2b016a226ecfb9b87a95555918a03af AS weaver
77

88
# OPA is used to test policies enforced by weaver.
99
FROM openpolicyagent/opa:1.5.1@sha256:7d30d984125161b7f30599c6bdf80a6f2301dbbd526725714c231aad8179e4b9 AS opa

model/cloud/registry.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,36 +180,57 @@ groups:
180180
brief: Azure Virtual Machines
181181
stability: development
182182
deprecated: "Replaced by `azure.vm`"
183+
annotations:
184+
code_generation:
185+
exclude: true
183186
- id: azure_container_apps
184187
value: 'azure_container_apps'
185188
brief: Azure Container Apps
186189
stability: development
187190
deprecated: "Replaced by `azure.container_apps`"
191+
annotations:
192+
code_generation:
193+
exclude: true
188194
- id: azure_container_instances
189195
value: 'azure_container_instances'
190196
brief: Azure Container Instances
191197
stability: development
192198
deprecated: "Replaced by `azure.container_instances`"
199+
annotations:
200+
code_generation:
201+
exclude: true
193202
- id: azure_aks
194203
value: 'azure_aks'
195204
brief: Azure Kubernetes Service
196205
stability: development
197206
deprecated: "Replaced by `azure.aks`"
207+
annotations:
208+
code_generation:
209+
exclude: true
198210
- id: azure_functions
199211
value: 'azure_functions'
200212
brief: Azure Functions
201213
stability: development
202214
deprecated: "Replaced by `azure.functions`"
215+
annotations:
216+
code_generation:
217+
exclude: true
203218
- id: azure_app_service
204219
value: 'azure_app_service'
205220
brief: Azure App Service
206221
stability: development
207222
deprecated: "Replaced by `azure.app_service`"
223+
annotations:
224+
code_generation:
225+
exclude: true
208226
- id: azure_openshift
209227
value: 'azure_openshift'
210228
brief: Azure Red Hat OpenShift
211229
stability: development
212230
deprecated: "Replaced by `azure.openshift`"
231+
annotations:
232+
code_generation:
233+
exclude: true
213234
- id: gcp_bare_metal_solution
214235
value: 'gcp_bare_metal_solution'
215236
brief: Google Bare Metal Solution (BMS)

policies/registry.rego

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,69 @@ deny contains attr_registry_violation(description, group.id, "") if {
8989
description := sprintf("Semconv group '%s' does not contain stability field. All semconv definitions must include stability level.", [group.id])
9090
}
9191

92+
# check that member ids do not collide within the same attribute
93+
deny contains attr_registry_violation(description, group.id, attr.id) if {
94+
group := input.groups[_]
95+
startswith(group.id, "registry.")
96+
97+
attr := group.attributes[_]
98+
member := attr.type.members[_]
99+
100+
collisions := [n | n := attr.type.members[_].id; n == member.id ]
101+
count(collisions) > 1
102+
103+
description := sprintf("Member with id '%s' is already defined on the attribute '%s' in the group '%s'. Member id must be unique.", [member.id, attr.id, group.id])
104+
}
105+
106+
# check that member values do not collide within the same attribute
107+
deny contains attr_registry_violation(description, group.id, attr.id) if {
108+
group := input.groups[_]
109+
startswith(group.id, "registry.")
110+
attr := group.attributes[_]
111+
member := attr.type.members[_]
112+
not is_property_set(member, "deprecated")
113+
114+
collisions := [m
115+
| m := attr.type.members[_]
116+
not is_property_set(m, "deprecated")
117+
m.value == member.value
118+
]
119+
count(collisions) > 1
120+
121+
description := sprintf("Member with value '%s' (id '%s') is already defined on the attribute '%s' in the group '%s'. Member value must be unique.", [member.value, member.id, attr.id, group.id])
122+
}
123+
124+
# check that member const names do not collide within the same attribute
125+
deny contains attr_registry_violation(description, group.id, attr.id) if {
126+
group := input.groups[_]
127+
startswith(group.id, "registry.")
128+
attr := group.attributes[_]
129+
member := attr.type.members[_]
130+
not member.annotations["code_generation"]["exclude"]
131+
132+
const_name := to_const_name(member.id)
133+
134+
collisions := [m
135+
| m := attr.type.members[_]
136+
to_const_name(m.id) == const_name
137+
not m.annotations["code_generation"]["exclude"]
138+
]
139+
count(collisions) > 1
140+
141+
description := sprintf("Member with const name '%s' (id '%s'), is already defined on the attribute '%s' in the group '%s'. Member const names must be unique.", [const_name, member.id, attr.id, group.id])
142+
}
143+
92144
get_attribute_name(attr, group) := name if {
93145
full_name := concat(".", [group.prefix, attr.id])
94146

95147
# if there was no prefix, we have a leading dot
96148
name := trim(full_name, ".")
97149
}
98150

151+
to_const_name(name) = const_name if {
152+
const_name := replace(name, ".", "_")
153+
}
154+
155+
is_property_set(obj, property) = true if {
156+
obj[property] != null
157+
} else = false

policies_test/registry_test.rego

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,44 @@ test_attribute_requirement_levels if {
6363
count(before_resolution.deny) > 0 with input as {"groups": [{"id": "registry.foo", "attributes": [{"id": "foo", "requirement_level": {"recommended": "if available"}, "stability": "rc"}]}]}
6464
count(before_resolution.deny) == 0 with input as {"groups": [{"id": "not_registry", "attributes": [{"ref": "foo", "requirement_level": "required"}]}]}
6565
}
66+
67+
test_fails_on_member_id_collision if {
68+
collision := {"groups": [
69+
{"id": "registry.test", "prefix": "", "attributes": [{"id": "foo.bar.baz", "type": {"members": [
70+
{"id": "member", "value": "value1", "brief": "brief", "stability": "stable"},
71+
{"id": "member", "value": "value2", "brief": "brief", "stability": "stable"},
72+
]}, "stability": "stable"}]},
73+
]}
74+
count(before_resolution.deny) == 2 with input as collision
75+
}
76+
77+
test_fails_on_member_const_name_collision if {
78+
collision := {"groups": [
79+
{"id": "registry.test", "prefix": "", "attributes": [{"id": "foo.bar.baz", "type": {"members": [
80+
{"id": "member_id", "value": "member_id", "brief": "brief", "stability": "stable"},
81+
{"id": "member.id", "value": "member.id", "brief": "brief", "stability": "stable"},
82+
]}, "stability": "stable"}]},
83+
]}
84+
count(before_resolution.deny) == 2 with input as collision
85+
}
86+
87+
test_fails_on_member_value_collision if {
88+
collision := {"groups": [
89+
{"id": "registry.test", "prefix": "", "attributes": [{"id": "foo.bar.baz", "type": {"members": [
90+
{"id": "member1", "value": "member", "brief": "brief", "stability": "stable"},
91+
{"id": "member2", "value": "member", "brief": "brief", "stability": "stable"},
92+
]}, "stability": "stable"}]},
93+
]}
94+
count(before_resolution.deny) == 2 with input as collision
95+
}
96+
97+
test_passes_on_member_value_collision_with_deprecated if {
98+
collision := {"groups": [
99+
{"id": "registry.test", "prefix": "", "attributes": [{"id": "foo.bar.baz", "type": {"members": [
100+
{"id": "member1", "value": "member", "brief": "brief", "stability": "stable", "deprecated": "renamed to member2"},
101+
{"id": "member2", "value": "member", "brief": "brief", "stability": "stable"},
102+
]}, "stability": "stable"}]},
103+
]}
104+
count(before_resolution.deny) == 0 with input as collision
105+
}
106+

0 commit comments

Comments
 (0)