7
7
use GuzzleHttp \Psr7 \ServerRequest ;
8
8
use Icinga \Application \Config ;
9
9
use Icinga \Application \Logger ;
10
- use Icinga \Exception \Http \HttpNotFoundException ;
11
10
use Icinga \Module \Kubernetes \Common \Database ;
12
11
use Icinga \Module \Kubernetes \Forms \DatabaseConfigForm ;
13
12
use Icinga \Module \Kubernetes \Forms \NotificationsConfigForm ;
13
+ use Icinga \Module \Kubernetes \Forms \PrometheusConfigForm ;
14
14
use Icinga \Module \Kubernetes \Model \Config as KConfig ;
15
15
use Icinga \Module \Kubernetes \Web \Controller ;
16
16
use Icinga \Module \Notifications \Common \Database as NotificationsDatabase ;
17
17
use Icinga \Module \Notifications \Forms \SourceForm ;
18
18
use Icinga \Module \Notifications \Model \Source ;
19
19
use Icinga \Web \Notification ;
20
+ use Icinga \Web \Session ;
20
21
use Icinga \Web \Widget \Tabs ;
21
22
use ipl \Sql \Connection ;
22
23
use ipl \Stdlib \Filter ;
24
+ use ipl \Web \Url ;
23
25
use LogicException ;
26
+ use Ramsey \Uuid \Uuid ;
24
27
use Throwable ;
25
28
26
29
class ConfigController extends Controller
@@ -55,18 +58,6 @@ public function notificationsAction()
55
58
{
56
59
$ this ->mergeTabs ($ this ->Module ()->getConfigTabs ()->activate ('notifications ' ));
57
60
58
- $ kconfig = [];
59
- $ q = KConfig::on (Database::connection ())
60
- ->filter (Filter::equal ('key ' , [
61
- KConfig::NOTIFICATIONS_URL ,
62
- KConfig::NOTIFICATIONS_USERNAME ,
63
- KConfig::NOTIFICATIONS_KUBERNETES_WEB_URL
64
- ]));
65
-
66
- foreach ($ q as $ r ) {
67
- $ kconfig [$ r ['key ' ]] = $ r ;
68
- }
69
-
70
61
$ sourceForm = new class (NotificationsDatabase::get ()) extends SourceForm {
71
62
public function hasBeenSent (): bool
72
63
{
@@ -80,53 +71,75 @@ public function hasBeenSubmitted(): bool
80
71
};
81
72
82
73
$ form = (new NotificationsConfigForm ())
83
- ->setKConfig ($ kconfig )
74
+ ->populate ([
75
+ 'cluster_uuid ' =>
76
+ $ this ->getRequest ()->get ('cluster_uuid ' ) ??
77
+ Session::getSession ()
78
+ ->getNamespace ('kubernetes ' )
79
+ ->get ('cluster_uuid ' )
80
+ ])
84
81
->on (
85
82
NotificationsConfigForm::ON_SUCCESS ,
86
- function (NotificationsConfigForm $ form ) use ($ kconfig , $ sourceForm ) {
83
+ function (NotificationsConfigForm $ form ) use ($ sourceForm ) {
87
84
if ($ form ->isLocked ()) {
88
85
$ form ->addMessage ($ this ->translate ('Notifications configuration is locked. ' ));
89
86
90
87
return ;
91
88
}
92
89
90
+ $ clusterUuid = $ form ->getClusterUuid ();
91
+ $ kconfig = $ form ->getKConfig ($ clusterUuid );
93
92
$ values = $ form ->getValues ();
94
93
94
+ /** @var ?Source $source */
95
+ $ source = Source::on (NotificationsDatabase::get ())
96
+ ->filter (Filter::all (
97
+ Filter::equal ('name ' , KConfig::DEFAULT_NOTIFICATIONS_NAME . " ( $ clusterUuid) " ),
98
+ Filter::equal ('type ' , KConfig::DEFAULT_NOTIFICATIONS_TYPE )
99
+ ))
100
+ ->first ();
101
+
95
102
if (
96
- ! ($ kconfig [KConfig::NOTIFICATIONS_USERNAME ]->locked ?? false )
97
- && ($ kconfig [KConfig::NOTIFICATIONS_USERNAME ]->value ?? '' ) === ''
103
+ $ source === null
104
+ // Must be kept in sync with SourceForm:292.
105
+ || password_hash (
106
+ $ kconfig [KConfig::NOTIFICATIONS_PASSWORD ]->value ,
107
+ SourceForm::HASH_ALGORITHM
108
+ ) !== $ source ->listener_password_hash
98
109
) {
99
110
try {
100
- $ values [KConfig::NOTIFICATIONS_PASSWORD ] = $ this ->createSource ($ sourceForm );
111
+ $ values [KConfig::NOTIFICATIONS_PASSWORD ] = $ this
112
+ ->createOrUpdateSource ($ sourceForm , $ clusterUuid );
113
+
114
+ /** @var ?Source $source */
115
+ $ source = Source::on (NotificationsDatabase::get ())
116
+ ->filter (Filter::all (
117
+ Filter::equal ('name ' , KConfig::DEFAULT_NOTIFICATIONS_NAME . " ( $ clusterUuid) " ),
118
+ Filter::equal ('type ' , KConfig::DEFAULT_NOTIFICATIONS_TYPE )
119
+ ))
120
+ ->first ();
121
+
122
+ if ($ source === null ) {
123
+ throw new LogicException ($ this ->translate ('Source not created ' ));
124
+ }
125
+
126
+ $ values [KConfig::NOTIFICATIONS_USERNAME ] = "source- $ source ->id " ;
101
127
} catch (Throwable $ e ) {
102
128
Logger::error ($ e );
103
129
Logger::error ($ e ->getTraceAsString ());
104
130
105
- $ form ->addMessage ($ e ->getMessage ());
106
-
107
- return ;
131
+ throw $ e ;
108
132
}
109
-
110
- /** @var ?Source $source */
111
- $ source = Source::on (NotificationsDatabase::get ())
112
- ->filter (Filter::all (
113
- Filter::equal ('name ' , KConfig::DEFAULT_NOTIFICATIONS_NAME ),
114
- Filter::equal ('type ' , KConfig::DEFAULT_NOTIFICATIONS_TYPE )
115
- ))
116
- ->first ();
117
-
118
- if ($ source === null ) {
119
- throw new LogicException ($ this ->translate ('Source not found ' ));
120
- }
121
-
122
- $ values [KConfig::NOTIFICATIONS_USERNAME ] = "source- $ source ->id " ;
123
133
}
124
134
125
135
try {
126
- Database::connection ()->transaction (function (Connection $ db ) use ($ values ) {
136
+ Database::connection ()->transaction (function (Connection $ db ) use ($ values , $ clusterUuid ) {
137
+ $ key = $ db ->quoteIdentifier ('key ' );
138
+
127
139
$ db ->delete ((new KConfig ())->getTableName (), [
128
- sprintf ('%s IN (?) ' , $ db ->quoteIdentifier ('key ' )) => array_keys ($ values ),
129
- 'locked = ? ' => 'n '
140
+ 'cluster_uuid = ? ' => Uuid::fromString ($ clusterUuid )->getBytes (),
141
+ sprintf ('%s IN (?) ' , $ key ) => array_keys ($ values ),
142
+ 'locked = ? ' => 'n '
130
143
]);
131
144
132
145
foreach ($ values as $ k => $ v ) {
@@ -135,44 +148,86 @@ function (NotificationsConfigForm $form) use ($kconfig, $sourceForm) {
135
148
}
136
149
137
150
$ db ->insert ((new KConfig ())->getTableName (), [
138
- $ db ->quoteIdentifier ('key ' ) => $ k ,
139
- 'value ' => $ v ,
151
+ 'cluster_uuid ' => Uuid::fromString ($ clusterUuid )->getBytes (),
152
+ $ key => $ k ,
153
+ 'value ' => $ v
140
154
]);
141
155
}
142
156
});
143
157
} catch (Throwable $ e ) {
144
158
Logger::error ($ e );
145
159
Logger::error ($ e ->getTraceAsString ());
146
160
147
- $ form ->addMessage ($ e ->getMessage ());
148
-
149
- return ;
161
+ throw $ e ;
150
162
}
151
163
152
164
Notification::success (
153
165
$ this ->translate ('New configuration has successfully been stored. ' )
154
166
);
155
167
156
- $ this ->redirectNow ('__REFRESH__ ' );
168
+ $ this ->redirectNow (
169
+ Url::fromPath ('kubernetes/config/notifications ' , ['cluster_uuid ' => $ clusterUuid ])
170
+ );
157
171
}
158
172
)->handleRequest ($ this ->getServerRequest ());
159
173
160
- if (
161
- preg_match (
162
- '/source-(\d+)/ ' ,
163
- $ kconfig [KConfig::NOTIFICATIONS_USERNAME ]->value ?? '' ,
164
- $ matches
165
- ) !== false
166
- && ! empty ($ matches )
167
- ) {
168
- try {
169
- $ sourceForm ->loadSource ($ matches [1 ]);
170
-
171
- // TODO(el): Check password mismatch.
172
- } catch (HttpNotFoundException $ e ) {
173
- // TODO(el): Add error box.
174
- }
175
- }
174
+ $ this ->addContent ($ form );
175
+ }
176
+
177
+ public function prometheusAction ()
178
+ {
179
+ $ form = (new PrometheusConfigForm ())
180
+ ->populate ([
181
+ 'cluster_uuid ' =>
182
+ $ this ->getRequest ()->get ('cluster_uuid ' ) ??
183
+ Session::getSession ()
184
+ ->getNamespace ('kubernetes ' )
185
+ ->get ('cluster_uuid ' )
186
+ ])
187
+ ->on (PrometheusConfigForm::ON_SUCCESS , function (PrometheusConfigForm $ form ) {
188
+ if ($ form ->isLocked ()) {
189
+ $ form ->addMessage ($ this ->translate ('Prometheus configuration is locked. ' ));
190
+
191
+ return ;
192
+ }
193
+
194
+ $ clusterUuid = $ form ->getClusterUuid ();
195
+ $ values = $ form ->getValues ();
196
+
197
+ try {
198
+ Database::connection ()->transaction (function (Connection $ db ) use ($ values , $ clusterUuid ) {
199
+ $ key = $ db ->quoteIdentifier ('key ' );
200
+
201
+ $ db ->delete ((new KConfig ())->getTableName (), [
202
+ 'cluster_uuid = ? ' => Uuid::fromString ($ clusterUuid )->getBytes (),
203
+ sprintf ('%s IN (?) ' , $ key ) => array_keys ($ values ),
204
+ 'locked = ? ' => 'n '
205
+ ]);
206
+
207
+ foreach ($ values as $ k => $ v ) {
208
+ if (empty ($ v )) {
209
+ continue ;
210
+ }
211
+
212
+ $ db ->insert ((new KConfig ())->getTableName (), [
213
+ 'cluster_uuid ' => Uuid::fromString ($ clusterUuid )->getBytes (),
214
+ $ key => $ k ,
215
+ 'value ' => $ v
216
+ ]);
217
+ }
218
+ });
219
+ } catch (Throwable $ e ) {
220
+ Logger::error ($ e );
221
+ Logger::error ($ e ->getTraceAsString ());
222
+
223
+ throw $ e ;
224
+ }
225
+
226
+ Notification::success ($ this ->translate ('New configuration has successfully been stored ' ));
227
+ $ this ->redirectNow (Url::fromPath ('kubernetes/config/prometheus ' , ['cluster_uuid ' => $ clusterUuid ]));
228
+ })->handleRequest ($ this ->getServerRequest ());
229
+
230
+ $ this ->mergeTabs ($ this ->Module ()->getConfigTabs ()->activate ('prometheus ' ));
176
231
177
232
$ this ->addContent ($ form );
178
233
}
@@ -189,24 +244,42 @@ protected function mergeTabs(Tabs $tabs): void
189
244
}
190
245
}
191
246
192
- protected function createSource (SourceForm $ sourceForm ): string
247
+ protected function createOrUpdateSource (SourceForm $ sourceForm, string $ clusterUuid ): string
193
248
{
194
249
$ password = sha1 (openssl_random_pseudo_bytes (16 ));
195
250
196
251
$ formData = [
197
252
'listener_password ' => $ password ,
198
253
'listener_password_dupe ' => $ password ,
199
- 'name ' => KConfig::DEFAULT_NOTIFICATIONS_NAME ,
254
+ 'name ' => KConfig::DEFAULT_NOTIFICATIONS_NAME . " ( $ clusterUuid ) " ,
200
255
'type ' => KConfig::DEFAULT_NOTIFICATIONS_TYPE ,
201
256
// TODO(el): Why?
202
257
'icinga2_insecure_tls ' => 'n '
203
258
];
204
259
205
- $ sourceForm
206
- ->populate ($ formData )
207
- ->on (SourceForm::ON_SUCCESS , function (SourceForm $ form ) {
260
+ /** @var ?Source $source */
261
+ $ source = Source::on (NotificationsDatabase::get ())
262
+ ->filter (Filter::all (
263
+ Filter::equal ('name ' , KConfig::DEFAULT_NOTIFICATIONS_NAME . " ( $ clusterUuid) " ),
264
+ Filter::equal ('type ' , KConfig::DEFAULT_NOTIFICATIONS_TYPE )
265
+ ))
266
+ ->first ();
267
+
268
+ if ($ source !== null ) {
269
+ $ sourceForm ->loadSource ($ source ->id );
270
+ }
271
+
272
+ $ sourceForm ->populate ($ formData );
273
+
274
+ if ($ source !== null ) {
275
+ $ sourceForm ->on (SourceForm::ON_SUCCESS , function (SourceForm $ form ) {
276
+ $ form ->editSource ();
277
+ });
278
+ } else {
279
+ $ sourceForm ->on (SourceForm::ON_SUCCESS , function (SourceForm $ form ) {
208
280
$ form ->addSource ();
209
281
});
282
+ }
210
283
211
284
$ sourceForm ->ensureAssembled ();
212
285
$ csrf = $ sourceForm ->getElement ('CSRFToken ' );
0 commit comments