ood_appkit 0.2.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a1328957b24d5ff03aaab0577ec558ad693c160
4
- data.tar.gz: 876a61e1e54f9cd39b7b9dc8cf9a10ef7e2084a5
3
+ metadata.gz: b6fbe94cce7c92a5b9ccf234d59a65c42a25af6d
4
+ data.tar.gz: 48b20a943231ce1ddcd150d482a9c84ede36a22d
5
5
  SHA512:
6
- metadata.gz: 12a2d748aaa83712d0124093127f076488004eb84b5512f5eaa86d1ba2a4a739fe46e13c3c2f87285870e4b50199627e8fe5bc885f1ca5986c3ad8f831ba415e
7
- data.tar.gz: 099456dd100204ef4bee14eda20537af1962b3c72ff54f6360ac4979cabc7f939ddc7fa6c69e5bb82d39ece628b883b4ad5a1162d1bae8ead38078bf23d74fd6
6
+ metadata.gz: e2b6601dbd55a03f526802e8c88e9104dbf43939b49fc10c09b649e5d23143d858c5b2520e6b3993f743fe33fdc394f55f0b6582304ce3d28fd45bee0e3355a0
7
+ data.tar.gz: f4052ec287e187c7c7469309c60aa7a40193538cf1b0306bedb0ac9efc7caf23fc42f1a8a1cd0824470d4a596946587f8d70682f7ad9829d4ae72ec18cc32dde
data/README.md CHANGED
@@ -448,119 +448,141 @@ breadcrumbs style will resemble the `navbar-brand` style.
448
448
 
449
449
  ### Cluster Information
450
450
 
451
- A hash of available clusters is accessible from this gem through:
451
+ Access to a list of clusters defined by the system administrator on a given
452
+ host is done through:
452
453
 
453
454
  ```ruby
454
- # Hash of all available clusters
455
- OodAppkit.clusters.all
456
- #=> {
457
- # cluster1: <OodAppkit::Cluster ...>,
458
- # cluster2: <OodAppkit::Cluster ...>,
459
- # ...
460
- # }
461
-
462
- # Hash of all available High Performance Computing (hpc) clusters
463
- OodAppkit.clusters.hpc
464
- #=> {
465
- # cluster1: <OodAppkit::Cluster ...>,
466
- # cluster2: <OodAppkit::Cluster ...>,
467
- # ...
468
- # }
469
-
470
- # Hash of all available Low Performance Computing (hpc) clusters
471
- # NB: A low performance computing cluster expects jobs that request a single
472
- # core and use minimal resources (e.g., a desktop for file browsing/editing,
473
- # a web server that submits jobs to an HPC cluster, visualization software)
474
- OodAppkit.clusters.lpc
475
- #=> {
476
- # cluster3: <OodAppkit::Cluster ...>,
477
- # cluster4: <OodAppkit::Cluster ...>,
478
- # ...
479
- # }
480
- ```
455
+ # An enumerable list of clusters
456
+ OodAppkit.clusters
457
+ #=> #<OodAppkit::Clusters>
481
458
 
482
- Each cluster object will have servers that the developer can communicate with
483
- or link to:
459
+ # Create list of cluster titles
460
+ OodAppkit.clusters.map(&:title)
461
+ #=> ["My Cluster", "Tiny Cluster", "Big Cluster"]
484
462
 
485
- ```ruby
486
- # Choose cluster from available list
487
- my_cluster = OodAppkit.clusters.hpc[:cluster1]
463
+ # Count number of clusters available
464
+ OodAppkit.clusters.count
465
+ #=> 3
488
466
 
489
- # Check if it has a login server
490
- my_cluster.login_server?
467
+ # Check if cluster called "tiny_cluster" exists
468
+ OodAppkit.clusters.include? :tiny_cluster
491
469
  #=> true
470
+ ```
492
471
 
493
- # View all available servers
494
- my_cluster.servers
495
- #=> {
496
- # login: <OodAppkit::Server ...>,
497
- # resource_mgr: <OodAppkit::Servers::Torque ...>,
498
- # scheduler: <OodAppkit::Servers::Moab ...>,
499
- # ...
500
- # }
472
+ You can access a given cluster with id `my_cluster` by:
473
+
474
+ ```ruby
475
+ # Get object describing my HPC center's `my_cluster`
476
+ OodAppkit.clusters[:my_cluster]
477
+ #=> #<OodAppkit::ClusterDecorator>
501
478
 
502
- # Choose a particular server
503
- login_server = my_cluster.login_server
479
+ # or...
480
+ OodAppkit.clusters["my_cluster"]
481
+ #=> #<OodAppkit::ClusterDecorator>
482
+
483
+ # Trying to access a non-existant cluster
484
+ OodAppkit.clusters[:invalid_cluster]
485
+ #=> nil
504
486
  ```
505
487
 
506
- Depending on the type of server chosen, different helper methods will be
507
- available to the developer. For all servers the `host` will be available:
488
+ A cluster object comes with some pre-defined helper methods to help you find
489
+ the cluster that meets your needs:
508
490
 
509
491
  ```ruby
510
- # Choose a particular server
511
- login_server = my_cluster.login_server
492
+ # Get the cluster of our choosing
493
+ my_cluster = OodAppkit.clusters[:my_cluster]
494
+
495
+ # Is this cluster valid (can I the user access the servers provided by it?)
496
+ my_cluster.valid?
497
+ #=> true
498
+
499
+ # Is this cluster considered a High Performance Computing (hpc) cluster?
500
+ # NB: A low performance computing cluster expects jobs that request a single
501
+ # core and use minimal resources (e.g., a desktop for file browsing/editing,
502
+ # a web server that submits jobs to an HPC cluster, visualization software)
503
+ my_cluster.hpc_cluster?
504
+ #=> false
512
505
 
513
- # Get host for this server
514
- login_server.host
515
- #=> "my_cluster.hpc_center.edu"
506
+ # ID of cluster object to find again in OodAppkit.clusters
507
+ my_cluster.id #=> :my_cluster
508
+
509
+ # URL of cluster
510
+ my_cluster.url #=> "https://hpc.center.edu/clusters/my_cluster"
511
+
512
+ # Check if it has a login server
513
+ my_cluster.login_server? #=> true
514
+
515
+ # Access login server object
516
+ my_cluster.login_server
517
+ #=> #<OodCluster::Servers::Ssh>
516
518
  ```
517
519
 
518
- The Torque/Moab servers will also supply information for the clients used to
519
- communicate with the servers
520
+ As this object is an `Enumerable` you can create subsets of clusters that your
521
+ app only cares for in an initializer:
520
522
 
521
523
  ```ruby
522
- # Get the Resource Manager server (known to be Torque at your HPC center)
523
- torque_server = my_cluster.resource_mgr_server
524
+ # I only want clusters that are valid for the currently running user
525
+ valid_clusters = OodAppkit::Clusters.new(
526
+ OodAppkit.clusters.select(&:valid?)
527
+ )
528
+ #=> #<OodAppkit::Clusters>
524
529
 
525
- # Get the path to the client library
526
- torque_server.lib.to_s
527
- #=> "/usr/local/torque/x.x.x/lib"
530
+ # Create list of cluster titles from these valid clusters
531
+ valid_clusters.map(&:title)
532
+ #=> ["My Cluster"]
528
533
 
529
- # Get the path to the client binaries
530
- torque_server.bin.to_s
531
- #=> "/usr/local/torque/x.x.x/bin"
534
+ # I only want HPC clusters that I can submit solver jobs to
535
+ hpc_clusters = OodAppkit::Clusters.new(
536
+ OodAppkit.clusters.select(&:hpc_cluster?)
537
+ )
532
538
  ```
533
539
 
534
- Web servers will have a URI method to access the server
540
+ Depending on the type of server chosen, different helper methods will be
541
+ available to the developer. You can find more details on this at
542
+ https://github.com/OSC/ood_cluster.
543
+
544
+ #### Reservations
545
+
546
+ If reservations are supported for the chosen cluster, then a cluster object can
547
+ be used to query reservation information for the current user:
535
548
 
536
549
  ```ruby
537
- # Get the Ganglia web server
538
- ganglia_server = my_cluster.ganglia_server
550
+ # Check if reservation query object is valid (am I allowed to use it)
551
+ # NB: Definitely use this as some users may be privileged and have access to
552
+ # view ALL reservations. This can cause the app to hang.
553
+ my_cluster.valid?(:rsv_query) #=> true
554
+
555
+ # Get reservation query object
556
+ my_rsv_query = my_cluster.rsv_query
557
+ #=> #<OodReservations::Queries::TorqueMoab>
539
558
 
540
- # Get URI used to access this web server
541
- ganglia_server.uri.to_s
542
- #=> "https://www.ganglia.com/gweb/graph.php?c=MyCluster"
559
+ # Try to get reservation query object from cluster that doesn't support
560
+ # reservations
561
+ cluster_with_no_rsvs.rsv_query
562
+ #=> nil
543
563
 
544
- # To add query values as options for the server
545
- ganglia_server.uri(query_values: {g: 'cpu_report'}).to_s
546
- #=> "https://www.ganglia.com/gweb/graph.php?c=MyCluster&g=cpu_report"
564
+ # Get all reservations I have on this cluster
565
+ my_rsv_query.reservations
566
+ #=> [ #<OodReservations::Reservation>, ... ]
547
567
  ```
548
568
 
549
- The hash of clusters generated by OodAppkit can be modified by supplying a
569
+ You can learn more about the reservation query object by visiting
570
+ https://github.com/OSC/ood_reservations.
571
+
572
+ #### Configuration
573
+
574
+ The list of clusters generated by OodAppkit can be modified by supplying a
550
575
  different config file through the environment variable `OOD_CLUSTERS`
551
576
 
552
- ```
577
+ ```sh
553
578
  OOD_CLUSTERS="/path/to/my/config.yml"
554
579
  ```
555
580
 
556
- or by modifying the configuration in an initializer
557
-
558
- ```ruby
559
- # config/initializers/ood_appkit.rb
581
+ Or a directory with aptly named configuration files (name of file is id of
582
+ cluster):
560
583
 
561
- OodAppkit.configure do |config|
562
- config.clusters.cache = OodAppkit::Cluster.all(file: "/path/to/my/config.yml")
563
- end
584
+ ```sh
585
+ OOD_CLUSTERS="/path/to/configs.d"
564
586
  ```
565
587
 
566
588
  ## Develop
@@ -0,0 +1,53 @@
1
+ require 'ood_cluster'
2
+ require 'ood_reservations'
3
+
4
+ module OodAppkit
5
+ # A decorator that adds a presentation layer to the {OodCluster::Cluster} object
6
+ class ClusterDecorator < SimpleDelegator
7
+ # The identifier used as the key in the OodAppkit clusters hash (used for
8
+ # reverse searching)
9
+ # @return [Symbol] the clusters hash key for this object
10
+ attr_reader :id
11
+
12
+ # The title used to describe this cluster to users
13
+ # @return [String] the cluster title
14
+ attr_reader :title
15
+
16
+ # The URL for this cluster that users can use to view more information
17
+ # @return [String] the cluster url
18
+ attr_reader :url
19
+
20
+ # @param cluster [OodCluster::Cluster] cluster object
21
+ # @param id [#to_sym] id used in clusters hash of OodAppkit
22
+ # @param title [#to_s] title of cluster
23
+ # @param url [#to_s] url of cluster
24
+ # @param validators [Hash{#to_sym=>Array<Validator>}] hash of validators
25
+ def initialize(cluster:, id:, title: "", url: "", validators: {}, **_)
26
+ super(cluster)
27
+ @id = id.to_sym
28
+ @title = title.to_s
29
+ @url = url.to_s
30
+ @validators = validators.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
31
+ end
32
+
33
+ # Whether the given method is valid (i.e., passes all supplied validators)
34
+ # @param method [#to_sym] method to check if valid
35
+ # @return [Boolean] whether this method is valid
36
+ def valid?(method = :cluster)
37
+ @validators.fetch(method.to_sym, []).all? { |v| v.success? }
38
+ end
39
+
40
+ # A reservation query object used to query reservations for current user
41
+ # @return [OodReservations::Query,nil] reservation query object
42
+ def rsv_query
43
+ OodReservations::Query.build(cluster: self)
44
+ end
45
+
46
+ # The comparison operator
47
+ # @param other [#to_sym] object to compare against
48
+ # @return [Boolean] whether objects are equivalent
49
+ def ==(other)
50
+ id == other.to_sym
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,24 @@
1
+ module OodAppkit
2
+ # An enumerable that holds a list of {ClusterDecorator} objects
3
+ class Clusters
4
+ include Enumerable
5
+
6
+ # @param clusters [Array<ClusterDecorator>] list of cluster decorator objects
7
+ def initialize(clusters = [])
8
+ @clusters = clusters
9
+ end
10
+
11
+ # Find object in list from object's id
12
+ # @param id [Object] id of cluster decorator object
13
+ # @return [ClusterDecorator, nil] object if found
14
+ def [](id)
15
+ @clusters.detect { |v| v == id }
16
+ end
17
+
18
+ # Iterate over each of the clusters
19
+ # @yield [obj] cluster decorator objects
20
+ def each(&block)
21
+ @clusters.each(&block)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ require 'yaml'
2
+ require 'json'
3
+
4
+ module OodAppkit
5
+ # Helper methods for parsing/deserializing yml configuration files
6
+ module ConfigParser
7
+ # Specific version hash in the yaml file to parse
8
+ YAML_VERSION = 'v1'
9
+
10
+ # Identifier used to distinguish class names when deserializing
11
+ CLASS_ID = 'type'
12
+
13
+ # Exception raise when unable to access config file or directory
14
+ class InvalidConfigPath < StandardError; end
15
+
16
+ # Parse/deserialize a configuration file or a set of configuration files
17
+ # @param config [#to_s] configuration file or directory
18
+ # @raise [InvalidConfigPath] if config path is inaccessible
19
+ # @return [Hash] hash of deserialized config file
20
+ def self.parse(config:)
21
+ # use 'type' to distinguish class name in yaml file
22
+ JSON.create_id = CLASS_ID
23
+
24
+ config = Pathname.new(config.to_s).expand_path
25
+ if config.file?
26
+ parse_file config
27
+ elsif config.directory?
28
+ config.children.each_with_object({}) do |f, h|
29
+ /^(.+)\.yml$/.match(f.basename.to_s) { h[$1.to_sym] = parse_file(f) }
30
+ end
31
+ else
32
+ raise InvalidConfigPath, "invalid config path: #{config}"
33
+ end
34
+ end
35
+
36
+ private
37
+ # Parse a single yaml file
38
+ def self.parse_file(file)
39
+ JSON.load(JSON.dump(YAML.load(File.read(file.to_s))[YAML_VERSION])).deep_symbolize_keys
40
+ end
41
+ end
42
+ end
@@ -65,22 +65,11 @@ module OodAppkit
65
65
  self.dataroot = ENV['OOD_DATAROOT'] || ENV['RAILS_DATAROOT']
66
66
 
67
67
  # Initialize list of available clusters
68
- # FIXME: use "/etc/ood/config/..." in the future
69
- # FIXME: use `ood_cluster` gem instead in the future
70
- self.clusters = OpenStruct.new(
71
- cache: OodAppkit::Cluster.all(
72
- file: ENV['OOD_CLUSTERS'] || File.expand_path('../../../config/clusters.yml', __FILE__)
73
- )
68
+ self.clusters = Clusters.new(
69
+ ConfigParser.parse(
70
+ config: ENV['OOD_CLUSTERS'] || Pathname.new('/etc/ood/config/clusters.d')
71
+ ).map { |k, v| ClusterDecorator.new(id: k.to_sym, **v) }
74
72
  )
75
- def clusters.all
76
- cache
77
- end
78
- def clusters.hpc
79
- all.select {|k,v| v.hpc_cluster?}
80
- end
81
- def clusters.lpc
82
- all.reject {|k,v| v.hpc_cluster?}
83
- end
84
73
 
85
74
  # Add markdown template support
86
75
  self.markdown = Redcarpet::Markdown.new(
@@ -0,0 +1,25 @@
1
+ module OodAppkit
2
+ class Validator
3
+ # Deserialize a validator object from JSON
4
+ # @param object [Hash{#to_sym=>Object}] hash used defining context
5
+ # @return [self] deserialized object
6
+ def self.json_create(object)
7
+ new object["data"].each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
8
+ end
9
+
10
+ def initialize(**_)
11
+ end
12
+
13
+ # Whether this validation was successful
14
+ # @return [Boolean] whether successful
15
+ def success?
16
+ true
17
+ end
18
+
19
+ # Whether this validation was a failure
20
+ # @return [Boolean] whether failure
21
+ def failure?
22
+ !success?
23
+ end
24
+ end
25
+ end
@@ -3,17 +3,36 @@ require 'ood_support'
3
3
  module OodAppkit
4
4
  module Validators
5
5
  # Class used to determine if user is in valid list of groups
6
- class Groups
7
- # @param groups [Array<String>] list of groups
8
- def initialize(groups:, **_)
9
- @groups = [*groups].map {|g| OodSupport::Group.new g}
6
+ class Groups < Validator
7
+ # @param groups [Array<#to_s>] list of groups
8
+ # @param allow [Boolean] whether these groups are allowed access
9
+ def initialize(groups: [], allow: true, **kwargs)
10
+ super(kwargs)
11
+ @groups = groups.map(&:to_s)
12
+ @allow = allow
10
13
  end
11
14
 
12
- # Whether user is in a valid group
13
- # @return [Boolean] whether in a valid group
14
- def valid?
15
- !(@groups & OodSupport::User.new.groups).empty?
15
+ # Whether this validation was successful
16
+ # @return [Boolean] whether successful
17
+ def success?
18
+ @allow ? in_user_groups?(@groups) : not_in_user_groups?(@groups)
16
19
  end
20
+
21
+ private
22
+ # List of groups user is in
23
+ def user_groups
24
+ OodSupport::User.new.groups.map(&:to_s)
25
+ end
26
+
27
+ # Whether any groups match user's groups
28
+ def in_user_groups?(groups)
29
+ !(groups & user_groups).empty?
30
+ end
31
+
32
+ # Whether groups don't correspond with any user group
33
+ def not_in_user_groups?(groups)
34
+ !in_user_groups?(groups)
35
+ end
17
36
  end
18
37
  end
19
38
  end
@@ -1,4 +1,4 @@
1
1
  module OodAppkit
2
2
  # The current version of OodAppkit
3
- VERSION = "0.2.8"
3
+ VERSION = "0.3.0"
4
4
  end
data/lib/ood_appkit.rb CHANGED
@@ -1,13 +1,13 @@
1
- require 'addressable'
2
-
3
1
  require 'ood_appkit/version'
4
2
  require 'ood_appkit/configuration'
5
3
  require 'ood_appkit/url'
6
4
  require 'ood_appkit/files_rack_app'
7
5
  require 'ood_appkit/markdown_template_handler'
8
6
  require 'ood_appkit/log_formatter'
9
- require 'ood_appkit/cluster'
10
- require 'ood_appkit/server'
7
+ require 'ood_appkit/config_parser'
8
+ require 'ood_appkit/cluster_decorator'
9
+ require 'ood_appkit/clusters'
10
+ require 'ood_appkit/validator'
11
11
 
12
12
  # The main namespace for OodAppkit. Provides a global configuration.
13
13
  module OodAppkit
@@ -23,13 +23,6 @@ module OodAppkit
23
23
  require 'ood_appkit/urls/editor'
24
24
  end
25
25
 
26
- # A namespace to hold all subclasses of {Server}
27
- module Servers
28
- require 'ood_appkit/servers/torque'
29
- require 'ood_appkit/servers/moab'
30
- require 'ood_appkit/servers/ganglia'
31
- end
32
-
33
26
  # A namespace for validators used to validate a cluster
34
27
  module Validators
35
28
  require 'ood_appkit/validators/groups'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ood_appkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Franz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-23 00:00:00.000000000 Z
11
+ date: 2016-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.0.7
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
29
  version: '4.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.0.7
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: ood_support
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +44,34 @@ dependencies:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
46
  version: '0.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: ood_cluster
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: ood_reservations
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.0'
41
75
  - !ruby/object:Gem::Dependency
42
76
  name: addressable
43
77
  requirement: !ruby/object:Gem::Requirement
@@ -114,25 +148,23 @@ files:
114
148
  - app/controllers/concerns/ood_appkit/wiki_page.rb
115
149
  - app/controllers/ood_appkit/wiki_controller.rb
116
150
  - app/views/ood_appkit/wiki/show.html.erb
117
- - config/clusters.yml
118
151
  - config/routes.rb
119
152
  - lib/ood_appkit.rb
120
- - lib/ood_appkit/cluster.rb
153
+ - lib/ood_appkit/cluster_decorator.rb
154
+ - lib/ood_appkit/clusters.rb
155
+ - lib/ood_appkit/config_parser.rb
121
156
  - lib/ood_appkit/configuration.rb
122
157
  - lib/ood_appkit/engine.rb
123
158
  - lib/ood_appkit/files_rack_app.rb
124
159
  - lib/ood_appkit/log_formatter.rb
125
160
  - lib/ood_appkit/markdown_template_handler.rb
126
- - lib/ood_appkit/server.rb
127
- - lib/ood_appkit/servers/ganglia.rb
128
- - lib/ood_appkit/servers/moab.rb
129
- - lib/ood_appkit/servers/torque.rb
130
161
  - lib/ood_appkit/url.rb
131
162
  - lib/ood_appkit/urls/dashboard.rb
132
163
  - lib/ood_appkit/urls/editor.rb
133
164
  - lib/ood_appkit/urls/files.rb
134
165
  - lib/ood_appkit/urls/public.rb
135
166
  - lib/ood_appkit/urls/shell.rb
167
+ - lib/ood_appkit/validator.rb
136
168
  - lib/ood_appkit/validators/groups.rb
137
169
  - lib/ood_appkit/version.rb
138
170
  - lib/tasks/ood_appkit_tasks.rake
@@ -184,7 +216,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
216
  requirements:
185
217
  - - ">="
186
218
  - !ruby/object:Gem::Version
187
- version: '0'
219
+ version: 2.2.0
188
220
  required_rubygems_version: !ruby/object:Gem::Requirement
189
221
  requirements:
190
222
  - - ">="
data/config/clusters.yml DELETED
@@ -1,112 +0,0 @@
1
- v1:
2
- oakley:
3
- title: 'Oakley'
4
- servers:
5
- login:
6
- type: 'OodAppkit::Server'
7
- host: 'oakley.osc.edu'
8
- resource_mgr:
9
- type: 'OodAppkit::Servers::Torque'
10
- host: 'oak-batch.osc.edu'
11
- prefix: '/usr/local/torque/5.1.1-1_fba25d92'
12
- version: '5.1.1'
13
- scheduler:
14
- type: 'OodAppkit::Servers::Moab'
15
- host: 'oak-batch.osc.edu'
16
- prefix: '/usr/local/moab/8.1.1.2-2015080516-eb28ad0-el6'
17
- version: '8.1.1'
18
- moabhomedir: '/var/spool/batch/moab'
19
- ganglia:
20
- type: 'OodAppkit::Servers::Ganglia'
21
- host: 'cts05.osc.edu'
22
- scheme: 'https://'
23
- segments:
24
- - 'gweb'
25
- - 'graph.php'
26
- req_query:
27
- c: 'Oakley nodes'
28
- opt_query:
29
- h: '%{h}.ten.osc.edu'
30
- version: '3'
31
- ruby:
32
- title: 'Ruby'
33
- validators:
34
- in_valid_groups:
35
- type: 'OodAppkit::Validators::Groups'
36
- groups:
37
- - 'ruby'
38
- servers:
39
- login:
40
- type: 'OodAppkit::Server'
41
- host: 'ruby.osc.edu'
42
- resource_mgr:
43
- type: 'OodAppkit::Servers::Torque'
44
- host: 'ruby-batch.osc.edu'
45
- prefix: '/usr/local/torque/5.1.1-1_fba25d92'
46
- version: '5.1.1'
47
- scheduler:
48
- type: 'OodAppkit::Servers::Moab'
49
- host: 'ruby-batch.osc.edu'
50
- prefix: '/usr/local/moab/8.1.1.2-2015080516-eb28ad0-el6'
51
- version: '8.1.1'
52
- moabhomedir: '/var/spool/batch/moab'
53
- ganglia:
54
- type: 'OodAppkit::Servers::Ganglia'
55
- host: 'cts05.osc.edu'
56
- scheme: 'https://'
57
- segments:
58
- - 'gweb'
59
- - 'graph.php'
60
- req_query:
61
- c: 'Ruby'
62
- opt_query:
63
- h: '%{h}.ten.osc.edu'
64
- version: '3'
65
- owens:
66
- title: 'Owens'
67
- validators:
68
- in_valid_groups:
69
- type: 'OodAppkit::Validators::Groups'
70
- groups:
71
- - 'owens'
72
- - 'oscsys'
73
- - 'hpcsys'
74
- - 'sysp'
75
- - 'appl'
76
- - 'oscgen'
77
- - 'hpcsoft'
78
- - 'oscadm'
79
- servers:
80
- login:
81
- type: 'OodAppkit::Server'
82
- host: 'owens.hpc.osc.edu'
83
- ganglia:
84
- type: 'OodAppkit::Servers::Ganglia'
85
- host: 'cts05.osc.edu'
86
- scheme: 'https://'
87
- segments:
88
- - 'gweb'
89
- - 'graph.php'
90
- req_query:
91
- c: 'Owens'
92
- opt_query:
93
- h: '%{h}.ten.osc.edu'
94
- version: '3'
95
- quick:
96
- title: 'Quick'
97
- hpc_cluster: false
98
- servers:
99
- resource_mgr:
100
- type: 'OodAppkit::Servers::Torque'
101
- host: 'quick-batch.osc.edu'
102
- prefix: '/usr/local/torque/5.1.1-1_fba25d92'
103
- version: '5.1.1'
104
- sub_cluster:
105
- - 'ruby'
106
- - 'oakley'
107
- scheduler:
108
- type: 'OodAppkit::Servers::Moab'
109
- host: 'quick-batch.osc.edu'
110
- prefix: '/usr/local/moab/8.1.1.2-2015080516-eb28ad0-el6'
111
- version: '8.1.1'
112
- moabhomedir: '/var/spool/batch/moab'
@@ -1,102 +0,0 @@
1
- require 'yaml'
2
-
3
- module OodAppkit
4
- # An object that describes a given cluster of nodes used by an HPC center
5
- class Cluster
6
- # YAML configuration version
7
- VERSION = :v1
8
-
9
- # Unique ID of the cluster
10
- # @return [Symbol] id of cluster
11
- attr_reader :id
12
-
13
- # Title of the cluster
14
- # @return [String] title of cluster
15
- attr_reader :title
16
-
17
- # Hash of validators this cluster validates against
18
- # @return [Hash<#valid?>] hash of validators
19
- attr_reader :validators
20
-
21
- # Hash of servers this cluster supports
22
- # @return [Hash<Server>] hash of servers
23
- attr_reader :servers
24
-
25
- # A list of accessible clusters for the currently running user
26
- # @param file [String] yaml file with cluster configurations
27
- # @param force [Boolean] whether we force invalid clusters to be included as well
28
- # @return [Hash<Cluster>] list of clusters user has access to
29
- def self.all(file: File.expand_path('../../../config/clusters.yml', __FILE__), force: false)
30
- parse_config(file).each_with_object({}) do |(k, v), h|
31
- c = Cluster.new v.merge(id: k)
32
- h[k] = c if c.valid? || force
33
- end
34
- end
35
-
36
- # @param id [Symbol] id of cluster
37
- # @param title [String] title of cluster
38
- # @param validators [Hash] hash of validations that describe the validators
39
- # @param servers [Hash] hash of servers with corresponding server info
40
- # @param hpc_cluster [Boolean] whether this is an hpc-style cluster
41
- def initialize(id:, title:, validators: {}, servers: {}, hpc_cluster: true)
42
- # Set id & title of cluster
43
- @id = id
44
- @title = title
45
-
46
- # Generate hash of validations
47
- @validators = validators.each_with_object({}) do |(k, v), h|
48
- h[k] = v[:type].constantize.new(v)
49
- end
50
-
51
- # Generate hash of servers
52
- @servers = servers.each_with_object({}) do |(k, v), h|
53
- h[k] = v[:type].constantize.new(v)
54
- end
55
-
56
- # Is this an hpc-style cluster?
57
- @hpc_cluster = hpc_cluster
58
- end
59
-
60
- # Whether this is a valid cluster
61
- # @example Whether I have access to this cluster
62
- # my_cluster.valid?
63
- # #=> true
64
- # @return [Boolean] whether user has access to this cluster
65
- def valid?
66
- !@validators.any? {|name, validator| !validator.valid?}
67
- end
68
-
69
- # Whether this is an hpc-style cluster (i.e., meant for heavy computation)
70
- # @return [Boolean] whether this an hpc-style cluster
71
- def hpc_cluster?
72
- @hpc_cluster
73
- end
74
-
75
- # Grab object from {@servers} hash or check if it exists
76
- # @param method_name the method name called
77
- # @param arguments the arguments to the call
78
- # @param block an optional block for the call
79
- def method_missing(method_name, *arguments, &block)
80
- if /^(.+)_server$/ =~ method_name.to_s
81
- @servers.fetch($1.to_sym, nil)
82
- elsif /^(.+)_server\?$/ =~ method_name.to_s
83
- @servers.has_key? $1.to_sym
84
- else
85
- super
86
- end
87
- end
88
-
89
- # Check if method ends with custom *_server or *_server?
90
- # @param method_name the method name to check
91
- # @return [Boolean]
92
- def respond_to_missing?(method_name, include_private = false)
93
- method_name.to_s.end_with?('_server', '_server?') || super
94
- end
95
-
96
- private
97
- # Parse the config file
98
- def self.parse_config(file)
99
- YAML.load(File.read(file)).deep_symbolize_keys.fetch(VERSION, {})
100
- end
101
- end
102
- end
@@ -1,15 +0,0 @@
1
- module OodAppkit
2
- # An object that describes a server hosted by a given cluster
3
- class Server
4
- # The host information for this server object
5
- # @example Host information for login node
6
- # "my_server.host" #=> "oakley.osc.edu"
7
- # @return [String] the host for this server
8
- attr_reader :host
9
-
10
- # @param host [String] host info
11
- def initialize(host:, **_)
12
- @host = host
13
- end
14
- end
15
- end
@@ -1,83 +0,0 @@
1
- module OodAppkit
2
- module Servers
3
- # This defines a Ganglia server and defining parameters
4
- class Ganglia < Server
5
- # Template used to describe URI
6
- # @see https://www.rfc-editor.org/rfc/rfc6570.txt RFC describing template format
7
- TEMPLATE = '{+scheme}{host}{/segments*}{?query*}'
8
-
9
- # The scheme of the URI
10
- # @example Scheme of SSL protocol
11
- # "my_ganglia.scheme" #=> "https://"
12
- # @return [String] scheme of uri
13
- attr_reader :scheme
14
-
15
- # The segments used to describe the path of the URI
16
- # @example Segments for URI with path "/ganglia/gweb.php"
17
- # "my_ganglia.segments"
18
- # #=> ["ganglia", "gweb.php"]
19
- # @return [Array<String>] segments of uri
20
- attr_reader :segments
21
-
22
- # The required query values of the URI
23
- # @example Required cluster query value
24
- # "my_ganglia.req_query"
25
- # #=> {c: "MyCluster"}
26
- # @return [Hash] required query values of uri
27
- attr_reader :req_query
28
-
29
- # Optional query values of the URI, these query values are
30
- # only defined if specified
31
- # NB: All optional values will be evaluated for string interpolations
32
- # @example Optional host query value
33
- # "my_ganglia.opt_query"
34
- # #=> {h: "%{h}.ten.osc.edu"}
35
- # @return [Hash] optional query values of uri
36
- attr_reader :opt_query
37
-
38
- # The version of this software
39
- # @return [String] version of software
40
- attr_reader :version
41
-
42
- # @param scheme [String] the scheme used for URI
43
- # @param segments [Array<String>] the segments used to construct path of URI
44
- # @param req_query [Hash] hash of required query values used for URI
45
- # @param opt_query [Hash] hash of optional query values if they exist
46
- # @param version [String] version of server software
47
- def initialize(scheme:, segments: [], req_query: {}, opt_query: {}, version:, **kwargs)
48
- super(kwargs)
49
-
50
- # uri
51
- @scheme = scheme
52
- @segments = segments
53
- @req_query = req_query
54
- @opt_query = opt_query
55
-
56
- # version
57
- @version = version
58
- end
59
-
60
- # The URI used to access information about given cluster
61
- # @param query [Hash] user specified query hash
62
- # @return [Addressable] the uri for ganglia server
63
- def uri(query: {})
64
- Addressable::Template.new(TEMPLATE).expand({
65
- scheme: scheme,
66
- host: host,
67
- segments: segments,
68
- query: query_hash(query)
69
- })
70
- end
71
-
72
- private
73
- # The full hash of query values used to construct URI
74
- def query_hash(query)
75
- req_query.merge(
76
- query.each_with_object({}) do |(k, v), h|
77
- h[k] = opt_query.has_key?(k) ? (opt_query[k] % req_query.merge(query)) : v
78
- end
79
- )
80
- end
81
- end
82
- end
83
- end
@@ -1,54 +0,0 @@
1
- module OodAppkit
2
- module Servers
3
- # This defines a Moab server / client software installation
4
- class Moab < Server
5
- # The path to the installation location for this software
6
- # @return [Pathname] the path to software installation location
7
- attr_reader :prefix
8
-
9
- # The version of this software
10
- # @return [String] version of software
11
- attr_reader :version
12
-
13
- # The required Moab environment variable
14
- # @return [Pathname] require moab env var
15
- attr_reader :moabhomedir
16
-
17
- # @param prefix [String] installation path of client software
18
- # @param version [String] version of client software
19
- # @param moabhomedir [String] required moab env var
20
- def initialize(prefix:, version:, moabhomedir:, **kwargs)
21
- super(kwargs)
22
-
23
- # installation path
24
- @prefix = Pathname.new prefix
25
- raise ArgumentError, "prefix path doesn't exist (#{@prefix})" unless @prefix.exist?
26
- raise ArgumentError, "prefix not valid directory (#{@prefix})" unless @prefix.directory?
27
-
28
- # version number
29
- @version = version
30
-
31
- # required moab env var
32
- @moabhomedir = Pathname.new moabhomedir
33
- raise ArgumentError, "moabhomedir path doesn't exist (#{@moabhomedir})" unless @moabhomedir.exist?
34
- raise ArgumentError, "moabhomedir not valid directory (#{@moabhomedir})" unless @moabhomedir.directory?
35
- end
36
-
37
- # The path to Torque software library
38
- # @example Locally installed Torque v5.1.1
39
- # "my_software.lib" #=> "/usr/local/torque/5.1.1/lib"
40
- # @return [Pathname] path to libraries
41
- def lib
42
- prefix.join('lib')
43
- end
44
-
45
- # The path to Torque software binaries
46
- # @example Locally installed Torque v5.1.1
47
- # "my_software.lib" #=> "/usr/local/torque/5.1.1/bin"
48
- # @return [Pathname] path to binaries
49
- def bin
50
- prefix.join('bin')
51
- end
52
- end
53
- end
54
- end
@@ -1,44 +0,0 @@
1
- module OodAppkit
2
- module Servers
3
- # This defines a Torque server / client software installation
4
- class Torque < Server
5
- # The path to the installation location for this software
6
- # @return [Pathname] the path to software installation location
7
- attr_reader :prefix
8
-
9
- # The version of this software
10
- # @return [String] version of software
11
- attr_reader :version
12
-
13
- # @param prefix [String] installation path of client software
14
- # @param version [String] version of client software
15
- def initialize(prefix:, version:, **kwargs)
16
- super(kwargs)
17
-
18
- # installation path
19
- @prefix = Pathname.new prefix
20
- raise ArgumentError, "prefix path doesn't exist (#{@prefix})" unless @prefix.exist?
21
- raise ArgumentError, "prefix not valid directory (#{@prefix})" unless @prefix.directory?
22
-
23
- # version number
24
- @version = version
25
- end
26
-
27
- # The path to Torque software library
28
- # @example Locally installed Torque v5.1.1
29
- # "my_software.lib" #=> "/usr/local/torque/5.1.1/lib"
30
- # @return [Pathname] path to libraries
31
- def lib
32
- prefix.join('lib')
33
- end
34
-
35
- # The path to Torque software binaries
36
- # @example Locally installed Torque v5.1.1
37
- # "my_software.lib" #=> "/usr/local/torque/5.1.1/bin"
38
- # @return [Pathname] path to binaries
39
- def bin
40
- prefix.join('bin')
41
- end
42
- end
43
- end
44
- end