ood_core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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