ruby-jss 0.9.2 → 0.10.0a1

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.

Potentially problematic release.


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

Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +13 -1
  3. data/README.md +7 -7
  4. data/bin/cgrouper +6 -6
  5. data/bin/netseg-update +1 -1
  6. data/lib/jss.rb +1 -0
  7. data/lib/jss/api_connection.rb +428 -44
  8. data/lib/jss/api_object.rb +119 -68
  9. data/lib/jss/api_object/account.rb +12 -12
  10. data/lib/jss/api_object/advanced_search.rb +12 -12
  11. data/lib/jss/api_object/categorizable.rb +4 -4
  12. data/lib/jss/api_object/category.rb +2 -2
  13. data/lib/jss/api_object/computer.rb +111 -58
  14. data/lib/jss/api_object/computer_invitation.rb +2 -2
  15. data/lib/jss/api_object/creatable.rb +19 -8
  16. data/lib/jss/api_object/criteriable/criteria.rb +8 -8
  17. data/lib/jss/api_object/distribution_point.rb +14 -48
  18. data/lib/jss/api_object/extension_attribute.rb +14 -11
  19. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +18 -18
  20. data/lib/jss/api_object/group.rb +7 -7
  21. data/lib/jss/api_object/ldap_server.rb +51 -60
  22. data/lib/jss/api_object/locatable.rb +2 -2
  23. data/lib/jss/api_object/matchable.rb +8 -9
  24. data/lib/jss/api_object/mobile_device.rb +61 -59
  25. data/lib/jss/api_object/mobile_device_application.rb +3 -3
  26. data/lib/jss/api_object/network_segment.rb +24 -19
  27. data/lib/jss/api_object/package.rb +6 -6
  28. data/lib/jss/api_object/peripheral.rb +5 -5
  29. data/lib/jss/api_object/policy.rb +5 -5
  30. data/lib/jss/api_object/restricted_software.rb +4 -4
  31. data/lib/jss/api_object/scopable/scope.rb +3 -3
  32. data/lib/jss/api_object/script.rb +1 -1
  33. data/lib/jss/api_object/self_servable.rb +3 -3
  34. data/lib/jss/api_object/self_servable/icon.rb +7 -2
  35. data/lib/jss/api_object/updatable.rb +2 -2
  36. data/lib/jss/api_object/uploadable.rb +1 -1
  37. data/lib/jss/api_object/user.rb +2 -2
  38. data/lib/jss/composer.rb +37 -10
  39. data/lib/jss/ruby_extensions/string.rb +51 -42
  40. data/lib/jss/server.rb +27 -6
  41. data/lib/jss/utility.rb +44 -0
  42. data/lib/jss/validate.rb +85 -0
  43. data/lib/jss/version.rb +1 -1
  44. metadata +5 -4
@@ -422,7 +422,7 @@ module JSS
422
422
  return nil if new_val == @switch_with_package
423
423
  new_val = nil if new_val.to_s.empty?
424
424
 
425
- raise JSS::NoSuchItemError, "No package named '#{new_val}' exists in the JSS" if new_val && (!self.class.all_names.include? new_val)
425
+ raise JSS::NoSuchItemError, "No package named '#{new_val}' exists in the JSS" if new_val && (!self.class.all_names(api: @api).include? new_val)
426
426
 
427
427
  new_val ||= DO_NOT_INSTALL
428
428
  @switch_with_package = new_val
@@ -460,7 +460,7 @@ module JSS
460
460
  def upload_master_file(local_file_path, rw_pw, unmount = true)
461
461
  raise JSS::NoSuchItemError, 'Please create this package in the JSS before uploading it.' unless @in_jss
462
462
 
463
- mdp = JSS::DistributionPoint.master_distribution_point
463
+ mdp = JSS::DistributionPoint.master_distribution_point api: @api
464
464
  destination = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
465
465
 
466
466
  local_path = Pathname.new local_file_path
@@ -520,7 +520,7 @@ module JSS
520
520
  ###
521
521
  def update_master_filename(old_file_name, new_file_name, rw_pw, unmount = true)
522
522
  raise JSS::NoSuchItemError, "#{old_file_name} does not exist in the jss." unless @in_jss
523
- mdp = JSS::DistributionPoint.master_distribution_point
523
+ mdp = JSS::DistributionPoint.master_distribution_point api: @api
524
524
  pkgs_dir = mdp.mount(rw_pw, :rw) + DIST_POINT_PKGS_FOLDER.to_s
525
525
  old_file = pkgs_dir + old_file_name
526
526
  raise JSS::NoSuchItemError, "File not found on the master distribution point at #{DIST_POINT_PKGS_FOLDER}/#{old_file_name}." unless \
@@ -548,7 +548,7 @@ module JSS
548
548
  ### @return [Boolean] was the file deleted?
549
549
  ###
550
550
  def delete_master_file(rw_pw, unmount = true)
551
- mdp = JSS::DistributionPoint.master_distribution_point
551
+ mdp = JSS::DistributionPoint.master_distribution_point api: @api
552
552
  file = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
553
553
  if file.exist?
554
554
  file.delete
@@ -631,7 +631,7 @@ module JSS
631
631
  # in >=9.72: jamf install -package foo.pkg -path http://mycasper.myorg.edu/CasperShare/Packages/foo.pkg
632
632
  #
633
633
  append_at_vers = JSS.parse_jss_version('9.72')[:version]
634
- our_vers = JSS.parse_jss_version(JSS.api_connection.server.raw_version)[:version]
634
+ our_vers = JSS.parse_jss_version(@api.server.raw_version)[:version]
635
635
  no_filename_in_url = (our_vers < append_at_vers)
636
636
 
637
637
  # use a provided alternative url for an http download
@@ -642,7 +642,7 @@ module JSS
642
642
 
643
643
  # use our appropriate dist. point for download
644
644
  else
645
- mdp = JSS::DistributionPoint.my_distribution_point
645
+ mdp = JSS::DistributionPoint.my_distribution_point api: @api
646
646
 
647
647
  ### how do we access our dist. point? with http?
648
648
  if mdp.http_downloads_enabled && !(args[:no_http])
@@ -129,7 +129,7 @@ module JSS
129
129
  if args[:id] == :new
130
130
  raise JSS::InvalidDataError, "New Peripherals must have a :type, which must be one of those defined in the JSS." unless args[:type]
131
131
  @type = args[:type]
132
- raise JSS::InvalidDataError, "No peripheral type '#{@type}' in the JSS" unless JSS::PeripheralType.all_names(:refresh).include? @type
132
+ raise JSS::InvalidDataError, "No peripheral type '#{@type}' in the JSS" unless JSS::PeripheralType.all_names(:refresh, api: @api).include? @type
133
133
  @fields = {}
134
134
  @rest_rsrc = 'peripherals/id/-1'
135
135
  @site = "None"
@@ -231,11 +231,11 @@ module JSS
231
231
  ###
232
232
  def associate(computer)
233
233
  if computer =~ /^d+$/
234
- raise JSS::NoSuchItemError, "No computer in the JSS with id #{computer}" unless JSS::Computer.all_ids.include? computer
234
+ raise JSS::NoSuchItemError, "No computer in the JSS with id #{computer}" unless JSS::Computer.all_ids(api: @api).include? computer
235
235
  @computer_id = computer
236
236
  else
237
- raise JSS::NoSuchItemError, "No computer in the JSS with name #{computer}" unless JSS::Computer.all_names.include? computer
238
- @computer_id = JSS::Computer.map_all_ids_to(:name).invert[computer]
237
+ raise JSS::NoSuchItemError, "No computer in the JSS with name #{computer}" unless JSS::Computer.all_names(api: @api).include? computer
238
+ @computer_id = JSS::Computer.map_all_ids_to(:name, api: @api).invert[computer]
239
239
  end
240
240
  @need_to_update = true
241
241
  end
@@ -268,7 +268,7 @@ module JSS
268
268
  ###
269
269
  def check_field(field, value)
270
270
  ### get the field defs for this PeriphType, omitting the leading nil
271
- @field_defs ||= JSS::PeripheralType.new(:name => @type).fields.compact
271
+ @field_defs ||= JSS::PeripheralType.new(:name => @type, api: @api).fields.compact
272
272
 
273
273
  ### we must have the right number of fields, and they must have the same names
274
274
  ### as the definition
@@ -1055,12 +1055,12 @@ module JSS
1055
1055
  opts[:fut] = false if opts[:fut].nil?
1056
1056
  opts[:update_autorun] = false if opts[:update_autorun].nil?
1057
1057
 
1058
- id = JSS::Package.valid_id identifier
1058
+ id = JSS::Package.valid_id identifier, api: @api
1059
1059
  raise JSS::NoSuchItemError, "No package matches '#{identifier}'" unless id
1060
1060
 
1061
1061
  return nil if @packages.map { |p| p[:id] }.include? id
1062
1062
 
1063
- name = JSS::Package.map_all_ids_to(:name)[id]
1063
+ name = JSS::Package.map_all_ids_to(:name, api: @api)[id]
1064
1064
 
1065
1065
  position = case opts[:position]
1066
1066
  when :start then 0
@@ -1163,11 +1163,11 @@ module JSS
1163
1163
  opts[:position] ||= -1
1164
1164
  opts[:priority] ||= :after
1165
1165
 
1166
- raise JSS::NoSuchItemError, "No script matches '#{identifier}'" unless (id = JSS::Script.valid_id(identifier))
1166
+ raise JSS::NoSuchItemError, "No script matches '#{identifier}'" unless (id = JSS::Script.valid_id(identifier, api: @api))
1167
1167
 
1168
1168
  return nil if @scripts.map { |s| s[:id] }.include? id
1169
1169
 
1170
- name = JSS::Script.map_all_ids_to(:name)[id]
1170
+ name = JSS::Script.map_all_ids_to(:name, api: @api)[id]
1171
1171
 
1172
1172
  position = case opts[:position]
1173
1173
  when :start then 0
@@ -1291,7 +1291,7 @@ module JSS
1291
1291
 
1292
1292
  interval = "#{LOG_FLUSH_INTERVAL_INTEGERS[older_than]}+#{LOG_FLUSH_INTERVAL_PERIODS[period]}"
1293
1293
 
1294
- JSS.api_connection.delete_rsrc "#{LOG_FLUSH_RSRC}/policy/id/#{@id}/interval/#{interval}"
1294
+ @api.delete_rsrc "#{LOG_FLUSH_RSRC}/policy/id/#{@id}/interval/#{interval}"
1295
1295
  end
1296
1296
 
1297
1297
  ###### Aliases
@@ -109,11 +109,11 @@ module JSS
109
109
 
110
110
  def site=(new_val)
111
111
  if new_val.is_a? Integer
112
- raise JSS::NoSuchItemError, "No site found with id #{new_val}" unless JSS::Site.all_ids.include? new_val
113
- new_val = JSS::Site.map_all_ids_to(:name)[new_val]
112
+ raise JSS::NoSuchItemError, "No site found with id #{new_val}" unless JSS::Site.all_ids(api: @api).include? new_val
113
+ new_val = JSS::Site.map_all_ids_to(:name, api: @api)[new_val]
114
114
  else
115
115
  new_val = new_val.to_s
116
- raise JSS::NoSuchItemError, "No site found with name #{new_val}" unless JSS::Site.all_names.include? new_val
116
+ raise JSS::NoSuchItemError, "No site found with name #{new_val}" unless JSS::Site.all_names(api: @api).include? new_val
117
117
  end
118
118
  @site = new_val
119
119
  @need_to_update = true
@@ -121,7 +121,7 @@ module JSS
121
121
 
122
122
  def create
123
123
  raise JSS::MissingDataError, 'process_name must be set before creating' if @process_name.to_s.empty?
124
- raise JSS::AlreadyExistsError, "A #{RSRC_OBJECT_KEY} named #{@name} already exists in the JSS" if self.class.all_names(:refresh).include? @name
124
+ raise JSS::AlreadyExistsError, "A #{RSRC_OBJECT_KEY} named #{@name} already exists in the JSS" if self.class.all_names(:refresh, api: @api).include? @name
125
125
  super
126
126
  end
127
127
 
@@ -595,15 +595,15 @@ module JSS
595
595
  ###
596
596
  def check_name(key, name)
597
597
 
598
- found_in_jss = SCOPING_CLASSES[key].all_names.include?(name)
598
+ found_in_jss = SCOPING_CLASSES[key].all_names(api: @api).include?(name)
599
599
 
600
600
  return true if found_in_jss
601
601
 
602
602
  return false unless CHECK_LDAP_KEYS.include?(key)
603
603
 
604
604
  begin
605
- return JSS::LDAPServer.user_in_ldap?(name) if LDAP_USER_KEYS.include?(key)
606
- return JSS::LDAPServer.group_in_ldap?(name) if LDAP_GROUP_KEYS.include?(key)
605
+ return JSS::LDAPServer.user_in_ldap?(name, api: @api) if LDAP_USER_KEYS.include?(key)
606
+ return JSS::LDAPServer.group_in_ldap?(name, api: @api) if LDAP_GROUP_KEYS.include?(key)
607
607
 
608
608
  # if an ldap server isn't connected, make a note of it and return true
609
609
  rescue JSS::InvalidConnectionError
@@ -468,7 +468,7 @@ module JSS
468
468
 
469
469
  # otherwise, get it from the dist. point
470
470
  else
471
- dist_point = JSS::DistributionPoint.my_distribution_point
471
+ dist_point = JSS::DistributionPoint.my_distribution_point api: @api
472
472
 
473
473
  ### how do we access our dist. point?
474
474
  if dist_point.http_downloads_enabled
@@ -272,9 +272,9 @@ module JSS
272
272
  # @return [void]
273
273
  #
274
274
  def add_self_service_category(new_cat, display_in: true, feature_in: false)
275
- new_cat = JSS::Category.map_all_ids_to(:name)[new_cat] if new_cat.is_a? Integer
275
+ new_cat = JSS::Category.map_all_ids_to(:name, api: @api)[new_cat] if new_cat.is_a? Integer
276
276
  feature_in = false if display_in == false
277
- raise JSS::NoSuchItemError, "No category '#{new_cat}' in the JSS" unless JSS::Category.all_names(:refresh).include? new_cat
277
+ raise JSS::NoSuchItemError, "No category '#{new_cat}' in the JSS" unless JSS::Category.all_names(:refresh, api: @api).include? new_cat
278
278
 
279
279
  raise JSS::InvalidDataError, 'display_in must be true or false' unless display_in.jss_boolean?
280
280
 
@@ -482,7 +482,7 @@ module JSS
482
482
  #
483
483
  def refresh_icon
484
484
  return nil unless @in_jss
485
- fresh_data = JSS.api_connection.get_rsrc(@rest_rsrc)[self.class::RSRC_OBJECT_KEY]
485
+ fresh_data = @api.get_rsrc(@rest_rsrc)[self.class::RSRC_OBJECT_KEY]
486
486
  icon_data = fresh_data[:self_service][:self_service_icon]
487
487
  @icon = JSS::Icon.new icon_data
488
488
  end # refresh icon
@@ -29,7 +29,8 @@ module JSS
29
29
  # An Icon in the JSS, used in Self Service.
30
30
  #
31
31
  # At the moment, icons are not API objects, they are collections of data
32
- # stored in the JSS that might be included in some API object's Self Service data.
32
+ # stored in the JSS that might be included in some API object's
33
+ # Self Service data.
33
34
  #
34
35
  # The data available for an icon are:
35
36
  #
@@ -38,13 +39,17 @@ module JSS
38
39
  # - uri: the uri to download or preview the icon
39
40
  # - data: the icon file itself, base-64 encoded.
40
41
  #
41
- # Icon instances are read-only. To change the icon for an self-servable object,
42
+ # Icon instances are read-only. To change the icon for a self-servable object,
42
43
  # see {SelfServable#icon=}.
43
44
  #
44
45
  # NOTE: Since icons are not APIObjects, there's no way to see a list of them
45
46
  # via the API. The JSS::Icon class methods .all, .all_ids, and .all_names
46
47
  # require MySQL database access. See {JSS::DBConnection}.
47
48
  #
49
+ # This also means, if you use multiple API connections, you'll have to
50
+ # make sure to connect to the correct MySQL server for the
51
+ # APIConnection you care about.
52
+ #
48
53
  class Icon
49
54
 
50
55
  # Class Methods
@@ -79,7 +79,7 @@ module JSS
79
79
  raise JSS::UnsupportedError, "Editing #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." unless UPDATABLE
80
80
  raise JSS::InvalidDataError, "Names can't be empty!" if newname.to_s.empty?
81
81
  raise JSS::AlreadyExistsError, "A #{self.class::RSRC_OBJECT_KEY} named '#{newname}' already exsists in the JSS" \
82
- if self.class.all_names(:refresh).include? newname
82
+ if self.class.all_names(:refresh, api: @api).include? newname
83
83
  @name = newname
84
84
  @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name}" if @rest_rsrc.include? '/name/'
85
85
  @need_to_update = true
@@ -93,7 +93,7 @@ module JSS
93
93
  return nil unless @need_to_update
94
94
  raise JSS::UnsupportedError, "Editing #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." unless UPDATABLE
95
95
  raise JSS::NoSuchItemError, "Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY} in the JSS before updating it." unless @in_jss
96
- JSS.api_connection.put_rsrc @rest_rsrc, rest_xml
96
+ @api.put_rsrc @rest_rsrc, rest_xml
97
97
  @need_to_update = false
98
98
  refresh_icon if self_servable?
99
99
  @id
@@ -130,7 +130,7 @@ module JSS
130
130
  file = File.new local_file.to_s, 'rb'
131
131
 
132
132
  # upload it!
133
- JSS.api_connection.cnx[upload_rsrc].post name: file
133
+ @api.cnx[upload_rsrc].post name: file
134
134
  end # def upload file
135
135
 
136
136
  end # module FileUpload
@@ -209,7 +209,7 @@ module JSS
209
209
 
210
210
  ###
211
211
  def ldap_server= (new_val)
212
- raise JSS::InvalidDataError, "No LDAP server in the JSS named #{new_val}" unless JSS::LDAPServer.all_names.include? new_val
212
+ raise JSS::InvalidDataError, "No LDAP server in the JSS named #{new_val}" unless JSS::LDAPServer.all_names(api: @api).include? new_val
213
213
  @ldap_server = new_val
214
214
  @need_to_update = true
215
215
  end
@@ -223,7 +223,7 @@ module JSS
223
223
  ###
224
224
  def add_site (site)
225
225
  return nil if @sites.map{|s| s[:name]}.include? site
226
- raise JSS::InvalidDataError, "No site in the JSS named #{site}" unless JSS::Site.all_names.include? site
226
+ raise JSS::InvalidDataError, "No site in the JSS named #{site}" unless JSS::Site.all_names(api: @api).include? site
227
227
  @sites << {:name => site}
228
228
  @need_to_update = true
229
229
  end
@@ -71,22 +71,37 @@ module JSS
71
71
  ###
72
72
  ### @param opts[Hash] the options for building the .pkg
73
73
  ###
74
- ### @options opts :pkg_id[String] the full package if for the new pkg.
74
+ ### @options opts :pkg_id[String] the full package if for the new pkg.
75
75
  ### e.g. 'com.mycompany.myapp'
76
76
  ###
77
77
  ### @option opts :bundle_id_prefix[String] the pkg bundle identifier prefix.
78
- ### If no :pkg_id is provided, one is made using this prefix and
79
- ### the name provided. e.g. 'com.mycompany'
78
+ ### If no :pkg_id is provided, one is made using this prefix and
79
+ ### the name provided. e.g. 'com.mycompany'
80
80
  ### Defaults to '{PKG_BUNDLE_ID_PFX}'. See 'man pkgbuild' for more info
81
81
  ###
82
- ### @option opts :out_dir[String,Pathname] he folder in which the .pkg will be
82
+ ### @option opts :out_dir[String,Pathname] he folder in which the .pkg will be
83
83
  ### created. Defaults to {DEFAULT_OUT_DIR}
84
84
  ###
85
- ### @option opts :preserve_ownership[Boolean] If true, the owner/group of the
85
+ ### @option opts :preserve_ownership[Boolean] If true, the owner/group of the
86
86
  ### rootpath are preserved.
87
- ### Default is false: they become the pkgbuild/installer "recommended"
87
+ ### Default is false: they become the pkgbuild/installer "recommended"
88
88
  ### (root/wheel or root/admin)
89
89
  ###
90
+ ### @option opts :signing_identity[String] the name of the signing identity to
91
+ ### use for signing the pkg. See `man pkgbuild` for details
92
+ ###
93
+ ### @option opts :keychain[String,Pathname] the path to the keychain
94
+ ### containing the the signing identity. See `man pkgbuild` for details
95
+ ###
96
+ ### @option opts :certs[String,Array<String>] the Common Name(s) of additional
97
+ ### certificates to include when signing the pkg. See `man pkgbuild` for
98
+ ### details
99
+ ###
100
+ ### @option opts :include_timestamp[Boolean] should a trusted timestamp be
101
+ ### included when signing the pkg. See `man pkgbuild` for details.
102
+ ### Default depends on the situation, but true is the same as using
103
+ ### --timestamp with pkgbuild, and false is --timestamp=none
104
+ ###
90
105
  ### @return [Pathname] the local path to the new .pkg
91
106
  ###
92
107
  def self.mk_pkg(name, version, root, opts = {})
@@ -101,6 +116,20 @@ module JSS
101
116
  pkg_out = "#{opts[:out_dir]}/#{pkg_filename}"
102
117
  pkg_ownership = opts[:preserve_ownership] ? "preserve" : "recommended"
103
118
 
119
+ if opts[:signing_identity]
120
+ signing = "--sign #{Shellwords.escape opts[:signing_identity]}"
121
+ signing << " --keychain #{Shellwords.escape opts[:keychain].to_s}" if opts[:keychain]
122
+ signing << ' --timestamp' if opts[:include_timestamp]
123
+ signing << ' --timestamp=none' if opts[:include_timestamp] == false
124
+ case opts[:certs]
125
+ when Array
126
+ opts[:certs].each { |c| signing << " --cert #{Shellwords.escape c}" }
127
+ when String
128
+ signing << " --cert #{Shellwords.escape opts[:certs]}"
129
+ end # case
130
+ else
131
+ signing = ''
132
+ end # if opts[:signing_identity]
104
133
 
105
134
  ### first, run 'analyze' to get a 'component plist' in which we can change some settings
106
135
  ### for any bundles in the root (bundles like .apps, frameworks, plugins, etc..)
@@ -138,9 +167,9 @@ module JSS
138
167
 
139
168
  ### now build the pkg
140
169
  begin
141
- system "#{PKGBUILD} --identifier '#{pkg_id}' --version '#{version}' --ownership #{pkg_ownership} --install-location / --root '#{root}' #{comp_plist_arg} '#{pkg_out}' "
170
+ it_built = system "#{PKGBUILD} --identifier '#{pkg_id}' --version '#{version}' --ownership #{pkg_ownership} --install-location / --root '#{root}' #{signing} #{comp_plist_arg} '#{pkg_out}' "
142
171
 
143
- raise RuntimeError, "There was an error building the .pkg" unless $?.exitstatus == 0
172
+ raise RuntimeError, "There was an error building the .pkg" unless it_built
144
173
  ensure
145
174
  comp_plist_out.delete if comp_plist_out.exist?
146
175
  end
@@ -182,5 +211,3 @@ module JSS
182
211
 
183
212
  end # module Composer
184
213
  end # module JSS
185
-
186
-
@@ -1,39 +1,39 @@
1
- ### Copyright 2017 Pixar
1
+ # Copyright 2017 Pixar
2
2
 
3
- ###
4
- ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
- ### with the following modification; you may not use this file except in
6
- ### compliance with the Apache License and the following modification to it:
7
- ### Section 6. Trademarks. is deleted and replaced with:
8
- ###
9
- ### 6. Trademarks. This License does not grant permission to use the trade
10
- ### names, trademarks, service marks, or product names of the Licensor
11
- ### and its affiliates, except as required to comply with Section 4(c) of
12
- ### the License and to reproduce the content of the NOTICE file.
13
- ###
14
- ### You may obtain a copy of the Apache License at
15
- ###
16
- ### http://www.apache.org/licenses/LICENSE-2.0
17
- ###
18
- ### Unless required by applicable law or agreed to in writing, software
19
- ### distributed under the Apache License with the above modification is
20
- ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
- ### KIND, either express or implied. See the Apache License for the specific
22
- ### language governing permissions and limitations under the Apache License.
23
- ###
24
- ###
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ # with the following modification; you may not use this file except in
6
+ # compliance with the Apache License and the following modification to it:
7
+ # Section 6. Trademarks. is deleted and replaced with:
8
+ #
9
+ # 6. Trademarks. This License does not grant permission to use the trade
10
+ # names, trademarks, service marks, or product names of the Licensor
11
+ # and its affiliates, except as required to comply with Section 4(c) of
12
+ # the License and to reproduce the content of the NOTICE file.
13
+ #
14
+ # You may obtain a copy of the Apache License at
15
+ #
16
+ # http://www.apache.org/licenses/LICENSE-2.0
17
+ #
18
+ # Unless required by applicable law or agreed to in writing, software
19
+ # distributed under the Apache License with the above modification is
20
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ # KIND, either express or implied. See the Apache License for the specific
22
+ # language governing permissions and limitations under the Apache License.
23
+ #
24
+ #
25
25
 
26
- ###
26
+ #
27
27
  class String
28
28
 
29
- ### Convert the strings "true" and "false"
30
- ### (after stripping whitespace and downcasing)
31
- ### to TrueClass and FalseClass respectively
32
- ###
33
- ### Return nil if any other string.
34
- ###
35
- ### @return [Boolean,nil] the boolean value
36
- ###
29
+ # Convert the strings "true" and "false"
30
+ # (after stripping whitespace and downcasing)
31
+ # to TrueClass and FalseClass respectively
32
+ #
33
+ # Return nil if any other string.
34
+ #
35
+ # @return [Boolean,nil] the boolean value
36
+ #
37
37
  def jss_to_bool
38
38
  case strip.downcase
39
39
  when 'true' then true
@@ -41,24 +41,33 @@ class String
41
41
  end # case
42
42
  end # to bool
43
43
 
44
- ### Convert a string to a Time object
45
- ###
46
- ### returns nil if not parsable by JSS::parse_datetime
47
- ###
48
- ### @return [Time] the time represented by the string.
49
- ###
44
+ # Convert a string to a Time object
45
+ #
46
+ # returns nil if not parsable by JSS::parse_datetime
47
+ #
48
+ # @return [Time] the time represented by the string.
49
+ #
50
50
  def jss_to_time
51
51
  JSS.parse_time self
52
52
  rescue
53
53
  return nil
54
54
  end
55
55
 
56
- ### Convert a String to a Pathname object
57
- ###
58
- ### @return [Pathname]
59
- ###
56
+ # Convert a String to a Pathname object
57
+ #
58
+ # @return [Pathname]
59
+ #
60
60
  def jss_to_pathname
61
61
  Pathname.new self
62
62
  end
63
63
 
64
+ # Is this string also a positive integer?
65
+ # (i.e. it consists only of numberic digits)
66
+ #
67
+ # @return [Boolean]
68
+ #
69
+ def jss_integer?
70
+ self =~ /\A[0-9]+\Z/ ? true : false
71
+ end
72
+
64
73
  end # class