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