ruby-jss 1.0.0b2 → 1.0.0b6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

@@ -148,7 +148,7 @@ module JSS
148
148
  @init_data[:general][:fields].each{|f| @fields[f[:name]] = f[:value] }
149
149
 
150
150
  ### get the field defs for this PeriphType, omitting the leading nil
151
- @field_defs ||= JSS::PeripheralType.new(:name => @type).fields.compact
151
+ @field_defs ||= JSS::PeripheralType.fetch(:name => @type).fields.compact
152
152
 
153
153
 
154
154
  end # initialize
@@ -269,7 +269,7 @@ module JSS
269
269
  ###
270
270
  def check_field(field, value)
271
271
  ### get the field defs for this PeriphType, omitting the leading nil
272
- @field_defs ||= JSS::PeripheralType.new(:name => @type, api: @api).fields.compact
272
+ @field_defs ||= JSS::PeripheralType.fetch(:name => @type, api: @api).fields.compact
273
273
 
274
274
  ### we must have the right number of fields, and they must have the same names
275
275
  ### as the definition
@@ -98,7 +98,7 @@ module JSS
98
98
  #
99
99
  def site_object
100
100
  return nil unless site_assigned?
101
- JSS::Site.new id: @site_id
101
+ JSS::Site.fetch id: @site_id
102
102
  end # cat obj
103
103
 
104
104
  # Does this object have a site assigned?
@@ -295,7 +295,7 @@ module JSS
295
295
  return identifier if all_ids(refresh, api: api).include? identifier
296
296
  all_lookup_keys.keys.each do |key|
297
297
  next if key == :id
298
- id = map_all_ids_to(key).invert[identifier]
298
+ id = map_all_ids_to(key, api: api).invert[identifier]
299
299
  return id if id
300
300
  end # do key
301
301
  nil
@@ -996,7 +996,7 @@ module JSS
996
996
 
997
997
  raise JSS::MissingDataError, "Args must include a lookup key, one of: :#{lookup_keys.join(', :')}" unless lookup_key
998
998
 
999
- vid = self.class.valid_id args[lookup_key], :refresh
999
+ vid = self.class.valid_id args[lookup_key], :refresh, api: args[:api]
1000
1000
 
1001
1001
  raise NoSuchItemError, "No #{self.class::RSRC_OBJECT_KEY} found with #{lookup_key} '#{args[lookup_key]}'" unless vid
1002
1002
 
@@ -63,8 +63,8 @@ module JSS
63
63
 
64
64
  # Skipping all the force-alerts stuff until we figure out cleaner
65
65
  # ways to do it in 10.13+
66
- # The plan is to make the NotificationCenter notification always be an
67
- # 'alert' (which stays visible til the user clicks) rather than a
66
+ # The plan is to be able to make the NotificationCenter notification be an
67
+ # 'alert' (which stays visible til the user clicks) or a
68
68
  # 'banner' (which vanishes in a few seconds), regardless of the user's
69
69
  # setting in the NC prefs.
70
70
 
data/lib/jss/utility.rb CHANGED
@@ -211,7 +211,7 @@ module JSS
211
211
  # if we're here, its a Pathname
212
212
  raise JSS::MissingDataError, "No such file: #{plist}" unless plist.file?
213
213
 
214
- Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape(plist.to_s)}`
214
+ Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape(plist.to_s)}`.force_encoding('UTF-8')
215
215
  end # parse_plist
216
216
 
217
217
  # Converts anything that responds to #to_s to a Time, or nil
data/lib/jss/validate.rb CHANGED
@@ -42,10 +42,13 @@ module JSS
42
42
  #
43
43
  # @param val[String] The value to validate
44
44
  #
45
+ # @param msg[String] A custom error message when the value is invalid
46
+ #
45
47
  # @return [String] The valid value
46
48
  #
47
- def self.mac_address(val)
48
- raise JSS::InvalidDataError, "Not a valid MAC address: '#{val}'" unless val =~ MAC_ADDR_RE
49
+ def self.mac_address(val, msg = nil)
50
+ msg ||= "Not a valid MAC address: '#{val}'"
51
+ raise JSS::InvalidDataError, msg unless val =~ MAC_ADDR_RE
49
52
  val
50
53
  end
51
54
 
@@ -53,14 +56,17 @@ module JSS
53
56
  #
54
57
  # @param val[String] The value to validate
55
58
  #
59
+ # @param msg[String] A custom error message when the value is invalid
60
+ #
56
61
  # @return [String] The valid value
57
62
  #
58
- def self.ip_address(val)
63
+ def self.ip_address(val, msg = nil)
64
+ msg ||= "Not a valid IPv4 address: '#{val}'"
59
65
  ok = true
60
66
  parts = val.strip.split '.'
61
67
  ok = false unless parts.size == 4
62
68
  parts.each { |p| ok = false unless p.jss_integer? && p.to_i < 256 && p.to_i >= 0 }
63
- raise JSS::InvalidDataError, "Not a valid IPv4 address: '#{val}'" unless ok
69
+ raise JSS::InvalidDataError, msg unless ok
64
70
  val
65
71
  end
66
72
 
@@ -77,11 +83,16 @@ module JSS
77
83
  #
78
84
  # @param val[Object] The value to check for uniqueness
79
85
  #
86
+ # @param msg[String] A custom error message when the value is invalid
87
+ #
88
+ # @param api[JSS::APIConnection] The api connection to use for validation
89
+ #
80
90
  # @return [Object] the validated unique value
81
91
  #
82
- def self.unique_identifier(klass, identifier, val, api: JSS.api)
92
+ def self.unique_identifier(klass, identifier, val, msg = nil, api: JSS.api)
93
+ msg ||= "A #{klass} already exists with #{identifier} '#{val}'"
83
94
  return val unless klass.all(:refresh, api: api).map { |i| i[identifier] }.include? val
84
- raise JSS::AlreadyExistsError, "A #{klass} already exists with #{identifier} '#{val}'"
95
+ raise JSS::AlreadyExistsError, msg
85
96
  end
86
97
 
87
98
  # Confirm that the given value is a boolean value, accepting
@@ -93,13 +104,16 @@ module JSS
93
104
  #
94
105
  # @param bool [Boolean,String,Symbol] The value to validate
95
106
  #
107
+ # @param msg[String] A custom error message when the value is invalid
108
+ #
96
109
  # @return [Boolean] the valid boolean
97
110
  #
98
- def self.boolean(bool)
111
+ def self.boolean(bool, msg = nil)
112
+ msg ||= 'Value must be boolean true or false'
99
113
  return bool if JSS::TRUE_FALSE.include? bool
100
114
  return true if bool.to_s =~ /^(true|yes)$/i
101
115
  return false if bool.to_s =~ /^(false|no)$/i
102
- raise JSS::InvalidDataError, 'Value must be boolean true or false'
116
+ raise JSS::InvalidDataError, msg
103
117
  end
104
118
 
105
119
  # Confirm that a value is an integer or a string representation of an
@@ -109,11 +123,14 @@ module JSS
109
123
  #
110
124
  # @param val[Object] the value to validate
111
125
  #
126
+ # @param msg[String] A custom error message when the value is invalid
127
+ #
112
128
  # @return [void]
113
129
  #
114
- def self.integer(val)
130
+ def self.integer(val, msg = nil)
131
+ msg ||= 'Value must be an integer'
115
132
  val = val.to_i if val.is_a?(String) && val.jss_integer?
116
- raise JSS::InvalidDataError, 'Value must be an integer' unless val.is_a? Integer
133
+ raise JSS::InvalidDataError, msg unless val.is_a? Integer
117
134
  val
118
135
  end
119
136
 
@@ -121,30 +138,16 @@ module JSS
121
138
  #
122
139
  # @param val [Object] the thing to validate
123
140
  #
141
+ # @param msg[String] A custom error message when the value is invalid
142
+ #
124
143
  # @return [String] the valid non-empty string
125
144
  #
126
- def self.non_empty_string(val)
127
- raise JSS::InvalidDataError, 'value must be a non-empty String' unless val.is_a?(String) && !val.empty?
145
+ def self.non_empty_string(val, msg = nil)
146
+ msg ||= 'value must be a non-empty String'
147
+ raise JSS::InvalidDataError, msg unless val.is_a?(String) && !val.empty?
128
148
  val
129
149
  end
130
150
 
131
- # Confirm that the given value is a boolean value, accepting
132
- # strings and symbols and returning real booleans as needed
133
- # Accepts: true, false, 'true', 'false', :true, :false, 'yes', 'no', :yes,
134
- # or :no (all Strings and Symbols are case insensitive)
135
- #
136
- #
137
- # @param bool [Boolean,String,Symbol] The value to validate
138
- #
139
- # @return [Boolean] the valid boolean
140
- #
141
- def self.boolean(bool)
142
- return bool if JSS::TRUE_FALSE.include? bool
143
- return true if bool.to_s =~ /^(true|yes)$/i
144
- return false if bool.to_s =~ /^(false|no)$/i
145
- raise JSS::InvalidDataError, 'Value must be boolean true or false'
146
- end
147
-
148
151
  end # module validate
149
152
 
150
153
  end # module JSS
data/lib/jss/version.rb CHANGED
@@ -27,6 +27,6 @@
27
27
  module JSS
28
28
 
29
29
  ### The version of the JSS ruby gem
30
- VERSION = '1.0.0b2'.freeze
30
+ VERSION = '1.0.0b6'.freeze
31
31
 
32
32
  end # module
data/test/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # About the ruby-jss test suite
2
+
3
+ For years, I've attempted to use some ruby testing framework to automate testing of ruby-jss.
4
+
5
+ Every time I've run into walls because unit testing suites are designed for unit testing, and that's not really what we need to do. Yes we need to test individual methods of classes and so on, but when working with a REST API, there's a lot of
6
+ scaffolding that needs to happen before tests can even start - and that scaffolding itself is testing the code. And the details of the scaffolding will vary in different environments.
7
+
8
+ For example, the tests *must* be very interactive from the start - you have to tell them what server to connect with, what credentials to use, and so on.
9
+
10
+ Once connected, objects have to be created before they can be listed, fetched, updated, or deleted - so test order matters.
11
+
12
+ Also, you need to be able to have later tests refer to the same objects you created in earlier tests. Once I've tested that I can create an object on the server and re-fetch it once, I shuold be able to use that object for all future tests without fetching every time.
13
+
14
+ Reading most tutorials about ruby testing just leads you in circles when you consider needs such as these.
15
+
16
+ Many propnents of unit testing might find this suite odd. Thats ok. Any functional testing suite is better than none and I'm open to suggestions for improvement.
17
+
18
+ ### Here's how to use it:
19
+
20
+ tldr:
21
+
22
+ `/path/to/your/ruby-jss/gem/installation/test/bin/runtests --server myjss.company.com --user myjssusername`
23
+
24
+ Must be run on a mac, it uses your keychain to store connection data and credentials, so you only have to provide them the first time or when changing them.
25
+
26
+ See below for the help output
27
+
28
+ ### Here's how this thing works:
29
+
30
+ - The tests are ultimatly MiniTest::Spec specifications, defined in files in the 'specs' folder.
31
+ - See http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest.html
32
+ - also, google around for help with minitest specs
33
+
34
+
35
+ - They do NOT use minitest/autorun. Instead, the 'runtests' executable handles loading and running them
36
+ - See below for the help output
37
+
38
+
39
+ - The runtests command, via methods in the JSSTestHelper module, handles connecting to servers.
40
+ - it takes options to define connection parameters.
41
+ - At the moment they are limited to user, hostname and port, but will be expanded eventually
42
+ - it prompts for passwords as needed
43
+ - it must be run on a Mac! It stores connection parameters in your keychain.
44
+ - it uses connection parameters from your keychain if they are present. meaning after the first use,
45
+ it will connect to the same server as the same user with no commandline options.
46
+ - If any commandline options are different from whats in the keychain, the keychain will be updated,
47
+ prompting for new passwords if needed.
48
+
49
+ - The JSSTestHelper module also provides ways for tests to share data.
50
+
51
+ - The runtests command will run the spec files listed on the command line, or all of them if none are listed.
52
+ - The tests are run verbosely, so you can see what tests are being run.
53
+ - Some tests are interactive - they will ask you to make choices about what's happening.
54
+
55
+ WARNING: **Be very careful about running these tests on your production JSS !!!**
56
+
57
+ These tests create and delete objects in the JSS. While they _shouldn't_ hurt any of the existing data - we cannot make any guarantees that they won't hurt something you care about.
58
+
59
+ As the license text for ruby-jss states:
60
+
61
+ ```
62
+ Unless required by applicable law or agreed to in writing, software
63
+ distributed under the Apache License with the above modification is
64
+ distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
65
+ KIND, either express or implied.
66
+ ```
67
+
68
+ As a reminder, if you connect to the same server that's listed in your /etc/ruby-jss.conf, you'll be asked for confirmation before the tests are run.
69
+
70
+
71
+ ### The Spec Files
72
+
73
+ Each spec file defines one or more MiniTest::Spec's, each one being a 'describe SomeClass' block, containing methods and individual tests in 'it' blocks.
74
+
75
+ If you plan to write any tests, please read up on how to write MiniTest Specs.
76
+
77
+ However, here's some info that wasn't obvious when I first started, and makes life much easier when writing specs:
78
+
79
+ - the 'describe' blocks eventually become classes
80
+ - you can do anything inside them that you would do in a class definition.
81
+ - the 'it' blocks become methods in the class defined by the 'describe' block.
82
+ - the 'it' blocks are run one at a time, each in a separate instance of the class defined by the 'describe' block.
83
+ - by default, the 'it' blocks are run in a random order. See below if you need them to run in the defined order.
84
+
85
+ All of the above means that you can use constants, class methods, class-instance variables and instance methods in concert for processing and passing things between the individual tests.
86
+
87
+ ### Running tests in order
88
+
89
+ The individual spec files are run in the order given on the command line. If none are given on the command line, all files are run in alphabetical order.
90
+
91
+ If you define multiple 'describe' blocks in a file, they will be run in random order.
92
+
93
+ The individual tests in a describe block are also run in random order, by default.
94
+
95
+ If you need the tests to run in order within a 'describe' block, then define this class method somewhere inside it:
96
+
97
+ def self.test_order
98
+ :alpha
99
+ end
100
+
101
+ The presence of that method will cause MiniTest to run them in the order defined.
102
+
103
+ ### Help output from 'runtests -H'
104
+
105
+
106
+ ```
107
+ Usage: runtests [options] [spec [spec ...]]
108
+
109
+ Runs one or more specification tests of ruby-jss.
110
+
111
+ The specifications are files in the directory:
112
+ /Users/chrisl/git/gemdev/ruby-jss/test/specs
113
+
114
+ The files must have a _spec.rb suffix, however you need not use the suffix when
115
+ listing tests to run on the command line, e.g. 'patch_source' will run
116
+ 'patch_source_spec.rb'
117
+
118
+ If no specs files are listed on the command line, all will be run, in
119
+ alphabetical order.
120
+
121
+ By default, JSS connection settings are used from your /etc/ruby-jss.conf file
122
+ and/or ~/.ruby-jss.conf. Connection settings from the command line will be used
123
+ if provided.
124
+
125
+ WARNING: These tests create, modify, and delete objects in the JSS.
126
+ While no existing objects should be changed, * Be Careful * running them on
127
+ a production server.
128
+ If the server you're connecting to matches one defined in /etc/ruby-jss.conf
129
+ you will be asked for confirmation before proceding.
130
+
131
+ The first time you connect from this machine to a given server, you must provide
132
+ a username for the connection with --user, and will be prompted for the password.
133
+ Once authenticated, credentials for the server are saved in your keychain, and
134
+ future connections to that server will read the user & password from there.
135
+ If a different user is later specified for that server, you'll be prompted again
136
+ for a password, and the keychain will be updated.
137
+
138
+ Options
139
+ --server, -s <host> the hostname for the JSS API connection
140
+ --port, -p <port> the port for the API connection
141
+ --user, -u <user> the API username for the connection
142
+ NOTE: must have permissions to perform the tests!
143
+ --db-server, -S <host> the hostname for the JSS API connection
144
+ --db-port, -P <port> the port for the API connectino
145
+ --db-user, -U <user> the API username for the connection
146
+ --gem-dir, -g, -i <path> the path from which to require ruby-jss
147
+ (sets GEM_HOME to this path before requiring)
148
+ --help, -h, -H show this help
149
+ ```
data/test/bin/runtests ADDED
@@ -0,0 +1,290 @@
1
+ #!/usr/bin/ruby
2
+
3
+ ### Copyright 2018 Pixar
4
+
5
+ ###
6
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
7
+ ### with the following modification; you may not use this file except in
8
+ ### compliance with the Apache License and the following modification to it:
9
+ ### Section 6. Trademarks. is deleted and replaced with:
10
+ ###
11
+ ### 6. Trademarks. This License does not grant permission to use the trade
12
+ ### names, trademarks, service marks, or product names of the Licensor
13
+ ### and its affiliates, except as required to comply with Section 4(c) of
14
+ ### the License and to reproduce the content of the NOTICE file.
15
+ ###
16
+ ### You may obtain a copy of the Apache License at
17
+ ###
18
+ ### http://www.apache.org/licenses/LICENSE-2.0
19
+ ###
20
+ ### Unless required by applicable law or agreed to in writing, software
21
+ ### distributed under the Apache License with the above modification is
22
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23
+ ### KIND, either express or implied. See the Apache License for the specific
24
+ ### language governing permissions and limitations under the Apache License.
25
+ ###
26
+ ###
27
+
28
+ # Uses the MiniTest::Spec infrastructure to run one or tests of ruby-jss
29
+ #
30
+ # We do not use minitest/autorun, so that we have more control over which tests
31
+ # are run and how. But the individual spec files are standard MiniTest::Spec
32
+ # 'describe' blocks
33
+ #
34
+ # Those blocks become classes when the tests are run, and for each test,
35
+ # an instance of the class is created.
36
+ # As such, the interior of the blocks can be treated like class definitions,
37
+ # defining constants, class methods, instance methods and so on.
38
+ #
39
+ # As well as that class-based infratructure, this tool includes a JSSTestHelper
40
+ # module which defines usefule constants and helper methods, accessible from
41
+ # anywhere via the module name.
42
+ #
43
+
44
+ require 'pathname'
45
+ require 'getoptlong'
46
+ require 'keychain'
47
+ require 'minitest/spec'
48
+ # require 'minitest/autorun' # DO NOT REQUIRE AUTORUN - we manually run each file below.
49
+
50
+ # app
51
+ class App
52
+
53
+ SPEC_SUFFIX = '_spec.rb'.freeze
54
+
55
+ # Server and port come from CLI opts or ruby-jss.conf
56
+ #
57
+ # User comes from CLI opt or keychain
58
+ #
59
+ # pw come from keychain, or is prompted and stored
60
+ # in keychain with user.
61
+ #
62
+ # TODO: support for other APIConnection options
63
+ #
64
+ OPTS = GetoptLong.new(
65
+ ['--server', '-s', GetoptLong::REQUIRED_ARGUMENT],
66
+ ['--port', '-p', GetoptLong::REQUIRED_ARGUMENT],
67
+ ['--user', '-u', GetoptLong::REQUIRED_ARGUMENT],
68
+ ['--db-server', '-S', GetoptLong::REQUIRED_ARGUMENT],
69
+ ['--db-port', '-P', GetoptLong::REQUIRED_ARGUMENT],
70
+ ['--db-user', '-U', GetoptLong::REQUIRED_ARGUMENT],
71
+ ['--gem-dir', '-g', '-i', GetoptLong::REQUIRED_ARGUMENT],
72
+ ['--saved-data', '-d', GetoptLong::NO_ARGUMENT],
73
+ ['--help', '-h', '-H', GetoptLong::NO_ARGUMENT]
74
+ )
75
+
76
+ # Setup
77
+ def initialize
78
+ load_ruby_jss
79
+ parse_opts
80
+
81
+ @bindir = Pathname.new File.dirname(__FILE__)
82
+ @appdir = @bindir.parent
83
+ @libdir = @appdir + 'lib'
84
+ @specdir = @appdir + 'specs'
85
+
86
+ @tests_to_run = ARGV.dup
87
+ @tests_to_run = @specdir.children.map { |c| c.basename.to_s }.sort if @tests_to_run .empty?
88
+
89
+ @minitest_opts = ['--verbose']
90
+
91
+ helper_module = @libdir + 'testhelper.rb'
92
+ load helper_module.to_s
93
+ end # init
94
+
95
+ # Load the gem
96
+ def load_ruby_jss
97
+ if @custom_gem_dir
98
+ ENV['GEM_HOME'] = @custom_gem_dir
99
+ ENV['GEM_PATH'] = "#{@custom_gem_dir}:#{ENV['GEM_PATH']}"
100
+ Gem.paths = ENV
101
+ end
102
+ require 'ruby-jss'
103
+ end
104
+
105
+ # Parse ARGV
106
+ def parse_opts
107
+ OPTS.each do |opt, arg|
108
+ case opt
109
+ when '--server'
110
+ @api_server = arg
111
+ when '--user'
112
+ @api_user = arg
113
+ when '--port'
114
+ @api_port = arg
115
+ when '--db-server'
116
+ @db_server = arg
117
+ when '--db-user'
118
+ @db_user = arg
119
+ when '--db-port'
120
+ @db_port = arg
121
+ when '--gem-dir'
122
+ @custom_gem_dir = arg
123
+ when '--saved-data'
124
+ @show_saved_data = true
125
+ when '--help'
126
+ @show_help = true
127
+ end # case
128
+ end # opts.each
129
+ end
130
+
131
+ # the default values
132
+ def apply_defaults
133
+ @api_server ||= JSS::CONFIG.api_server_name
134
+ @api_port ||= JSS::CONFIG.api_server_port
135
+ @db_server ||= JSS::CONFIG.db_server_name
136
+ @db_port ||= JSS::CONFIG.db_server_port
137
+ end
138
+
139
+ def run
140
+ return if show_help
141
+ return if show_saved_data
142
+ connect_to_servers
143
+ return unless prod_server_confirmed_if_needed?
144
+ run_tests
145
+ end
146
+
147
+ # if @api_server == matches the one in /etc/ruby-jss.conf
148
+ # get confirmation before running tests on the production server.
149
+ # If a local ~/.ruby-jss.conf defines a diferent server,
150
+ # or a different server if given with --server, no confirmation is needed
151
+ def prod_server_confirmed_if_needed?
152
+ conf = Pathname.new '/etc/ruby-jss.conf'
153
+ return true unless conf.file?
154
+
155
+ prod_server_line = conf.readlines.select { |l| l.start_with? 'api_server_name' }.first
156
+ return true unless prod_server_line
157
+
158
+ prod_server = prod_server_line.chomp.split(': ').last
159
+ return true unless prod_server == @api_server
160
+
161
+ print "Really run the tests on the production server '#{prod_server}'? (y/n): "
162
+ doit = gets.chomp
163
+ doit == 'y'
164
+ end
165
+
166
+ def connect_to_servers
167
+ jss_keychain_creds = JSSTestHelper::Auth.rw_credentials_from_keychain(:jss)
168
+ if jss_keychain_creds
169
+ @api_server ||= jss_keychain_creds[:server]
170
+ @api_port ||= jss_keychain_creds[:port]
171
+ @api_user ||= jss_keychain_creds[:user]
172
+ pw = jss_keychain_creds[:pw]
173
+ else
174
+ apply_defaults
175
+ raise 'Please specify a server with --server' unless @api_server
176
+ raise 'Please specify a user with --user' unless @api_user
177
+ pw = 'nopw'
178
+ end
179
+
180
+ JSSTestHelper::Auth.connect_to_api(server: @api_server, port: @api_port, user: @api_user, pw: pw )
181
+ end
182
+
183
+ def run_tests
184
+ JSSTestHelper.say "Starting tests of ruby-jss v #{JSS::VERSION}"
185
+ JSSTestHelper.say "API Connection: #{@api_user}@#{@api_server}:#{@api_port} running Jamf Pro #{JSS.api.server.version}"
186
+
187
+ base_runnables = MiniTest::Runnable.runnables.dup
188
+
189
+ @tests_to_run.each do |t|
190
+ t += SPEC_SUFFIX unless t.end_with? SPEC_SUFFIX
191
+ specfile = @specdir + t
192
+
193
+ puts
194
+
195
+ if specfile.file?
196
+ JSSTestHelper.say "Running test #{specfile.basename}: "
197
+ load specfile.to_s
198
+
199
+ MiniTest.run @minitest_opts.dup
200
+
201
+ # clear this files specs from the run list..
202
+ MiniTest::Runnable.runnables.select! { |r| base_runnables.include? r }
203
+ puts
204
+ else
205
+ JSSTestHelper.say "Skipping unknown test #{specfile.basename}"
206
+ end # if
207
+
208
+ end # each
209
+ end # run tests
210
+
211
+ # display saved keychain data if asked
212
+ def show_saved_data
213
+ return false unless @show_saved_data
214
+ jss_keychain_creds = JSSTestHelper::Auth.rw_credentials_from_keychain(:jss)
215
+ msg =
216
+ if jss_keychain_creds
217
+ "JSS API Tests will run as user '#{jss_keychain_creds[:user]}' on server '#{jss_keychain_creds[:server]}', port #{jss_keychain_creds[:port]}"
218
+ else
219
+ 'No JSS API credentials saved, please use --server, --user and --port (if needed)'
220
+ end
221
+ puts msg
222
+ true
223
+ end
224
+
225
+ # display help if asked
226
+ def show_help
227
+ return false unless @show_help
228
+ puts <<-USAGEBLURB
229
+ Usage: #{File.basename __FILE__} [options] [spec [spec ...]]
230
+
231
+ Runs one or more specification tests of ruby-jss.
232
+
233
+ The specifications are files in the directory:
234
+ #{@specdir}
235
+
236
+ The files must have a _spec.rb suffix, however you need not use the suffix when
237
+ listing tests to run on the command line, e.g. 'patch_source' will run
238
+ 'patch_source_spec.rb'
239
+
240
+ If no specs files are listed on the command line, all will be run, in
241
+ alphabetical order.
242
+
243
+ By default, JSS connection settings are used from your /etc/ruby-jss.conf file
244
+ and/or ~/.ruby-jss.conf. Connection settings from the command line will be used
245
+ if provided.
246
+
247
+ WARNING: These tests create, modify, and delete objects in the JSS.
248
+ While no existing objects should be changed, * Be Careful * running them on
249
+ a production server.
250
+ If the server you're connecting to matches one defined in /etc/ruby-jss.conf
251
+ you will be asked for confirmation before proceding.
252
+
253
+ The first time you connect from this machine to a given server, you must provide
254
+ a username for the connection with --user, and will be prompted for the password.
255
+ Once authenticated, credentials for the server are saved in your keychain, and
256
+ future connections to that server will read the user & password from there.
257
+ If a different user is later specified for that server, you'll be prompted again
258
+ for a password, and the keychain will be updated.
259
+
260
+ Options
261
+ --server, -s <host> the hostname for the JSS API connection
262
+ --port, -p <port> the port for the API connection
263
+ --user, -u <user> the API username for the connection
264
+ NOTE: must have permissions to perform the tests!
265
+ --db-server, -S <host> the hostname for the JSS API connection
266
+ --db-port, -P <port> the port for the API connectino
267
+ --db-user, -U <user> the API username for the connection
268
+ --gem-dir, -g, -i <path> the path from which to require ruby-jss
269
+ (sets GEM_HOME to this path before requiring)
270
+ --saved-data, -d show the connection data saved in the keychain,
271
+ if any. (no tests run, password not shown)
272
+ --help, -h, -H show this help
273
+ USAGEBLURB
274
+ true
275
+ end # show_help
276
+
277
+ end # class app
278
+
279
+ ################# The main block ########################
280
+ if $PROGRAM_NAME == __FILE__
281
+ begin
282
+ app = App.new
283
+ app.run
284
+ exit 0
285
+ rescue => the_exception
286
+ warn "An error occurred: #{the_exception.message}"
287
+ warn the_exception.backtrace
288
+ exit 1
289
+ end # begin
290
+ end # if $0 == __FILE__