jss-api 0.5.8 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +55 -7
- data/README.md +2 -1
- data/bin/cgrouper +1 -1
- data/bin/subnet-update +1 -1
- data/lib/jss-api.rb +2 -363
- data/lib/jss-api/api_connection.rb +78 -15
- data/lib/jss-api/api_object.rb +1 -1
- data/lib/jss-api/api_object/advanced_search.rb +1 -1
- data/lib/jss-api/api_object/advanced_search/advanced_computer_search.rb +1 -1
- data/lib/jss-api/api_object/advanced_search/advanced_mobile_device_search.rb +1 -1
- data/lib/jss-api/api_object/advanced_search/advanced_user_search.rb +1 -1
- data/lib/jss-api/api_object/building.rb +1 -1
- data/lib/jss-api/api_object/category.rb +1 -1
- data/lib/jss-api/api_object/computer.rb +1 -1
- data/lib/jss-api/api_object/creatable.rb +1 -1
- data/lib/jss-api/api_object/criteriable.rb +1 -1
- data/lib/jss-api/api_object/criteriable/criteria.rb +1 -1
- data/lib/jss-api/api_object/criteriable/criterion.rb +1 -1
- data/lib/jss-api/api_object/department.rb +1 -1
- data/lib/jss-api/api_object/distribution_point.rb +92 -22
- data/lib/jss-api/api_object/extendable.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/extension_attribute/user_extension_attribute.rb +1 -1
- data/lib/jss-api/api_object/group.rb +1 -1
- data/lib/jss-api/api_object/group/computer_group.rb +1 -1
- data/lib/jss-api/api_object/group/mobile_device_group.rb +1 -1
- data/lib/jss-api/api_object/group/user_group.rb +1 -1
- data/lib/jss-api/api_object/ldap_server.rb +1 -1
- data/lib/jss-api/api_object/locatable.rb +1 -1
- data/lib/jss-api/api_object/matchable.rb +1 -1
- data/lib/jss-api/api_object/mobile_device.rb +1 -1
- data/lib/jss-api/api_object/netboot_server.rb +1 -1
- data/lib/jss-api/api_object/network_segment.rb +1 -1
- data/lib/jss-api/api_object/osx_configuration_profile.rb +1 -1
- data/lib/jss-api/api_object/package.rb +117 -64
- data/lib/jss-api/api_object/peripheral.rb +1 -1
- data/lib/jss-api/api_object/peripheral_type.rb +1 -1
- data/lib/jss-api/api_object/policy.rb +1 -1
- data/lib/jss-api/api_object/purchasable.rb +1 -1
- data/lib/jss-api/api_object/removable_macaddr.rb +1 -1
- data/lib/jss-api/api_object/scopable.rb +1 -1
- data/lib/jss-api/api_object/scopable/scope.rb +1 -1
- data/lib/jss-api/api_object/script.rb +1 -1
- data/lib/jss-api/api_object/self_servable.rb +1 -1
- data/lib/jss-api/api_object/site.rb +1 -1
- data/lib/jss-api/api_object/software_update_server.rb +1 -1
- data/lib/jss-api/api_object/updatable.rb +1 -1
- data/lib/jss-api/api_object/uploadable.rb +1 -1
- data/lib/jss-api/api_object/user.rb +1 -1
- data/lib/jss-api/client.rb +22 -21
- data/lib/jss-api/compatibility.rb +1 -1
- data/lib/jss-api/composer.rb +2 -2
- data/lib/jss-api/configuration.rb +1 -1
- data/lib/jss-api/db_connection.rb +63 -12
- data/lib/jss-api/exceptions.rb +1 -1
- data/lib/jss-api/ruby_extensions.rb +1 -1
- data/lib/jss-api/ruby_extensions/filetest.rb +1 -1
- data/lib/jss-api/ruby_extensions/hash.rb +1 -1
- data/lib/jss-api/ruby_extensions/ipaddr.rb +1 -1
- data/lib/jss-api/ruby_extensions/pathname.rb +1 -1
- data/lib/jss-api/ruby_extensions/string.rb +17 -1
- data/lib/jss-api/ruby_extensions/time.rb +1 -1
- data/lib/jss-api/server.rb +1 -1
- data/lib/jss-api/utility.rb +416 -0
- data/lib/jss-api/version.rb +8 -8
- metadata +3 -2
@@ -1,25 +1,25 @@
|
|
1
|
-
### Copyright
|
2
|
-
###
|
1
|
+
### Copyright 2016 Pixar
|
2
|
+
###
|
3
3
|
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
4
4
|
### with the following modification; you may not use this file except in
|
5
5
|
### compliance with the Apache License and the following modification to it:
|
6
6
|
### Section 6. Trademarks. is deleted and replaced with:
|
7
|
-
###
|
7
|
+
###
|
8
8
|
### 6. Trademarks. This License does not grant permission to use the trade
|
9
9
|
### names, trademarks, service marks, or product names of the Licensor
|
10
10
|
### and its affiliates, except as required to comply with Section 4(c) of
|
11
11
|
### the License and to reproduce the content of the NOTICE file.
|
12
|
-
###
|
12
|
+
###
|
13
13
|
### You may obtain a copy of the Apache License at
|
14
|
-
###
|
14
|
+
###
|
15
15
|
### http://www.apache.org/licenses/LICENSE-2.0
|
16
|
-
###
|
16
|
+
###
|
17
17
|
### Unless required by applicable law or agreed to in writing, software
|
18
18
|
### distributed under the Apache License with the above modification is
|
19
19
|
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
20
20
|
### KIND, either express or implied. See the Apache License for the specific
|
21
21
|
### language governing permissions and limitations under the Apache License.
|
22
|
-
###
|
22
|
+
###
|
23
23
|
###
|
24
24
|
|
25
25
|
###
|
@@ -86,6 +86,8 @@ module JSS
|
|
86
86
|
### The possible values for cpu_type (required_processor) in a JSS package
|
87
87
|
CPU_TYPES = ["None", "x86", "ppc"]
|
88
88
|
|
89
|
+
# TO DO - this is redundant with DEFAULT_PROCESSOR, but both are in use
|
90
|
+
# clean them up!
|
89
91
|
### which is default? there must be one to make a new pkg
|
90
92
|
DEFAULT_CPU_TYPE = "None"
|
91
93
|
|
@@ -115,10 +117,10 @@ module JSS
|
|
115
117
|
|
116
118
|
### @return [String] the filename of the .pkg, .mpkg, or .dmg on the Casper server
|
117
119
|
attr_reader :filename
|
118
|
-
|
119
|
-
### @return [Pathname] the local receipt when this pkg is installed
|
120
|
+
|
121
|
+
### @return [Pathname] the local receipt when this pkg is installed
|
120
122
|
attr_reader :receipt
|
121
|
-
|
123
|
+
|
122
124
|
### @return [Boolean] does this item 'Fill Existing Users' when jamf installs it?
|
123
125
|
attr_reader :fill_existing_users
|
124
126
|
|
@@ -130,16 +132,16 @@ module JSS
|
|
130
132
|
|
131
133
|
### @return [Array<String>] the OS versions this can be installed onto. For all minor versions, the format is 10.5.x
|
132
134
|
attr_reader :os_requirements
|
133
|
-
|
135
|
+
|
134
136
|
### @return [String] limit installation to these architectures: 'x86', 'ppc', 'None'
|
135
137
|
attr_reader :required_processor
|
136
|
-
|
138
|
+
|
137
139
|
### @return [String] the name of a pkg to install (or "Do Not Install") when this pkg can't be installed
|
138
140
|
attr_reader :switch_with_package
|
139
141
|
|
140
142
|
### @return [Boolean] can this item be uninstalled? Some, e.g. OS Updates, can't
|
141
143
|
attr_reader :allow_uninstalled
|
142
|
-
|
144
|
+
|
143
145
|
### @return [String] the category of this pkg, stored in the JSS as the id number from the categories table
|
144
146
|
attr_reader :category
|
145
147
|
|
@@ -151,16 +153,16 @@ module JSS
|
|
151
153
|
|
152
154
|
### @return [Boolean] only install this pkg if it's available in the commandline softwareupdate.
|
153
155
|
attr_reader :install_if_reported_available
|
154
|
-
|
156
|
+
|
155
157
|
### @return [Boolean] should this pkg be installed on the boot volume during imaging
|
156
158
|
attr_reader :boot_volume_required
|
157
|
-
|
159
|
+
|
158
160
|
### @return [Integer] Priority to use for deploying or uninstalling the package
|
159
161
|
attr_reader :priority
|
160
162
|
|
161
163
|
### @return [Boolean] does this pkg cause a notification to be sent on self-heal?
|
162
164
|
attr_reader :send_notification
|
163
|
-
|
165
|
+
|
164
166
|
|
165
167
|
###
|
166
168
|
### @see JSS::APIObject#initialize
|
@@ -173,6 +175,7 @@ module JSS
|
|
173
175
|
@allow_uninstalled = @init_data[:allow_uninstalled]
|
174
176
|
@boot_volume_required = @init_data[:boot_volume_required]
|
175
177
|
@category = JSS::APIObject.get_name(@init_data[:category])
|
178
|
+
@category = nil if @category.to_s.casecmp("No category assigned") == 0
|
176
179
|
@filename = @init_data[:filename] || @init_data[:name]
|
177
180
|
@fill_existing_users = @init_data[:fill_existing_users]
|
178
181
|
@fill_user_template = @init_data[:fill_user_template]
|
@@ -185,12 +188,12 @@ module JSS
|
|
185
188
|
@priority = @init_data[:priority] || DEFAULT_PRIORITY
|
186
189
|
@reboot_required = @init_data[:reboot_required]
|
187
190
|
@required_processor = @init_data[:required_processor] || DEFAULT_CPU_TYPE
|
191
|
+
@required_processor = nil if @required_processor.to_s.casecmp('none') == 0
|
188
192
|
@send_notification = @init_data[:send_notification]
|
189
193
|
@switch_with_package = @init_data[:switch_with_package] || DO_NOT_INSTALL
|
190
|
-
|
194
|
+
|
191
195
|
# the receipt is the filename with any .zip extension removed.
|
192
|
-
@receipt = @
|
193
|
-
|
196
|
+
@receipt = @filename ? (JSS::Client::RECEIPTS_FOLDER + @filename.to_s.sub(/.zip$/, '')) : nil
|
194
197
|
end # init
|
195
198
|
|
196
199
|
|
@@ -478,7 +481,7 @@ module JSS
|
|
478
481
|
def installed?
|
479
482
|
@receipt.file?
|
480
483
|
end
|
481
|
-
|
484
|
+
|
482
485
|
###
|
483
486
|
### Upload a locally-readable file to the master distribution point.
|
484
487
|
### If the file is a directory (like a bundle .pk/.mpkg) it will be zipped before
|
@@ -489,7 +492,7 @@ module JSS
|
|
489
492
|
###
|
490
493
|
### @param local_file_path[String,Pathname] the local path to the file to be uploaded
|
491
494
|
###
|
492
|
-
### @param rw_pw[String,Symbol] the password for the read/write account on the master Distribution Point,
|
495
|
+
### @param rw_pw[String,Symbol] the password for the read/write account on the master Distribution Point,
|
493
496
|
### or :prompt, or :stdin# where # is the line of stdin containing the password See {JSS::DistributionPoint#mount}
|
494
497
|
###
|
495
498
|
### @param unmount[Boolean] whether or not ot unount the distribution point when finished.
|
@@ -499,7 +502,7 @@ module JSS
|
|
499
502
|
def upload_master_file (local_file_path, rw_pw, unmount = true)
|
500
503
|
|
501
504
|
raise JSS::NoSuchItemError, "Please create this package in the JSS before uploading it." unless @in_jss
|
502
|
-
|
505
|
+
|
503
506
|
mdp = JSS::DistributionPoint.master_distribution_point
|
504
507
|
destination = mdp.mount(rw_pw, :rw) +"#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
|
505
508
|
|
@@ -534,11 +537,11 @@ module JSS
|
|
534
537
|
local_path = zipfile
|
535
538
|
|
536
539
|
self.filename = zipfile.basename.to_s
|
537
|
-
|
540
|
+
|
538
541
|
end # if directory
|
539
542
|
self.update
|
540
543
|
FileUtils.copy_entry local_path, destination
|
541
|
-
|
544
|
+
|
542
545
|
mdp.unmount if unmount
|
543
546
|
end # upload
|
544
547
|
|
@@ -569,21 +572,23 @@ module JSS
|
|
569
572
|
end # delete master file
|
570
573
|
|
571
574
|
|
575
|
+
### Install this package via the jamf binary 'install' command from the
|
576
|
+
### distribution point for this machine.
|
577
|
+
### See {JSS::DistributionPoint.my_distribution_point}
|
572
578
|
###
|
573
579
|
### @note This code must be run as root to install packages
|
574
580
|
###
|
575
|
-
###
|
576
|
-
###
|
577
|
-
###
|
578
|
-
### The read-only or http passwd for the dist. point must be provided, except for
|
579
|
-
### non-authenticated http downloads)
|
581
|
+
### The read-only or http passwd for the dist. point must be provided,
|
582
|
+
### except for non-authenticated http downloads)
|
580
583
|
###
|
581
584
|
### @param args[Hash] the arguments for installation
|
582
585
|
###
|
583
|
-
### @option args :ro_pw[String] the read-only or http password for the
|
584
|
-
###
|
586
|
+
### @option args :ro_pw[String] the read-only or http password for the
|
587
|
+
### distribution point for the local machine
|
588
|
+
### (http will be used if available, and may not need a pw)
|
585
589
|
###
|
586
|
-
### @option args :target[String,Pathname] The drive on which to install
|
590
|
+
### @option args :target[String,Pathname] The drive on which to install
|
591
|
+
### the package, defaults to '/'
|
587
592
|
###
|
588
593
|
### @option args :verbose [Boolean] be verbose to stdout, defaults to false
|
589
594
|
###
|
@@ -591,14 +596,21 @@ module JSS
|
|
591
596
|
###
|
592
597
|
### @option args :fut[Boolean] fill user template, defaults to false
|
593
598
|
###
|
594
|
-
### @option args :unmount[Boolean] unmount the distribution point when
|
595
|
-
### defaults to false
|
599
|
+
### @option args :unmount[Boolean] unmount the distribution point when
|
600
|
+
### finished?(if we mounted it), defaults to false
|
601
|
+
###
|
602
|
+
### @option args :no_http[Boolean] don't use http downloads even if they
|
603
|
+
### are enabled for the dist. point.
|
596
604
|
###
|
597
|
-
### @option args :
|
605
|
+
### @option args :alt_download_url [String] Use this url for an http
|
606
|
+
### download, regardless of distribution point settings. This can be used
|
607
|
+
### to access Cloud Distribution Points if the fileshare isn't available.
|
608
|
+
### The URL should already be ur
|
609
|
+
### The package filename will be removed or appended as needed.
|
598
610
|
###
|
599
|
-
### @return [
|
611
|
+
### @return [Boolean] did the jamf install succeed?
|
600
612
|
###
|
601
|
-
### @todo deal with cert-based https authentication
|
613
|
+
### @todo deal with cert-based https authentication in dist points
|
602
614
|
###
|
603
615
|
def install (args = {})
|
604
616
|
|
@@ -608,46 +620,73 @@ module JSS
|
|
608
620
|
|
609
621
|
ro_pw = args[:ro_pw]
|
610
622
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
+
# as of Casper 9.72, with http downloads, the jamf binary requires
|
624
|
+
# the filename must be at the end of the -path url, but before 9.72
|
625
|
+
# it can't be.
|
626
|
+
# e.g.
|
627
|
+
# in <9.72: jamf install -package foo.pkg -path http://mycasper.myorg.edu/CasperShare/Packages
|
628
|
+
# but
|
629
|
+
# in >=9.72: jamf install -package foo.pkg -path http://mycasper.myorg.edu/CasperShare/Packages/foo.pkg
|
630
|
+
#
|
631
|
+
append_at_vers = JSS.parse_jss_version("9.72")[:version]
|
632
|
+
our_vers = JSS.parse_jss_version(JSS::API.server.raw_version)[:version]
|
633
|
+
no_filename_in_url = (our_vers < append_at_vers)
|
634
|
+
|
635
|
+
# use a provided alternative url for an http download
|
636
|
+
if args[:alt_download_url]
|
637
|
+
|
638
|
+
# we'll re-add the filename below if needed.
|
639
|
+
src_path = args[:alt_download_url].chomp "/#{@filename}"
|
640
|
+
|
641
|
+
# use our appropriate dist. point for download
|
642
|
+
else
|
643
|
+
mdp = JSS::DistributionPoint.my_distribution_point
|
644
|
+
|
645
|
+
### how do we access our dist. point? with http?
|
646
|
+
if mdp.http_downloads_enabled and (not args[:no_http])
|
647
|
+
using_http = true
|
648
|
+
src_path = mdp.http_url
|
649
|
+
if mdp.username_password_required
|
650
|
+
raise JSS::MissingDataError, "No password provided for http download" unless ro_pw
|
651
|
+
raise JSS::InvaldDatatError, "Incorrect password for http access to distribution point." unless mdp.check_pw(:http, ro_pw)
|
652
|
+
# insert the name and pw into the uri
|
653
|
+
reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]") # we'll escape all the chars that aren't unreserved
|
654
|
+
src_path = src_path.sub(%r{(https?://)(\S)}, "#{$1}#{URI.escape mdp.http_username,reserved_chars}:#{URI.escape ro_pw, reserved_chars}@#{$2}")
|
655
|
+
end
|
656
|
+
|
657
|
+
# or with filesharing?
|
658
|
+
else
|
659
|
+
using_http = false
|
660
|
+
src_path = mdp.mount(ro_pw)
|
623
661
|
end
|
624
662
|
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
663
|
+
# look at the pkgs folder
|
664
|
+
src_path += "#{DIST_POINT_PKGS_FOLDER}"
|
665
|
+
end # if args[:alt_download_url]
|
666
|
+
|
667
|
+
src_path += "/#{@filename}" unless no_filename_in_url
|
630
668
|
|
631
|
-
# look at the pkgs folder
|
632
|
-
src_path += "/#{DIST_POINT_PKGS_FOLDER}"
|
633
669
|
|
634
670
|
### are we doing "fill existing users" or "fill user template"?
|
635
671
|
do_feu = args[:feu] ? "-feu" : ""
|
636
672
|
do_fut = args[:fut] ? "-fut" : ""
|
637
673
|
|
638
674
|
### the install args for jamf
|
639
|
-
command_args = "-package '#{@filename}' -path '#{src_path}' -target '#{args[:target]}' #{do_feu} #{do_fut} -showProgress -verbose
|
675
|
+
command_args = "-package '#{@filename}' -path '#{src_path}' -target '#{args[:target]}' #{do_feu} #{do_fut} -showProgress -verbose"
|
640
676
|
|
641
|
-
### run it via a client
|
677
|
+
### run it via a client cmd
|
642
678
|
install_out = JSS::Client.run_jamf :install, command_args, args[:verbose]
|
643
679
|
|
644
|
-
|
680
|
+
install_out =~ %r{<exitCode>(\d+)</exitCode>}
|
681
|
+
install_exit = $1 ? $1.to_i : nil
|
682
|
+
install_exit ||= $?.exitstatus
|
683
|
+
|
645
684
|
|
646
685
|
if (args.include? :unmount)
|
647
686
|
mdp.unmount unless using_http
|
648
687
|
end
|
649
688
|
|
650
|
-
return install_exit
|
689
|
+
return install_exit == 0 ? true : false
|
651
690
|
end
|
652
691
|
|
653
692
|
###
|
@@ -668,7 +707,7 @@ module JSS
|
|
668
707
|
### @return [Process::Status] the result of the 'jamf uninstall' command
|
669
708
|
###
|
670
709
|
def uninstall (args = {})
|
671
|
-
|
710
|
+
|
672
711
|
raise JSS::UnsupportedError, \
|
673
712
|
"This package cannot be uninstalled. Please use CasperAdmin to index it and allow uninstalls" unless removable?
|
674
713
|
raise JSS::UnsupportedError, "You must have root privileges to uninstall packages" unless JSS.superuser?
|
@@ -689,6 +728,18 @@ module JSS
|
|
689
728
|
|
690
729
|
|
691
730
|
|
731
|
+
### What type of package is this?
|
732
|
+
###
|
733
|
+
### @return [Symbol] :pkg or :dmg or:unknown
|
734
|
+
###
|
735
|
+
def type
|
736
|
+
case @filename
|
737
|
+
when /\.m?pkg(\.zip)?$/ then :pkg
|
738
|
+
when /\.dmg$/ then :dmg
|
739
|
+
else :unknown
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
692
743
|
|
693
744
|
################################
|
694
745
|
### Private Instance Methods
|
@@ -706,7 +757,7 @@ module JSS
|
|
706
757
|
pkg = doc.add_element "package"
|
707
758
|
pkg.add_element('allow_uninstalled').text = @allow_uninstalled
|
708
759
|
pkg.add_element('boot_volume_required').text = @boot_volume_required
|
709
|
-
pkg.add_element('category').text = @category
|
760
|
+
pkg.add_element('category').text = @category.to_s.casecmp("No category assigned") == 0 ? "" : @category
|
710
761
|
pkg.add_element('filename').text = @filename
|
711
762
|
pkg.add_element('fill_existing_users').text = @fill_existing_users
|
712
763
|
pkg.add_element('fill_user_template').text = @fill_user_template
|
@@ -717,7 +768,7 @@ module JSS
|
|
717
768
|
pkg.add_element('os_requirements').text = JSS.to_s_and_a(@os_requirements)[:stringform]
|
718
769
|
pkg.add_element('priority').text = @priority
|
719
770
|
pkg.add_element('reboot_required').text = @reboot_required
|
720
|
-
pkg.add_element('required_processor').text = @required_processor
|
771
|
+
pkg.add_element('required_processor').text = @required_processor.to_s.empty? ? "None" : @required_processor
|
721
772
|
pkg.add_element('send_notification').text = @send_notification
|
722
773
|
pkg.add_element('switch_with_package').text = @switch_with_package
|
723
774
|
return doc.to_s
|
@@ -741,7 +792,7 @@ module JSS
|
|
741
792
|
alias boot boot_volume_required
|
742
793
|
alias boot? boot_volume_required
|
743
794
|
alias notify send_notification
|
744
|
-
|
795
|
+
|
745
796
|
alias removable= allow_uninstalled=
|
746
797
|
alias boot= boot_volume_required=
|
747
798
|
alias feu= fill_existing_users=
|
@@ -754,6 +805,8 @@ module JSS
|
|
754
805
|
|
755
806
|
|
756
807
|
|
808
|
+
|
809
|
+
|
757
810
|
end # class Package
|
758
811
|
|
759
812
|
end # module jss
|