|
| 1 | +require "ostruct" |
| 2 | + |
| 3 | +require "ood_core/refinements/hash_extensions" |
| 4 | + |
| 5 | +module OodCore |
| 6 | + # An object that describes a cluster and its given features that third-party |
| 7 | + # code can take advantage of. |
| 8 | + class Cluster |
| 9 | + using Refinements::HashExtensions |
| 10 | + |
| 11 | + # The unique identifier for a given cluster |
| 12 | + # @return [Symbol] the cluster id |
| 13 | + attr_reader :id |
| 14 | + |
| 15 | + # Metadata configuration providing descriptive information about cluster |
| 16 | + # @return [Hash] the metadata configuration |
| 17 | + attr_reader :metadata_config |
| 18 | + |
| 19 | + # The login configuration used for this cluster |
| 20 | + # @return [Hash] the login configuration |
| 21 | + attr_reader :login_config |
| 22 | + |
| 23 | + # The job adapter configuration used for this cluster |
| 24 | + # @return [Hash] the job configuration |
| 25 | + attr_reader :job_config |
| 26 | + |
| 27 | + # The acls configuration describing the permissions for this cluster |
| 28 | + # @return [Hash] the acls configuration |
| 29 | + attr_reader :acls_config |
| 30 | + |
| 31 | + # @param cluster [#to_h] the cluster object |
| 32 | + # @option cluster [#to_sym] :id The cluster id |
| 33 | + # @option cluster [#to_h] :metadata ({}) The cluster's metadata |
| 34 | + # @option cluster [#to_h] :login ({}) The cluster's SSH host |
| 35 | + # @option cluster [#to_h] :job ({}) The job adapter for this cluster |
| 36 | + # @option cluster [#to_h] :custom ({}) Any custom resources for this cluster |
| 37 | + # @option cluster [Array<#to_h>] :acls ([]) List of ACLs to validate against |
| 38 | + def initialize(cluster) |
| 39 | + c = cluster.to_h.symbolize_keys |
| 40 | + |
| 41 | + # Required options |
| 42 | + @id = c.fetch(:id) { raise ArgumentError, "No id specified. Missing argument: id" }.to_sym |
| 43 | + |
| 44 | + # General options |
| 45 | + @metadata_config = c.fetch(:metadata, {}).to_h.symbolize_keys |
| 46 | + @login_config = c.fetch(:login, {}) .to_h.symbolize_keys |
| 47 | + @job_config = c.fetch(:job, {}) .to_h.symbolize_keys |
| 48 | + @custom_config = c.fetch(:custom, {}) .to_h.symbolize_keys |
| 49 | + @acls_config = c.fetch(:acls, []) .map(&:to_h) |
| 50 | + end |
| 51 | + |
| 52 | + # Metadata that provides extra information about this cluster |
| 53 | + # @return [OpenStruct] the metadata |
| 54 | + def metadata |
| 55 | + OpenStruct.new metadata_config |
| 56 | + end |
| 57 | + |
| 58 | + # The login used for this cluster |
| 59 | + # @return [OpenStruct] the login |
| 60 | + def login |
| 61 | + OpenStruct.new(login_config) |
| 62 | + end |
| 63 | + |
| 64 | + # Whether the login feature is allowed |
| 65 | + # @return [Boolean] is login allowed |
| 66 | + def login_allow? |
| 67 | + allow? && !login.empty? |
| 68 | + end |
| 69 | + |
| 70 | + # Build a job adapter from the job configuration |
| 71 | + # @return [JobAdapters::AbstractAdapter] the job adapter |
| 72 | + def job_adapter |
| 73 | + JobFactory.build(job_config) |
| 74 | + end |
| 75 | + |
| 76 | + # Whether the job feature is allowed based on the ACLs |
| 77 | + # @return [Boolean] is the job feature allowed |
| 78 | + def job_allow? |
| 79 | + allow? && |
| 80 | + !job_config.empty? && |
| 81 | + build_acls(job_config.fetch(:acls, []).map(&:to_h)).all?(&:allow?) |
| 82 | + end |
| 83 | + |
| 84 | + # The configuration for any custom features or resources for this cluster |
| 85 | + # @param feature [#to_sym, nil] the feature or resource |
| 86 | + # @return [Hash] configuration for custom feature or resource |
| 87 | + def custom_config(feature = nil) |
| 88 | + feature ? @custom_config.fetch(feature.to_sym, {}).to_h.symbolize_keys : @custom_config |
| 89 | + end |
| 90 | + |
| 91 | + # Whether the custom feature is allowed based on the ACLs |
| 92 | + # @return [Boolean] is this custom feature allowed |
| 93 | + def custom_allow?(feature) |
| 94 | + allow? && |
| 95 | + !custom_config(feature).empty? && |
| 96 | + build_acls(custom_config(feature).fetch(:acls, []).map(&:to_h)).all?(&:allow?) |
| 97 | + end |
| 98 | + |
| 99 | + # Build the ACL adapters from the ACL list configuration |
| 100 | + # @return [Array<AclAdapters::AbstractAdapter>] the acl adapter list |
| 101 | + def acls |
| 102 | + build_acls acls_config |
| 103 | + end |
| 104 | + |
| 105 | + # Whether this cluster is allowed to be used |
| 106 | + # @return [Boolean] whether cluster is allowed |
| 107 | + def allow? |
| 108 | + acls.all?(&:allow?) |
| 109 | + end |
| 110 | + |
| 111 | + # The comparison operator |
| 112 | + # @param other [#to_sym] object to compare against |
| 113 | + # @return [Boolean] whether objects are equivalent |
| 114 | + def ==(other) |
| 115 | + id == other.to_sym |
| 116 | + end |
| 117 | + |
| 118 | + # Convert object to symbol |
| 119 | + # @return [Symbol] the symbol describing this object |
| 120 | + def to_sym |
| 121 | + id |
| 122 | + end |
| 123 | + |
| 124 | + # Convert object to hash |
| 125 | + # @return [Hash] the hash describing this object |
| 126 | + def to_h |
| 127 | + { |
| 128 | + id: id, |
| 129 | + metadata: metadata_config, |
| 130 | + login: login_config, |
| 131 | + job: job_config, |
| 132 | + custom: custom_config, |
| 133 | + acls: acls_config |
| 134 | + } |
| 135 | + end |
| 136 | + |
| 137 | + private |
| 138 | + # Build acl adapter objects from array |
| 139 | + def build_acls(ary) |
| 140 | + ary.map { |a| AclFactory.build a } |
| 141 | + end |
| 142 | + end |
| 143 | +end |
0 commit comments