ruby-jss 0.9.2 → 0.10.0a1

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.

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