]> git.apps.os.sepia.ceph.com Git - ceph.git/blob
91271ed78d755c8ed8794e1aec447dfdd9b8deb7
[ceph.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         <cd-alert-panel *ngIf="serviceForm.controls.service_type.value === 'rgw' && showRealmCreationForm"
11                         type="info"
12                         spacingClass="mb-3"
13                         i18n>
14           <a class="text-decoration-underline"
15              (click)="createMultisiteSetup()">
16              Click here</a> to create a new Realm/Zone Group/Zone
17         </cd-alert-panel>
18
19         <cd-alert-panel *ngIf="serviceForm.controls.service_type.value === 'oauth2-proxy'"
20                         type="info"
21                         spacingClass="mb-3"
22                         i18n>
23           Authentication must be enabled in an active `mgtm-gateway` service to enable Single Sign-On(SSO) with `oauth2-proxy`
24         </cd-alert-panel>
25
26         <!-- Service type -->
27         <div class="form-group row">
28           <label class="cd-col-form-label required"
29                  for="service_type"
30                  i18n>Type</label>
31           <div class="cd-col-form-input">
32             <select id="service_type"
33                     name="service_type"
34                     class="form-select"
35                     formControlName="service_type"
36                     (change)="onServiceTypeChange($event.target.value)">
37               <option i18n
38                       [ngValue]="null">-- Select a service type --</option>
39               <option *ngFor="let serviceType of serviceTypes"
40                       [value]="serviceType">
41                 {{ serviceType }}
42               </option>
43             </select>
44             <span class="invalid-feedback"
45                   *ngIf="serviceForm.showError('service_type', frm, 'required')"
46                   i18n>This field is required.</span>
47           </div>
48         </div>
49
50         <!-- backend_service -->
51         <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
52              class="form-group row">
53           <label i18n
54                  class="cd-col-form-label"
55                  [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
56                  for="backend_service">Backend Service</label>
57           <div class="cd-col-form-input">
58             <select id="backend_service"
59                     name="backend_service"
60                     class="form-select"
61                     formControlName="backend_service"
62                     (change)="prePopulateId()">
63               <option *ngIf="services === null"
64                       [ngValue]="null"
65                       i18n>Loading...</option>
66               <option *ngIf="services !== null && services.length === 0"
67                       [ngValue]="null"
68                       i18n>-- No service available --</option>
69               <option *ngIf="services !== null && services.length > 0"
70                       [ngValue]="null"
71                       i18n>-- Select an existing service --</option>
72               <option *ngFor="let service of services"
73                       [value]="service.service_name">{{ service.service_name }}</option>
74             </select>
75             <span class="invalid-feedback"
76                   *ngIf="serviceForm.showError('backend_service', frm, 'required')"
77                   i18n>This field is required.</span>
78           </div>
79         </div>
80
81         <!-- NVMe/TCP -->
82         <!-- Block Pool -->
83         <div class="form-group row"
84              *ngIf="serviceForm.controls.service_type.value === 'nvmeof'">
85           <label i18n
86                  class="cd-col-form-label required"
87                  for="pool">Block Pool</label>
88           <div class="cd-col-form-input">
89             <select id="pool"
90                     name="pool"
91                     class="form-select"
92                     formControlName="pool"
93                     (change)="onBlockPoolChange()">
94               <option *ngIf="rbdPools === null"
95                       [ngValue]="null"
96                       i18n>Loading...</option>
97               <option *ngIf="rbdPools && rbdPools.length === 0"
98                       [ngValue]="null"
99                       i18n>-- No block pools available --</option>
100               <option *ngIf="rbdPools && rbdPools.length > 0"
101                       [ngValue]="null"
102                       i18n>-- Select a pool --</option>
103               <option *ngFor="let pool of rbdPools"
104                       [value]="pool.pool_name">{{ pool.pool_name }}</option>
105             </select>
106             <cd-help-text i18n>
107               An RBD application-enabled pool in which the gateway configuration can be managed.
108             </cd-help-text>
109             <span class="invalid-feedback"
110                   *ngIf="serviceForm.showError('pool', frm, 'required')"
111                   i18n>This field is required.</span>
112           </div>
113         </div>
114
115         <!-- Group Name -->
116         <div class="form-group row"
117              *ngIf="serviceForm.controls.service_type.value === 'nvmeof'">
118           <label class="cd-col-form-label required"
119                  for="group">
120             <span i18n>Group Name</span>
121           </label>
122           <div class="cd-col-form-input">
123             <div class="input-group">
124               <input id="group"
125                      class="form-control"
126                      type="text"
127                      formControlName="group"
128                      (change)="onNvmeofGroupChange($event.target.value)">
129             </div>
130             <cd-help-text i18n>
131               The name of the gateway group.
132             </cd-help-text>
133             <span class="invalid-feedback"
134                   *ngIf="serviceForm.showError('service_id', frm, 'required')"
135                   i18n>This field is required.</span>
136           </div>
137         </div>
138
139         <!-- Service id -->
140         <div class="form-group row"
141              *ngIf="serviceForm.controls.service_type.value !== 'snmp-gateway'">
142           <label class="cd-col-form-label"
143                  [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)}"
144                  for="service_id">
145             <span i18n>Service Name</span>
146           </label>
147           <div class="cd-col-form-input">
148             <div class="input-group">
149               <span class="input-group-text"
150                     *ngIf="serviceForm.controls.service_type.value && ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)"
151                     for="userId"
152                     i18n>{{serviceForm.controls.service_type.value}}.
153               </span>
154               <input id="service_id"
155                      class="form-control"
156                      type="text"
157                      formControlName="service_id">
158             </div>
159             <span class="invalid-feedback"
160                   *ngIf="serviceForm.showError('service_id', frm, 'required')"
161                   i18n>This field is required.</span>
162             <span class="invalid-feedback"
163                   *ngIf="serviceForm.showError('service_id', frm, 'uniqueName')"
164                   i18n>This service id is already in use.</span>
165             <span class="invalid-feedback"
166                   *ngIf="serviceForm.showError('service_id', frm, 'mdsPattern')"
167                   i18n>MDS service id must start with a letter and contain alphanumeric characters or '.', '-', and '_'</span>
168           </div>
169         </div>
170
171         <div class="form-group row"
172              *ngIf="serviceForm.controls.service_type.value === 'rgw'">
173           <label class="cd-col-form-label"
174                  for="realm_name"
175                  i18n>Realm</label>
176           <div class="cd-col-form-input">
177             <select class="form-select"
178                     id="realm_name"
179                     formControlName="realm_name"
180                     name="realm_name"
181                     [attr.disabled]="realmList.length === 0  || editing ? true : null">
182             <option *ngIf="realmList.length === 0"
183                     i18n
184                     selected>-- No realm available --</option>
185             <option *ngFor="let realm of realmList"
186                     [value]="realm.name">
187                   {{ realm.name }}
188             </option>
189             </select>
190           </div>
191         </div>
192
193         <div class="form-group row"
194              *ngIf="serviceForm.controls.service_type.value === 'rgw'">
195           <label class="cd-col-form-label"
196                  for="zonegroup_name"
197                  i18n>Zone Group</label>
198           <div class="cd-col-form-input">
199             <select class="form-select"
200                     id="zonegroup_name"
201                     formControlName="zonegroup_name"
202                     name="zonegroup_name"
203                     [attr.disabled]="zonegroupList.length === 0  || editing ? true : null">
204               <option *ngFor="let zonegroup of zonegroupList"
205                       [value]="zonegroup.name">
206               {{ zonegroup.name }}
207               </option>
208             </select>
209           </div>
210         </div>
211
212         <div class="form-group row"
213              *ngIf="serviceForm.controls.service_type.value === 'rgw'">
214           <label class="cd-col-form-label"
215                  for="zone_name"
216                  i18n>Zone</label>
217           <div class="cd-col-form-input">
218             <select class="form-select"
219                     id="zone_name"
220                     formControlName="zone_name"
221                     name="zone_name"
222                     [attr.disabled]="zoneList.length === 0  || editing ? true : null">
223               <option *ngFor="let zone of zoneList"
224                       [value]="zone.name">
225               {{ zone.name }}
226               </option>
227             </select>
228           </div>
229         </div>
230
231         <!-- unmanaged -->
232         <div class="form-group row">
233           <div class="cd-col-form-offset">
234             <div class="custom-control custom-checkbox">
235               <input class="custom-control-input"
236                      id="unmanaged"
237                      type="checkbox"
238                      formControlName="unmanaged">
239               <label class="custom-control-label m-0"
240                      for="unmanaged"
241                      i18n>Unmanaged</label>
242               <cd-help-text i18n>If Unmanaged is selected, the orchestrator will not stop or stop any daemons associated with this service. Placement and all other properties will be ignored.</cd-help-text>
243             </div>
244           </div>
245         </div>
246
247         <!-- Placement -->
248         <div *ngIf="!serviceForm.controls.unmanaged.value"
249              class="form-group row">
250           <label class="cd-col-form-label"
251                  for="placement"
252                  i18n>Placement</label>
253           <div class="cd-col-form-input">
254             <select id="placement"
255                     class="form-select"
256                     formControlName="placement"
257                     (change)="onPlacementChange($event.target.value)">
258               <option i18n
259                       value="hosts">Hosts</option>
260               <option i18n
261                       value="label">Label</option>
262             </select>
263           </div>
264         </div>
265
266         <!-- Label -->
267         <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'label'"
268              class="form-group row">
269           <label i18n
270                  class="cd-col-form-label"
271                  for="label">Label</label>
272           <div class="cd-col-form-input">
273             <input id="label"
274                    class="form-control"
275                    type="text"
276                    formControlName="label"
277                    [ngbTypeahead]="searchLabels"
278                    (focus)="labelFocus.next($any($event).target.value)"
279                    (click)="labelClick.next($any($event).target.value)">
280             <span class="invalid-feedback"
281                   *ngIf="serviceForm.showError('label', frm, 'required')"
282                   i18n>This field is required.</span>
283           </div>
284         </div>
285
286         <!-- Hosts -->
287         <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'hosts'"
288              class="form-group row">
289           <label class="cd-col-form-label"
290                  for="hosts"
291                  i18n>Hosts</label>
292           <div class="cd-col-form-input">
293             <cd-select-badges id="hosts"
294                               [data]="serviceForm.controls.hosts.value"
295                               [options]="hosts.options"
296                               [messages]="hosts.messages">
297             </cd-select-badges>
298           </div>
299         </div>
300
301         <!-- Count -->
302         <div *ngIf="!serviceForm.controls.unmanaged.value"
303              class="form-group row">
304           <label class="cd-col-form-label"
305                  for="count">
306             <span i18n>Count</span>
307           </label>
308           <div class="cd-col-form-input">
309             <input id="count"
310                    class="form-control"
311                    type="number"
312                    formControlName="count"
313                    min="1">
314             <cd-help-text i18n>Number of deamons that will be deployed</cd-help-text>
315             <span class="invalid-feedback"
316                   *ngIf="serviceForm.showError('count', frm, 'min')"
317                   i18n>The value must be at least 1.</span>
318             <span class="invalid-feedback"
319                   *ngIf="serviceForm.showError('count', frm, 'pattern')"
320                   i18n>The entered value needs to be a number.</span>
321           </div>
322         </div>
323
324         <!-- RGW -->
325         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'rgw'">
326           <!-- rgw_frontend_port -->
327           <div class="form-group row">
328             <label i18n
329                    class="cd-col-form-label"
330                    for="rgw_frontend_port">Port</label>
331             <div class="cd-col-form-input">
332               <input id="rgw_frontend_port"
333                      class="form-control"
334                      type="number"
335                      formControlName="rgw_frontend_port"
336                      min="1"
337                      max="65535">
338               <span class="invalid-feedback"
339                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'pattern')"
340                     i18n>The entered value needs to be a number.</span>
341               <span class="invalid-feedback"
342                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'min')"
343                     i18n>The value must be at least 1.</span>
344               <span class="invalid-feedback"
345                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'max')"
346                     i18n>The value cannot exceed 65535.</span>
347             </div>
348           </div>
349         </ng-container>
350
351         <!-- iSCSI -->
352         <!-- pool -->
353         <div class="form-group row"
354              *ngIf="serviceForm.controls.service_type.value === 'iscsi'">
355           <label i18n
356                  class="cd-col-form-label required"
357                  for="pool">Pool</label>
358           <div class="cd-col-form-input">
359             <select id="pool"
360                     name="pool"
361                     class="form-select"
362                     formControlName="pool">
363               <option *ngIf="pools === null"
364                       [ngValue]="null"
365                       i18n>Loading...</option>
366               <option *ngIf="pools && pools.length === 0"
367                       [ngValue]="null"
368                       i18n>-- No pools available --</option>
369               <option *ngIf="pools && pools.length > 0"
370                       [ngValue]="null"
371                       i18n>-- Select a pool --</option>
372               <option *ngFor="let pool of pools"
373                       [value]="pool.pool_name">{{ pool.pool_name }}</option>
374             </select>
375             <span class="invalid-feedback"
376                   *ngIf="serviceForm.showError('pool', frm, 'required')"
377                   i18n>This field is required.</span>
378           </div>
379         </div>
380
381         <!-- fields in iSCSI which are hidden when unmanaged is true -->
382         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'iscsi'">
383           <!-- trusted_ip_list -->
384           <div class="form-group row">
385             <label class="cd-col-form-label"
386                    for="trusted_ip_list">
387               <span i18n>Trusted IPs</span>
388               <cd-helper>
389                 <span i18n>Comma separated list of IP addresses.</span>
390                 <br>
391                 <span i18n>Please add the <b>Ceph Manager</b> IP addresses here, otherwise the iSCSI gateways can't be reached.</span>
392               </cd-helper>
393             </label>
394             <div class="cd-col-form-input">
395               <input id="trusted_ip_list"
396                      class="form-control"
397                      type="text"
398                      formControlName="trusted_ip_list">
399             </div>
400           </div>
401
402           <!-- api_port -->
403           <div class="form-group row">
404             <label i18n
405                    class="cd-col-form-label"
406                    for="api_port">Port</label>
407             <div class="cd-col-form-input">
408               <input id="api_port"
409                      class="form-control"
410                      type="number"
411                      formControlName="api_port"
412                      min="1"
413                      max="65535">
414               <span class="invalid-feedback"
415                     *ngIf="serviceForm.showError('api_port', frm, 'pattern')"
416                     i18n>The entered value needs to be a number.</span>
417               <span class="invalid-feedback"
418                     *ngIf="serviceForm.showError('api_port', frm, 'min')"
419                     i18n>The value must be at least 1.</span>
420               <span class="invalid-feedback"
421                     *ngIf="serviceForm.showError('api_port', frm, 'max')"
422                     i18n>The value cannot exceed 65535.</span>
423             </div>
424           </div>
425
426           <!-- api_user -->
427           <div class="form-group row">
428             <label i18n
429                    class="cd-col-form-label"
430                    [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
431                    for="api_user">User</label>
432             <div class="cd-col-form-input">
433               <input id="api_user"
434                      class="form-control"
435                      type="text"
436                      formControlName="api_user">
437               <span class="invalid-feedback"
438                     *ngIf="serviceForm.showError('api_user', frm, 'required')"
439                     i18n>This field is required.</span>
440             </div>
441           </div>
442
443           <!-- api_password -->
444           <div class="form-group row">
445             <label i18n
446                    class="cd-col-form-label"
447                    [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
448                    for="api_password">Password</label>
449             <div class="cd-col-form-input">
450               <div class="input-group">
451                 <input id="api_password"
452                        class="form-control"
453                        type="password"
454                        autocomplete="new-password"
455                        formControlName="api_password">
456                 <button type="button"
457                         class="btn btn-light"
458                         cdPasswordButton="api_password">
459                 </button>
460                 <cd-copy-2-clipboard-button source="api_password">
461                 </cd-copy-2-clipboard-button>
462                 <span class="invalid-feedback"
463                       *ngIf="serviceForm.showError('api_password', frm, 'required')"
464                       i18n>This field is required.</span>
465               </div>
466             </div>
467           </div>
468         </ng-container>
469
470         <!-- smb -->
471         <ng-container *ngIf="serviceForm.controls.service_type.value === 'smb'">
472           <div class="form-group row">
473             <label class="cd-col-form-label required"
474                    for="cluster_id"
475                    i18n>
476               Cluster id
477               <cd-helper>
478                 <span>A short name identifying the SMB “cluster”. In this case a cluster is simply a management unit of one or more Samba services sharing a common configuration,
479                    and may not provide actual clustering or availability mechanisms.</span>
480               </cd-helper>
481             </label>
482             <div class="cd-col-form-input">
483               <input id="cluster_id"
484                      class="form-control"
485                      type="text"
486                      formControlName="cluster_id"
487                      placeholder="foo"
488                      i18n-placeholder>
489               <span class="invalid-feedback"
490                     *ngIf="serviceForm.showError('cluster_id', frm, 'required')"
491                     i18n>This field is required.</span>
492             </div>
493           </div>
494
495           <div class="form-group row">
496             <label class="cd-col-form-label required"
497                    for="config_uri">
498               <span i18n>Config URI</span>
499               <cd-helper i18n>
500                 Configuration source that should be loaded by the samba-container as the primary configuration file.
501               </cd-helper>
502             </label>
503             <div class="cd-col-form-input">
504               <input id="config_uri"
505                      class="form-control"
506                      type="text"
507                      formControlName="config_uri"
508                      placeholder="rados://.smb/foo/scc.toml"
509                      i18n-placeholder>
510               <span class="invalid-feedback"
511                     *ngIf="serviceForm.showError('config_uri', frm, 'required')"
512                     i18n>This field is required.</span>
513               <span class="invalid-feedback"
514                     *ngIf="serviceForm.showError('config_uri', frm, 'configUriPattern')"
515                     i18n>The value must start with either 'http:', 'https:', 'rados:' or 'rados:mon-config-key:'</span>
516             </div>
517           </div>
518
519           <div class="form-group row"
520                formGroupName="features">
521             <label class="cd-col-form-label"
522                    for="features"
523                    i18n>Features
524               <cd-helper>
525                 <span>Pre-defined terms enabling specific deployment characteristics.</span>
526               </cd-helper>
527             </label>
528             <div class="cd-col-form-input">
529               <div class="custom-control custom-checkbox"
530                    *ngFor="let feature of smbFeaturesList">
531                 <input class="custom-control-input"
532                        type="checkbox"
533                        name="{{feature}}"
534                        id="{{feature}}"
535                        formControlName="{{feature}}">
536                 <label class="custom-control-label"
537                        for="{{feature}}"
538                        i18n>{{feature}}
539                 </label>
540               </div>
541             </div>
542           </div>
543
544           <div class="form-group row">
545             <label class="cd-col-form-label"
546                    for="custom_dns">
547               <span i18n>Custom DNS</span>
548               <cd-helper i18n>
549                 <span>Comma separated list of DNSs.</span>
550                 <br>
551                 <span>A list of IP addresses that will be used as the DNS servers for a Samba container.</span>
552               </cd-helper>
553             </label>
554             <div class="cd-col-form-input">
555               <input id="custom_dns"
556                      class="form-control"
557                      type="text"
558                      formControlName="custom_dns"
559                      placeholder="192.168.76.204"
560                      i18n-placeholder>
561             </div>
562           </div>
563
564           <div class="form-group row">
565             <label class="cd-col-form-label"
566                    for="join_sources">
567               <span i18n>Join sources</span>
568               <cd-helper i18n>
569                 <span>Comma separated list of URIs.</span>
570                 <br>
571                 <span>A list of values that will be used to identify where authentication data that will be used to perform domain joins are located.</span>
572               </cd-helper>
573             </label>
574             <div class="cd-col-form-input">
575               <input id="join_sources"
576                      class="form-control"
577                      type="text"
578                      formControlName="join_sources"
579                      placeholder="rados:mon-config-key:smb/config/foo/join1.json"
580                      i18n-placeholder>
581             </div>
582           </div>
583
584           <div class="form-group row">
585             <label class="cd-col-form-label"
586                    for="user_sources">
587               <span i18n>User sources</span>
588               <cd-helper i18n>
589                 <span>Comma separated list of URIs.</span>
590                 <br>
591                 <span>A list of pseudo-uris containing data the samba-container can use to create users (and/or
592                   groups). A ceph based samba container may typically use a rados uri
593                   or a mon config-key store uri </span>
594               </cd-helper>
595             </label>
596             <div class="cd-col-form-input">
597               <input id="user_sources"
598                      class="form-control"
599                      type="text"
600                      formControlName="user_sources"
601                      placeholder="rados:mon-config-key:smb/config/foo/join2.json"
602                      i18n-placeholder>
603             </div>
604           </div>
605
606           <div class="form-group row">
607             <label class="cd-col-form-label"
608                    for="include_ceph_users">
609               <span i18n>Ceph users</span>
610               <cd-helper i18n>
611                 <span>Comma separated list of Ceph users.</span>
612                 <br>
613                 <span>A list of cephx user names that the Samba Containers may use.</span>
614               </cd-helper>
615             </label>
616             <div class="cd-col-form-input">
617               <input id="include_ceph_users"
618                      class="form-control"
619                      type="text"
620                      formControlName="include_ceph_users"
621                      placeholder="client.smb.fs.cluster.foo"
622                      i18n-placeholder>
623             </div>
624           </div>
625
626         </ng-container>
627
628         <!-- Ingress -->
629         <ng-container *ngIf="serviceForm.controls.service_type.value === 'ingress'">
630           <!-- virtual_ip -->
631           <div class="form-group row">
632             <label class="cd-col-form-label"
633                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
634                    for="virtual_ip">
635               <span i18n>Virtual IP</span>
636               <cd-helper>
637                 <span i18n>The virtual IP address and subnet (in CIDR notation) where the ingress service will be available.</span>
638               </cd-helper>
639             </label>
640             <div class="cd-col-form-input">
641               <input id="virtual_ip"
642                      class="form-control"
643                      type="text"
644                      formControlName="virtual_ip">
645               <span class="invalid-feedback"
646                     *ngIf="serviceForm.showError('virtual_ip', frm, 'required')"
647                     i18n>This field is required.</span>
648             </div>
649           </div>
650
651           <!-- frontend_port -->
652           <div class="form-group row">
653             <label class="cd-col-form-label"
654                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
655                    for="frontend_port">
656               <span i18n>Frontend Port</span>
657               <cd-helper>
658                 <span i18n>The port used to access the ingress service.</span>
659               </cd-helper>
660             </label>
661             <div class="cd-col-form-input">
662               <input id="frontend_port"
663                      class="form-control"
664                      type="number"
665                      formControlName="frontend_port"
666                      min="1"
667                      max="65535">
668               <span class="invalid-feedback"
669                     *ngIf="serviceForm.showError('frontend_port', frm, 'pattern')"
670                     i18n>The entered value needs to be a number.</span>
671               <span class="invalid-feedback"
672                     *ngIf="serviceForm.showError('frontend_port', frm, 'min')"
673                     i18n>The value must be at least 1.</span>
674               <span class="invalid-feedback"
675                     *ngIf="serviceForm.showError('frontend_port', frm, 'max')"
676                     i18n>The value cannot exceed 65535.</span>
677               <span class="invalid-feedback"
678                     *ngIf="serviceForm.showError('frontend_port', frm, 'required')"
679                     i18n>This field is required.</span>
680             </div>
681           </div>
682
683           <!-- monitor_port -->
684           <div class="form-group row">
685             <label class="cd-col-form-label"
686                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
687                    for="monitor_port">
688               <span i18n>Monitor Port</span>
689               <cd-helper>
690                 <span i18n>The port used by haproxy for load balancer status.</span>
691               </cd-helper>
692             </label>
693             <div class="cd-col-form-input">
694               <input id="monitor_port"
695                      class="form-control"
696                      type="number"
697                      formControlName="monitor_port"
698                      min="1"
699                      max="65535">
700               <span class="invalid-feedback"
701                     *ngIf="serviceForm.showError('monitor_port', frm, 'pattern')"
702                     i18n>The entered value needs to be a number.</span>
703               <span class="invalid-feedback"
704                     *ngIf="serviceForm.showError('monitor_port', frm, 'min')"
705                     i18n>The value must be at least 1.</span>
706               <span class="invalid-feedback"
707                     *ngIf="serviceForm.showError('monitor_port', frm, 'max')"
708                     i18n>The value cannot exceed 65535.</span>
709               <span class="invalid-feedback"
710                     *ngIf="serviceForm.showError('monitor_port', frm, 'required')"
711                     i18n>This field is required.</span>
712             </div>
713           </div>
714           <!-- virtual_interface_networks -->
715           <div class="form-group row"
716                *ngIf="!serviceForm.controls.unmanaged.value">
717             <label class="cd-col-form-label"
718                    for="virtual_interface_networks">
719               <span i18n>CIDR Networks</span>
720               <cd-helper>
721                 <span i18n>A list of networks to identify which network interface to use for the virtual IP address.</span>
722               </cd-helper>
723             </label>
724             <div class="cd-col-form-input">
725               <input id="virtual_interface_networks"
726                      class="form-control"
727                      type="text"
728                      formControlName="virtual_interface_networks">
729             </div>
730           </div>
731         </ng-container>
732
733         <!-- SNMP-Gateway -->
734         <ng-container *ngIf="serviceForm.controls.service_type.value === 'snmp-gateway'">
735           <!-- snmp-version -->
736           <div class="form-group row">
737             <label class="cd-col-form-label required"
738                    for="snmp_version"
739                    i18n>Version</label>
740             <div class="cd-col-form-input">
741               <select id="snmp_version"
742                       name="snmp_version"
743                       class="form-select"
744                       formControlName="snmp_version"
745                       (change)="clearValidations()">
746                 <option i18n
747                         [ngValue]="null">-- Select SNMP version --</option>
748                 <option *ngFor="let snmpVersion of ['V2c', 'V3']"
749                         [value]="snmpVersion">{{ snmpVersion }}</option>
750               </select>
751               <span class="invalid-feedback"
752                     *ngIf="serviceForm.showError('snmp_version', frm, 'required')"
753                     i18n>This field is required.</span>
754             </div>
755           </div>
756           <!-- Destination -->
757           <div class="form-group row">
758             <label class="cd-col-form-label required"
759                    for="snmp_destination">
760               <span i18n>Destination</span>
761               <cd-helper>
762                 <span i18n>Must be of the format hostname:port.</span>
763               </cd-helper>
764             </label>
765             <div class="cd-col-form-input">
766               <input id="snmp_destination"
767                      class="form-control"
768                      type="text"
769                      formControlName="snmp_destination">
770               <span class="invalid-feedback"
771                     *ngIf="serviceForm.showError('snmp_destination', frm, 'required')"
772                     i18n>This field is required.</span>
773               <span class="invalid-feedback"
774                     *ngIf="serviceForm.showError('snmp_destination', frm, 'snmpDestinationPattern')"
775                     i18n>The value does not match the pattern: <strong>hostname:port</strong></span>
776             </div>
777           </div>
778           <!-- Engine id for snmp V3 -->
779           <div class="form-group row"
780                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
781             <label class="cd-col-form-label required"
782                    for="engine_id">
783               <span i18n>Engine Id</span>
784               <cd-helper>
785                 <span i18n>Unique identifier for the device (in hex).</span>
786               </cd-helper>
787             </label>
788             <div class="cd-col-form-input">
789               <input id="engine_id"
790                      class="form-control"
791                      type="text"
792                      formControlName="engine_id">
793               <span class="invalid-feedback"
794                     *ngIf="serviceForm.showError('engine_id', frm, 'required')"
795                     i18n>This field is required.</span>
796               <span class="invalid-feedback"
797                     *ngIf="serviceForm.showError('engine_id', frm, 'snmpEngineIdPattern')"
798                     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>
799             </div>
800           </div>
801           <!-- Auth protocol for snmp V3 -->
802           <div class="form-group row"
803                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
804             <label class="cd-col-form-label required"
805                    for="auth_protocol"
806                    i18n>Auth Protocol</label>
807             <div class="cd-col-form-input">
808               <select id="auth_protocol"
809                       name="auth_protocol"
810                       class="form-select"
811                       formControlName="auth_protocol">
812                 <option i18n
813                         [ngValue]="null">-- Select auth protocol --</option>
814                 <option *ngFor="let authProtocol of ['SHA', 'MD5']"
815                         [value]="authProtocol">
816                   {{ authProtocol }}
817                 </option>
818               </select>
819               <span class="invalid-feedback"
820                     *ngIf="serviceForm.showError('auth_protocol', frm, 'required')"
821                     i18n>This field is required.</span>
822             </div>
823           </div>
824           <!-- Privacy protocol for snmp V3 -->
825           <div class="form-group row"
826                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
827             <label class="cd-col-form-label"
828                    for="privacy_protocol"
829                    i18n>Privacy Protocol</label>
830             <div class="cd-col-form-input">
831               <select id="privacy_protocol"
832                       name="privacy_protocol"
833                       class="form-select"
834                       formControlName="privacy_protocol">
835                 <option i18n
836                         [ngValue]="null">-- Select privacy protocol --</option>
837                 <option *ngFor="let privacyProtocol of ['DES', 'AES']"
838                         [value]="privacyProtocol">
839                   {{ privacyProtocol }}
840                 </option>
841               </select>
842             </div>
843           </div>
844           <!-- Credentials -->
845           <fieldset>
846             <legend i18n>Credentials</legend>
847             <!-- snmp v2c snmp_community -->
848             <div class="form-group row"
849                  *ngIf="serviceForm.controls.snmp_version.value === 'V2c'">
850               <label class="cd-col-form-label required"
851                      for="snmp_community">
852                 <span i18n>SNMP Community</span>
853               </label>
854               <div class="cd-col-form-input">
855                 <input id="snmp_community"
856                        class="form-control"
857                        type="text"
858                        formControlName="snmp_community">
859                 <span class="invalid-feedback"
860                       *ngIf="serviceForm.showError('snmp_community', frm, 'required')"
861                       i18n>This field is required.</span>
862               </div>
863             </div>
864             <!-- snmp v3 auth username -->
865             <div class="form-group row"
866                  *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
867               <label class="cd-col-form-label required"
868                      for="snmp_v3_auth_username">
869                 <span i18n>Username</span>
870               </label>
871               <div class="cd-col-form-input">
872                 <input id="snmp_v3_auth_username"
873                        class="form-control"
874                        type="text"
875                        formControlName="snmp_v3_auth_username">
876                 <span class="invalid-feedback"
877                       *ngIf="serviceForm.showError('snmp_v3_auth_username', frm, 'required')"
878                       i18n>This field is required.</span>
879               </div>
880             </div>
881             <!-- snmp v3 auth password -->
882             <div class="form-group row"
883                  *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
884               <label class="cd-col-form-label required"
885                      for="snmp_v3_auth_password">
886                 <span i18n>Password</span>
887               </label>
888               <div class="cd-col-form-input">
889                 <input id="snmp_v3_auth_password"
890                        class="form-control"
891                        type="password"
892                        formControlName="snmp_v3_auth_password">
893                 <span class="invalid-feedback"
894                       *ngIf="serviceForm.showError('snmp_v3_auth_password', frm, 'required')"
895                       i18n>This field is required.</span>
896               </div>
897             </div>
898             <!-- snmp v3 priv password -->
899             <div class="form-group row"
900                  *ngIf="serviceForm.controls.snmp_version.value === 'V3' && serviceForm.controls.privacy_protocol.value !== null && serviceForm.controls.privacy_protocol.value !== undefined">
901               <label class="cd-col-form-label required"
902                      for="snmp_v3_priv_password">
903                 <span i18n>Encryption</span>
904               </label>
905               <div class="cd-col-form-input">
906                 <input id="snmp_v3_priv_password"
907                        class="form-control"
908                        type="password"
909                        formControlName="snmp_v3_priv_password">
910                 <span class="invalid-feedback"
911                       *ngIf="serviceForm.showError('snmp_v3_priv_password', frm, 'required')"
912                       i18n>This field is required.</span>
913               </div>
914             </div>
915           </fieldset>
916         </ng-container>
917
918         <!-- oauth2-proxy -->
919         <ng-container *ngIf="serviceForm.controls.service_type.value === 'oauth2-proxy'">
920           <!-- provider_display_name -->
921           <div class="form-group row">
922             <label class="cd-col-form-label required"
923                    for="provider_display_name">
924               <span i18n>Provider display name</span>
925             </label>
926             <div class="cd-col-form-input">
927               <input id="provider_display_name"
928                      class="form-control"
929                      type="text"
930                      formControlName="provider_display_name"
931                      placeholder="My OIDC Provider"
932                      i18n-placeholder>
933               <cd-help-text i18n>The display name for the identity provider (IdP) in the UI.</cd-help-text>
934               <span class="invalid-feedback"
935                     *ngIf="serviceForm.showError('provider_display_name', frm, 'required')"
936                     i18n>This field is required.</span>
937             </div>
938           </div>
939           <!-- client_id -->
940           <div class="form-group row">
941             <label class="cd-col-form-label required"
942                    for="client_id">
943               <span i18n>Client ID</span>
944             </label>
945             <div class="cd-col-form-input">
946               <input id="client_id"
947                      class="form-control"
948                      type="text"
949                      formControlName="client_id"
950                      placeholder="oauth2-client">
951               <cd-help-text i18n>The client ID for authenticating with the IdP.</cd-help-text>
952               <span class="invalid-feedback"
953                     *ngIf="serviceForm.showError('client_id', frm, 'required')"
954                     i18n>This field is required.</span>
955             </div>
956           </div>
957           <!-- client_secret -->
958           <div class="form-group row">
959             <label class="cd-col-form-label required"
960                    for="client_secret">
961               <span i18n>Client secret</span>
962             </label>
963             <div class="cd-col-form-input">
964               <div class="input-group">
965                 <input id="client_secret"
966                        class="form-control"
967                        type="password"
968                        formControlName="client_secret">
969                 <span class="input-group-append">
970                   <button type="button"
971                           class="btn btn-light"
972                           cdPasswordButton="client_secret">
973                   </button>
974                   <cd-copy-2-clipboard-button source="client_secret">
975                   </cd-copy-2-clipboard-button>
976                 </span>
977               </div>
978               <cd-help-text i18n>The client secret for authenticating with the IdP.</cd-help-text>
979               <span class="invalid-feedback"
980                     *ngIf="serviceForm.showError('client_secret', frm, 'required')"
981                     i18n>This field is required.</span>
982             </div>
983           </div>
984           <!-- oidc_issuer_url -->
985           <div class="form-group row">
986             <label class="cd-col-form-label required"
987                    for="oidc_issuer_url">
988               <span i18n>OIDC Issuer URL</span>
989             </label>
990             <div class="cd-col-form-input">
991               <input id="oidc_issuer_url"
992                      class="form-control"
993                      type="text"
994                      formControlName="oidc_issuer_url"
995                      placeholder="https://<IdPs-domain>/realms/<realm-name>">
996               <cd-help-text i18n>The URL of the OpenID Connect (OIDC) issuer.</cd-help-text>
997               <span class="invalid-feedback"
998                     *ngIf="serviceForm.showError('oidc_issuer_url', frm, 'required')"
999                     i18n>This field is required.</span>
1000               <span class="invalid-feedback"
1001                     *ngIf="serviceForm.showError('oidc_issuer_url', frm, 'validUrl')"
1002                     i18n>Invalid url.</span>
1003             </div>
1004           </div>
1005           <!-- https_address -->
1006           <div class="form-group row">
1007             <label class="cd-col-form-label"
1008                    for="https_address">
1009               <span i18n>Https address</span>
1010             </label>
1011             <div class="cd-col-form-input">
1012               <input id="https_address"
1013                      class="form-control"
1014                      type="text"
1015                      formControlName="https_address"
1016                      placeholder="0.0.0.0:4180">
1017               <cd-help-text i18n>The address for HTTPS connections as [IP|Hostname]:port.</cd-help-text>
1018               <span class="invalid-feedback"
1019                     *ngIf="serviceForm.showError('https_address', frm, 'invalidAddress')"
1020                     i18n>Format must be [IP|Hostname]:port and the port between 0 and 65535</span>
1021             </div>
1022           </div>
1023           <!-- redirect_url -->
1024           <div class="form-group row">
1025             <label class="cd-col-form-label"
1026                    for="redirect_url">
1027               <span i18n>Redirect URL</span>
1028             </label>
1029             <div class="cd-col-form-input">
1030               <input id="redirect_url"
1031                      class="form-control"
1032                      type="text"
1033                      formControlName="redirect_url"
1034                      placeholder="https://<IP|Hostname>:4180/oauth2/callback">
1035               <cd-help-text i18n>The URL the oauth2-proxy service will redirect to after a successful login.</cd-help-text>
1036             </div>
1037           </div>
1038           <!-- Allowlist_domains -->
1039           <div class="form-group row">
1040             <label class="cd-col-form-label"
1041                    for="allowlist_domains">
1042               <span i18n>Allowlist domains</span>
1043             </label>
1044             <div class="cd-col-form-input">
1045               <input id="allowlist_domains"
1046                      class="form-control"
1047                      type="text"
1048                      formControlName="allowlist_domains"
1049                      placeholder="domain1.com,192.168.100.1:8080">
1050               <cd-help-text i18n>Comma separated list of domains to be allowed to redirect to, used for login or logout.</cd-help-text>
1051             </div>
1052           </div>
1053         </ng-container>
1054
1055         <!-- RGW, Ingress, iSCSI & Oauth2-proxy -->
1056         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && ['rgw', 'iscsi', 'ingress', 'oauth2-proxy'].includes(serviceForm.controls.service_type.value)">
1057           <!-- ssl -->
1058           <div class="form-group row">
1059             <div class="cd-col-form-offset">
1060               <div class="custom-control custom-checkbox">
1061                 <input class="custom-control-input"
1062                        id="ssl"
1063                        type="checkbox"
1064                        formControlName="ssl">
1065                 <label class="custom-control-label"
1066                        for="ssl"
1067                        i18n>SSL</label>
1068               </div>
1069             </div>
1070           </div>
1071
1072           <!-- ssl_cert -->
1073           <div *ngIf="serviceForm.controls.ssl.value"
1074                class="form-group row">
1075             <label class="cd-col-form-label"
1076                    for="ssl_cert">
1077               <span i18n>Certificate</span>
1078               <cd-helper i18n>The SSL certificate in PEM format.</cd-helper>
1079             </label>
1080             <div class="cd-col-form-input">
1081               <textarea id="ssl_cert"
1082                         class="form-control resize-vertical text-monospace text-pre"
1083                         formControlName="ssl_cert"
1084                         rows="5">
1085               </textarea>
1086               <input type="file"
1087                      (change)="fileUpload($event.target.files, 'ssl_cert')">
1088               <span class="invalid-feedback"
1089                     *ngIf="serviceForm.showError('ssl_cert', frm, 'required')"
1090                     i18n>This field is required.</span>
1091               <span class="invalid-feedback"
1092                     *ngIf="serviceForm.showError('ssl_cert', frm, 'pattern')"
1093                     i18n>Invalid SSL certificate.</span>
1094             </div>
1095           </div>
1096
1097           <!-- ssl_key -->
1098           <div *ngIf="serviceForm.controls.ssl.value && !(['rgw', 'ingress'].includes(serviceForm.controls.service_type.value))"
1099                class="form-group row">
1100             <label class="cd-col-form-label"
1101                    for="ssl_key">
1102               <span i18n>Private key</span>
1103               <cd-helper i18n>The SSL private key in PEM format.</cd-helper>
1104             </label>
1105             <div class="cd-col-form-input">
1106               <textarea id="ssl_key"
1107                         class="form-control resize-vertical text-monospace text-pre"
1108                         formControlName="ssl_key"
1109                         rows="5">
1110               </textarea>
1111               <input type="file"
1112                      (change)="fileUpload($event.target.files,'ssl_key')">
1113               <span class="invalid-feedback"
1114                     *ngIf="serviceForm.showError('ssl_key', frm, 'required')"
1115                     i18n>This field is required.</span>
1116               <span class="invalid-feedback"
1117                     *ngIf="serviceForm.showError('ssl_key', frm, 'pattern')"
1118                     i18n>Invalid SSL private key.</span>
1119             </div>
1120           </div>
1121         </ng-container>
1122         <!-- Grafana -->
1123         <ng-container *ngIf="serviceForm.controls.service_type.value === 'grafana'">
1124           <div class="form-group row">
1125             <label class="cd-col-form-label"
1126                    for="grafana_port">
1127               <span i18n>Grafana Port</span>
1128               <cd-helper>
1129                 <span i18n>The default port used by grafana.</span>
1130               </cd-helper>
1131             </label>
1132             <div class="cd-col-form-input">
1133               <input id="grafana_port"
1134                      class="form-control"
1135                      type="number"
1136                      formControlName="grafana_port"
1137                      min="1"
1138                      max="65535">
1139               <span class="invalid-feedback"
1140                     *ngIf="serviceForm.showError('grafana_port', frm, 'pattern')"
1141                     i18n>The entered value needs to be a number.</span>
1142               <span class="invalid-feedback"
1143                     *ngIf="serviceForm.showError('grafana_port', frm, 'min')"
1144                     i18n>The value must be at least 1.</span>
1145               <span class="invalid-feedback"
1146                     *ngIf="serviceForm.showError('grafana_port', frm, 'max')"
1147                     i18n>The value cannot exceed 65535.</span>
1148               <span class="invalid-feedback"
1149                     *ngIf="serviceForm.showError('grafana_port', frm, 'required')"
1150                     i18n>This field is required.</span>
1151             </div>
1152           </div>
1153
1154           <div class="form-group row">
1155             <label i18n
1156                    class="cd-col-form-label"
1157                    for="grafana_admin_password">
1158               <span>Grafana Password</span>
1159               <cd-helper>The password of the default Grafana Admin. Set once on first-run.</cd-helper>
1160             </label>
1161             <div class="cd-col-form-input">
1162               <div class="input-group">
1163                 <input id="grafana_admin_password"
1164                        class="form-control"
1165                        type="password"
1166                        autocomplete="new-password"
1167                        [attr.disabled]="editing ? true:null"
1168                        formControlName="grafana_admin_password">
1169                 <span class="input-group-append">
1170                   <button type="button"
1171                           class="btn btn-light"
1172                           cdPasswordButton="grafana_admin_password">
1173                   </button>
1174                   <cd-copy-2-clipboard-button source="grafana_admin_password">
1175                   </cd-copy-2-clipboard-button>
1176                 </span>
1177               </div>
1178             </div>
1179           </div>
1180         </ng-container>
1181       </div>
1182
1183       <div class="modal-footer">
1184         <div class="text-right">
1185           <cd-form-button-panel (submitActionEvent)="onSubmit()"
1186                                 [form]="serviceForm"
1187                                 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"></cd-form-button-panel>
1188         </div>
1189       </div>
1190     </form>
1191   </ng-container>
1192 </cd-modal>