]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
6c465d46998d8b682e2dc63ed9b473c9e84ea0ae
[ceph-ci.git] /
1 <cd-modal [pageURL]="pageURL"
2           [modalRef]="activeModal">
3   <span class="modal-title"
4         i18n>{{ action | titlecase }} {{ resource | upperFirst }}</span>
5   <ng-container class="modal-content">
6     <form #frm="ngForm"
7           [formGroup]="serviceForm"
8           novalidate>
9       <div class="modal-body">
10
11         <!-- Service type -->
12         <div class="form-group row">
13           <label class="cd-col-form-label required"
14                  for="service_type"
15                  i18n>Type</label>
16           <div class="cd-col-form-input">
17             <select id="service_type"
18                     name="service_type"
19                     class="form-select"
20                     formControlName="service_type"
21                     (change)="getServiceIds($event.target.value)">
22               <option i18n
23                       [ngValue]="null">-- Select a service type --</option>
24               <option *ngFor="let serviceType of serviceTypes"
25                       [value]="serviceType">
26                 {{ serviceType }}
27               </option>
28             </select>
29             <span class="invalid-feedback"
30                   *ngIf="serviceForm.showError('service_type', frm, 'required')"
31                   i18n>This field is required.</span>
32           </div>
33         </div>
34
35         <!-- backend_service -->
36           <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
37                class="form-group row">
38             <label i18n
39                    class="cd-col-form-label"
40                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
41                    for="backend_service">Backend Service</label>
42             <div class="cd-col-form-input">
43               <select id="backend_service"
44                       name="backend_service"
45                       class="form-select"
46                       formControlName="backend_service"
47                       (change)="prePopulateId()">
48                 <option *ngIf="services === null"
49                         [ngValue]="null"
50                         i18n>Loading...</option>
51                 <option *ngIf="services !== null && services.length === 0"
52                         [ngValue]="null"
53                         i18n>-- No service available --</option>
54                 <option *ngIf="services !== null && services.length > 0"
55                         [ngValue]="null"
56                         i18n>-- Select an existing service --</option>
57                 <option *ngFor="let service of services"
58                         [value]="service.service_name">{{ service.service_name }}</option>
59               </select>
60               <span class="invalid-feedback"
61                     *ngIf="serviceForm.showError('backend_service', frm, 'required')"
62                     i18n>This field is required.</span>
63             </div>
64           </div>
65
66         <!-- Service id -->
67         <div class="form-group row"
68              *ngIf="serviceForm.controls.service_type.value !== 'snmp-gateway'">
69           <label class="cd-col-form-label"
70                  [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)}"
71                  for="service_id">
72             <span i18n>Id</span>
73             <cd-helper i18n>Used in the service name which is &lt;service_type.service_id&gt;</cd-helper>
74           </label>
75           <div class="cd-col-form-input">
76             <input id="service_id"
77                    class="form-control"
78                    type="text"
79                    formControlName="service_id">
80             <span class="invalid-feedback"
81                   *ngIf="serviceForm.showError('service_id', frm, 'required')"
82                   i18n>This field is required.</span>
83             <span class="invalid-feedback"
84                   *ngIf="serviceForm.showError('service_id', frm, 'uniqueName')"
85                   i18n>This service id is already in use.</span>
86             <span class="invalid-feedback"
87                   *ngIf="serviceForm.showError('service_id', frm, 'rgwPattern')"
88                   i18n>The value does not match the pattern <strong>&lt;service_id&gt;[.&lt;realm_name&gt;.&lt;zone_name&gt;]</strong>.</span>
89             <span class="invalid-feedback"
90                   *ngIf="serviceForm.showError('service_id', frm, 'mdsPattern')"
91                   i18n>MDS service id must start with a letter and contain alphanumeric characters or '.', '-', and '_'</span>
92           </div>
93         </div>
94
95         <!-- unmanaged -->
96         <div class="form-group row">
97           <div class="cd-col-form-offset">
98             <div class="custom-control custom-checkbox">
99               <input class="custom-control-input"
100                      id="unmanaged"
101                      type="checkbox"
102                      formControlName="unmanaged">
103               <label class="custom-control-label"
104                      for="unmanaged"
105                      i18n>Unmanaged</label>
106               <cd-helper i18n>If set to true, the orchestrator will not start nor stop any daemon associated with this service.
107                  Placement and all other properties will be ignored.</cd-helper>
108             </div>
109           </div>
110         </div>
111
112         <!-- Placement -->
113         <div *ngIf="!serviceForm.controls.unmanaged.value"
114              class="form-group row">
115           <label class="cd-col-form-label"
116                  for="placement"
117                  i18n>Placement</label>
118           <div class="cd-col-form-input">
119             <select id="placement"
120                     class="form-select"
121                     formControlName="placement">
122               <option i18n
123                       value="hosts">Hosts</option>
124               <option i18n
125                       value="label">Label</option>
126             </select>
127           </div>
128         </div>
129
130         <!-- Label -->
131         <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'label'"
132              class="form-group row">
133           <label i18n
134                  class="cd-col-form-label"
135                  for="label">Label</label>
136           <div class="cd-col-form-input">
137             <input id="label"
138                    class="form-control"
139                    type="text"
140                    formControlName="label"
141                    [ngbTypeahead]="searchLabels"
142                    (focus)="labelFocus.next($any($event).target.value)"
143                    (click)="labelClick.next($any($event).target.value)">
144             <span class="invalid-feedback"
145                   *ngIf="serviceForm.showError('label', frm, 'required')"
146                   i18n>This field is required.</span>
147           </div>
148         </div>
149
150         <!-- Hosts -->
151         <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'hosts'"
152              class="form-group row">
153           <label class="cd-col-form-label"
154                  for="hosts"
155                  i18n>Hosts</label>
156           <div class="cd-col-form-input">
157             <cd-select-badges id="hosts"
158                               [data]="serviceForm.controls.hosts.value"
159                               [options]="hosts.options"
160                               [messages]="hosts.messages">
161             </cd-select-badges>
162           </div>
163         </div>
164
165         <!-- count -->
166         <div *ngIf="!serviceForm.controls.unmanaged.value"
167              class="form-group row">
168           <label class="cd-col-form-label"
169                  for="count">
170             <span i18n>Count</span>
171             <cd-helper i18n>Only that number of daemons will be created.</cd-helper>
172           </label>
173           <div class="cd-col-form-input">
174             <input id="count"
175                    class="form-control"
176                    type="number"
177                    formControlName="count"
178                    min="1">
179             <span class="invalid-feedback"
180                   *ngIf="serviceForm.showError('count', frm, 'min')"
181                   i18n>The value must be at least 1.</span>
182             <span class="invalid-feedback"
183                   *ngIf="serviceForm.showError('count', frm, 'pattern')"
184                   i18n>The entered value needs to be a number.</span>
185           </div>
186         </div>
187
188         <!-- RGW -->
189         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'rgw'">
190           <!-- rgw_frontend_port -->
191           <div class="form-group row">
192             <label i18n
193                    class="cd-col-form-label"
194                    for="rgw_frontend_port">Port</label>
195             <div class="cd-col-form-input">
196               <input id="rgw_frontend_port"
197                      class="form-control"
198                      type="number"
199                      formControlName="rgw_frontend_port"
200                      min="1"
201                      max="65535">
202               <span class="invalid-feedback"
203                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'pattern')"
204                     i18n>The entered value needs to be a number.</span>
205               <span class="invalid-feedback"
206                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'min')"
207                     i18n>The value must be at least 1.</span>
208               <span class="invalid-feedback"
209                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'max')"
210                     i18n>The value cannot exceed 65535.</span>
211             </div>
212           </div>
213         </ng-container>
214
215         <!-- iSCSI -->
216         <!-- pool -->
217         <div class="form-group row"
218              *ngIf="serviceForm.controls.service_type.value === 'iscsi'">
219           <label i18n
220                  class="cd-col-form-label required"
221                  for="pool">Pool</label>
222           <div class="cd-col-form-input">
223             <select id="pool"
224                     name="pool"
225                     class="form-select"
226                     formControlName="pool">
227               <option *ngIf="pools === null"
228                       [ngValue]="null"
229                       i18n>Loading...</option>
230               <option *ngIf="pools && pools.length === 0"
231                       [ngValue]="null"
232                       i18n>-- No pools available --</option>
233               <option *ngIf="pools && pools.length > 0"
234                       [ngValue]="null"
235                       i18n>-- Select a pool --</option>
236               <option *ngFor="let pool of pools"
237                       [value]="pool.pool_name">{{ pool.pool_name }}</option>
238             </select>
239             <span class="invalid-feedback"
240                   *ngIf="serviceForm.showError('pool', frm, 'required')"
241                   i18n>This field is required.</span>
242           </div>
243         </div>
244
245         <!-- fields in iSCSI which are hidden when unmanaged is true -->
246         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'iscsi'">
247           <!-- trusted_ip_list -->
248           <div class="form-group row">
249             <label class="cd-col-form-label"
250                    for="trusted_ip_list">
251               <span i18n>Trusted IPs</span>
252               <cd-helper>
253                 <span i18n>Comma separated list of IP addresses.</span>
254                 <br>
255                 <span i18n>Please add the <b>Ceph Manager</b> IP addresses here, otherwise the iSCSI gateways can't be reached.</span>
256               </cd-helper>
257             </label>
258             <div class="cd-col-form-input">
259               <input id="trusted_ip_list"
260                      class="form-control"
261                      type="text"
262                      formControlName="trusted_ip_list">
263             </div>
264           </div>
265
266           <!-- api_port -->
267           <div class="form-group row">
268             <label i18n
269                    class="cd-col-form-label"
270                    for="api_port">Port</label>
271             <div class="cd-col-form-input">
272               <input id="api_port"
273                      class="form-control"
274                      type="number"
275                      formControlName="api_port"
276                      min="1"
277                      max="65535">
278               <span class="invalid-feedback"
279                     *ngIf="serviceForm.showError('api_port', frm, 'pattern')"
280                     i18n>The entered value needs to be a number.</span>
281               <span class="invalid-feedback"
282                     *ngIf="serviceForm.showError('api_port', frm, 'min')"
283                     i18n>The value must be at least 1.</span>
284               <span class="invalid-feedback"
285                     *ngIf="serviceForm.showError('api_port', frm, 'max')"
286                     i18n>The value cannot exceed 65535.</span>
287             </div>
288           </div>
289
290           <!-- api_user -->
291           <div class="form-group row">
292             <label i18n
293                    class="cd-col-form-label"
294                    [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
295                    for="api_user">User</label>
296             <div class="cd-col-form-input">
297               <input id="api_user"
298                      class="form-control"
299                      type="text"
300                      formControlName="api_user">
301               <span class="invalid-feedback"
302                     *ngIf="serviceForm.showError('api_user', frm, 'required')"
303                     i18n>This field is required.</span>
304             </div>
305           </div>
306
307           <!-- api_password -->
308           <div class="form-group row">
309             <label i18n
310                    class="cd-col-form-label"
311                    [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
312                    for="api_password">Password</label>
313             <div class="cd-col-form-input">
314               <div class="input-group">
315                 <input id="api_password"
316                        class="form-control"
317                        type="password"
318                        autocomplete="new-password"
319                        formControlName="api_password">
320                 <button type="button"
321                         class="btn btn-light"
322                         cdPasswordButton="api_password">
323                 </button>
324                 <cd-copy-2-clipboard-button source="api_password">
325                 </cd-copy-2-clipboard-button>
326                 <span class="invalid-feedback"
327                       *ngIf="serviceForm.showError('api_password', frm, 'required')"
328                       i18n>This field is required.</span>
329               </div>
330             </div>
331           </div>
332         </ng-container>
333
334         <!-- Ingress -->
335         <ng-container *ngIf="serviceForm.controls.service_type.value === 'ingress'">
336           <!-- virtual_ip -->
337           <div class="form-group row">
338             <label class="cd-col-form-label"
339                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
340                    for="virtual_ip">
341               <span i18n>Virtual IP</span>
342               <cd-helper>
343                 <span i18n>The virtual IP address and subnet (in CIDR notation) where the ingress service will be available.</span>
344               </cd-helper>
345             </label>
346             <div class="cd-col-form-input">
347               <input id="virtual_ip"
348                      class="form-control"
349                      type="text"
350                      formControlName="virtual_ip">
351               <span class="invalid-feedback"
352                     *ngIf="serviceForm.showError('virtual_ip', frm, 'required')"
353                     i18n>This field is required.</span>
354             </div>
355           </div>
356
357           <!-- frontend_port -->
358           <div class="form-group row">
359             <label class="cd-col-form-label"
360                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
361                    for="frontend_port">
362               <span i18n>Frontend Port</span>
363               <cd-helper>
364                 <span i18n>The port used to access the ingress service.</span>
365               </cd-helper>
366             </label>
367             <div class="cd-col-form-input">
368               <input id="frontend_port"
369                      class="form-control"
370                      type="number"
371                      formControlName="frontend_port"
372                      min="1"
373                      max="65535">
374               <span class="invalid-feedback"
375                     *ngIf="serviceForm.showError('frontend_port', frm, 'pattern')"
376                     i18n>The entered value needs to be a number.</span>
377               <span class="invalid-feedback"
378                     *ngIf="serviceForm.showError('frontend_port', frm, 'min')"
379                     i18n>The value must be at least 1.</span>
380               <span class="invalid-feedback"
381                     *ngIf="serviceForm.showError('frontend_port', frm, 'max')"
382                     i18n>The value cannot exceed 65535.</span>
383               <span class="invalid-feedback"
384                     *ngIf="serviceForm.showError('frontend_port', frm, 'required')"
385                     i18n>This field is required.</span>
386             </div>
387           </div>
388
389           <!-- monitor_port -->
390           <div class="form-group row">
391             <label class="cd-col-form-label"
392                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
393                    for="monitor_port">
394               <span i18n>Monitor Port</span>
395               <cd-helper>
396                 <span i18n>The port used by haproxy for load balancer status.</span>
397               </cd-helper>
398             </label>
399             <div class="cd-col-form-input">
400               <input id="monitor_port"
401                      class="form-control"
402                      type="number"
403                      formControlName="monitor_port"
404                      min="1"
405                      max="65535">
406               <span class="invalid-feedback"
407                     *ngIf="serviceForm.showError('monitor_port', frm, 'pattern')"
408                     i18n>The entered value needs to be a number.</span>
409               <span class="invalid-feedback"
410                     *ngIf="serviceForm.showError('monitor_port', frm, 'min')"
411                     i18n>The value must be at least 1.</span>
412               <span class="invalid-feedback"
413                     *ngIf="serviceForm.showError('monitor_port', frm, 'max')"
414                     i18n>The value cannot exceed 65535.</span>
415               <span class="invalid-feedback"
416                     *ngIf="serviceForm.showError('monitor_port', frm, 'required')"
417                     i18n>This field is required.</span>
418             </div>
419           </div>
420           <!-- virtual_interface_networks -->
421           <div class="form-group row"
422                *ngIf="!serviceForm.controls.unmanaged.value">
423             <label class="cd-col-form-label"
424                    for="virtual_interface_networks">
425               <span i18n>CIDR Networks</span>
426               <cd-helper>
427                 <span i18n>A list of networks to identify which network interface to use for the virtual IP address.</span>
428               </cd-helper>
429             </label>
430             <div class="cd-col-form-input">
431               <input id="virtual_interface_networks"
432                      class="form-control"
433                      type="text"
434                      formControlName="virtual_interface_networks">
435             </div>
436           </div>
437         </ng-container>
438
439         <!-- SNMP-Gateway -->
440         <ng-container *ngIf="serviceForm.controls.service_type.value === 'snmp-gateway'">
441           <!-- snmp-version -->
442           <div class="form-group row">
443             <label class="cd-col-form-label required"
444                    for="snmp_version"
445                    i18n>Version</label>
446             <div class="cd-col-form-input">
447               <select id="snmp_version"
448                       name="snmp_version"
449                       class="form-select"
450                       formControlName="snmp_version"
451                       (change)="clearValidations()">
452                 <option i18n
453                         [ngValue]="null">-- Select SNMP version --</option>
454                 <option *ngFor="let snmpVersion of ['V2c', 'V3']"
455                         [value]="snmpVersion">{{ snmpVersion }}</option>
456               </select>
457               <span class="invalid-feedback"
458                     *ngIf="serviceForm.showError('snmp_version', frm, 'required')"
459                     i18n>This field is required.</span>
460             </div>
461           </div>
462           <!-- Destination -->
463           <div class="form-group row">
464             <label class="cd-col-form-label required"
465                    for="snmp_destination">
466               <span i18n>Destination</span>
467               <cd-helper>
468                 <span i18n>Must be of the format hostname:port.</span>
469               </cd-helper>
470             </label>
471             <div class="cd-col-form-input">
472               <input id="snmp_destination"
473                      class="form-control"
474                      type="text"
475                      formControlName="snmp_destination">
476               <span class="invalid-feedback"
477                     *ngIf="serviceForm.showError('snmp_destination', frm, 'required')"
478                     i18n>This field is required.</span>
479               <span class="invalid-feedback"
480                     *ngIf="serviceForm.showError('snmp_destination', frm, 'snmpDestinationPattern')"
481                     i18n>The value does not match the pattern: <strong>hostname:port</strong></span>
482             </div>
483           </div>
484           <!-- Engine id for snmp V3 -->
485           <div class="form-group row"
486                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
487             <label class="cd-col-form-label required"
488                    for="engine_id">
489               <span i18n>Engine Id</span>
490               <cd-helper>
491                 <span i18n>Unique identifier for the device (in hex).</span>
492               </cd-helper>
493             </label>
494             <div class="cd-col-form-input">
495               <input id="engine_id"
496                      class="form-control"
497                      type="text"
498                      formControlName="engine_id">
499               <span class="invalid-feedback"
500                     *ngIf="serviceForm.showError('engine_id', frm, 'required')"
501                     i18n>This field is required.</span>
502               <span class="invalid-feedback"
503                     *ngIf="serviceForm.showError('engine_id', frm, 'snmpEngineIdPattern')"
504                     i18n>The value does not match the pattern: <strong>Must be in hexadecimal and length must be multiple of 2 with min value = 10 amd max value = 64.</strong></span>
505             </div>
506           </div>
507           <!-- Auth protocol for snmp V3 -->
508           <div class="form-group row"
509                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
510             <label class="cd-col-form-label required"
511                    for="auth_protocol"
512                    i18n>Auth Protocol</label>
513             <div class="cd-col-form-input">
514               <select id="auth_protocol"
515                       name="auth_protocol"
516                       class="form-select"
517                       formControlName="auth_protocol">
518                 <option i18n
519                         [ngValue]="null">-- Select auth protocol --</option>
520                 <option *ngFor="let authProtocol of ['SHA', 'MD5']"
521                         [value]="authProtocol">
522                   {{ authProtocol }}
523                 </option>
524               </select>
525               <span class="invalid-feedback"
526                     *ngIf="serviceForm.showError('auth_protocol', frm, 'required')"
527                     i18n>This field is required.</span>
528             </div>
529           </div>
530           <!-- Privacy protocol for snmp V3 -->
531           <div class="form-group row"
532                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
533             <label class="cd-col-form-label"
534                    for="privacy_protocol"
535                    i18n>Privacy Protocol</label>
536             <div class="cd-col-form-input">
537               <select id="privacy_protocol"
538                       name="privacy_protocol"
539                       class="form-select"
540                       formControlName="privacy_protocol">
541                 <option i18n
542                         [ngValue]="null">-- Select privacy protocol --</option>
543                 <option *ngFor="let privacyProtocol of ['DES', 'AES']"
544                         [value]="privacyProtocol">
545                   {{ privacyProtocol }}
546                 </option>
547               </select>
548             </div>
549           </div>
550           <!-- Credentials -->
551           <fieldset>
552             <legend i18n>Credentials</legend>
553             <!-- snmp v2c snmp_community -->
554             <div class="form-group row"
555                  *ngIf="serviceForm.controls.snmp_version.value === 'V2c'">
556               <label class="cd-col-form-label required"
557                      for="snmp_community">
558                 <span i18n>SNMP Community</span>
559               </label>
560               <div class="cd-col-form-input">
561                 <input id="snmp_community"
562                        class="form-control"
563                        type="text"
564                        formControlName="snmp_community">
565                 <span class="invalid-feedback"
566                       *ngIf="serviceForm.showError('snmp_community', frm, 'required')"
567                       i18n>This field is required.</span>
568               </div>
569             </div>
570             <!-- snmp v3 auth username -->
571             <div class="form-group row"
572                  *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
573               <label class="cd-col-form-label required"
574                      for="snmp_v3_auth_username">
575                 <span i18n>Username</span>
576               </label>
577               <div class="cd-col-form-input">
578                 <input id="snmp_v3_auth_username"
579                        class="form-control"
580                        type="text"
581                        formControlName="snmp_v3_auth_username">
582                 <span class="invalid-feedback"
583                       *ngIf="serviceForm.showError('snmp_v3_auth_username', frm, 'required')"
584                       i18n>This field is required.</span>
585               </div>
586             </div>
587             <!-- snmp v3 auth password -->
588             <div class="form-group row"
589                  *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
590               <label class="cd-col-form-label required"
591                      for="snmp_v3_auth_password">
592                 <span i18n>Password</span>
593               </label>
594               <div class="cd-col-form-input">
595                 <input id="snmp_v3_auth_password"
596                        class="form-control"
597                        type="password"
598                        formControlName="snmp_v3_auth_password">
599                 <span class="invalid-feedback"
600                       *ngIf="serviceForm.showError('snmp_v3_auth_password', frm, 'required')"
601                       i18n>This field is required.</span>
602               </div>
603             </div>
604             <!-- snmp v3 priv password -->
605             <div class="form-group row"
606                  *ngIf="serviceForm.controls.snmp_version.value === 'V3' && serviceForm.controls.privacy_protocol.value !== null && serviceForm.controls.privacy_protocol.value !== undefined">
607               <label class="cd-col-form-label required"
608                      for="snmp_v3_priv_password">
609                 <span i18n>Encryption</span>
610               </label>
611               <div class="cd-col-form-input">
612                 <input id="snmp_v3_priv_password"
613                        class="form-control"
614                        type="password"
615                        formControlName="snmp_v3_priv_password">
616                 <span class="invalid-feedback"
617                       *ngIf="serviceForm.showError('snmp_v3_priv_password', frm, 'required')"
618                       i18n>This field is required.</span>
619               </div>
620             </div>
621           </fieldset>
622         </ng-container>
623         <!-- RGW, Ingress & iSCSI -->
624         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && ['rgw', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)">
625           <!-- ssl -->
626           <div class="form-group row">
627             <div class="cd-col-form-offset">
628               <div class="custom-control custom-checkbox">
629                 <input class="custom-control-input"
630                        id="ssl"
631                        type="checkbox"
632                        formControlName="ssl">
633                 <label class="custom-control-label"
634                        for="ssl"
635                        i18n>SSL</label>
636               </div>
637             </div>
638           </div>
639
640           <!-- ssl_cert -->
641           <div *ngIf="serviceForm.controls.ssl.value"
642                class="form-group row">
643             <label class="cd-col-form-label"
644                    for="ssl_cert">
645               <span i18n>Certificate</span>
646               <cd-helper i18n>The SSL certificate in PEM format.</cd-helper>
647             </label>
648             <div class="cd-col-form-input">
649               <textarea id="ssl_cert"
650                         class="form-control resize-vertical text-monospace text-pre"
651                         formControlName="ssl_cert"
652                         rows="5">
653               </textarea>
654               <input type="file"
655                      (change)="fileUpload($event.target.files, 'ssl_cert')">
656               <span class="invalid-feedback"
657                     *ngIf="serviceForm.showError('ssl_cert', frm, 'required')"
658                     i18n>This field is required.</span>
659               <span class="invalid-feedback"
660                     *ngIf="serviceForm.showError('ssl_cert', frm, 'pattern')"
661                     i18n>Invalid SSL certificate.</span>
662             </div>
663           </div>
664
665           <!-- ssl_key -->
666           <div *ngIf="serviceForm.controls.ssl.value && !(['rgw', 'ingress'].includes(serviceForm.controls.service_type.value))"
667                class="form-group row">
668             <label class="cd-col-form-label"
669                    for="ssl_key">
670               <span i18n>Private key</span>
671               <cd-helper i18n>The SSL private key in PEM format.</cd-helper>
672             </label>
673             <div class="cd-col-form-input">
674               <textarea id="ssl_key"
675                         class="form-control resize-vertical text-monospace text-pre"
676                         formControlName="ssl_key"
677                         rows="5">
678               </textarea>
679               <input type="file"
680                      (change)="fileUpload($event.target.files,'ssl_key')">
681               <span class="invalid-feedback"
682                     *ngIf="serviceForm.showError('ssl_key', frm, 'required')"
683                     i18n>This field is required.</span>
684               <span class="invalid-feedback"
685                     *ngIf="serviceForm.showError('ssl_key', frm, 'pattern')"
686                     i18n>Invalid SSL private key.</span>
687             </div>
688           </div>
689         </ng-container>
690         <!-- Grafana -->
691         <ng-container *ngIf="serviceForm.controls.service_type.value === 'grafana'">
692           <div class="form-group row">
693             <label class="cd-col-form-label"
694                    for="grafana_port">
695               <span i18n>Grafana Port</span>
696               <cd-helper>
697                 <span i18n>The default port used by grafana.</span>
698               </cd-helper>
699             </label>
700             <div class="cd-col-form-input">
701               <input id="grafana_port"
702                      class="form-control"
703                      type="number"
704                      formControlName="grafana_port"
705                      min="1"
706                      max="65535">
707               <span class="invalid-feedback"
708                     *ngIf="serviceForm.showError('grafana_port', frm, 'pattern')"
709                     i18n>The entered value needs to be a number.</span>
710               <span class="invalid-feedback"
711                     *ngIf="serviceForm.showError('grafana_port', frm, 'min')"
712                     i18n>The value must be at least 1.</span>
713               <span class="invalid-feedback"
714                     *ngIf="serviceForm.showError('grafana_port', frm, 'max')"
715                     i18n>The value cannot exceed 65535.</span>
716               <span class="invalid-feedback"
717                     *ngIf="serviceForm.showError('grafana_port', frm, 'required')"
718                     i18n>This field is required.</span>
719             </div>
720           </div>
721
722           <div class="form-group row">
723             <label i18n
724                    class="cd-col-form-label"
725                    for="grafana_admin_password">
726               <span>Grafana Password</span>
727               <cd-helper>The password of the default Grafana Admin. Set once on first-run.</cd-helper>
728             </label>
729             <div class="cd-col-form-input">
730               <div class="input-group">
731                 <input id="grafana_admin_password"
732                        class="form-control"
733                        type="password"
734                        autocomplete="new-password"
735                        [attr.disabled]="editing ? true:null"
736                        formControlName="grafana_admin_password">
737                 <span class="input-group-append">
738                   <button type="button"
739                           class="btn btn-light"
740                           cdPasswordButton="grafana_admin_password">
741                   </button>
742                   <cd-copy-2-clipboard-button source="grafana_admin_password">
743                   </cd-copy-2-clipboard-button>
744                 </span>
745               </div>
746             </div>
747           </div>
748         </ng-container>
749       </div>
750
751       <div class="modal-footer">
752         <div class="text-right">
753           <cd-form-button-panel (submitActionEvent)="onSubmit()"
754                                 [form]="serviceForm"
755                                 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"></cd-form-button-panel>
756         </div>
757       </div>
758     </form>
759   </ng-container>
760 </cd-modal>