sovereign 0.19.3__py3-none-any.whl → 1.0.0b148__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.
Potentially problematic release.
This version of sovereign might be problematic. Click here for more details.
- sovereign/__init__.py +13 -81
- sovereign/app.py +59 -48
- sovereign/cache/__init__.py +172 -0
- sovereign/cache/backends/__init__.py +110 -0
- sovereign/cache/backends/s3.py +143 -0
- sovereign/cache/filesystem.py +73 -0
- sovereign/cache/types.py +15 -0
- sovereign/configuration.py +573 -0
- sovereign/constants.py +1 -0
- sovereign/context.py +271 -104
- sovereign/dynamic_config/__init__.py +113 -0
- sovereign/dynamic_config/deser.py +78 -0
- sovereign/dynamic_config/loaders.py +120 -0
- sovereign/events.py +49 -0
- sovereign/logging/access_logger.py +85 -0
- sovereign/logging/application_logger.py +54 -0
- sovereign/logging/base_logger.py +41 -0
- sovereign/logging/bootstrapper.py +36 -0
- sovereign/logging/types.py +10 -0
- sovereign/middlewares.py +8 -7
- sovereign/modifiers/lib.py +1 -0
- sovereign/rendering.py +192 -0
- sovereign/response_class.py +18 -0
- sovereign/server.py +93 -35
- sovereign/sources/file.py +1 -1
- sovereign/sources/inline.py +1 -0
- sovereign/sources/lib.py +1 -0
- sovereign/sources/poller.py +296 -53
- sovereign/statistics.py +17 -20
- sovereign/templates/base.html +59 -46
- sovereign/templates/resources.html +203 -102
- sovereign/testing/loaders.py +8 -0
- sovereign/{modifiers/test.py → testing/modifiers.py} +0 -2
- sovereign/tracing.py +102 -0
- sovereign/types.py +299 -0
- sovereign/utils/auth.py +26 -13
- sovereign/utils/crypto/__init__.py +0 -0
- sovereign/utils/crypto/crypto.py +135 -0
- sovereign/utils/crypto/suites/__init__.py +21 -0
- sovereign/utils/crypto/suites/aes_gcm_cipher.py +42 -0
- sovereign/utils/crypto/suites/base_cipher.py +21 -0
- sovereign/utils/crypto/suites/disabled_cipher.py +25 -0
- sovereign/utils/crypto/suites/fernet_cipher.py +29 -0
- sovereign/utils/dictupdate.py +2 -1
- sovereign/utils/eds.py +37 -21
- sovereign/utils/mock.py +54 -16
- sovereign/utils/resources.py +17 -0
- sovereign/utils/version_info.py +8 -0
- sovereign/views/__init__.py +4 -0
- sovereign/views/api.py +61 -0
- sovereign/views/crypto.py +46 -15
- sovereign/views/discovery.py +37 -116
- sovereign/views/healthchecks.py +87 -18
- sovereign/views/interface.py +112 -112
- sovereign/worker.py +204 -0
- {sovereign-0.19.3.dist-info → sovereign-1.0.0b148.dist-info}/METADATA +79 -76
- sovereign-1.0.0b148.dist-info/RECORD +77 -0
- {sovereign-0.19.3.dist-info → sovereign-1.0.0b148.dist-info}/WHEEL +1 -1
- sovereign-1.0.0b148.dist-info/entry_points.txt +38 -0
- sovereign_files/__init__.py +0 -0
- sovereign_files/static/darkmode.js +51 -0
- sovereign_files/static/node_expression.js +42 -0
- sovereign_files/static/panel.js +76 -0
- sovereign_files/static/resources.css +246 -0
- sovereign_files/static/resources.js +642 -0
- sovereign_files/static/sass/style.scss +33 -0
- sovereign_files/static/style.css +16143 -0
- sovereign_files/static/style.css.map +1 -0
- sovereign/config_loader.py +0 -225
- sovereign/discovery.py +0 -175
- sovereign/logs.py +0 -131
- sovereign/schemas.py +0 -780
- sovereign/static/sass/style.scss +0 -27
- sovereign/static/style.css +0 -13553
- sovereign/templates/ul_filter.html +0 -22
- sovereign/utils/crypto.py +0 -103
- sovereign/views/admin.py +0 -120
- sovereign-0.19.3.dist-info/LICENSE.txt +0 -13
- sovereign-0.19.3.dist-info/RECORD +0 -47
- sovereign-0.19.3.dist-info/entry_points.txt +0 -10
sovereign/statistics.py
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Optional, Any, Callable, Dict
|
|
3
3
|
from functools import wraps
|
|
4
|
-
from sovereign.
|
|
4
|
+
from sovereign.configuration import config as sovereign_config
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
STATSD: Dict[str, Optional["StatsDProxy"]] = {"instance": None}
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class StatsDProxy:
|
|
10
10
|
def __init__(self, statsd_instance: Optional[Any] = None) -> None:
|
|
11
11
|
self.statsd = statsd_instance
|
|
12
|
-
self.emitted = emitted
|
|
13
12
|
|
|
14
13
|
def __getattr__(self, item: str) -> Any:
|
|
15
14
|
if self.statsd is not None:
|
|
@@ -20,14 +19,12 @@ class StatsDProxy:
|
|
|
20
19
|
return self.do_nothing
|
|
21
20
|
|
|
22
21
|
def do_nothing(self, *args: Any, **kwargs: Any) -> None:
|
|
23
|
-
|
|
24
|
-
emitted[k] = emitted.setdefault(k, 0) + 1
|
|
22
|
+
_ = args[0]
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
class StatsdNoop:
|
|
28
|
-
def __init__(self, *args
|
|
29
|
-
|
|
30
|
-
emitted[k] = emitted.setdefault(k, 0) + 1
|
|
26
|
+
def __init__(self, *args, **kwargs):
|
|
27
|
+
pass
|
|
31
28
|
|
|
32
29
|
def __enter__(self): # type: ignore
|
|
33
30
|
return self
|
|
@@ -43,21 +40,18 @@ class StatsdNoop:
|
|
|
43
40
|
return wrapped
|
|
44
41
|
|
|
45
42
|
|
|
46
|
-
def configure_statsd(
|
|
43
|
+
def configure_statsd() -> StatsDProxy:
|
|
44
|
+
if STATSD["instance"] is not None:
|
|
45
|
+
return STATSD["instance"]
|
|
46
|
+
config = sovereign_config.statsd
|
|
47
47
|
try:
|
|
48
48
|
from datadog import DogStatsd
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
self.emitted: Dict[str, Any] = dict()
|
|
54
|
-
self.emitted[metric] = self.emitted.setdefault(metric, 0) + 1
|
|
55
|
-
|
|
56
|
-
module: Optional[CustomStatsd]
|
|
57
|
-
module = CustomStatsd()
|
|
58
|
-
if config.enabled:
|
|
50
|
+
module: Optional[DogStatsd]
|
|
51
|
+
module = DogStatsd()
|
|
52
|
+
if config.enabled and module:
|
|
59
53
|
module.host = config.host
|
|
60
|
-
module.port = config.port
|
|
54
|
+
module.port = int(config.port)
|
|
61
55
|
module.namespace = config.namespace
|
|
62
56
|
module.use_ms = config.use_ms
|
|
63
57
|
for tag, value in config.tags.items():
|
|
@@ -71,4 +65,7 @@ def configure_statsd(config: StatsdConfig) -> StatsDProxy:
|
|
|
71
65
|
raise
|
|
72
66
|
module = None
|
|
73
67
|
|
|
74
|
-
|
|
68
|
+
ret = StatsDProxy(module)
|
|
69
|
+
if STATSD["instance"] is None:
|
|
70
|
+
STATSD["instance"] = ret
|
|
71
|
+
return ret
|
sovereign/templates/base.html
CHANGED
|
@@ -1,64 +1,77 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en"
|
|
2
|
+
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
|
7
7
|
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
|
8
8
|
<title>{% block title %}{% endblock %} - Sovereign</title>
|
|
9
|
+
<script src="/static/darkmode.js"></script>
|
|
9
10
|
{%- block head %}{% endblock %}
|
|
10
11
|
</head>
|
|
11
12
|
<body>
|
|
12
|
-
<div class="columns">
|
|
13
|
-
<div class="column"></div>
|
|
14
13
|
{%- block nav %}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<a
|
|
34
|
-
|
|
35
|
-
|
|
14
|
+
<div class="hero">
|
|
15
|
+
<div class="hero-body p-4">
|
|
16
|
+
<a href="#">
|
|
17
|
+
<h3 class="title is-3" style="margin-bottom: 0px">sovereign</h3>
|
|
18
|
+
<h7 class="title is-7">version {{ sovereign_version }}</h7>
|
|
19
|
+
</a>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="columns is-gapless" style="min-height: calc(100vh - 120px);">
|
|
24
|
+
<div class="column is-narrow" style="width: 250px;">
|
|
25
|
+
<aside class="menu p-4" style="height: 100%;">
|
|
26
|
+
<div class="mb-4">
|
|
27
|
+
<p class="menu-label">RESOURCES</p>
|
|
28
|
+
<ul class="menu-list">
|
|
29
|
+
{%- set active_page = resource_type|default('redirect_to_docs') -%}
|
|
30
|
+
{%- for type in all_types %}
|
|
31
|
+
<li style="padding: 2px">
|
|
32
|
+
<a href="/ui/resources/{{ type }}"
|
|
33
|
+
style="padding: 3px; border-radius: 4px"
|
|
34
|
+
{% if type == active_page %}class="is-active has-background-primary has-text-white"{% endif %}>
|
|
35
|
+
{{ type|capitalize }}
|
|
36
36
|
</a>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</
|
|
37
|
+
</li>
|
|
38
|
+
{%- endfor %}
|
|
39
|
+
</ul>
|
|
40
40
|
</div>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
|
|
42
|
+
<div class="mb-4">
|
|
43
|
+
<p class="menu-label">LINKS</p>
|
|
44
|
+
<ul class="menu-list">
|
|
45
|
+
<li>
|
|
46
|
+
<a href="/docs">OpenAPI Spec</a>
|
|
47
|
+
</li>
|
|
48
|
+
<li>
|
|
49
|
+
<a href="https://developer.atlassian.com/platform/sovereign/">Documentation</a>
|
|
50
|
+
</li>
|
|
51
|
+
<li>
|
|
52
|
+
<a href="https://bitbucket.org/atlassian/sovereign">Repository</a>
|
|
53
|
+
</li>
|
|
54
|
+
</ul>
|
|
47
55
|
</div>
|
|
56
|
+
|
|
57
|
+
<p class="menu-label">THEME</p>
|
|
58
|
+
<button id="dark-mode-toggle" class="button is-small">
|
|
59
|
+
<span>🌘</span>
|
|
60
|
+
</button>
|
|
61
|
+
</aside>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="column">
|
|
65
|
+
<div class="p-4" style="max-width: 1000px">
|
|
66
|
+
{%- endblock %}
|
|
67
|
+
{%- block body %}
|
|
68
|
+
{% endblock -%}
|
|
48
69
|
</div>
|
|
49
|
-
</
|
|
50
|
-
{%- endblock %}
|
|
51
|
-
|
|
52
|
-
{%- block subnav %}
|
|
53
|
-
{%- endblock %}
|
|
54
|
-
|
|
55
|
-
{%- block body %}
|
|
56
|
-
{% endblock -%}
|
|
70
|
+
</div>
|
|
57
71
|
</div>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
</footer>
|
|
72
|
+
|
|
73
|
+
<footer class="footer">
|
|
74
|
+
{% block footer %}{% endblock %}
|
|
75
|
+
</footer>
|
|
63
76
|
</body>
|
|
64
77
|
</html>
|
|
@@ -1,66 +1,82 @@
|
|
|
1
1
|
{%- extends 'base.html' %}
|
|
2
|
-
{%- import 'ul_filter.html' as filter %}
|
|
3
2
|
{% block title %}{{ resource_type|capitalize }}{% endblock %}
|
|
4
3
|
|
|
5
4
|
{% block head %}
|
|
6
|
-
<
|
|
7
|
-
|
|
5
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
6
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
8
|
+
<link rel="stylesheet" href="/static/resources.css">
|
|
9
|
+
<script src="/static/resources.js"></script>
|
|
10
|
+
<script src="/static/panel.js"></script>
|
|
8
11
|
{% endblock %}
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
{%- block body %}
|
|
12
15
|
<div class="content">
|
|
16
|
+
{% if error %}
|
|
17
|
+
<span class="panel-icon">
|
|
18
|
+
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
|
19
|
+
</span>
|
|
20
|
+
<div class="notification is-danger">
|
|
21
|
+
{{ error }}
|
|
22
|
+
</div>
|
|
23
|
+
{% endif %}
|
|
13
24
|
<p class="content">
|
|
14
|
-
<div class="
|
|
15
|
-
<div class="
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<div class="dropdown-
|
|
26
|
-
<
|
|
25
|
+
<div class="columns">
|
|
26
|
+
<div class="column is-narrow">
|
|
27
|
+
<div class="dropdown is-hoverable">
|
|
28
|
+
<div class="dropdown-trigger">
|
|
29
|
+
<button class="button is-primary" aria-haspopup="true" aria-controls="dropdown-menu">
|
|
30
|
+
<span>Template Version</span>
|
|
31
|
+
<span class="icon is-small">
|
|
32
|
+
<i class="fas fa-angle-down" aria-hidden="false"></i>
|
|
33
|
+
</span>
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
|
37
|
+
<div class="dropdown-content">
|
|
38
|
+
<div class="dropdown-item">
|
|
39
|
+
<p>All resources will be formatted for the selected version</p>
|
|
40
|
+
</div>
|
|
41
|
+
{% for v in available_versions %}
|
|
42
|
+
<a class="dropdown-item{% if v == version %} is-active{% endif %}"
|
|
43
|
+
href="#" onclick="setEnvoyVersion('{{ v }}'); return false;">
|
|
44
|
+
{{ v.replace('_', '') }}
|
|
45
|
+
</a>
|
|
46
|
+
{% endfor %}
|
|
47
|
+
</div>
|
|
27
48
|
</div>
|
|
28
|
-
{% for v in available_versions %}
|
|
29
|
-
<a class="dropdown-item{% if v == version %} is-active{% endif %}"
|
|
30
|
-
href="/ui/set-version?version={{ v }}">
|
|
31
|
-
{{ v.replace('_', '') }}
|
|
32
|
-
</a>
|
|
33
|
-
{% endfor %}
|
|
34
49
|
</div>
|
|
35
50
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<i class="fas fa-angle-down" aria-hidden="true"></i>
|
|
43
|
-
</span>
|
|
44
|
-
</button>
|
|
51
|
+
<!-- node expression box -->
|
|
52
|
+
<div class="column">
|
|
53
|
+
<form id="filterForm">
|
|
54
|
+
<input id="filterInput" class="input" type="text" placeholder="Node filter expression"/>
|
|
55
|
+
</form>
|
|
56
|
+
<p id="filterMessage" class="help"></p>
|
|
45
57
|
</div>
|
|
46
|
-
<div class="
|
|
47
|
-
<div class="
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
<div class="column is-narrow">
|
|
59
|
+
<div class="tooltip">
|
|
60
|
+
<span class="button is-primary">?</span>
|
|
61
|
+
<div class="tooltip-text">
|
|
62
|
+
<p>Space-delimited Node filter.<p>
|
|
63
|
+
Examples:<br>
|
|
64
|
+
<code>id=envoy-1234</code><br>
|
|
65
|
+
<code>cluster=a_service_cluster</code><br>
|
|
66
|
+
<code>locality.zone=us-east-1</code><br>
|
|
67
|
+
<code>locality.sub_zone=a</code><br>
|
|
68
|
+
<code>metadata.field_name=abcdef</code>
|
|
69
|
+
</div>
|
|
57
70
|
</div>
|
|
58
71
|
</div>
|
|
72
|
+
</p>
|
|
59
73
|
</div>
|
|
60
|
-
</p>
|
|
61
74
|
</div>
|
|
62
75
|
|
|
63
|
-
|
|
76
|
+
|
|
77
|
+
{% set count = resources|length %}
|
|
78
|
+
{% if count > 0 %}
|
|
79
|
+
<nav class="panel is-primary" id="resources">
|
|
64
80
|
<p class="panel-heading">
|
|
65
81
|
{{ resource_type|capitalize }}
|
|
66
82
|
</p>
|
|
@@ -71,8 +87,8 @@
|
|
|
71
87
|
class="input"
|
|
72
88
|
type="text"
|
|
73
89
|
id="search_filter"
|
|
74
|
-
onkeyup="filter_results('search_filter'
|
|
75
|
-
placeholder="Filter
|
|
90
|
+
onkeyup="filter_results('search_filter')"
|
|
91
|
+
placeholder="Filter {{ resource_type }} by any string"
|
|
76
92
|
>
|
|
77
93
|
</label>
|
|
78
94
|
<span class="icon is-left">
|
|
@@ -82,78 +98,163 @@
|
|
|
82
98
|
</div>
|
|
83
99
|
|
|
84
100
|
{% set res = resources|selectattr('get')|list %}
|
|
85
|
-
{% set count = res|length %}
|
|
86
101
|
{% set plural = {
|
|
87
102
|
0: 'resources',
|
|
88
103
|
1: 'resource'
|
|
89
104
|
} %}
|
|
90
|
-
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
|
96
|
-
</span>
|
|
97
|
-
{{ name }}
|
|
98
|
-
</a>
|
|
99
|
-
{% endfor %}
|
|
105
|
+
{# begin pagination #}
|
|
106
|
+
<div id="resource-container">
|
|
107
|
+
{# Will be filled in #}
|
|
108
|
+
</div>
|
|
109
|
+
{# pagination control bar #}
|
|
100
110
|
<div class="panel-block">
|
|
101
|
-
<p class="content is-small">
|
|
111
|
+
<p class="content is-small" id="resource-count">
|
|
102
112
|
{{ count }} {{ plural.get(count, 'resources') }}
|
|
103
113
|
</p>
|
|
104
114
|
</div>
|
|
105
115
|
</nav>
|
|
116
|
+
{% if count < 10 %}
|
|
117
|
+
{% set hidden = "display: none;" %}
|
|
118
|
+
{% endif %}
|
|
119
|
+
<div style="{{ hidden }}">
|
|
120
|
+
<nav class="pagination is-right is-small" role="navigation" aria-label="pagination">
|
|
121
|
+
<a id="prev-btn" class="pagination-previous">Previous</a>
|
|
122
|
+
<a id="next-btn" class="pagination-next">Next</a>
|
|
123
|
+
<ul id="page-numbers" class="pagination-list"></ul>
|
|
124
|
+
</nav>
|
|
125
|
+
</div>
|
|
106
126
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
</p>
|
|
112
|
-
<div class="panel-block">
|
|
127
|
+
{% if resource_type == 'routes' %}
|
|
128
|
+
<nav class="panel is-primary">
|
|
129
|
+
<p class="panel-heading">Virtual Hosts</p>
|
|
130
|
+
<div class="panel-block">
|
|
113
131
|
<p class="control has-icons-left">
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
id="search_filter_virtual_hosts"
|
|
119
|
-
onkeyup="filter_results('search_filter_virtual_hosts', 'virtual_hosts')"
|
|
120
|
-
placeholder="Filter resources by any string"
|
|
121
|
-
>
|
|
122
|
-
</label>
|
|
123
|
-
<span class="icon is-left">
|
|
124
|
-
<i class="fas fa-search" aria-hidden="true"></i>
|
|
125
|
-
</span>
|
|
132
|
+
<input id="searchInput" class="input" type="text" placeholder="Filter virtual-hosts by any string" />
|
|
133
|
+
<span class="icon is-left">
|
|
134
|
+
<i class="fas fa-search" aria-hidden="true"></i>
|
|
135
|
+
</span>
|
|
126
136
|
</p>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
{% if loop.first and loop.last %}
|
|
135
|
-
{# A single virtualhost makes no sense to render. It will be in one of the routes above. #}
|
|
136
|
-
{% else %}
|
|
137
|
-
<a class="panel-block"
|
|
138
|
-
href="/ui/resources/routes/{{ resource['name'] }}/{{ virtualhost['name'] }}">
|
|
139
|
-
<span class="panel-icon">
|
|
140
|
-
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
|
141
|
-
</span>
|
|
142
|
-
{{ virtualhost['name'] }}
|
|
143
|
-
</a>
|
|
144
|
-
{% endif %}
|
|
137
|
+
</div>
|
|
138
|
+
<p class="panel-tabs">
|
|
139
|
+
<a class="is-active" onclick="filterTabs(this, 'all')">All</a>
|
|
140
|
+
{% for resource in res %}
|
|
141
|
+
<a onclick="filterTabs(this, '{{ resource["name"] }}')">
|
|
142
|
+
{{ resource['name'] }}
|
|
143
|
+
</a>
|
|
145
144
|
{% endfor %}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
</p>
|
|
146
|
+
{% for resource in res %}
|
|
147
|
+
{% if resource["virtual_hosts"] %}
|
|
148
|
+
{% for virtualhost in resource['virtual_hosts'] %}
|
|
149
|
+
<a class="panel-block virtualhost"
|
|
150
|
+
data-category="{{ resource['name'] }}"
|
|
151
|
+
href="#"
|
|
152
|
+
onclick="loadVirtualHostInSidePanel('{{ resource['name'] }}', '{{ virtualhost['name'] }}'); return false;">
|
|
153
|
+
<p class="tag is-small is-primary">
|
|
154
|
+
{{ resource['name'] }}
|
|
155
|
+
</p>
|
|
156
|
+
<span class="panel-icon">
|
|
157
|
+
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
|
158
|
+
</span>
|
|
159
|
+
{{ virtualhost['name'] }}
|
|
160
|
+
</a>
|
|
161
|
+
{% endfor %}
|
|
162
|
+
{% else %}
|
|
163
|
+
<span class="panel-icon">
|
|
164
|
+
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
|
165
|
+
</span>
|
|
166
|
+
<div class="notification is-danger">
|
|
167
|
+
No resources found
|
|
168
|
+
<script>
|
|
169
|
+
setTimeout(() => location.reload(), 6000);
|
|
170
|
+
</script>
|
|
171
|
+
</div>
|
|
172
|
+
{% endif %}
|
|
173
|
+
{% endfor %}
|
|
174
|
+
</nav>
|
|
175
|
+
{% endif %}
|
|
176
|
+
{% else %}
|
|
177
|
+
<span class="panel-icon">
|
|
178
|
+
<i class="fas fa-arrow-right" aria-hidden="true"></i>
|
|
179
|
+
</span>
|
|
180
|
+
<div class="notification is-danger">
|
|
181
|
+
No resources found
|
|
182
|
+
<script>
|
|
183
|
+
setTimeout(() => location.reload(), 2000);
|
|
184
|
+
</script>
|
|
185
|
+
</div>
|
|
186
|
+
{% endif %}
|
|
187
|
+
{% if show_debuginfo %}
|
|
188
|
+
<pre>
|
|
189
|
+
{%- if discovery_request != None %}
|
|
190
|
+
---
|
|
191
|
+
DiscoveryRequest:
|
|
192
|
+
Node:
|
|
193
|
+
Id: {{ discovery_request.node.id }}
|
|
194
|
+
Cluster: {{ discovery_request.node.cluster }}
|
|
195
|
+
Metadata: {{ discovery_request.node.metadata }}
|
|
196
|
+
Locality: {{ discovery_request.node.locality }}
|
|
197
|
+
Build Version: {{ discovery_request.node.build_version }}
|
|
198
|
+
Version Info: {{ discovery_request.version_info }}
|
|
199
|
+
Resource Names: {{ discovery_request.resources or "*" }}
|
|
200
|
+
# Sovereign-generated fields
|
|
201
|
+
Envoy Version: {{ discovery_request.envoy_version }}
|
|
202
|
+
Host Header: {{ discovery_request.desired_controlplane }}
|
|
203
|
+
{%- endif %}
|
|
204
|
+
{%- if discovery_response != None %}
|
|
205
|
+
---
|
|
206
|
+
DiscoveryResponse:
|
|
207
|
+
Config version: {{ discovery_response.version }}
|
|
208
|
+
{%- endif %}
|
|
209
|
+
</pre>
|
|
153
210
|
{% endif %}
|
|
211
|
+
|
|
212
|
+
<!-- Side Panel Backdrop -->
|
|
213
|
+
<div id="sidePanelBackdrop" class="side-panel-backdrop"></div>
|
|
214
|
+
|
|
215
|
+
<!-- Side Panel -->
|
|
216
|
+
<div id="sidePanel" class="side-panel has-background-dark has-text-white">
|
|
217
|
+
<div class="hero is-primary is-small">
|
|
218
|
+
<div class="hero-body p-4">
|
|
219
|
+
<div class="level">
|
|
220
|
+
<div class="level-left">
|
|
221
|
+
<h4 class="title is-4 has-text-white mb-0">
|
|
222
|
+
<span id="sidePanelTitle">Resource Details</span>
|
|
223
|
+
</h4>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="level-right">
|
|
226
|
+
<button class="delete is-large" onclick="closeSidePanel()"></button>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
<div class="side-panel-content">
|
|
232
|
+
<div id="sidePanelContent">
|
|
233
|
+
<div class="content has-text-centered p-6">
|
|
234
|
+
<p>Select a resource to view its details.</p>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
154
239
|
{% endblock -%}
|
|
155
240
|
{% block footer %}
|
|
156
241
|
<div class="content has-text-centered is-small">
|
|
157
|
-
<
|
|
242
|
+
<script src="/static/node_expression.js"></script>
|
|
243
|
+
<script>
|
|
244
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
245
|
+
const resourceNames = [
|
|
246
|
+
{% for resource in resources %}
|
|
247
|
+
"{{ resource.name or resource.cluster_name or 'Unknown' }}"{% if not loop.last %},{% endif %}
|
|
248
|
+
{% endfor %}
|
|
249
|
+
];
|
|
250
|
+
if (typeof initializeResources === 'function') {
|
|
251
|
+
initializeResources(resourceNames, '{{ resource_type }}');
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
function setEnvoyVersion(version) {
|
|
255
|
+
document.cookie = `envoy_version=${version}; path=/ui/resources/; max-age=31536000`;
|
|
256
|
+
window.location.reload();
|
|
257
|
+
}
|
|
258
|
+
</script>
|
|
158
259
|
</div>
|
|
159
260
|
{% endblock %}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from sovereign import template_context
|
|
2
1
|
from sovereign.modifiers.lib import Modifier
|
|
3
2
|
from sovereign.utils import eds, templates
|
|
4
3
|
|
|
@@ -8,7 +7,6 @@ class Test(Modifier):
|
|
|
8
7
|
return True
|
|
9
8
|
|
|
10
9
|
def apply(self) -> None:
|
|
11
|
-
assert template_context
|
|
12
10
|
assert eds
|
|
13
11
|
assert templates
|
|
14
12
|
self.instance["modifier_test_executed"] = True
|