-
Notifications
You must be signed in to change notification settings - Fork 907
/
entities.go
1544 lines (1367 loc) · 62.3 KB
/
entities.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package cluster
import (
"context"
"database/sql"
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
"github.com/canonical/lxd/lxd/instance/instancetype"
"github.com/canonical/lxd/shared"
"github.com/canonical/lxd/shared/api"
"github.com/canonical/lxd/shared/entity"
)
// EntityType is a database representation of an entity type.
//
// EntityType is defined on string so that entity.Type constants can be converted by casting. The sql.Scanner and
// driver.Valuer interfaces are implemented on this type such that the string constants are converted into their int64
// counterparts as they are written to the database, or converted back into an EntityType as they are read from the
// database. It is not possible to read/write invalid entity types from/to the database when using this type.
type EntityType string
const (
entityTypeNone int64 = -1
entityTypeContainer int64 = 0
entityTypeImage int64 = 1
entityTypeProfile int64 = 2
entityTypeProject int64 = 3
entityTypeCertificate int64 = 4
entityTypeInstance int64 = 5
entityTypeInstanceBackup int64 = 6
entityTypeInstanceSnapshot int64 = 7
entityTypeNetwork int64 = 8
entityTypeNetworkACL int64 = 9
entityTypeNode int64 = 10
entityTypeOperation int64 = 11
entityTypeStoragePool int64 = 12
entityTypeStorageVolume int64 = 13
entityTypeStorageVolumeBackup int64 = 14
entityTypeStorageVolumeSnapshot int64 = 15
entityTypeWarning int64 = 16
entityTypeClusterGroup int64 = 17
entityTypeStorageBucket int64 = 18
entityTypeNetworkZone int64 = 19
entityTypeImageAlias int64 = 20
entityTypeServer int64 = 21
entityTypeAuthGroup int64 = 22
entityTypeIdentityProviderGroup int64 = 23
entityTypeIdentity int64 = 24
)
// Scan implements sql.Scanner for EntityType. This converts the integer value back into the correct entity.Type
// constant or returns an error.
func (e *EntityType) Scan(value any) error {
// Always expect null values to be coalesced into entityTypeNone (-1).
if value == nil {
return fmt.Errorf("Entity type cannot be null")
}
intValue, err := driver.Int32.ConvertValue(value)
if err != nil {
return fmt.Errorf("Invalid entity type `%v`: %w", value, err)
}
entityTypeInt, ok := intValue.(int64)
if !ok {
return fmt.Errorf("Entity should be an integer, got `%v` (%T)", intValue, intValue)
}
switch entityTypeInt {
case entityTypeNone:
*e = ""
case entityTypeContainer:
*e = EntityType(entity.TypeContainer)
case entityTypeImage:
*e = EntityType(entity.TypeImage)
case entityTypeProfile:
*e = EntityType(entity.TypeProfile)
case entityTypeProject:
*e = EntityType(entity.TypeProject)
case entityTypeCertificate:
*e = EntityType(entity.TypeCertificate)
case entityTypeInstance:
*e = EntityType(entity.TypeInstance)
case entityTypeInstanceBackup:
*e = EntityType(entity.TypeInstanceBackup)
case entityTypeInstanceSnapshot:
*e = EntityType(entity.TypeInstanceSnapshot)
case entityTypeNetwork:
*e = EntityType(entity.TypeNetwork)
case entityTypeNetworkACL:
*e = EntityType(entity.TypeNetworkACL)
case entityTypeNode:
*e = EntityType(entity.TypeNode)
case entityTypeOperation:
*e = EntityType(entity.TypeOperation)
case entityTypeStoragePool:
*e = EntityType(entity.TypeStoragePool)
case entityTypeStorageVolume:
*e = EntityType(entity.TypeStorageVolume)
case entityTypeStorageVolumeBackup:
*e = EntityType(entity.TypeStorageVolumeBackup)
case entityTypeStorageVolumeSnapshot:
*e = EntityType(entity.TypeStorageVolumeSnapshot)
case entityTypeWarning:
*e = EntityType(entity.TypeWarning)
case entityTypeClusterGroup:
*e = EntityType(entity.TypeClusterGroup)
case entityTypeStorageBucket:
*e = EntityType(entity.TypeStorageBucket)
case entityTypeNetworkZone:
*e = EntityType(entity.TypeNetworkZone)
case entityTypeImageAlias:
*e = EntityType(entity.TypeImageAlias)
case entityTypeServer:
*e = EntityType(entity.TypeServer)
case entityTypeAuthGroup:
*e = EntityType(entity.TypeAuthGroup)
case entityTypeIdentityProviderGroup:
*e = EntityType(entity.TypeIdentityProviderGroup)
case entityTypeIdentity:
*e = EntityType(entity.TypeIdentity)
default:
return fmt.Errorf("Unknown entity type %d", entityTypeInt)
}
return nil
}
// Value implements driver.Valuer for EntityType. This converts the EntityType into an integer or throws an error.
func (e EntityType) Value() (driver.Value, error) {
switch e {
case "":
return entityTypeNone, nil
case EntityType(entity.TypeContainer):
return entityTypeContainer, nil
case EntityType(entity.TypeImage):
return entityTypeImage, nil
case EntityType(entity.TypeProfile):
return entityTypeProfile, nil
case EntityType(entity.TypeProject):
return entityTypeProject, nil
case EntityType(entity.TypeCertificate):
return entityTypeCertificate, nil
case EntityType(entity.TypeInstance):
return entityTypeInstance, nil
case EntityType(entity.TypeInstanceBackup):
return entityTypeInstanceBackup, nil
case EntityType(entity.TypeInstanceSnapshot):
return entityTypeInstanceSnapshot, nil
case EntityType(entity.TypeNetwork):
return entityTypeNetwork, nil
case EntityType(entity.TypeNetworkACL):
return entityTypeNetworkACL, nil
case EntityType(entity.TypeNode):
return entityTypeNode, nil
case EntityType(entity.TypeOperation):
return entityTypeOperation, nil
case EntityType(entity.TypeStoragePool):
return entityTypeStoragePool, nil
case EntityType(entity.TypeStorageVolume):
return entityTypeStorageVolume, nil
case EntityType(entity.TypeStorageVolumeBackup):
return entityTypeStorageVolumeBackup, nil
case EntityType(entity.TypeStorageVolumeSnapshot):
return entityTypeStorageVolumeSnapshot, nil
case EntityType(entity.TypeWarning):
return entityTypeWarning, nil
case EntityType(entity.TypeClusterGroup):
return entityTypeClusterGroup, nil
case EntityType(entity.TypeStorageBucket):
return entityTypeStorageBucket, nil
case EntityType(entity.TypeNetworkZone):
return entityTypeNetworkZone, nil
case EntityType(entity.TypeImageAlias):
return entityTypeImageAlias, nil
case EntityType(entity.TypeServer):
return entityTypeServer, nil
case EntityType(entity.TypeAuthGroup):
return entityTypeAuthGroup, nil
case EntityType(entity.TypeIdentityProviderGroup):
return entityTypeIdentityProviderGroup, nil
case EntityType(entity.TypeIdentity):
return entityTypeIdentity, nil
default:
return nil, fmt.Errorf("Unknown entity type %q", e)
}
}
/*
The following queries return the information required for generating a unique URL of an entity in a common format.
Each row returned by all of these queries has the following format:
1. Entity type. Including the entity type in the result allows for querying multiple entity types at once by performing
a UNION of two or more queries.
2. Entity ID. The caller will likely have an entity type and an ID that they are trying to get a URL for (see warnings
API/table). In other cases the caller may want to list all URLs of a particular type, so returning the ID along with
the URL allows for subsequent mapping or usage.
3. The project name (empty if the entity is not project specific).
4. The location (target) of the entity. Some entities require this parameter for uniqueness (e.g. storage volumes and buckets).
5. Path arguments that comprise the URL of the entity. These are returned as a JSON array in the order that they appear
in the URL.
*/
// containerEntities returns all entities of type entity.TypeContainer. These are just instance entities with an addition type constraint.
var containerEntities = fmt.Sprintf(`%s WHERE instances.type = %d`, instanceEntities, instancetype.Container)
// containerEntityByID gets the entity of type entity.TypeContainer with a particular ID.
var containerEntityByID = fmt.Sprintf(`%s AND instances.type = %d`, instanceEntityByID, instancetype.Container)
// containerEntitiesByProjectName returns all entities of type entity.TypeContainer in a particular project.
var containerEntitiesByProjectName = fmt.Sprintf(`%s AND instances.type = %d`, instanceEntitiesByProjectName, instancetype.Container)
// imageEntities returns all entities of type entity.TypeImage.
var imageEntities = fmt.Sprintf(`SELECT %d, images.id, projects.name, '', json_array(images.fingerprint) FROM images JOIN projects ON images.project_id = projects.id`, entityTypeImage)
// imageEntities gets the entity of type entity.TypeImage with a particular ID.
var imageEntityByID = fmt.Sprintf(`%s WHERE images.id = ?`, imageEntities)
// imageEntities returns all entities of type entity.TypeImage in a particular project.
var imageEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, imageEntities)
// profileEntities returns all entities of type entity.TypeProfile.
var profileEntities = fmt.Sprintf(`SELECT %d, profiles.id, projects.name, '', json_array(profiles.name) FROM profiles JOIN projects ON profiles.project_id = projects.id`, entityTypeProfile)
// profileEntities gets the entity of type entity.TypeProfile with a particular ID.
var profileEntityByID = fmt.Sprintf(`%s WHERE profiles.id = ?`, profileEntities)
// profileEntities returns all entities of type entity.TypeProfile in a particular project.
var profileEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, profileEntities)
// projectEntities returns all entities of type entity.TypeProject.
var projectEntities = fmt.Sprintf(`SELECT %d, projects.id, '', '', json_array(projects.name) FROM projects`, entityTypeProject)
// projectEntities gets the entity of type entity.TypeProject with a particular ID.
var projectEntityByID = fmt.Sprintf(`%s WHERE id = ?`, projectEntities)
// certificateEntities returns all entities of type entity.TypeCertificate.
var certificateEntities = fmt.Sprintf(`SELECT %d, identities.id, '', '', json_array(identities.identifier) FROM identities WHERE auth_method = %d`, entityTypeCertificate, authMethodTLS)
// certificateEntities gets the entity of type entity.TypeCertificate with a particular ID.
var certificateEntityByID = fmt.Sprintf(`%s AND identities.id = ?`, certificateEntities)
// instanceEntities returns all entities of type entity.TypeInstance.
var instanceEntities = fmt.Sprintf(`SELECT %d, instances.id, projects.name, '', json_array(instances.name) FROM instances JOIN projects ON instances.project_id = projects.id`, entityTypeInstance)
// instanceEntities gets the entity of type entity.TypeInstance with a particular ID.
var instanceEntityByID = fmt.Sprintf(`%s WHERE instances.id = ?`, instanceEntities)
// instanceEntities returns all entities of type entity.TypeInstance in a particular project.
var instanceEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, instanceEntities)
// instanceBackupEntities returns all entities of type entity.TypeInstanceBackup.
var instanceBackupEntities = fmt.Sprintf(`SELECT %d, instances_backups.id, projects.name, '', json_array(instances.name, instances_backups.name) FROM instances_backups JOIN instances ON instances_backups.instance_id = instances.id JOIN projects ON instances.project_id = projects.id`, entityTypeInstanceBackup)
// instanceBackupEntities gets the entity of type entity.TypeInstanceBackup with a particular ID.
var instanceBackupEntityByID = fmt.Sprintf(`%s WHERE instances_backups.id = ?`, instanceBackupEntities)
// instanceBackupEntities returns all entities of type entity.TypeInstanceBackup in a particular project.
var instanceBackupEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, instanceBackupEntities)
// instanceSnapshotEntities returns all entities of type entity.TypeInstanceSnapshot.
var instanceSnapshotEntities = fmt.Sprintf(`SELECT %d, instances_snapshots.id, projects.name, '', json_array(instances.name, instances_snapshots.name) FROM instances_snapshots JOIN instances ON instances_snapshots.instance_id = instances.id JOIN projects ON instances.project_id = projects.id`, entityTypeInstanceBackup)
// instanceSnapshotEntities gets the entity of type entity.TypeInstanceSnapshot with a particular ID.
var instanceSnapshotEntityByID = fmt.Sprintf(`%s WHERE instances_snapshots.id = ?`, instanceSnapshotEntities)
// instanceSnapshotEntities returns all entities of type entity.TypeInstanceSnapshot in a particular project.
var instanceSnapshotEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, instanceSnapshotEntities)
// networkEntities returns all entities of type entity.TypeNetwork.
var networkEntities = fmt.Sprintf(`SELECT %d, networks.id, projects.name, '', json_array(networks.name) FROM networks JOIN projects ON networks.project_id = projects.id`, entityTypeNetwork)
// networkEntities gets the entity of type entity.TypeNetwork with a particular ID.
var networkEntityByID = fmt.Sprintf(`%s WHERE networks.id = ?`, networkEntities)
// networkEntities returns all entities of type entity.TypeNetwork in a particular project.
var networkEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, networkEntities)
// networkACLEntities returns all entities of type entity.TypeNetworkACL.
var networkACLEntities = fmt.Sprintf(`SELECT %d, networks_acls.id, projects.name, '', json_array(networks_acls.name) FROM networks_acls JOIN projects ON networks_acls.project_id = projects.id`, entityTypeNetworkACL)
// networkACLEntities gets the entity of type entity.TypeNetworkACL with a particular ID.
var networkACLEntityByID = fmt.Sprintf(`%s WHERE networks_acls.id = ?`, networkACLEntities)
// networkACLEntities returns all entities of type entity.TypeNetworkACL in a particular project.
var networkACLEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, networkACLEntities)
// networkZoneEntities returns all entities of type entity.TypeNetworkZone.
var networkZoneEntities = fmt.Sprintf(`SELECT %d, networks_zones.id, projects.name, '', json_array(networks_zones.name) FROM networks_zones JOIN projects ON networks_zones.project_id = projects.id`, entityTypeNetworkZone)
// networkZoneEntityByID gets the entity of type entity.TypeNetworkZone with a particular ID.
var networkZoneEntityByID = fmt.Sprintf(`%s WHERE networks_zones.id = ?`, networkZoneEntities)
// networkZoneEntitiesByProjectName returns all entities of type entity.TypeNetworkZone in a particular project.
var networkZoneEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, networkZoneEntities)
// imageAliasEntities returns all entities of type entity.TypeImageAlias.
var imageAliasEntities = fmt.Sprintf(`SELECT %d, images_aliases.id, projects.name, '', json_array(images_aliases.name) FROM images_aliases JOIN projects ON images_aliases.project_id = projects.id`, entityTypeImageAlias)
// imageAliasEntityByID gets the entity of type entity.TypeImageAlias with a particular ID.
var imageAliasEntityByID = fmt.Sprintf(`%s WHERE images_aliases.id = ?`, imageAliasEntities)
// imageAliasEntitiesByProjectName returns all the entities of type entity.TypeImageAlias in a particular project.
var imageAliasEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, imageAliasEntities)
// nodeEntities returns all entities of type entity.TypeNode.
var nodeEntities = fmt.Sprintf(`SELECT %d, nodes.id, '', '', json_array(nodes.name) FROM nodes`, entityTypeNode)
// nodeEntities gets the entity of type entity.TypeNode with a particular ID.
var nodeEntityByID = fmt.Sprintf(`%s WHERE nodes.id = ?`, nodeEntities)
// operationEntities returns all entities of type entity.TypeOperation.
var operationEntities = fmt.Sprintf(`SELECT %d, operations.id, coalesce(projects.name, ''), '', json_array(operations.uuid) FROM operations LEFT JOIN projects ON operations.project_id = projects.id`, entityTypeOperation)
// operationEntities gets the entity of type entity.TypeOperation with a particular ID.
var operationEntityByID = fmt.Sprintf(`%s WHERE operations.id = ?`, operationEntities)
// operationEntities returns all entities of type entity.TypeOperation in a particular project.
var operationEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, strings.Replace(operationEntities, "LEFT JOIN projects", "JOIN projects", 1))
// storagePoolEntities returns all entities of type entity.TypeStoragePool.
var storagePoolEntities = fmt.Sprintf(`SELECT %d, storage_pools.id, '', '', json_array(storage_pools.name) FROM storage_pools`, entityTypeStoragePool)
// storagePoolEntities gets the entity of type entity.TypeStoragePool with a particular ID.
var storagePoolEntityByID = fmt.Sprintf(`%s WHERE storage_pools.id = ?`, storagePoolEntities)
// storageVolumeEntities returns all entities of type entity.TypeStorageVolume.
var storageVolumeEntities = fmt.Sprintf(`
SELECT
%d,
storage_volumes.id,
projects.name,
replace(coalesce(nodes.name, ''), 'none', ''),
json_array(
storage_pools.name,
CASE storage_volumes.type
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END,
storage_volumes.name
)
FROM storage_volumes
JOIN projects ON storage_volumes.project_id = projects.id
JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_volumes.node_id = nodes.id
`,
entityTypeStorageVolume,
StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeNameContainer,
StoragePoolVolumeTypeImage, StoragePoolVolumeTypeNameImage,
StoragePoolVolumeTypeCustom, StoragePoolVolumeTypeNameCustom,
StoragePoolVolumeTypeVM, StoragePoolVolumeTypeNameVM,
)
// storageVolumeEntities gets the entity of type entity.TypeStorageVolume with a particular ID.
var storageVolumeEntityByID = fmt.Sprintf(`%s WHERE storage_volumes.id = ?`, storageVolumeEntities)
// storageVolumeEntities returns all entities of type entity.TypeStorageVolume in a particular project.
var storageVolumeEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, storageVolumeEntities)
// storageVolumeBackupEntities returns all entities of type entity.TypeStorageVolumeBackup.
var storageVolumeBackupEntities = fmt.Sprintf(`
SELECT
%d,
storage_volumes_backups.id,
projects.name,
replace(coalesce(nodes.name, ''), 'none', ''),
json_array(
storage_pools.name,
CASE storage_volumes.type
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END,
storage_volumes.name,
storage_volumes_backups.name
)
FROM storage_volumes_backups
JOIN storage_volumes ON storage_volumes_backups.storage_volume_id = storage_volumes.id
JOIN projects ON storage_volumes.project_id = projects.id
JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_volumes.node_id = nodes.id
`,
entityTypeStorageVolumeBackup,
StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeNameContainer,
StoragePoolVolumeTypeImage, StoragePoolVolumeTypeNameImage,
StoragePoolVolumeTypeCustom, StoragePoolVolumeTypeNameCustom,
StoragePoolVolumeTypeVM, StoragePoolVolumeTypeNameVM,
)
// storageVolumeBackupEntities gets the entity of type entity.TypeStorageVolumeBackup with a particular ID.
var storageVolumeBackupEntityByID = fmt.Sprintf(`%s WHERE storage_volumes_backups.id = ?`, storageVolumeBackupEntities)
// storageVolumeBackupEntities returns all entities of type entity.TypeStorageVolumeBackup in a particular project.
var storageVolumeBackupEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, storageVolumeBackupEntities)
// storageVolumeSnapshotEntities returns all entities of type entity.TypeStorageVolumeSnapshot.
var storageVolumeSnapshotEntities = fmt.Sprintf(`
SELECT
%d,
storage_volumes_snapshots.id,
projects.name,
replace(coalesce(nodes.name, ''), 'none', ''),
json_array(
storage_pools.name,
CASE storage_volumes.type
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END,
storage_volumes.name,
storage_volumes_snapshots.name
)
FROM storage_volumes_snapshots
JOIN storage_volumes ON storage_volumes_snapshots.storage_volume_id = storage_volumes.id
JOIN projects ON storage_volumes.project_id = projects.id
JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_volumes.node_id = nodes.id
`,
entityTypeStorageVolumeSnapshot,
StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeNameContainer,
StoragePoolVolumeTypeImage, StoragePoolVolumeTypeNameImage,
StoragePoolVolumeTypeCustom, StoragePoolVolumeTypeNameCustom,
StoragePoolVolumeTypeVM, StoragePoolVolumeTypeNameVM,
)
// storageVolumeSnapshotEntities gets the entity of type entity.TypeStorageVolumeSnapshot with a particular ID.
var storageVolumeSnapshotEntityByID = fmt.Sprintf(`%s WHERE storage_volumes_snapshots.id = ?`, storageVolumeSnapshotEntities)
// storageVolumeSnapshotEntities returns all entities of type entity.TypeStorageVolumeSnapshot in a particular project.
var storageVolumeSnapshotEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, storageVolumeSnapshotEntities)
// warningEntities returns all entities of type entity.TypeWarning.
var warningEntities = fmt.Sprintf(`SELECT %d, warnings.id, coalesce(projects.name, ''), replace(coalesce(nodes.name, ''), 'none', ''), json_array(warnings.uuid) FROM warnings LEFT JOIN projects ON warnings.project_id = projects.id LEFT JOIN nodes ON warnings.node_id = nodes.id`, entityTypeWarning)
// warningEntities gets the entity of type entity.TypeWarning with a particular ID.
var warningEntityByID = fmt.Sprintf(`%s WHERE warnings.id = ?`, warningEntities)
// warningEntities returns all entities of type entity.TypeWarning in a particular project.
var warningEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, strings.Replace(warningEntities, "LEFT JOIN projects", "JOIN projects", 1))
// clusterGroupEntities returns all entities of type entity.TypeClusterGroup.
var clusterGroupEntities = fmt.Sprintf(`SELECT %d, cluster_groups.id, '', '', json_array(cluster_groups.name) FROM cluster_groups`, entityTypeClusterGroup)
// clusterGroupEntities gets the entity of type entity.TypeClusterGroup with a particular ID.
var clusterGroupEntityByID = fmt.Sprintf(`%s WHERE cluster_groups.id = ?`, clusterGroupEntities)
// storageBucketEntities returns all entities of type entity.TypeStorageBucket.
var storageBucketEntities = fmt.Sprintf(`
SELECT %d, storage_buckets.id, projects.name, replace(coalesce(nodes.name, ''), 'none', ''), json_array(storage_pools.name, storage_buckets.name)
FROM storage_buckets
JOIN projects ON storage_buckets.project_id = projects.id
JOIN storage_pools ON storage_buckets.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_buckets.node_id = nodes.id
`, entityTypeStorageBucket,
)
// storageBucketEntityByID gets the entity of type entity.TypeStorageBucket with a particular ID.
var storageBucketEntityByID = fmt.Sprintf(`%s WHERE storage_buckets.id = ?`, storageBucketEntities)
// storageBucketEntities returns all entities of type entity.TypeStorageBucket in a particular project.
var storageBucketEntitiesByProjectName = fmt.Sprintf(`%s WHERE projects.name = ?`, storageBucketEntities)
// authGroupEntities returns all entities of type entity.TypeGroup.
var authGroupEntities = fmt.Sprintf(`SELECT %d, auth_groups.id, '', '', json_array(auth_groups.name) FROM auth_groups`, entityTypeAuthGroup)
// authGroupEntityByID gets the entity of type entity.TypeGroup with a particular ID.
var authGroupEntityByID = fmt.Sprintf(`%s WHERE auth_groups.id = ?`, authGroupEntities)
// identityProviderGroupEntities returns all entities of type entity.TypeIdentityProviderGroup.
var identityProviderGroupEntities = fmt.Sprintf(`SELECT %d, identity_provider_groups.id, '', '', json_array(identity_provider_groups.name) FROM identity_provider_groups`, entityTypeIdentityProviderGroup)
// identityProviderGroupByEntityID gets the entity of type entity.TypeIdentityProviderGroup with a particular ID.
var identityProviderGroupEntityByID = fmt.Sprintf(`%s WHERE identity_provider_groups.id = ?`, identityProviderGroupEntities)
// identityEntities returns all entities of type entity.TypeIdentity.
var identityEntities = fmt.Sprintf(`
SELECT
%d,
identities.id,
'',
'',
json_array(
CASE identities.auth_method
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END,
identities.identifier
)
FROM identities
`,
entityTypeIdentity,
authMethodTLS, api.AuthenticationMethodTLS,
authMethodOIDC, api.AuthenticationMethodOIDC,
)
// identityEntityByID gets the entity of type entity.TypeIdentity with a particular ID.
var identityEntityByID = fmt.Sprintf(`%s WHERE identities.id = ?`, identityEntities)
// entityStatementsAll is a map of entity type to the statement which queries for all URL information for entities of that type.
var entityStatementsAll = map[entity.Type]string{
entity.TypeContainer: containerEntities,
entity.TypeImage: imageEntities,
entity.TypeProfile: profileEntities,
entity.TypeProject: projectEntities,
entity.TypeCertificate: certificateEntities,
entity.TypeInstance: instanceEntities,
entity.TypeInstanceBackup: instanceBackupEntities,
entity.TypeInstanceSnapshot: instanceSnapshotEntities,
entity.TypeNetwork: networkEntities,
entity.TypeNetworkACL: networkACLEntities,
entity.TypeNode: nodeEntities,
entity.TypeOperation: operationEntities,
entity.TypeStoragePool: storagePoolEntities,
entity.TypeStorageVolume: storageVolumeEntities,
entity.TypeStorageVolumeBackup: storageVolumeBackupEntities,
entity.TypeStorageVolumeSnapshot: storageVolumeSnapshotEntities,
entity.TypeWarning: warningEntities,
entity.TypeClusterGroup: clusterGroupEntities,
entity.TypeStorageBucket: storageBucketEntities,
entity.TypeImageAlias: imageAliasEntities,
entity.TypeNetworkZone: networkZoneEntities,
entity.TypeAuthGroup: authGroupEntities,
entity.TypeIdentityProviderGroup: identityProviderGroupEntities,
entity.TypeIdentity: identityEntities,
}
// entityStatementsByID is a map of entity type to the statement which queries for all URL information for a single entity of that type with a given ID.
var entityStatementsByID = map[entity.Type]string{
entity.TypeContainer: containerEntityByID,
entity.TypeImage: imageEntityByID,
entity.TypeProfile: profileEntityByID,
entity.TypeProject: projectEntityByID,
entity.TypeCertificate: certificateEntityByID,
entity.TypeInstance: instanceEntityByID,
entity.TypeInstanceBackup: instanceBackupEntityByID,
entity.TypeInstanceSnapshot: instanceSnapshotEntityByID,
entity.TypeNetwork: networkEntityByID,
entity.TypeNetworkACL: networkACLEntityByID,
entity.TypeNode: nodeEntityByID,
entity.TypeOperation: operationEntityByID,
entity.TypeStoragePool: storagePoolEntityByID,
entity.TypeStorageVolume: storageVolumeEntityByID,
entity.TypeStorageVolumeBackup: storageVolumeBackupEntityByID,
entity.TypeStorageVolumeSnapshot: storageVolumeSnapshotEntityByID,
entity.TypeWarning: warningEntityByID,
entity.TypeClusterGroup: clusterGroupEntityByID,
entity.TypeStorageBucket: storageBucketEntityByID,
entity.TypeImageAlias: imageAliasEntityByID,
entity.TypeNetworkZone: networkZoneEntityByID,
entity.TypeAuthGroup: authGroupEntityByID,
entity.TypeIdentityProviderGroup: identityProviderGroupEntityByID,
entity.TypeIdentity: identityEntityByID,
}
// entityStatementsByProjectName is a map of entity type to the statement which queries for all URL information for all entities of that type within a given project.
var entityStatementsByProjectName = map[entity.Type]string{
entity.TypeContainer: containerEntitiesByProjectName,
entity.TypeImage: imageEntitiesByProjectName,
entity.TypeProfile: profileEntitiesByProjectName,
entity.TypeInstance: instanceEntitiesByProjectName,
entity.TypeInstanceBackup: instanceBackupEntitiesByProjectName,
entity.TypeInstanceSnapshot: instanceSnapshotEntitiesByProjectName,
entity.TypeNetwork: networkEntitiesByProjectName,
entity.TypeNetworkACL: networkACLEntitiesByProjectName,
entity.TypeOperation: operationEntitiesByProjectName,
entity.TypeStorageVolume: storageVolumeEntitiesByProjectName,
entity.TypeStorageVolumeBackup: storageVolumeBackupEntitiesByProjectName,
entity.TypeStorageVolumeSnapshot: storageVolumeSnapshotEntitiesByProjectName,
entity.TypeWarning: warningEntitiesByProjectName,
entity.TypeStorageBucket: storageBucketEntitiesByProjectName,
entity.TypeImageAlias: imageAliasEntitiesByProjectName,
entity.TypeNetworkZone: networkZoneEntitiesByProjectName,
}
// EntityRef represents the expected format of entity URL queries.
type EntityRef struct {
EntityType EntityType
EntityID int
ProjectName string
Location string
PathArgs []string
}
// scan accepts a scanning function (e.g. `(*sql.Row).Scan`) and uses it to parse the row and set its fields.
func (e *EntityRef) scan(scan func(dest ...any) error) error {
var pathArgs string
err := scan(&e.EntityType, &e.EntityID, &e.ProjectName, &e.Location, &pathArgs)
if err != nil {
return fmt.Errorf("Failed to scan entity URL: %w", err)
}
err = json.Unmarshal([]byte(pathArgs), &e.PathArgs)
if err != nil {
return fmt.Errorf("Failed to unmarshal entity URL path arguments: %w", err)
}
return nil
}
// getURL is a convenience for generating a URL from the EntityRef.
func (e *EntityRef) getURL() (*api.URL, error) {
u, err := entity.Type(e.EntityType).URL(e.ProjectName, e.Location, e.PathArgs...)
if err != nil {
return nil, fmt.Errorf("Failed to create entity URL: %w", err)
}
return u, nil
}
// GetEntityURL returns the *api.URL of a single entity by its type and ID.
func GetEntityURL(ctx context.Context, tx *sql.Tx, entityType entity.Type, entityID int) (*api.URL, error) {
if entityType == entity.TypeServer {
return entity.ServerURL(), nil
}
stmt, ok := entityStatementsByID[entityType]
if !ok {
return nil, fmt.Errorf("Could not get entity URL: No statement found for entity type %q", entityType)
}
row := tx.QueryRowContext(ctx, stmt, entityID)
entityRef := &EntityRef{}
err := entityRef.scan(row.Scan)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("Failed to scan entity URL: %w", err)
} else if err != nil {
return nil, api.StatusErrorf(http.StatusNotFound, "No entity found with id `%d` and type %q", entityID, entityType)
}
return entityRef.getURL()
}
// GetEntityURLs accepts a project name and a variadic of entity types and returns a map of entity.Type to map of entity ID, to *api.URL.
// This method combines the above queries into a single query using the UNION operator. If no entity types are given, this function will
// return URLs for all entity types. If no project name is given, this function will return URLs for all projects. This may result in
// stupendously large queries, so use with caution!
func GetEntityURLs(ctx context.Context, tx *sql.Tx, projectName string, entityTypes ...entity.Type) (map[entity.Type]map[int]*api.URL, error) { //nolint:unused // This will be used in a forthcoming feature.
var stmts []string
var args []any
result := make(map[entity.Type]map[int]*api.URL)
// If the server entity type is in the list of entity types, or if we are getting all entity types and
// not filtering by project, we need to add a server URL to the result. The entity ID of the server entity type is
// always zero.
if shared.ValueInSlice(entity.TypeServer, entityTypes) || (len(entityTypes) == 0 && projectName == "") {
result[entity.TypeServer] = map[int]*api.URL{0: entity.ServerURL()}
// Return early if there are no other entity types in the list (no queries to execute).
if len(entityTypes) == 1 {
return result, nil
}
}
// Collate all the statements we need.
// If the project is not empty, each statement will need an argument for the project name.
// Additionally, pre-populate the result map as we know the entity types in advance (this is so that we don't have
// to check and assign on each loop iteration when scanning rows).
if len(entityTypes) == 0 && projectName == "" {
for entityType, stmt := range entityStatementsAll {
stmts = append(stmts, stmt)
result[entityType] = make(map[int]*api.URL)
}
} else if len(entityTypes) == 0 && projectName != "" {
for entityType, stmt := range entityStatementsByProjectName {
stmts = append(stmts, stmt)
args = append(args, projectName)
result[entityType] = make(map[int]*api.URL)
}
} else if projectName == "" {
for _, entityType := range entityTypes {
// We've already added the server url to the result.
if entityType == entity.TypeServer {
continue
}
stmt, ok := entityStatementsAll[entityType]
if !ok {
return nil, fmt.Errorf("Could not get entity URLs: No statement found for entity type %q", entityType)
}
stmts = append(stmts, stmt)
result[entityType] = make(map[int]*api.URL)
}
} else {
for _, entityType := range entityTypes {
// We've already added the server url to the result.
if entityType == entity.TypeServer {
continue
}
stmt, ok := entityStatementsByProjectName[entityType]
if !ok {
return nil, fmt.Errorf("Could not get entity URLs: No statement found for entity type %q", entityType)
}
stmts = append(stmts, stmt)
args = append(args, projectName)
result[entityType] = make(map[int]*api.URL)
}
}
// Join into a single statement with UNION and query.
stmt := strings.Join(stmts, " UNION ")
rows, err := tx.QueryContext(ctx, stmt, args...)
if err != nil {
return nil, fmt.Errorf("Failed to perform entity URL query: %w", err)
}
for rows.Next() {
entityRef := &EntityRef{}
err := entityRef.scan(rows.Scan)
if err != nil {
return nil, fmt.Errorf("Failed to scan entity URL: %w", err)
}
u, err := entityRef.getURL()
if err != nil {
return nil, err
}
result[entity.Type(entityRef.EntityType)][entityRef.EntityID] = u
}
return result, nil
}
/*
The following queries return the ID of an entity by the information contained in its unique URL in a common format.
These queries are not used in isolation, they are used together as part of a larger UNION query.
Because of this, all of the below queries expect as arguments the project name, the location, and the path arguments of
the URL.
Some entity types don't require a project name or location, so that's why they explicitly check for an empty project
name or location being passed in.
Additionally, all of the queries accept an index number as their first binding so that the results can be correlated in
the calling function (see PopulateEntityReferencesFromURLs below).
TODO: We could avoid a query snippet per entity by making these snippets support multiple entities for a single entity type.
(e.g. `WHERE projects.name IN (?, ...) AND instances.name IN (?, ...)` we'd need to be very careful!).
*/
// containerIDFromURL gets the ID of a container from its URL.
var containerIDFromURL = fmt.Sprintf(`
SELECT ?, instances.id
FROM instances
JOIN projects ON instances.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND instances.name = ?
AND instances.type = %d
`, instancetype.Container)
// imageIDFromURL gets the ID of an image from its URL.
var imageIDFromURL = `
SELECT ?, images.id
FROM images
JOIN projects ON images.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND images.fingerprint = ?`
// profileIDFromURL gets the ID of a profile from its URL.
var profileIDFromURL = `
SELECT ?, profiles.id
FROM profiles
JOIN projects ON profiles.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND profiles.name = ?`
// projectIDFromURL gets the ID of a project from its URL.
var projectIDFromURL = `
SELECT ?, projects.id
FROM projects
WHERE '' = ?
AND '' = ?
AND projects.name = ?`
// certificateIDFromURL gets the ID of a certificate from its URL.
var certificateIDFromURL = fmt.Sprintf(`
SELECT ?, identities.id
FROM identities
WHERE '' = ?
AND '' = ?
AND identities.identifier = ?
AND identities.auth_method = %d
`, authMethodTLS)
// instanceIDFromURL gets the ID of an instance from its URL.
var instanceIDFromURL = `
SELECT ?, instances.id
FROM instances
JOIN projects ON instances.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND instances.name = ?`
// instanceBackupIDFromURL gets the ID of an instance backup from its URL.
var instanceBackupIDFromURL = `
SELECT ?, instances_backups.id
FROM instances_backups
JOIN instances ON instances_backups.instance_id = instances.id
JOIN projects ON instances.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND instances.name = ?
AND instances_backups.name = ?`
// instanceSnapshotIDFromURL gets the ID of an instance snapshot from its URL.
var instanceSnapshotIDFromURL = `
SELECT ?, instances_snapshots.id
FROM instances_snapshots
JOIN instances ON instances_snapshots.instance_id = instances.id
JOIN projects ON instances.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND instances.name = ?
AND instances_snapshots.name = ?`
// networkIDFromURL gets the ID of a network from its URL.
var networkIDFromURL = `
SELECT ?, networks.id
FROM networks
JOIN projects ON networks.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND networks.name = ?`
// networkACLIDFromURL gets the ID of a network ACL from its URL.
var networkACLIDFromURL = `
SELECT ?, networks_acls.id
FROM networks_acls
JOIN projects ON networks_acls.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND networks_acls.name = ?`
// nodeIDFromURL gets the ID of a node from its URL.
var nodeIDFromURL = `
SELECT ?, nodes.id
FROM nodes
WHERE '' = ?
AND '' = ?
AND nodes.name = ?`
// operationIDFromURL gets the ID of an operation from its URL.
var operationIDFromURL = `
SELECT ?, operations.id
FROM operations
LEFT JOIN projects ON operations.project_id = projects.id
WHERE coalesce(projects.name, '') = ?
AND '' = ?
AND operations.uuid = ?`
// storagePoolIDFromURL gets the ID of a storage pool from its URL.
var storagePoolIDFromURL = `
SELECT ?, storage_pools.id
FROM storage_pools
WHERE '' = ?
AND '' = ?
AND storage_pools.name = ?`
// storageVolumeIDFromURL gets the ID of a storage volume from its URL.
var storageVolumeIDFromURL = fmt.Sprintf(`
SELECT ?, storage_volumes.id
FROM storage_volumes
JOIN projects ON storage_volumes.project_id = projects.id
JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_volumes.node_id = nodes.id
WHERE projects.name = ?
AND replace(coalesce(nodes.name, ''), 'none', '') = ?
AND storage_pools.name = ?
AND CASE storage_volumes.type
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END = ?
AND storage_volumes.name = ?
`, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeNameContainer,
StoragePoolVolumeTypeImage, StoragePoolVolumeTypeNameImage,
StoragePoolVolumeTypeCustom, StoragePoolVolumeTypeNameCustom,
StoragePoolVolumeTypeVM, StoragePoolVolumeTypeNameVM)
// storageVolumeBackupIDFromURL gets the ID of a storageVolumeBackup from its URL.
var storageVolumeBackupIDFromURL = fmt.Sprintf(`
SELECT ?, storage_volumes_backups.id
FROM storage_volumes_backups
JOIN storage_volumes ON storage_volumes_backups.storage_volume_id = storage_volumes.id
JOIN projects ON storage_volumes.project_id = projects.id
JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_volumes.node_id = nodes.id
WHERE projects.name = ?
AND replace(coalesce(nodes.name, ''), 'none', '') = ?
AND storage_pools.name = ?
AND CASE storage_volumes.type
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END = ?
AND storage_volumes.name = ?
AND storage_volumes_backups.name = ?
`, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeNameContainer,
StoragePoolVolumeTypeImage, StoragePoolVolumeTypeNameImage,
StoragePoolVolumeTypeCustom, StoragePoolVolumeTypeNameCustom,
StoragePoolVolumeTypeVM, StoragePoolVolumeTypeNameVM)
// storageVolumeSnapshotIDFromURL gets the ID of a storageVolumeSnapshot from its URL.
var storageVolumeSnapshotIDFromURL = fmt.Sprintf(`
SELECT ?, storage_volumes_snapshots.id
FROM storage_volumes_snapshots
JOIN storage_volumes ON storage_volumes_snapshots.storage_volume_id = storage_volumes.id
JOIN projects ON storage_volumes.project_id = projects.id
JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_volumes.node_id = nodes.id
WHERE projects.name = ?
AND replace(coalesce(nodes.name, ''), 'none', '') = ?
AND storage_pools.name = ?
AND CASE storage_volumes.type
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
WHEN %d THEN '%s'
END = ?
AND storage_volumes.name = ?
AND storage_volumes_snapshots.name = ?
`, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeNameContainer, StoragePoolVolumeTypeImage, StoragePoolVolumeTypeNameImage, StoragePoolVolumeTypeCustom, StoragePoolVolumeTypeNameCustom, StoragePoolVolumeTypeVM, StoragePoolVolumeTypeNameVM)
// warningIDFromURL gets the ID of a warning from its URL.
var warningIDFromURL = `
SELECT ?, warnings.id
FROM warnings
LEFT JOIN projects ON warnings.project_id = projects.id
WHERE coalesce(projects.name, '') = ?
AND '' = ?
AND warnings.uuid = ?`
// clusterGroupIDFromURL gets the ID of a clusterGroup from its URL.
var clusterGroupIDFromURL = `
SELECT ?, cluster_groups.id
FROM cluster_groups
WHERE '' = ?
AND '' = ?
AND cluster_groups.name = ?`
// storageBucketIDFromURL gets the ID of a storageBucket from its URL.
var storageBucketIDFromURL = `
SELECT ?, storage_buckets.id
FROM storage_buckets
JOIN projects ON storage_buckets.project_id = projects.id
JOIN storage_pools ON storage_buckets.storage_pool_id = storage_pools.id
LEFT JOIN nodes ON storage_buckets.node_id = nodes.id
WHERE projects.name = ?
AND replace(coalesce(nodes.name, ''), 'none', '') = ?
AND storage_pools.name = ?
AND storage_buckets.name = ?
`
// networkZoneIDFromURL gets the ID of a networkZone from its URL.
var networkZoneIDFromURL = `
SELECT ?, networks_zones.id
FROM networks_zones
JOIN projects ON networks_zones.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND networks_zones.name = ?`
// imageAliasIDFromURL gets the ID of a imageAlias from its URL.
var imageAliasIDFromURL = `
SELECT ?, images_aliases.id
FROM images_aliases
JOIN projects ON images_aliases.project_id = projects.id
WHERE projects.name = ?
AND '' = ?
AND images_aliases.name = ? `
// authGroupIDFromURL gets the ID of a group from its URL.
var authGroupIDFromURL = `
SELECT ?, auth_groups.id
FROM auth_groups
WHERE '' = ?
AND '' = ?
AND auth_groups.name = ?`
// identityProviderGroupIDFromURL gets the ID of a identityProviderGroup from its URL.
var identityProviderGroupIDFromURL = `
SELECT ?, identity_provider_groups.id
FROM identity_provider_groups
WHERE '' = ?
AND '' = ?
AND identity_provider_groups.name = ?`