github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/serializers/volume.js (about) 1 import { set, get } from '@ember/object'; 2 import ApplicationSerializer from './application'; 3 import classic from 'ember-classic-decorator'; 4 import { capitalize } from '@ember/string'; 5 @classic 6 export default class VolumeSerializer extends ApplicationSerializer { 7 attrs = { 8 externalId: 'ExternalID', 9 }; 10 11 embeddedRelationships = ['writeAllocations', 'readAllocations']; 12 13 // Volumes treat Allocations as embedded records. Ember has an 14 // EmbeddedRecords mixin, but it assumes an application is using 15 // the REST serializer and Nomad does not. 16 normalize(typeHash, hash) { 17 hash.NamespaceID = hash.Namespace; 18 19 hash.PlainId = hash.ID; 20 21 // TODO These shouldn't hardcode `csi/` as part of the IDs, 22 // but it is necessary to make the correct find requests and the 23 // payload does not contain the required information to derive 24 // this identifier. 25 hash.ID = JSON.stringify([`csi/${hash.ID}`, hash.NamespaceID || 'default']); 26 hash.PluginID = `csi/${hash.PluginID}`; 27 28 // Populate read/write allocation lists from aggregate allocation list 29 const readAllocs = hash.ReadAllocs || {}; 30 const writeAllocs = hash.WriteAllocs || {}; 31 32 hash.ReadAllocations = []; 33 hash.WriteAllocations = []; 34 35 if (hash.Allocations) { 36 hash.Allocations.forEach(function (alloc) { 37 const id = alloc.ID; 38 if (id in readAllocs) { 39 hash.ReadAllocations.push(alloc); 40 } 41 if (id in writeAllocs) { 42 hash.WriteAllocations.push(alloc); 43 } 44 }); 45 delete hash.Allocations; 46 } 47 48 const normalizedHash = super.normalize(typeHash, hash); 49 return this.extractEmbeddedRecords( 50 this, 51 this.store, 52 typeHash, 53 normalizedHash 54 ); 55 } 56 57 keyForRelationship(attr, relationshipType) { 58 //Embedded relationship attributes don't end in IDs 59 if (this.embeddedRelationships.includes(attr)) return capitalize(attr); 60 return super.keyForRelationship(attr, relationshipType); 61 } 62 63 // Convert the embedded relationship arrays into JSONAPI included records 64 extractEmbeddedRecords(serializer, store, typeHash, partial) { 65 partial.included = partial.included || []; 66 67 this.embeddedRelationships.forEach((embed) => { 68 const relationshipMeta = typeHash.relationshipsByName.get(embed); 69 const relationship = get(partial, `data.relationships.${embed}.data`); 70 71 if (!relationship) return; 72 73 // Create a sidecar relationships array 74 const hasMany = new Array(relationship.length); 75 76 // For each embedded allocation, normalize the allocation JSON according 77 // to the allocation serializer. 78 relationship.forEach((alloc, idx) => { 79 const { data, included } = this.normalizeEmbeddedRelationship( 80 store, 81 relationshipMeta, 82 alloc 83 ); 84 85 // In JSONAPI, embedded records go in the included array. 86 partial.included.push(data); 87 if (included) { 88 partial.included.push(...included); 89 } 90 91 // In JSONAPI, the main payload value is an array of IDs that 92 // map onto the objects in the included array. 93 hasMany[idx] = { id: data.id, type: data.type }; 94 }); 95 96 // Set the JSONAPI relationship value to the sidecar. 97 const relationshipJson = { data: hasMany }; 98 set(partial, `data.relationships.${embed}`, relationshipJson); 99 }); 100 101 return partial; 102 } 103 104 normalizeEmbeddedRelationship(store, relationshipMeta, relationshipHash) { 105 const modelName = relationshipMeta.type; 106 const modelClass = store.modelFor(modelName); 107 const serializer = store.serializerFor(modelName); 108 109 return serializer.normalize(modelClass, relationshipHash, null); 110 } 111 }