ruby-jss 1.2.9 → 1.5.1

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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +196 -1
  3. data/lib/jamf.rb +10 -3
  4. data/lib/jamf/api/abstract_classes/collection_resource.rb +329 -150
  5. data/lib/jamf/api/abstract_classes/generic_reference.rb +9 -1
  6. data/lib/jamf/api/abstract_classes/json_object.rb +107 -83
  7. data/lib/jamf/api/abstract_classes/prestage.rb +55 -30
  8. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +21 -0
  9. data/lib/jamf/api/abstract_classes/resource.rb +4 -4
  10. data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
  11. data/lib/jamf/api/connection.rb +20 -12
  12. data/lib/jamf/api/connection/api_error.rb +8 -8
  13. data/lib/jamf/api/connection/token.rb +36 -15
  14. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +14 -1
  15. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  16. data/lib/jamf/api/json_objects/device_enrollment_device_sync_state.rb +81 -0
  17. data/lib/jamf/api/json_objects/locale.rb +59 -0
  18. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  19. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  20. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  21. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  22. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  23. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  24. data/lib/jamf/api/mixins/change_log.rb +201 -51
  25. data/lib/jamf/api/mixins/filterable.rb +51 -0
  26. data/lib/jamf/api/mixins/pageable.rb +208 -0
  27. data/lib/jamf/api/mixins/sortable.rb +59 -0
  28. data/lib/jamf/api/resources/collection_resources/building.rb +19 -8
  29. data/lib/jamf/api/resources/collection_resources/category.rb +5 -3
  30. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +11 -4
  31. data/lib/jamf/api/resources/collection_resources/department.rb +1 -1
  32. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +13 -13
  33. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  34. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +24 -22
  35. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  36. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  37. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +14 -14
  38. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  39. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  40. data/lib/jamf/configuration.rb +7 -9
  41. data/lib/jamf/ruby_extensions.rb +1 -0
  42. data/lib/jamf/ruby_extensions/array.rb +1 -1
  43. data/lib/jamf/ruby_extensions/array/utils.rb +3 -3
  44. data/lib/jamf/ruby_extensions/dig.rb +52 -0
  45. data/lib/jamf/validate.rb +63 -24
  46. data/lib/jamf/version.rb +1 -1
  47. data/lib/jss.rb +4 -1
  48. data/lib/jss/api_connection.rb +110 -397
  49. data/lib/jss/api_object.rb +16 -13
  50. data/lib/jss/api_object/advanced_search.rb +27 -26
  51. data/lib/jss/api_object/app_store_country_codes.rb +298 -0
  52. data/lib/jss/api_object/categorizable.rb +1 -1
  53. data/lib/jss/api_object/computer.rb +5 -1
  54. data/lib/jss/api_object/configuration_profile.rb +34 -3
  55. data/lib/jss/api_object/directory_binding.rb +273 -0
  56. data/lib/jss/api_object/directory_binding_type.rb +96 -0
  57. data/lib/jss/api_object/directory_binding_type/active_directory.rb +539 -0
  58. data/lib/jss/api_object/directory_binding_type/admitmac.rb +594 -0
  59. data/lib/jss/api_object/directory_binding_type/centrify.rb +226 -0
  60. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  61. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  62. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  63. data/lib/jss/api_object/distribution_point.rb +97 -37
  64. data/lib/jss/api_object/dock_item.rb +143 -0
  65. data/lib/jss/api_object/ebook.rb +1 -2
  66. data/lib/jss/api_object/extendable.rb +68 -32
  67. data/lib/jss/api_object/extension_attribute.rb +4 -3
  68. data/lib/jss/api_object/group.rb +33 -2
  69. data/lib/jss/api_object/mac_application.rb +107 -8
  70. data/lib/jss/api_object/mobile_device.rb +3 -0
  71. data/lib/jss/api_object/mobile_device_application.rb +12 -0
  72. data/lib/jss/api_object/network_segment.rb +195 -70
  73. data/lib/jss/api_object/package.rb +105 -40
  74. data/lib/jss/api_object/patch_source.rb +10 -9
  75. data/lib/jss/api_object/policy.rb +491 -7
  76. data/lib/jss/api_object/printer.rb +446 -0
  77. data/lib/jss/api_object/scopable.rb +10 -15
  78. data/lib/jss/api_object/scopable/scope.rb +386 -71
  79. data/lib/jss/api_object/self_servable.rb +17 -9
  80. data/lib/jss/api_object/uploadable.rb +1 -1
  81. data/lib/jss/api_object/user.rb +42 -1
  82. data/lib/jss/api_object/vpp_account.rb +209 -0
  83. data/lib/jss/api_object/vppable.rb +169 -13
  84. data/lib/jss/composer.rb +1 -1
  85. data/lib/jss/exceptions.rb +3 -0
  86. data/lib/jss/server.rb +15 -0
  87. data/lib/jss/utility.rb +8 -22
  88. data/lib/jss/validate.rb +53 -10
  89. data/lib/jss/version.rb +1 -1
  90. metadata +50 -22
@@ -849,11 +849,7 @@ module JSS
849
849
  raise ArgumentError, 'Missing searchterm or fetch key'
850
850
  end
851
851
 
852
- begin
853
- return new fetch_rsrc: fetch_rsrc, api: api
854
- rescue RestClient::NotFound
855
- raise JSS::NoSuchItemError, "No #{self::RSRC_OBJECT_KEY} found #{err_detail}" unless fetch_rsrc
856
- end
852
+ new fetch_rsrc: fetch_rsrc, api: api
857
853
  end # fetch
858
854
 
859
855
  # Fetch the mostly- or fully-raw JSON or XML data for an object of this
@@ -895,8 +891,6 @@ module JSS
895
891
  return data if format == :json || as_string
896
892
 
897
893
  REXML::Document.new(data)
898
- rescue RestClient::NotFound
899
- raise JSS::NoSuchItemError, "No #{self} with id #{id}"
900
894
  end
901
895
 
902
896
  # PUT some raw XML to the API for a given id in this subclass.
@@ -925,8 +919,6 @@ module JSS
925
919
  validate_not_metaclass(self)
926
920
  rsrc = "#{self::RSRC_BASE}/id/#{id}"
927
921
  REXML::Document.new(api.put_rsrc rsrc, xml.to_s)
928
- rescue RestClient::NotFound
929
- raise JSS::NoSuchItemError, "No #{self} with id #{id}"
930
922
  end
931
923
 
932
924
  # POST some raw XML to the API for a given id in this subclass.
@@ -1222,8 +1214,10 @@ module JSS
1222
1214
  # @return [void]
1223
1215
  #
1224
1216
  def delete
1225
- return nil unless @in_jss
1217
+ return unless @in_jss
1218
+
1226
1219
  @api.delete_rsrc @rest_rsrc
1220
+
1227
1221
  @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name.to_s}"
1228
1222
  @id = nil
1229
1223
  @in_jss = false
@@ -1350,7 +1344,10 @@ module JSS
1350
1344
  #
1351
1345
  def ppx
1352
1346
  return nil unless creatable? || updatable?
1353
- REXML::Document.new(rest_xml).write $stdout, 2
1347
+
1348
+ formatter = REXML::Formatters::Pretty.new(2)
1349
+ formatter.compact = true
1350
+ formatter.write(REXML::Document.new(rest_xml), $stdout)
1354
1351
  puts
1355
1352
  end
1356
1353
 
@@ -1422,8 +1419,6 @@ module JSS
1422
1419
  end
1423
1420
 
1424
1421
  raw_json[args[:rsrc_object_key]]
1425
- rescue RestClient::ResourceNotFound
1426
- raise NoSuchItemError, "No #{self.class::RSRC_OBJECT_KEY} found matching resource #{rsrc}"
1427
1422
  end
1428
1423
 
1429
1424
  # Start examining the @init_data recieved from the API
@@ -1655,9 +1650,13 @@ require 'jss/api_object/category'
1655
1650
  require 'jss/api_object/computer'
1656
1651
  require 'jss/api_object/computer_invitation'
1657
1652
  require 'jss/api_object/department'
1653
+ require 'jss/api_object/disk_encryption_configurations'
1654
+ require "jss/api_object/directory_binding_type"
1655
+ require 'jss/api_object/directory_binding'
1658
1656
  require 'jss/api_object/distribution_point'
1659
1657
  require 'jss/api_object/ebook'
1660
1658
  require 'jss/api_object/ibeacon'
1659
+ require 'jss/api_object/dock_item'
1661
1660
  require 'jss/api_object/ldap_server'
1662
1661
  require 'jss/api_object/mac_application'
1663
1662
  require 'jss/api_object/mobile_device'
@@ -1677,5 +1676,9 @@ require 'jss/api_object/site'
1677
1676
  require 'jss/api_object/software_update_server'
1678
1677
  require 'jss/api_object/user'
1679
1678
  require 'jss/api_object/webhook'
1679
+ require 'jss/api_object/printer'
1680
+
1681
+ ### Other
1682
+ require 'jss/api_object/app_store_country_codes'
1680
1683
 
1681
1684
  JSS::APIObject.define_identifier_list_methods
@@ -62,6 +62,7 @@ module JSS
62
62
  include JSS::Criteriable
63
63
  include JSS::Sitable
64
64
 
65
+
65
66
  # Class Constants
66
67
  #####################################
67
68
 
@@ -85,6 +86,22 @@ module JSS
85
86
  #
86
87
  attr_reader :search_results
87
88
 
89
+ # @return [Array<String>] the fields to be returned with the search results
90
+ #
91
+ # The API delivers these as an array of Hashes,
92
+ # where each hash has only one key, :name => the name of the fields/ExtAttrib
93
+ # to display. It should probably not have the underlying Hashes, and just
94
+ # be an array of names. This class converts it to just an Array of field names
95
+ # (Strings) for internal use.
96
+ #
97
+ # These fields are returned in the @search_results
98
+ # data along with :id, :name, and other unique identifiers
99
+ # for each found item. In that data, their names have colons removed, abd
100
+ # spaces and dashes converted to underscores, and they are
101
+ # symbolized. See attribute result_display_keys
102
+ #
103
+ attr_reader :display_fields
104
+
88
105
  # @return [Array<Symbol>]
89
106
  #
90
107
  # The search result Hash keys for the {#display_fields} of the search
@@ -95,8 +112,9 @@ module JSS
95
112
  # methods are for.
96
113
  #
97
114
  # However, when those names come back as the Hash Keys of the {#search_results}
98
- # they (inconsistently) have spaces and/or dashes converted to underscores, and,
99
- # the JSON module converts the keys to Symbols, so they don't match the {#display_fields}.
115
+ # they (inconsistently) have spaces and/or dashes converted to underscores,
116
+ # and colons are removed. The JSON module then converts the keys to Symbols,
117
+ # so they don't match the {#display_fields}.
100
118
  #
101
119
  # For example, the display field "Last Check-in" might come back as any of these Symbols:
102
120
  # - :"Last Check-in"
@@ -147,13 +165,13 @@ module JSS
147
165
  # make sure each hash of the search results
148
166
  # has a key matching a standard key.
149
167
  #
150
- @search_results.each do |hash|
151
- hash.keys.each do |key|
152
- std_key = key.to_s.gsub(/ |-/, '_').to_sym
153
- next if hash[std_key]
154
- hash[std_key] = hash[key]
155
- end
156
- end
168
+ # @search_results.each do |hash|
169
+ # hash.keys.each do |key|
170
+ # std_key = key.to_s.gsub(':', '').gsub(/ |-/, '_').to_sym
171
+ # next if hash[std_key]
172
+ # hash[std_key] = hash[key]
173
+ # end
174
+ # end
157
175
  end # init
158
176
 
159
177
  # Public Instance Methods
@@ -231,23 +249,6 @@ module JSS
231
249
  end
232
250
  end
233
251
 
234
- # @return [Array<String>] the fields to be returned with the search results
235
- #
236
- # The API delivers these as an array of Hashes,
237
- # where each hash has only one key, :name => the name of the fields/ExtAttrib
238
- # to display. It should probably not have the underlying Hashes, and just
239
- # be an array of names. This class converts it to just an Array of field names
240
- # (Strings) for internal use.
241
- #
242
- # These fields are returned in the @search_results
243
- # data along with :id, :name, and other unique identifiers
244
- # for each found item. In that data, their names have
245
- # spaces and dashes converted to underscores, and they are
246
- # symbolized.
247
- #
248
- #
249
- attr_reader :display_fields
250
-
251
252
  # Set the list of fields to be retrieved with the
252
253
  # search results.
253
254
  #
@@ -0,0 +1,298 @@
1
+ ### Copyright 2020 Pixar
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
+ ###
25
+
26
+ ###
27
+ module JSS
28
+
29
+ # Return the names and codes containing a given string
30
+ # (case insentitive).
31
+ #
32
+ # @param str [String] the string to look for, must be >=2 chars long
33
+ #
34
+ # @return [Hash] the country names => codes that contain the string.
35
+ #
36
+ def self.country_code_match(str)
37
+ raise ArgumentError, 'Match string must be at least 2 characters long' if str.size < 2
38
+
39
+ str = str.to_s.upcase
40
+ APP_STORE_COUNTRY_CODES.select { |n, c| n.upcase.include?(str) || c.include?(str) }
41
+ end
42
+
43
+ # The official names and two-letter codes for countries known to the App Store.
44
+ # These were retrieved from the Jamf Pro API endpoint in August 2020.
45
+ # They should be updated regularly. To do so using the Jamf Module, just
46
+ # replace this Hash with the one you get from:
47
+ # Jamf::AppStoreCountryCodes.codes_by_name
48
+ #
49
+ APP_STORE_COUNTRY_CODES = {
50
+ 'Afghanistan' => 'AF',
51
+ 'Aland Islands' => 'AX',
52
+ 'Albania' => 'AL',
53
+ 'Algeria' => 'DZ',
54
+ 'American Samoa' => 'AS',
55
+ 'Andorra' => 'AD',
56
+ 'Angola' => 'AO',
57
+ 'Anguilla' => 'AI',
58
+ 'Antarctica' => 'AQ',
59
+ 'Antigua and Barbuda' => 'AG',
60
+ 'Argentina' => 'AR',
61
+ 'Armenia' => 'AM',
62
+ 'Aruba' => 'AW',
63
+ 'Australia' => 'AU',
64
+ 'Austria' => 'AT',
65
+ 'Azerbaijan' => 'AZ',
66
+ 'Bahamas' => 'BS',
67
+ 'Bahrain' => 'BH',
68
+ 'Bangladesh' => 'BD',
69
+ 'Barbados' => 'BB',
70
+ 'Belarus' => 'BY',
71
+ 'Belgium' => 'BE',
72
+ 'Belize' => 'BZ',
73
+ 'Benin' => 'BJ',
74
+ 'Bermuda' => 'BM',
75
+ 'Bhutan' => 'BT',
76
+ 'Bolivia, Plurinational State of' => 'BO',
77
+ 'Bosnia and Herzegovina' => 'BA',
78
+ 'Botswana' => 'BW',
79
+ 'Bouvet Island' => 'BV',
80
+ 'Brazil' => 'BR',
81
+ 'British Indian Ocean Territory' => 'IO',
82
+ 'Brunei Darussalam' => 'BN',
83
+ 'Bulgaria' => 'BG',
84
+ 'Burkina Faso' => 'BF',
85
+ 'Burundi' => 'BI',
86
+ 'Cambodia' => 'KH',
87
+ 'Cameroon' => 'CM',
88
+ 'Canada' => 'CA',
89
+ 'Cape Verde' => 'CV',
90
+ 'Cayman Islands' => 'KY',
91
+ 'Central African Republic' => 'CF',
92
+ 'Chad' => 'TD',
93
+ 'Chile' => 'CL',
94
+ 'China' => 'CN',
95
+ 'Christmas Island' => 'CX',
96
+ 'Cocos (Keeling) Islands' => 'CC',
97
+ 'Colombia' => 'CO',
98
+ 'Comoros' => 'KM',
99
+ 'Congo' => 'CG',
100
+ 'Congo, the Democratic Republic of the' => 'CD',
101
+ 'Cook Islands' => 'CK',
102
+ 'Costa Rica' => 'CR',
103
+ "Cote d'Ivoire" => 'CI',
104
+ 'Croatia' => 'HR',
105
+ 'Cuba' => 'CU',
106
+ 'Cyprus' => 'CY',
107
+ 'Czech Republic' => 'CZ',
108
+ 'Denmark' => 'DK',
109
+ 'Djibouti' => 'DJ',
110
+ 'Dominica' => 'DM',
111
+ 'Dominican Republic' => 'DO',
112
+ 'Ecuador' => 'EC',
113
+ 'Egypt' => 'EG',
114
+ 'El Salvador' => 'SV',
115
+ 'Equatorial Guinea' => 'GQ',
116
+ 'Eritrea' => 'ER',
117
+ 'Estonia' => 'EE',
118
+ 'Ethiopia' => 'ET',
119
+ 'Falkland Islands (Malvinas)' => 'FK',
120
+ 'Faroe Islands' => 'FO',
121
+ 'Fiji' => 'FJ',
122
+ 'Finland' => 'FI',
123
+ 'France' => 'FR',
124
+ 'French Guiana' => 'GF',
125
+ 'French Polynesia' => 'PF',
126
+ 'French Southern Territories' => 'TF',
127
+ 'Gabon' => 'GA',
128
+ 'Gambia' => 'GM',
129
+ 'Georgia' => 'GE',
130
+ 'Germany' => 'DE',
131
+ 'Ghana' => 'GH',
132
+ 'Gibraltar' => 'GI',
133
+ 'Greece' => 'GR',
134
+ 'Greenland' => 'GL',
135
+ 'Grenada' => 'GD',
136
+ 'Guadeloupe' => 'GP',
137
+ 'Guam' => 'GU',
138
+ 'Guatemala' => 'GT',
139
+ 'Guernsey' => 'GG',
140
+ 'Guinea' => 'GN',
141
+ 'Guinea-Bissau' => 'GW',
142
+ 'Guyana' => 'GY',
143
+ 'Haiti' => 'HT',
144
+ 'Heard Island and McDonald Islands' => 'HM',
145
+ 'Holy See (Vatican City State)' => 'VA',
146
+ 'Honduras' => 'HN',
147
+ 'Hong Kong' => 'HK',
148
+ 'Hungary' => 'HU',
149
+ 'Iceland' => 'IS',
150
+ 'India' => 'IN',
151
+ 'Indonesia' => 'ID',
152
+ 'Iran, Islamic Republic of' => 'IR',
153
+ 'Iraq' => 'IQ',
154
+ 'Ireland' => 'IE',
155
+ 'Isle of Man' => 'IM',
156
+ 'Israel' => 'IL',
157
+ 'Italy' => 'IT',
158
+ 'Jamaica' => 'JM',
159
+ 'Japan' => 'JP',
160
+ 'Jersey' => 'JE',
161
+ 'Jordan' => 'JO',
162
+ 'Kazakhstan' => 'KZ',
163
+ 'Kenya' => 'KE',
164
+ 'Kiribati' => 'KI',
165
+ "Korea, Democratic People's Republic of" => 'KP',
166
+ 'Korea, Republic of' => 'KR',
167
+ 'Kuwait' => 'KW',
168
+ 'Kyrgyzstan' => 'KG',
169
+ "Lao People's Democratic Republic" => 'LA',
170
+ 'Latvia' => 'LV',
171
+ 'Lebanon' => 'LB',
172
+ 'Lesotho' => 'LS',
173
+ 'Liberia' => 'LR',
174
+ 'Libyan Arab Jamahiriya' => 'LY',
175
+ 'Liechtenstein' => 'LI',
176
+ 'Lithuania' => 'LT',
177
+ 'Luxembourg' => 'LU',
178
+ 'Macao' => 'MO',
179
+ 'Macedonia, the former Yugoslav Republic of' => 'MK',
180
+ 'Madagascar' => 'MG',
181
+ 'Malawi' => 'MW',
182
+ 'Malaysia' => 'MY',
183
+ 'Maldives' => 'MV',
184
+ 'Mali' => 'ML',
185
+ 'Malta' => 'MT',
186
+ 'Marshall Islands' => 'MH',
187
+ 'Martinique' => 'MQ',
188
+ 'Mauritania' => 'MR',
189
+ 'Mauritius' => 'MU',
190
+ 'Mayotte' => 'YT',
191
+ 'Mexico' => 'MX',
192
+ 'Micronesia, Federated States of' => 'FM',
193
+ 'Moldova, Republic of' => 'MD',
194
+ 'Monaco' => 'MC',
195
+ 'Mongolia' => 'MN',
196
+ 'Montenegro' => 'ME',
197
+ 'Montserrat' => 'MS',
198
+ 'Morocco' => 'MA',
199
+ 'Mozambique' => 'MZ',
200
+ 'Myanmar' => 'MM',
201
+ 'Namibia' => 'NA',
202
+ 'Nauru' => 'NR',
203
+ 'Nepal' => 'NP',
204
+ 'Netherlands' => 'NL',
205
+ 'Netherlands Antilles' => 'AN',
206
+ 'New Caledonia' => 'NC',
207
+ 'New Zealand' => 'NZ',
208
+ 'Nicaragua' => 'NI',
209
+ 'Niger' => 'NE',
210
+ 'Nigeria' => 'NG',
211
+ 'Niue' => 'NU',
212
+ 'Norfolk Island' => 'NF',
213
+ 'Northern Mariana Islands' => 'MP',
214
+ 'Norway' => 'NO',
215
+ 'Oman' => 'OM',
216
+ 'Pakistan' => 'PK',
217
+ 'Palau' => 'PW',
218
+ 'Palestinian Territory, Occupied' => 'PS',
219
+ 'Panama' => 'PA',
220
+ 'Papua New Guinea' => 'PG',
221
+ 'Paraguay' => 'PY',
222
+ 'Peru' => 'PE',
223
+ 'Philippines' => 'PH',
224
+ 'Pitcairn' => 'PN',
225
+ 'Poland' => 'PL',
226
+ 'Portugal' => 'PT',
227
+ 'Puerto Rico' => 'PR',
228
+ 'Qatar' => 'QA',
229
+ 'Reunion' => 'RE',
230
+ 'Romania' => 'RO',
231
+ 'Russian Federation' => 'RU',
232
+ 'Rwanda' => 'RW',
233
+ 'Saint Barthelemy' => 'BL',
234
+ 'Saint Helena, Ascension and Tristan da Cunha' => 'SH',
235
+ 'Saint Kitts and Nevis' => 'KN',
236
+ 'Saint Lucia' => 'LC',
237
+ 'Saint Martin (French part)' => 'MF',
238
+ 'Saint Pierre and Miquelon' => 'PM',
239
+ 'Saint Vincent and the Grenadines' => 'VC',
240
+ 'Samoa' => 'WS',
241
+ 'San Marino' => 'SM',
242
+ 'Sao Tome and Principe' => 'ST',
243
+ 'Saudi Arabia' => 'SA',
244
+ 'Senegal' => 'SN',
245
+ 'Serbia' => 'RS',
246
+ 'Seychelles' => 'SC',
247
+ 'Sierra Leone' => 'SL',
248
+ 'Singapore' => 'SG',
249
+ 'Slovakia' => 'SK',
250
+ 'Slovenia' => 'SI',
251
+ 'Solomon Islands' => 'SB',
252
+ 'Somalia' => 'SO',
253
+ 'South Africa' => 'ZA',
254
+ 'South Georgia and the South Sandwich Islands' => 'GS',
255
+ 'Spain' => 'ES',
256
+ 'Sri Lanka' => 'LK',
257
+ 'Sudan' => 'SD',
258
+ 'Suriname' => 'SR',
259
+ 'Svalbard and Jan Mayen' => 'SJ',
260
+ 'Swaziland' => 'SZ',
261
+ 'Sweden' => 'SE',
262
+ 'Switzerland' => 'CH',
263
+ 'Syrian Arab Republic' => 'SY',
264
+ 'Taiwan, Province of China' => 'TW',
265
+ 'Tajikistan' => 'TJ',
266
+ 'Tanzania, United Republic of' => 'TZ',
267
+ 'Thailand' => 'TH',
268
+ 'Timor-Leste' => 'TL',
269
+ 'Togo' => 'TG',
270
+ 'Tokelau' => 'TK',
271
+ 'Tonga' => 'TO',
272
+ 'Trinidad and Tobago' => 'TT',
273
+ 'Tunisia' => 'TN',
274
+ 'Turkey' => 'TR',
275
+ 'Turkmenistan' => 'TM',
276
+ 'Turks and Caicos Islands' => 'TC',
277
+ 'Tuvalu' => 'TV',
278
+ 'Uganda' => 'UG',
279
+ 'Ukraine' => 'UA',
280
+ 'United Arab Emirates' => 'AE',
281
+ 'United Kingdom' => 'GB',
282
+ 'United States' => 'US',
283
+ 'United States Minor Outlying Islands' => 'UM',
284
+ 'Uruguay' => 'UY',
285
+ 'Uzbekistan' => 'UZ',
286
+ 'Vanuatu' => 'VU',
287
+ 'Venezuela, Bolivarian Republic of' => 'VE',
288
+ 'Viet Nam' => 'VN',
289
+ 'Virgin Islands, British' => 'VG',
290
+ 'Virgin Islands, U.S.' => 'VI',
291
+ 'Wallis and Futuna' => 'WF',
292
+ 'Western Sahara' => 'EH',
293
+ 'Yemen' => 'YE',
294
+ 'Zambia' => 'ZM',
295
+ 'Zimbabwe' => 'ZW'
296
+ }.freeze
297
+
298
+ end # JSS