ood_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 782152957ec640f1ad747a00996a8f1dd723831e
4
+ data.tar.gz: 46bc4f5f5697cf66af2de7628be05d83c75eb9f7
5
+ SHA512:
6
+ metadata.gz: 37ae31a647021f728f49fc57c4c6c88c194ce14e458dd2c127f2fc6a1de9f3cdd115f9bd0acbf23e4c7f0783ade982a172b1a14e439b06495c719bee4366ece6
7
+ data.tar.gz: 7207ff48dcb977700d2974426eb9e993830c661e17d4db2ab9c020e3b984d07c4afe990763606bca9f169555e0fb397baf580f8d1c4799d5a8eb1488bf7d1738
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ Gemfile.lock
46
+ .ruby-version
47
+ .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,9 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.2
5
+ before_install: gem install bundler -v 1.7.8
6
+ notifications:
7
+ email:
8
+ on_success: never
9
+ on_failure: always
@@ -0,0 +1,5 @@
1
+ ## Unreleased
2
+
3
+ ## 0.0.1 (2017-04-17)
4
+
5
+ Initial release!
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ood_core.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Ohio Supercomputer Center
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ # OodCore
2
+
3
+ [![Build Status](https://travis-ci.org/OSC/ood_core.svg?branch=master)](https://travis-ci.org/OSC/ood_core)
4
+ ![GitHub Release](https://img.shields.io/github/release/osc/ood_core.svg)
5
+ ![GitHub License](https://img.shields.io/github/license/osc/ood_core.svg)
6
+
7
+ Welcome to your new gem! In this directory, you'll find the files you need to
8
+ be able to package up your Ruby library into a gem. Put your Ruby code in the
9
+ file `lib/ood_core`. To experiment with that code, run `bin/console` for an
10
+ interactive prompt.
11
+
12
+ TODO: Delete this and the text above, and describe your gem
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'ood_core'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ ```sh
25
+ bundle
26
+ ```
27
+
28
+ Or install it yourself as:
29
+
30
+ ```sh
31
+ gem install ood_core
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ TODO: Write usage instructions here
37
+
38
+ ## Development
39
+
40
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
41
+ `bundle exec rspec spec` to run the tests. You can also run `bin/console` for
42
+ an interactive prompt that will allow you to experiment.
43
+
44
+ To install this gem onto your local machine, run `bundle exec rake install`. To
45
+ release a new version, update and commit the version number in `version.rb`,
46
+ and then run `bundle exec rake release`, which will create a git tag for the
47
+ version, push git commits and tags, and push the `.gem` file to
48
+ [rubygems.org](https://rubygems.org).
49
+
50
+ ## Contributing
51
+
52
+ Bug reports and pull requests are welcome on GitHub at
53
+ https://github.com/OSC/ood_core.
54
+
55
+
56
+ ## License
57
+
58
+ The gem is available as open source under the terms of the [MIT
59
+ License](http://opensource.org/licenses/MIT).
60
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ood_core"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install --path=vendor/bundle
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,34 @@
1
+ require "ood_core/version"
2
+ require "ood_core/errors"
3
+ require "ood_core/cluster"
4
+ require "ood_core/clusters"
5
+
6
+ # The main namespace for ood_core
7
+ module OodCore
8
+ # A namespace for job access
9
+ module Job
10
+ require "ood_core/job/node_info"
11
+ require "ood_core/job/node_request"
12
+ require "ood_core/job/script"
13
+ require "ood_core/job/info"
14
+ require "ood_core/job/status"
15
+ require "ood_core/job/adapter"
16
+ require "ood_core/job/factory"
17
+
18
+ # A namespace for job adapters
19
+ # @note These are dynamically loaded upon request
20
+ module Adapters
21
+ end
22
+ end
23
+
24
+ # A namespace for acl code
25
+ module Acl
26
+ require "ood_core/acl/adapter"
27
+ require "ood_core/acl/factory"
28
+
29
+ # A namespace for acl adapters
30
+ # @note These are dynamically loaded upon request
31
+ module Adapters
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ require "ood_support"
2
+
3
+ module OodCore
4
+ module Acl
5
+ # A class that handles the permissions for a resource through an ACL
6
+ # @abstract
7
+ class Adapter
8
+ # Whether this ACL allows access for the principle
9
+ # @abstract Subclass is expected to implement {#allow?}
10
+ # @raise [NotImplementedError] if subclass did not define {#allow?}
11
+ # @return [Boolean] whether principle is allowed
12
+ def allow?
13
+ raise NotImplementedError, "subclass did not define #allow?"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,59 @@
1
+ require "ood_core/refinements/hash_extensions"
2
+
3
+ module OodCore
4
+ module Acl
5
+ class Factory
6
+ using Refinements::HashExtensions
7
+
8
+ # Build the group acl adapter from a configuration
9
+ # @param config [#to_h] the configuration for an acl adapter
10
+ # @option config [Array<#to_s>] :groups The list of groups
11
+ # @option config [#to_s] :type ('whitelist') The type of ACL ('whitelist' or 'blacklist')
12
+ def self.build_group(config)
13
+ c = config.to_h.symbolize_keys
14
+
15
+ groups = c.fetch(:groups) { raise ArgumentError, "No groups specified. Missing argument: groups" }.map(&:to_s)
16
+ acl = OodSupport::ACL.new(entries: groups.map { |g| OodSupport::ACLEntry.new principle: g })
17
+
18
+ type = c.fetch(:type, "whitelist").to_s
19
+ if type == "whitelist"
20
+ allow = true
21
+ elsif type == "blacklist"
22
+ allow = false
23
+ else
24
+ raise ArgumentError, "Invalid type specified. Valid types: whitelist, blacklist"
25
+ end
26
+
27
+ Adapters::Group.new(acl: acl, allow: allow)
28
+ end
29
+ end
30
+
31
+ module Adapters
32
+ # An adapter object that describes a group permission ACL
33
+ class Group < Adapter
34
+ using Refinements::HashExtensions
35
+
36
+ # @api private
37
+ # @param opts [#to_h] the options defining this adapter
38
+ # @option opts [OodSupport::ACL] :acl The ACL permission
39
+ # @option opts [Boolean] :allow (true) Whether this ACL allows access
40
+ # @see Factory.build_group
41
+ def initialize(opts)
42
+ o = opts.to_h.symbolize_keys
43
+ @acl = o.fetch(:acl) { raise ArgumentError, "No acl specified. Missing argument: acl" }
44
+ @allow = o.fetch(:allow, true)
45
+ end
46
+
47
+ # Whether this ACL allows the active user access based on their groups
48
+ # @return [Boolean] whether principle is allowed
49
+ def allow?
50
+ if @allow
51
+ OodSupport::User.new.groups.map(&:to_s).any? { |g| @acl.allow?(principle: g) }
52
+ else
53
+ OodSupport::User.new.groups.map(&:to_s).none? { |g| @acl.allow?(principle: g) }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,41 @@
1
+ require "ood_core/refinements/hash_extensions"
2
+
3
+ module OodCore
4
+ module Acl
5
+ # A factory that builds acl adapter objects from a configuration.
6
+ class Factory
7
+ using Refinements::HashExtensions
8
+
9
+ class << self
10
+ # Build an acl adapter from a configuration
11
+ # @param config [#to_h] configuration describing acl adapter
12
+ # @option config [#to_s] :adapter The acl adapter to use
13
+ # @raise [AdapterNotSpecified] if no adapter is specified
14
+ # @raise [AdapterNotFound] if the specified adapter does not exist
15
+ # @return [Acl::Adapter] the acl adapter object
16
+ def build(config)
17
+ c = config.to_h.symbolize_keys
18
+
19
+ adapter = c.fetch(:adapter) { raise AdapterNotSpecified, "acl configuration does not specify adapter" }.to_s
20
+
21
+ path_to_adapter = "ood_core/acl/adapters/#{adapter}"
22
+ begin
23
+ require path_to_adapter
24
+ rescue Gem::LoadError => e
25
+ raise Gem::LoadError, "Specified '#{adapter}' for acl adapter, but the gem is not loaded."
26
+ rescue LoadError => e
27
+ raise LoadError, "Could not load '#{adapter}'. Make sure that the acl adapter in the configuration file is valid."
28
+ end
29
+
30
+ adapter_method = "build_#{adapter}"
31
+
32
+ unless respond_to?(adapter_method)
33
+ raise AdapterNotFound, "acl configuration specifies nonexistent #{adapter} adapter"
34
+ end
35
+
36
+ send(adapter_method, c)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,143 @@
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 [Job::Adapter] the job adapter
72
+ def job_adapter
73
+ Job::Factory.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<Acl::Adapter>] 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| Acl::Factory.build a }
141
+ end
142
+ end
143
+ end