overseer-testing-protocol 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +75 -0
- data/SOURCE.json +6 -0
- data/bin/overseer-testing-conformance +53 -0
- data/docs/testing-control-implementation-guide.md +116 -0
- data/docs/testing-control-protocol.md +432 -0
- data/lib/overseer/testing_control/conformance/case_file.rb +120 -0
- data/lib/overseer/testing_control/conformance/http_transport.rb +114 -0
- data/lib/overseer/testing_control/conformance/report.rb +104 -0
- data/lib/overseer/testing_control/conformance/runner.rb +783 -0
- data/lib/overseer/testing_control/discovery.rb +79 -0
- data/lib/overseer/testing_control/json_subset_matcher.rb +120 -0
- data/lib/overseer/testing_control/protocol_v3.rb +298 -0
- data/lib/overseer/testing_control/redaction.rb +111 -0
- data/lib/overseer/testing_protocol.rb +9 -0
- data/protocol/testing-control/v3/conformance-case.schema.json +151 -0
- data/protocol/testing-control/v3/conformance-report.schema.json +255 -0
- data/protocol/testing-control/v3/fixtures/capabilities-response.json +147 -0
- data/protocol/testing-control/v3/fixtures/conformance-case.json +23 -0
- data/protocol/testing-control/v3/fixtures/conformance-report.json +88 -0
- data/protocol/testing-control/v3/fixtures/error-response.json +20 -0
- data/protocol/testing-control/v3/fixtures/manifest.json +13 -0
- data/protocol/testing-control/v3/fixtures/probe-request.json +20 -0
- data/protocol/testing-control/v3/fixtures/probe-response.json +22 -0
- data/protocol/testing-control/v3/fixtures/reset-response.json +15 -0
- data/protocol/testing-control/v3/fixtures/sink-query-request.json +26 -0
- data/protocol/testing-control/v3/fixtures/sink-query-response.json +39 -0
- data/protocol/testing-control/v3/fixtures/state-request.json +20 -0
- data/protocol/testing-control/v3/fixtures/state-response.json +23 -0
- data/protocol/testing-control/v3/openapi.yaml +343 -0
- data/protocol/testing-control/v3/schema.json +772 -0
- metadata +85 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'json_schemer'
|
|
5
|
+
|
|
6
|
+
module Overseer
|
|
7
|
+
module TestingControl
|
|
8
|
+
module Conformance
|
|
9
|
+
module Report
|
|
10
|
+
SCHEMA_PATH = File.expand_path(
|
|
11
|
+
'../../../../protocol/testing-control/v3/conformance-report.schema.json',
|
|
12
|
+
__dir__
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
class Error < StandardError; end
|
|
16
|
+
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
def validate!(report)
|
|
20
|
+
errors = schemer.validate(report).take(5)
|
|
21
|
+
return report if errors.empty?
|
|
22
|
+
|
|
23
|
+
details = errors.map { |error| "#{error.fetch('data_pointer', '/')} #{error.fetch('type')}" }.join('; ')
|
|
24
|
+
raise Error, "Invalid testing-control conformance report: #{details}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def render(report)
|
|
28
|
+
target = report.fetch('target')
|
|
29
|
+
capabilities = report['capabilities']
|
|
30
|
+
lines = [
|
|
31
|
+
"Testing-control v#{report.fetch('protocolVersion')} conformance: #{report.fetch('aggregateStatus')}",
|
|
32
|
+
"Target: #{target.fetch('label')}",
|
|
33
|
+
"Source: #{target.fetch('sourceVersion') || 'unavailable'}",
|
|
34
|
+
"Origin: #{target.fetch('origin') || 'unavailable'}"
|
|
35
|
+
]
|
|
36
|
+
lines.concat(optional_provenance_lines(target['provenance']))
|
|
37
|
+
lines.concat(identity_lines(report['identity']))
|
|
38
|
+
lines.concat(capability_lines(capabilities))
|
|
39
|
+
lines << 'Checks:'
|
|
40
|
+
report.fetch('checks').each do |check|
|
|
41
|
+
lines << check_line(check)
|
|
42
|
+
end
|
|
43
|
+
lifecycle = report.fetch('lifecycle')
|
|
44
|
+
lines << "Lifecycle: #{lifecycle.fetch('ownership')}; cleanup #{lifecycle.fetch('cleanup')}"
|
|
45
|
+
lines << ''
|
|
46
|
+
lines.join("\n")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def optional_provenance_lines(provenance)
|
|
50
|
+
provenance ? provenance_lines(provenance) : []
|
|
51
|
+
end
|
|
52
|
+
private_class_method :optional_provenance_lines
|
|
53
|
+
|
|
54
|
+
def identity_lines(identity)
|
|
55
|
+
return [] unless identity
|
|
56
|
+
|
|
57
|
+
["Runtime identity: #{identity.fetch('applicationId')} #{identity.fetch('applicationVersion')} " \
|
|
58
|
+
"(#{identity.fetch('environmentId')})"]
|
|
59
|
+
end
|
|
60
|
+
private_class_method :identity_lines
|
|
61
|
+
|
|
62
|
+
def capability_lines(capabilities)
|
|
63
|
+
return [] unless capabilities
|
|
64
|
+
|
|
65
|
+
["Capabilities: #{capabilities.fetch('arrangements').length} arrangements, " \
|
|
66
|
+
"#{capabilities.fetch('observations').length} observations, " \
|
|
67
|
+
"#{capabilities.fetch('sinks').length} sinks; reset #{capabilities.fetch('resetStrategy')}"]
|
|
68
|
+
end
|
|
69
|
+
private_class_method :capability_lines
|
|
70
|
+
|
|
71
|
+
def check_line(check)
|
|
72
|
+
scenario = check['scenarioId'] ? " [#{check.fetch('scenarioId')}]" : ''
|
|
73
|
+
" #{check.fetch('status').upcase} #{check.fetch('id')}#{scenario}: #{check.fetch('message')}"
|
|
74
|
+
end
|
|
75
|
+
private_class_method :check_line
|
|
76
|
+
|
|
77
|
+
def provenance_lines(provenance)
|
|
78
|
+
project = provenance.fetch('project')
|
|
79
|
+
manifest = provenance.fetch('backendManifest')
|
|
80
|
+
runtime = provenance.fetch('runtime')
|
|
81
|
+
lines = [
|
|
82
|
+
"Project target: #{project.fetch('id')} revision #{project.fetch('revision')} / " \
|
|
83
|
+
"#{provenance.fetch('targetKey')}",
|
|
84
|
+
"Backend: #{provenance.dig('backend', 'applicationId')} " \
|
|
85
|
+
"(registry #{provenance.dig('backend', 'registryId')})",
|
|
86
|
+
"Manifest: v#{manifest.fetch('version')} sha256:#{manifest.fetch('sha256')}",
|
|
87
|
+
"Runtime: #{runtime.fetch('mode')}; profile #{runtime.fetch('profileName')} " \
|
|
88
|
+
"policy v#{runtime.fetch('profilePolicyVersion')}"
|
|
89
|
+
]
|
|
90
|
+
return lines unless provenance['conformanceCase']
|
|
91
|
+
|
|
92
|
+
selected_case = provenance.fetch('conformanceCase')
|
|
93
|
+
lines << "Conformance case: #{selected_case.fetch('id')} sha256:#{selected_case.fetch('sha256')}"
|
|
94
|
+
end
|
|
95
|
+
private_class_method :provenance_lines
|
|
96
|
+
|
|
97
|
+
def schemer
|
|
98
|
+
@schemer ||= JSONSchemer.schema(JSON.parse(File.read(SCHEMA_PATH, encoding: 'UTF-8')))
|
|
99
|
+
end
|
|
100
|
+
private_class_method :schemer
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|