ood_appkit 0.2.8 → 0.3.0

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.
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