airbyte-internal-ops 0.4.2__py3-none-any.whl → 0.5.1__py3-none-any.whl

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.
Files changed (130) hide show
  1. {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/METADATA +2 -1
  2. {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/RECORD +21 -129
  3. airbyte_ops_mcp/cli/cloud.py +31 -2
  4. airbyte_ops_mcp/cloud_admin/api_client.py +506 -33
  5. airbyte_ops_mcp/cloud_admin/models.py +56 -0
  6. airbyte_ops_mcp/constants.py +58 -0
  7. airbyte_ops_mcp/{_legacy/airbyte_ci/metadata_service/docker_hub.py → docker_hub.py} +16 -10
  8. airbyte_ops_mcp/mcp/cloud_connector_versions.py +491 -10
  9. airbyte_ops_mcp/mcp/prerelease.py +5 -44
  10. airbyte_ops_mcp/mcp/prod_db_queries.py +128 -4
  11. airbyte_ops_mcp/mcp/regression_tests.py +10 -5
  12. airbyte_ops_mcp/{_legacy/airbyte_ci/metadata_service/validators/metadata_validator.py → metadata_validator.py} +18 -12
  13. airbyte_ops_mcp/prod_db_access/queries.py +51 -0
  14. airbyte_ops_mcp/prod_db_access/sql.py +76 -0
  15. airbyte_ops_mcp/regression_tests/ci_output.py +8 -4
  16. airbyte_ops_mcp/regression_tests/connection_fetcher.py +16 -5
  17. airbyte_ops_mcp/regression_tests/http_metrics.py +21 -2
  18. airbyte_ops_mcp/regression_tests/models.py +7 -1
  19. airbyte_ops_mcp/telemetry.py +162 -0
  20. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/.gitignore +0 -1
  21. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/README.md +0 -420
  22. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/__init__.py +0 -2
  23. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/__init__.py +0 -1
  24. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/__init__.py +0 -8
  25. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/base_backend.py +0 -16
  26. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/duckdb_backend.py +0 -87
  27. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/file_backend.py +0 -165
  28. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/connection_objects_retrieval.py +0 -377
  29. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/connector_runner.py +0 -247
  30. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/errors.py +0 -7
  31. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/evaluation_modes.py +0 -25
  32. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/hacks.py +0 -23
  33. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/json_schema_helper.py +0 -384
  34. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/mitm_addons.py +0 -37
  35. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/models.py +0 -595
  36. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/proxy.py +0 -207
  37. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/secret_access.py +0 -47
  38. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/segment_tracking.py +0 -45
  39. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/utils.py +0 -214
  40. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/conftest.py.disabled +0 -751
  41. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/consts.py +0 -4
  42. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/poetry.lock +0 -4480
  43. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/pytest.ini +0 -9
  44. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/__init__.py +0 -1
  45. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_check.py +0 -61
  46. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_discover.py +0 -117
  47. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_read.py +0 -627
  48. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_spec.py +0 -43
  49. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/report.py +0 -542
  50. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/stash_keys.py +0 -38
  51. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/templates/__init__.py +0 -0
  52. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/templates/private_details.html.j2 +0 -305
  53. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/templates/report.html.j2 +0 -515
  54. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/utils.py +0 -187
  55. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/__init__.py +0 -0
  56. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_check.py +0 -61
  57. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_discover.py +0 -217
  58. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_read.py +0 -177
  59. airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_spec.py +0 -631
  60. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/README.md +0 -91
  61. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/bin/bundle-schemas.js +0 -48
  62. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/bin/generate-metadata-models.sh +0 -36
  63. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ActorDefinitionResourceRequirements.py +0 -54
  64. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/AirbyteInternal.py +0 -22
  65. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/AllowedHosts.py +0 -18
  66. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorBreakingChanges.py +0 -65
  67. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorBuildOptions.py +0 -15
  68. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorIPCOptions.py +0 -25
  69. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorMetadataDefinitionV0.json +0 -897
  70. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorMetadataDefinitionV0.py +0 -478
  71. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorMetrics.py +0 -24
  72. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorPackageInfo.py +0 -12
  73. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistryDestinationDefinition.py +0 -407
  74. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistryReleases.py +0 -406
  75. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistrySourceDefinition.py +0 -407
  76. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistryV0.py +0 -413
  77. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorReleases.py +0 -98
  78. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorTestSuiteOptions.py +0 -58
  79. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/GeneratedFields.py +0 -62
  80. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/GitInfo.py +0 -31
  81. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/JobType.py +0 -23
  82. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/NormalizationDestinationDefinitionConfig.py +0 -24
  83. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/RegistryOverrides.py +0 -111
  84. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ReleaseStage.py +0 -15
  85. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/RemoteRegistries.py +0 -23
  86. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ResourceRequirements.py +0 -18
  87. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/RolloutConfiguration.py +0 -29
  88. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/Secret.py +0 -34
  89. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SecretStore.py +0 -22
  90. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SourceFileInfo.py +0 -16
  91. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SuggestedStreams.py +0 -18
  92. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SupportLevel.py +0 -15
  93. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/TestConnections.py +0 -14
  94. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/__init__.py +0 -31
  95. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/airbyte-connector-metadata-schema.json +0 -0
  96. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ActorDefinitionResourceRequirements.yaml +0 -30
  97. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/AirbyteInternal.yaml +0 -32
  98. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/AllowedHosts.yaml +0 -13
  99. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorBreakingChanges.yaml +0 -65
  100. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorBuildOptions.yaml +0 -10
  101. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorIPCOptions.yaml +0 -29
  102. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorMetadataDefinitionV0.yaml +0 -172
  103. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorMetrics.yaml +0 -30
  104. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorPackageInfo.yaml +0 -9
  105. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistryDestinationDefinition.yaml +0 -90
  106. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistryReleases.yaml +0 -35
  107. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistrySourceDefinition.yaml +0 -92
  108. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistryV0.yaml +0 -18
  109. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorReleases.yaml +0 -16
  110. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorTestSuiteOptions.yaml +0 -28
  111. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/GeneratedFields.yaml +0 -16
  112. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/GitInfo.yaml +0 -21
  113. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/JobType.yaml +0 -14
  114. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/NormalizationDestinationDefinitionConfig.yaml +0 -21
  115. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/RegistryOverrides.yaml +0 -38
  116. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ReleaseStage.yaml +0 -11
  117. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/RemoteRegistries.yaml +0 -25
  118. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ResourceRequirements.yaml +0 -16
  119. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/RolloutConfiguration.yaml +0 -29
  120. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/Secret.yaml +0 -19
  121. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SecretStore.yaml +0 -16
  122. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SourceFileInfo.yaml +0 -17
  123. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SuggestedStreams.yaml +0 -13
  124. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SupportLevel.yaml +0 -10
  125. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/TestConnections.yaml +0 -17
  126. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/package-lock.json +0 -62
  127. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/package.json +0 -12
  128. airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/transform.py +0 -71
  129. {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/WHEEL +0 -0
  130. {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/entry_points.txt +0 -0
@@ -1,305 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Test Report</title>
7
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tokyo-night-dark.min.css">
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
9
-
10
- <script>
11
- hljs.highlightAll();
12
- function copyToClipboard(elementId) {
13
- var toCopy = document.getElementById(elementId).innerText;
14
- navigator.clipboard.writeText(toCopy);
15
- }
16
- function refreshPage() {
17
- {% if not fully_generated %}
18
- window.location.reload();
19
- {% else %}
20
- console.log("Report is fully generated");
21
- {% endif %}
22
- }
23
-
24
- setInterval(refreshPage, 10000);
25
- </script>
26
- <style>
27
- body {
28
- font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
29
- background-color: #0d1117;
30
- color: #c9d1d9;
31
- padding: 16px;
32
- font-size: 14px;
33
- }
34
-
35
- a {
36
- color: #4493f8;
37
- text-decoration: underline;
38
- text-underline-offset: .2rem;
39
- }
40
-
41
- button {
42
- border: 1px solid #30363d;
43
- background-color: #1a1c26;
44
- padding: 5px;
45
- cursor: pointer;
46
- opacity: 0.7;
47
- border-radius: 5px;
48
- transition: opacity 0.5s;
49
- }
50
-
51
- button:hover {
52
- opacity: 1;
53
- }
54
-
55
- section {
56
- margin-bottom: 30px;
57
- border: 1px solid #30363d;
58
- border-radius: 6px;
59
- }
60
-
61
- h1 {
62
- font-optical-sizing: auto;
63
- font-weight: 600;
64
- font-size: 2rem;
65
- }
66
-
67
- h2 {
68
- font-size: 1.5rem;
69
- font-optical-sizing: auto;
70
- font-weight: 600;
71
- margin: 0;
72
- display: block;
73
- background-color: #161b22;
74
- padding-left: 15px;
75
- padding-top: 10px;
76
- padding-bottom: 10px;
77
- border-bottom: 1px solid #30363d;
78
- }
79
-
80
- h3 {
81
- font-size: 1.25rem;
82
- font-optical-sizing: auto;
83
- font-weight: 600;
84
- margin: 0;
85
- margin-top: 15px;
86
- margin-bottom: 15px;
87
- }
88
-
89
- h4 {
90
- font-size: 1rem;
91
- font-optical-sizing: auto;
92
- font-weight: 600;
93
- margin: 0;
94
- margin-top: 15px;
95
- }
96
-
97
- ul {
98
- list-style: none;
99
- padding: 0;
100
- }
101
-
102
- li {
103
- margin-bottom: 15px;
104
- }
105
-
106
- table {
107
- border-collapse: collapse;
108
- margin-top: 15px;
109
- width: 100%;
110
- }
111
-
112
- th, td {
113
- border: 1px solid #30363d;
114
- padding: 8px;
115
- text-align: left;
116
- min-width: 15px;
117
- max-width: 400px;
118
- overflow-x: auto;
119
- scrollbar-color: hotpink #0d1116;
120
- }
121
-
122
- th {
123
- text-align: center;
124
- }
125
-
126
- code {
127
- border: 1px solid #30363d;
128
- border-radius: 6px;
129
- max-height: 500px;
130
- scrollbar-color: hotpink #1a1b26;
131
- white-space: pre-wrap;
132
- }
133
-
134
- .monospace {
135
- font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
136
- margin: 0;
137
- font-size: 85%;
138
- color: #fff;
139
- }
140
-
141
- .test-name {
142
- font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
143
- font-size: 1.15rem
144
- }
145
-
146
- .metric {
147
- text-align: center;
148
- }
149
-
150
- .highlighted {
151
- background-color: #212c36;
152
- }
153
-
154
- .container {
155
- max-width: 1280px;
156
- margin-right: auto;
157
- margin-left: auto;
158
- }
159
-
160
- .section_content {
161
- padding: 15px;
162
- }
163
-
164
- .no-border {
165
- border: none;
166
- }
167
-
168
- .full-width {
169
- width: 100%;
170
- }
171
-
172
- .test-result {
173
- margin-top: 15px;
174
- border-bottom: 1px solid #30363d;
175
- }
176
-
177
- .loader {
178
- width: 20px;
179
- height: 20px;
180
- border: 2px solid #FFF;
181
- border-radius: 50%;
182
- display: inline-block;
183
- position: relative;
184
- box-sizing: border-box;
185
- animation: rotation 1s linear infinite;
186
- margin-right: 10px;
187
- }
188
-
189
- .loader::after,
190
- .loader::before {
191
- content: '';
192
- box-sizing: border-box;
193
- position: absolute;
194
- left: 0;
195
- top: 0;
196
- background: #FF3D00;
197
- width: 6px;
198
- height: 6px;
199
- transform: translate(150%, 150%);
200
- border-radius: 50%;
201
- }
202
-
203
- .loader::before {
204
- left: auto;
205
- top: auto;
206
- right: 0;
207
- bottom: 0;
208
- transform: translate(-150%, -150%);
209
- }
210
-
211
- .clipped {
212
- max-height: 500px;
213
- overflow-y: auto;
214
- scrollbar-color: hotpink #0d1116;
215
- }
216
-
217
- .testDescription {
218
- color: #9c9c9c;
219
- }
220
-
221
- .secondaryButton {
222
- font-size: 0.75rem;
223
- padding: 2px 10px;
224
- }
225
-
226
- @keyframes rotation {
227
- 0% {
228
- transform: rotate(0deg);
229
- }
230
- 100% {
231
- transform: rotate(360deg);
232
- }
233
- }
234
- </style>
235
- </head>
236
- <body>
237
- <div class="container">
238
- <h1 style="text-align: center;">Live test private details</h1>
239
- <section>
240
- <h2>Context</h2>
241
- <div class="section_content">
242
- <ul>
243
- <li>Tester: <span class="monospace">{{ user }}</span></li>
244
- <li>Test date: <span class="monospace">{{ test_date }}</span></li>
245
- <li>Connector image: <span class="monospace">{{ connector_image }}</span></li>
246
- <li>Control version: <span class="monospace">{{ control_version }}</span></li>
247
- <li>Target version: <span class="monospace">{{ target_version }}</span></li>
248
- </ul>
249
- </div>
250
- </section>
251
- <section>
252
- <h2>Connections used for testing</h2>
253
- {% for connection_objects in all_connection_objects %}
254
- <div class="section_content">
255
- <h3>Details for {{ connection_objects['hashed_connection_id'] }} </h3>
256
- <ul>
257
- <li><b><a href="{{connection_objects["url"]}}" target="_blank">Connection in Airbyte Cloud</a></b></li>
258
- <li>Workpace ID: {{ connection_objects['workspace_id'] }}</li>
259
- <li>Connection ID: {{ connection_objects['connection_id']}}</li>
260
- </ul>
261
- <h3>Source configuration <button class="monospace secondaryButton" onclick="copyToClipboard('config')">📋 copy</button></h3>
262
- <p class="testDescription">The configuration object taken from the given connection that was passed to each version of the connector during the test.</p>
263
- <pre><code class="language-json" id="config">{{ connection_objects['source_config'] }}</code></pre>
264
- </div>
265
- {% endfor %}
266
- </section>
267
- <section>
268
- {% if not fully_generated %}
269
- <h2><span class="loader"></span>Requested URLs</h2>
270
- {% else%}
271
- <h2>Requested URLs</h2>
272
- {% endif %}
273
- <div class="section_content">
274
- {% for command, flows in requested_urls_per_command.items() %}
275
- <h3>{{ command.value.upper() }}</h3>
276
- {% if flows %}
277
- <div class="clipped">
278
- <table class="full-width">
279
- <thead>
280
- <tr>
281
- <th class="no-border"></th>
282
- <th>Control URL</th>
283
- <th>Target URL</th>
284
- </tr>
285
- </thead>
286
- <tbody>
287
- {% for index, control_url, target_url in flows %}
288
- <tr>
289
- <td class="monospace highlighted metric">{{ index }}</td>
290
- <td class="monospace">{{ control_url }}</td>
291
- <td class="monospace">{{ target_url }}</td>
292
- </tr>
293
- {% endfor %}
294
- </tbody>
295
- </table>
296
- </div>
297
- {% else %}
298
- <p>No URLs requested</p>
299
- {% endif %}
300
- {% endfor%}
301
- </div>
302
- </section>
303
- </div>
304
- </body>
305
- </html>