ood_core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +60 -0
- data/Rakefile +6 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/ood_core.rb +34 -0
- data/lib/ood_core/acl/adapter.rb +17 -0
- data/lib/ood_core/acl/adapters/group.rb +59 -0
- data/lib/ood_core/acl/factory.rb +41 -0
- data/lib/ood_core/cluster.rb +143 -0
- data/lib/ood_core/clusters.rb +114 -0
- data/lib/ood_core/errors.rb +19 -0
- data/lib/ood_core/job/adapter.rb +89 -0
- data/lib/ood_core/job/adapters/lsf.rb +193 -0
- data/lib/ood_core/job/adapters/lsf/batch.rb +160 -0
- data/lib/ood_core/job/adapters/lsf/helper.rb +26 -0
- data/lib/ood_core/job/adapters/slurm.rb +470 -0
- data/lib/ood_core/job/adapters/torque.rb +274 -0
- data/lib/ood_core/job/factory.rb +41 -0
- data/lib/ood_core/job/info.rb +141 -0
- data/lib/ood_core/job/node_info.rb +47 -0
- data/lib/ood_core/job/node_request.rb +51 -0
- data/lib/ood_core/job/script.rb +235 -0
- data/lib/ood_core/job/status.rb +128 -0
- data/lib/ood_core/refinements/array_extensions.rb +22 -0
- data/lib/ood_core/refinements/hash_extensions.rb +25 -0
- data/lib/ood_core/version.rb +4 -0
- data/ood_core.gemspec +32 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
@@ -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
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -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
|
data/bin/setup
ADDED
data/lib/ood_core.rb
ADDED
@@ -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
|