diff options
author | Marc A. Paradise <marc.paradise@gmail.com> | 2021-03-09 11:33:24 -0500 |
---|---|---|
committer | Marc A. Paradise <marc.paradise@gmail.com> | 2021-03-10 12:57:09 -0500 |
commit | f3a0dab093a23836de6488a29c3ae0031c1524bd (patch) | |
tree | c75f2e371b7f140b7567c26bae72843eeb523fbd | |
parent | e53e48d0f937a14f49c99d03e216ad989c6231da (diff) | |
download | chef-f3a0dab093a23836de6488a29c3ae0031c1524bd.tar.gz |
Add supporting gem files
Signed-off-by: Marc A. Paradise <marc.paradise@gmail.com>
-rw-r--r-- | knife/Gemfile | 13 | ||||
-rw-r--r-- | knife/Gemfile.lock | 336 | ||||
-rw-r--r-- | knife/LICENSE | 201 | ||||
-rw-r--r-- | knife/README.md | 35 | ||||
-rwxr-xr-x | knife/bin/knife | 24 | ||||
-rw-r--r-- | knife/knife.gemspec | 72 | ||||
-rw-r--r-- | knife/spec/spec_helper.rb | 332 | ||||
-rw-r--r-- | knife/spec/tiny_server.rb | 190 |
8 files changed, 1203 insertions, 0 deletions
diff --git a/knife/Gemfile b/knife/Gemfile new file mode 100644 index 0000000000..46492c1437 --- /dev/null +++ b/knife/Gemfile @@ -0,0 +1,13 @@ + +gemspec + +source "https://rubygems.org" + +gem "cheffish", ">= 14" # testing only , but why didn't this need to explicit in chef? +gem "webmock" # testing only +gem "rake" +gem "chef", path: ".." +gem "ohai", git: "https://github.com/chef/ohai.git", branch: "master" + +gem "chef-utils", path: File.expand_path("chef-utils", __dir__) if File.exist?(File.expand_path("chef-utils", __dir__)) +gem "chef-config", path: File.expand_path("chef-config", __dir__) if File.exist?(File.expand_path("chef-config", __dir__)) diff --git a/knife/Gemfile.lock b/knife/Gemfile.lock new file mode 100644 index 0000000000..d475162266 --- /dev/null +++ b/knife/Gemfile.lock @@ -0,0 +1,336 @@ +GIT + remote: https://github.com/chef/ohai.git + revision: 2397af29ecc3c3e849d817a8519d32866aab89ff + branch: master + specs: + ohai (17.0.24) + chef-config (>= 12.8, < 18) + chef-utils (>= 16.0, < 18) + ffi (~> 1.9) + ffi-yajl (~> 2.2) + ipaddress + mixlib-cli (>= 1.7.0) + mixlib-config (>= 2.0, < 4.0) + mixlib-log (>= 2.0.1, < 4.0) + mixlib-shellout (>= 2.0, < 4.0) + plist (~> 3.1) + train-core + wmi-lite (~> 1.0) + +PATH + remote: .. + specs: + chef (17.0.134) + addressable + bcrypt_pbkdf (~> 1.1) + chef-config (= 17.0.134) + chef-utils (= 17.0.134) + chef-vault + chef-zero (>= 14.0.11) + diff-lcs (>= 1.2.4, < 1.4.0) + ed25519 (~> 1.2) + erubis (~> 2.7) + ffi (>= 1.9.25, < 1.14.0) + ffi-libarchive (~> 1.0, >= 1.0.3) + ffi-yajl (~> 2.2) + highline (>= 1.6.9, < 3) + iniparse (~> 1.4) + inspec-core (~> 4.23) + license-acceptance (>= 1.0.5, < 3) + mixlib-archive (>= 0.4, < 2.0) + mixlib-authentication (>= 2.1, < 4) + mixlib-cli (>= 2.1.1, < 3.0) + mixlib-log (>= 2.0.3, < 4.0) + mixlib-shellout (>= 3.1.1, < 4.0) + net-sftp (>= 2.1.2, < 4.0) + net-ssh (>= 5.1, < 7) + net-ssh-multi (~> 1.2, >= 1.2.1) + ohai (~> 17.0) + pastel + plist (~> 3.2) + proxifier (~> 1.0) + syslog-logger (~> 1.6) + train-core (~> 3.2, >= 3.2.28) + train-winrm (>= 0.2.5) + tty-prompt (~> 0.21) + tty-screen (~> 0.6) + tty-table (~> 0.11) + uuidtools (>= 2.1.5, < 3.0) + chef-config (17.0.134) + addressable + chef-utils (= 17.0.134) + fuzzyurl + mixlib-config (>= 2.2.12, < 4.0) + mixlib-shellout (>= 2.0, < 4.0) + tomlrb (~> 1.2) + chef-utils (17.0.134) + +PATH + remote: . + specs: + knife (17.0.134) + bcrypt_pbkdf (~> 1.1) + chef (= 17.0.134) + chef-config (= 17.0.134) + chef-utils (= 17.0.134) + chef-vault + ed25519 (~> 1.2) + erubis (~> 2.7) + ffi (>= 1.9.25, < 1.14.0) + ffi-yajl (~> 2.2) + highline (>= 1.6.9, < 3) + license-acceptance (>= 1.0.5, < 3) + mixlib-archive (>= 0.4, < 2.0) + mixlib-cli (>= 2.1.1, < 3.0) + net-ssh (>= 5.1, < 7) + net-ssh-multi (~> 1.2, >= 1.2.1) + ohai (~> 17.0) + pastel + train-core (~> 3.2, >= 3.2.28) + train-winrm (>= 0.2.5) + tty-prompt (~> 0.21) + tty-screen (~> 0.6) + tty-table (~> 0.11) + +GEM + remote: https://rubygems.org/ + specs: + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + ast (2.4.2) + bcrypt_pbkdf (1.1.0) + builder (3.2.4) + chef-telemetry (1.0.29) + chef-config + concurrent-ruby (~> 1.0) + chef-vault (4.1.0) + chef-zero (15.0.4) + ffi-yajl (~> 2.2) + hashie (>= 2.0, < 5.0) + mixlib-log (>= 2.0, < 4.0) + rack (~> 2.0, >= 2.0.6) + uuidtools (~> 2.1) + webrick + cheffish (16.0.12) + chef-zero (>= 14.0) + net-ssh + chefstyle (1.7.1) + rubocop (= 1.10.0) + coderay (1.1.3) + concurrent-ruby (1.1.8) + crack (0.4.5) + rexml + diff-lcs (1.3) + ed25519 (1.2.4) + erubi (1.10.0) + erubis (2.7.0) + faraday (1.3.0) + faraday-net_http (~> 1.0) + multipart-post (>= 1.2, < 3) + ruby2_keywords + faraday-net_http (1.0.1) + faraday_middleware (1.0.0) + faraday (~> 1.0) + ffi (1.13.1) + ffi-libarchive (1.0.17) + ffi (~> 1.0) + ffi-yajl (2.3.4) + libyajl2 (~> 1.2) + fuzzyurl (0.9.0) + gssapi (1.3.1) + ffi (>= 1.0.1) + gyoku (1.3.1) + builder (>= 2.1.2) + hashdiff (1.0.1) + hashie (4.1.0) + highline (2.0.3) + httpclient (2.8.3) + iniparse (1.5.0) + inspec-core (4.26.13) + addressable (~> 2.4) + chef-telemetry (~> 1.0) + faraday (>= 0.9.0, < 1.4) + faraday_middleware (~> 1.0) + hashie (>= 3.4, < 5.0) + license-acceptance (>= 0.2.13, < 3.0) + method_source (>= 0.8, < 2.0) + mixlib-log (~> 3.0) + multipart-post (~> 2.0) + parallel (~> 1.9) + parslet (>= 1.5, < 2.0) + pry (~> 0.13) + rspec (>= 3.9, < 3.11) + rspec-its (~> 1.2) + rubyzip (>= 1.2.2, < 3.0) + semverse (~> 3.0) + sslshake (~> 1.2) + thor (>= 0.20, < 2.0) + tomlrb (>= 1.2, < 2.1) + train-core (~> 3.0) + tty-prompt (~> 0.17) + tty-table (~> 0.10) + ipaddress (0.8.3) + json (2.5.1) + libyajl2 (1.2.0) + license-acceptance (2.1.13) + pastel (~> 0.7) + tomlrb (>= 1.2, < 3.0) + tty-box (~> 0.6) + tty-prompt (~> 0.20) + little-plugger (1.1.4) + logging (2.3.0) + little-plugger (~> 1.1) + multi_json (~> 1.14) + method_source (1.0.0) + mixlib-archive (1.1.7) + mixlib-log + mixlib-authentication (3.0.7) + mixlib-cli (2.1.8) + mixlib-config (3.0.9) + tomlrb + mixlib-log (3.0.9) + mixlib-shellout (3.2.5) + chef-utils + multi_json (1.15.0) + multipart-post (2.1.1) + net-scp (3.0.0) + net-ssh (>= 2.6.5, < 7.0.0) + net-sftp (3.0.0) + net-ssh (>= 5.0.0, < 7.0.0) + net-ssh (6.1.0) + net-ssh-gateway (2.0.0) + net-ssh (>= 4.0.0) + net-ssh-multi (1.2.1) + net-ssh (>= 2.6.5) + net-ssh-gateway (>= 1.2.0) + nori (2.6.0) + parallel (1.20.1) + parser (3.0.0.0) + ast (~> 2.4.1) + parslet (1.8.2) + pastel (0.8.0) + tty-color (~> 0.5) + plist (3.6.0) + proxifier (1.0.3) + pry (0.14.0) + coderay (~> 1.1) + method_source (~> 1.0) + public_suffix (4.0.6) + rack (2.2.3) + rainbow (3.0.0) + rake (13.0.3) + regexp_parser (2.1.1) + rexml (3.2.4) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-its (1.3.0) + rspec-core (>= 3.0.0) + rspec-expectations (>= 3.0.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.2) + rubocop (1.10.0) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.2.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.4.1) + parser (>= 2.7.1.5) + ruby-progressbar (1.11.0) + ruby2_keywords (0.0.4) + rubyntlm (0.6.3) + rubyzip (2.3.0) + semverse (3.0.0) + sslshake (1.3.1) + strings (0.2.0) + strings-ansi (~> 0.2) + unicode-display_width (~> 1.5) + unicode_utils (~> 1.4) + strings-ansi (0.2.0) + syslog-logger (1.6.8) + thor (1.1.0) + tomlrb (1.3.0) + train-core (3.5.2) + addressable (~> 2.5) + ffi (!= 1.13.0) + json (>= 1.8, < 3.0) + mixlib-shellout (>= 2.0, < 4.0) + net-scp (>= 1.2, < 4.0) + net-ssh (>= 2.9, < 7.0) + train-winrm (0.2.12) + winrm (>= 2.3.6, < 3.0) + winrm-elevated (~> 1.2.2) + winrm-fs (~> 1.0) + tty-box (0.7.0) + pastel (~> 0.8) + strings (~> 0.2.0) + tty-cursor (~> 0.7) + tty-color (0.6.0) + tty-cursor (0.7.1) + tty-prompt (0.23.0) + pastel (~> 0.8) + tty-reader (~> 0.8) + tty-reader (0.9.0) + tty-cursor (~> 0.7) + tty-screen (~> 0.8) + wisper (~> 2.0) + tty-screen (0.8.1) + tty-table (0.12.0) + pastel (~> 0.8) + strings (~> 0.2.0) + tty-screen (~> 0.8) + unicode-display_width (1.7.0) + unicode_utils (1.4.0) + uuidtools (2.2.0) + webmock (3.12.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + webrick (1.7.0) + winrm (2.3.6) + builder (>= 2.1.2) + erubi (~> 1.8) + gssapi (~> 1.2) + gyoku (~> 1.0) + httpclient (~> 2.2, >= 2.2.0.2) + logging (>= 1.6.1, < 3.0) + nori (~> 2.0) + rubyntlm (~> 0.6.0, >= 0.6.3) + winrm-elevated (1.2.3) + erubi (~> 1.8) + winrm (~> 2.0) + winrm-fs (~> 1.0) + winrm-fs (1.3.5) + erubi (~> 1.8) + logging (>= 1.6.1, < 3.0) + rubyzip (~> 2.0) + winrm (~> 2.0) + wisper (2.0.1) + wmi-lite (1.0.5) + +PLATFORMS + ruby + +DEPENDENCIES + chef! + cheffish (>= 14) + chefstyle + knife! + ohai! + rake + webmock + +BUNDLED WITH + 2.1.4 diff --git a/knife/LICENSE b/knife/LICENSE new file mode 100644 index 0000000000..11069edd79 --- /dev/null +++ b/knife/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/knife/README.md b/knife/README.md new file mode 100644 index 0000000000..4ca16a2242 --- /dev/null +++ b/knife/README.md @@ -0,0 +1,35 @@ +# Knife gem + +**Umbrella Project**: [Chef Infra](https://github.com/chef/chef-oss-practices/blob/master/projects/chef-infra.md) + +**Project State**: [Active](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md#active) + +**Issues [Response Time Maximum](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)**: 14 days + +**Pull Request [Response Time Maximum](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)**: 14 days + +## Getting Started + +The Knife gem contains the `knife` command and its core subcommands. This gem should be a required dependency for any knife plugin. + +## Getting Involved + +We'd love to have your help developing Chef Infra. See our [Contributing Document](../CONTRIBUTING.md) for more information on getting started. + +## License and Copyright + +Copyright 2008-2021, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/knife/bin/knife b/knife/bin/knife new file mode 100755 index 0000000000..85ac3b91e9 --- /dev/null +++ b/knife/bin/knife @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# +# ./knife - Chef CLI interface +# +# Author:: Adam Jacob (<adam@chef.io>) +# Copyright:: Copyright 2009-2018, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +$:.unshift(File.expand_path(File.join(__dir__, "..", "lib"))) +require "chef/application/knife" + +Chef::Application::Knife.new.run diff --git a/knife/knife.gemspec b/knife/knife.gemspec new file mode 100644 index 0000000000..bfcd731991 --- /dev/null +++ b/knife/knife.gemspec @@ -0,0 +1,72 @@ +$:.unshift(File.dirname(__FILE__) + "/lib") +require_relative "lib/chef/knife/version" +# vs_path = File.expand_path("chef-utils/lib/chef-utils/version_string.rb", __dir__) +# +# if File.exist?(vs_path) +# # this is the moral equivalent of a require_relative since bundler makes require_relative here fail hard +# eval(IO.read(vs_path)) +# else +# # if the path doesn't exist then we're just in the wild gem and not in the git repo +# require "chef-utils/version_string" +# end +# +Gem::Specification.new do |s| + s.name = "knife" + # TDMP: - making this its own thing for now, it gets a little harder + # to share the version because chef is a dependency. + s.version = Chef::Knife::VERSION + s.platform = Gem::Platform::RUBY + s.extra_rdoc_files = ["README.md", "LICENSE" ] + s.summary = "Let's find a good description." + s.description = s.summary + s.license = "Apache-2.0" + s.author = "Adam Jacob" + s.email = "adam@chef.io" # These seem a bit out of date, and this address probably doesn't go anywhere anymore? + s.homepage = "https://www.chef.io" + + s.required_ruby_version = ">= 2.6.0" + + s.add_dependency "chef-config", "= #{Chef::Knife::VERSION}" + s.add_dependency "chef-utils", "= #{Chef::Knife::VERSION}" + s.add_dependency "chef", "= #{Chef::Knife::VERSION}" + s.add_dependency "train-core", "~> 3.2", ">= 3.2.28" # 3.2.28 fixes sudo prompts. See https://github.com/chef/chef/pull/9635 + s.add_dependency "train-winrm", ">= 0.2.5" + s.add_dependency "license-acceptance", ">= 1.0.5", "< 3" + s.add_dependency "mixlib-cli", ">= 2.1.1", "< 3.0" + s.add_dependency "mixlib-archive", ">= 0.4", "< 2.0" + s.add_dependency "ohai", "~> 17.0" + s.add_dependency "ffi", ">= 1.9.25", "< 1.14.0" # 1.14 breaks i386 windows. It should be fixed in 1.14.3 + s.add_dependency "ffi-yajl", "~> 2.2" + s.add_dependency "net-ssh", ">= 5.1", "< 7" + s.add_dependency "net-ssh-multi", "~> 1.2", ">= 1.2.1" + s.add_dependency "ed25519", "~> 1.2" # ed25519 ssh key support + s.add_dependency "bcrypt_pbkdf", "~> 1.1" # ed25519 ssh key support + s.add_dependency "highline", ">= 1.6.9", "< 3" # Used in UI to present a list, no other usage. + + s.add_dependency "tty-prompt", "~> 0.21" # knife ui.ask prompt + s.add_dependency "tty-screen", "~> 0.6" # knife list + s.add_dependency "tty-table", "~> 0.11" # knife render table output. + s.add_dependency "pastel" # knife ui.color + s.add_dependency "erubis", "~> 2.7" + s.add_dependency "chef-vault" # knife vault + + s.add_development_dependency "chefstyle" + + s.bindir = "bin" + s.executables = %w{ knife } + + s.require_paths = %w{ lib } + s.files = %w{Gemfile Rakefile LICENSE README.md} + + Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) } + + Dir.glob("*.gemspec") # + + # Dir.glob("../tasks/rspec.rb") + + s.metadata = { + "bug_tracker_uri" => "https://github.com/chef/chef/issues", + "changelog_uri" => "https://github.com/chef/chef/blob/master/CHANGELOG.md", + "documentation_uri" => "https://docs.chef.io/", + "homepage_uri" => "https://www.chef.io", + "mailing_list_uri" => "https://discourse.chef.io/", + "source_code_uri" => "https://github.com/chef/chef/", + } +end diff --git a/knife/spec/spec_helper.rb b/knife/spec/spec_helper.rb new file mode 100644 index 0000000000..552cb71f96 --- /dev/null +++ b/knife/spec/spec_helper.rb @@ -0,0 +1,332 @@ +# +# Author:: Adam Jacob (<adam@chef.io>) +# Copyright:: Copyright (c) Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# If you need to add anything in here, don't. +# Add it to one of the files in spec/support + +# Abuse ruby's constant lookup to avoid undefined constant errors + +$LOAD_PATH.unshift File.expand_path("..", __dir__) +$LOAD_PATH.unshift File.expand_path("../../chef-config/lib", __dir__) +$LOAD_PATH.unshift File.expand_path("../../chef-utils/lib", __dir__) + +require "rubygems" +require "rspec/mocks" +require "rexml/document" +require "webmock/rspec" + +require "chef" +require "chef/knife" + +Dir["lib/chef/knife/**/*.rb"] + .map { |f| f.gsub("lib/", "") } + .map { |f| f.gsub(/\.rb$/, "") } + .each { |f| require f } + +require "chef/resource_resolver" +require "chef/provider_resolver" + +require "chef/mixins" +require "chef/dsl" +# MPTD Hopefully not, this is a mess to unwind: +# require "chef/application" +# require "chef/applications" + +require "chef/shell" +require "chef/util/file_edit" + +require "chef/config" + +require "chef/chef_fs/file_system_cache" + +require "chef/api_client_v1" + +require "chef/mixin/versioned_api" +require "chef/server_api_versions" + +if ENV["CHEF_FIPS"] == "1" + Chef::Config.init_openssl +end + +# If you want to load anything into the testing environment +# without versioning it, add it to spec/support/local_gems.rb +# #MPTD needed now? +require "spec/support/local_gems" if File.exist?(File.join(File.dirname(__FILE__), "support", "local_gems.rb")) + +# Explicitly require spec helpers that need to load first +require "spec/support/platform_helpers" +require "spec/support/shared/unit/mock_shellout" + +require "spec/support/recipe_dsl_helper" + +# Autoloads support files +# Excludes support/platforms by default +# Do not change the gsub. +Dir["spec/support/**/*.rb"] + .reject { |f| f =~ %r{^spec/support/platforms} } + .reject { |f| f =~ %r{^spec/support/pedant} } + .map { |f| f.gsub(/.rb$/, "") } + .map { |f| f.gsub(%r{spec/}, "") } + .each { |f| require f } + +OHAI_SYSTEM = Ohai::System.new +OHAI_SYSTEM.all_plugins(["platform", "hostname", "languages/powershell", "uptime"]) + +test_node = Chef::Node.new +test_node.automatic["os"] = (OHAI_SYSTEM["os"] || "unknown_os").dup.freeze +test_node.automatic["platform_family"] = (OHAI_SYSTEM["platform_family"] || "unknown_platform_family").dup.freeze +test_node.automatic["platform"] = (OHAI_SYSTEM["platform"] || "unknown_platform").dup.freeze +test_node.automatic["platform_version"] = (OHAI_SYSTEM["platform_version"] || "unknown_platform_version").dup.freeze +TEST_NODE = test_node.freeze +TEST_OS = TEST_NODE["os"] +TEST_PLATFORM = TEST_NODE["platform"] +TEST_PLATFORM_VERSION = TEST_NODE["platform_version"] +TEST_PLATFORM_FAMILY = TEST_NODE["platform_family"] + +provider_priority_map ||= nil +resource_priority_map ||= nil +provider_handler_map ||= nil +resource_handler_map ||= nil + +class UnexpectedSystemExit < RuntimeError + def self.from(system_exit) + new(system_exit.message).tap { |e| e.set_backtrace(system_exit.backtrace) } + end +end + +RSpec.configure do |config| + config.include(Matchers) + config.include(MockShellout::RSpec) + config.filter_run focus: true + config.filter_run_excluding external: true + config.raise_on_warning = true + + # Explicitly disable :should syntax + # And set max_formatted_output_length to nil to prevent RSpec from doing truncation. + config.expect_with :rspec do |c| + c.syntax = :expect + c.max_formatted_output_length = nil + end + config.mock_with :rspec do |c| + c.syntax = :expect + c.allow_message_expectations_on_nil = false + end + + # Only run these tests on platforms that are also chef workstations + config.filter_run_excluding :workstation if solaris? || aix? + + # Tests that randomly fail, but may have value. + config.filter_run_excluding volatile: true + config.filter_run_excluding volatile_on_solaris: true if solaris? + config.filter_run_excluding volatile_from_verify: false + + config.filter_run_excluding skip_buildkite: true if ENV["BUILDKITE"] + + config.filter_run_excluding windows_only: true unless windows? + config.filter_run_excluding not_supported_on_windows: true if windows? + config.filter_run_excluding not_supported_on_macos: true if macos? + config.filter_run_excluding macos_only: true unless macos? + config.filter_run_excluding macos_1013: true unless macos_1013? + config.filter_run_excluding macos_gte_1014: true unless macos_gte_1014? + config.filter_run_excluding not_supported_on_aix: true if aix? + config.filter_run_excluding not_supported_on_solaris: true if solaris? + config.filter_run_excluding not_supported_on_gce: true if gce? + config.filter_run_excluding win2012r2_only: true unless windows_2012r2? + config.filter_run_excluding windows64_only: true unless windows64? + config.filter_run_excluding windows32_only: true unless windows32? + config.filter_run_excluding windows_gte_10: true unless windows_gte_10? + config.filter_run_excluding windows_lt_10: true if windows_gte_10? + config.filter_run_excluding ruby64_only: true unless ruby_64bit? + config.filter_run_excluding ruby32_only: true unless ruby_32bit? + config.filter_run_excluding windows_powershell_dsc_only: true unless windows_powershell_dsc? + config.filter_run_excluding windows_powershell_no_dsc_only: true if windows_powershell_dsc? + config.filter_run_excluding windows_domain_joined_only: true unless windows_domain_joined? + config.filter_run_excluding windows_not_domain_joined_only: true if windows_domain_joined? + config.filter_run_excluding windows_service_requires_assign_token: true if !STDOUT.isatty && !windows_user_right?("SeAssignPrimaryTokenPrivilege") + config.filter_run_excluding solaris_only: true unless solaris? + config.filter_run_excluding unix_only: true unless unix? + config.filter_run_excluding linux_only: true unless linux? + config.filter_run_excluding aix_only: true unless aix? + config.filter_run_excluding suse_only: true unless suse? + config.filter_run_excluding opensuse: true unless opensuse? + config.filter_run_excluding debian_family_only: true unless debian_family? + config.filter_run_excluding supports_cloexec: true unless supports_cloexec? + config.filter_run_excluding selinux_only: true unless selinux_enabled? + config.filter_run_excluding requires_root: true unless root? + config.filter_run_excluding requires_root_or_running_windows: true unless root? || windows? + config.filter_run_excluding requires_unprivileged_user: true if root? + config.filter_run_excluding openssl_gte_101: true unless openssl_gte_101? + config.filter_run_excluding openssl_lt_101: true unless openssl_lt_101? + config.filter_run_excluding aes_256_gcm_only: true unless aes_256_gcm? + config.filter_run_excluding broken: true + config.filter_run_excluding not_wpar: true unless wpar? + config.filter_run_excluding not_supported_under_fips: true if fips? + config.filter_run_excluding rhel: true unless rhel? + config.filter_run_excluding rhel6: true unless rhel6? + config.filter_run_excluding rhel7: true unless rhel7? + config.filter_run_excluding rhel8: true unless rhel8? + config.filter_run_excluding rhel_gte_8: true unless rhel_gte_8? + config.filter_run_excluding intel_64bit: true unless intel_64bit? + config.filter_run_excluding not_rhel: true if rhel? + config.filter_run_excluding not_rhel6: true if rhel6? + config.filter_run_excluding not_rhel7: true if rhel7? + config.filter_run_excluding not_intel_64bit: true if intel_64bit? + + # these let us use chef: ">= 13" or ruby: "~> 2.0.0" or any other Gem::Dependency-style constraint + config.filter_run_excluding chef: DependencyProc.with(Chef::VERSION) + config.filter_run_excluding ruby: DependencyProc.with(RUBY_VERSION) + + # check for particular binaries we need + config.filter_run_excluding choco_installed: true unless choco_installed? + config.filter_run_excluding requires_ifconfig: true unless ifconfig? + config.filter_run_excluding pwsh_installed: true unless pwsh_installed? + + running_platform_arch = `uname -m`.strip unless windows? + + config.filter_run_excluding arch: lambda { |target_arch| + running_platform_arch != target_arch + } + + # Functional Resource tests that are provider-specific: + # context "on platforms that use useradd", :provider => {:user => Chef::Provider::User::Useradd}} do #... + config.filter_run_excluding provider: lambda { |criteria| + type, target_provider = criteria.first + + node = TEST_NODE.dup + resource_class = Chef::ResourceResolver.resolve(type, node: node) + if resource_class + resource = resource_class.new("test", Chef::RunContext.new(node, nil, nil)) + begin + provider = resource.provider_for_action(Array(resource_class.default_action).first) + provider.class != target_provider + rescue Chef::Exceptions::ProviderNotFound # no provider for platform + true + end + else + true + end + } + + config.run_all_when_everything_filtered = true + + config.before(:each) do + # it'd be nice to run this with connections blocked or only to localhost, but we do make lots + # of real connections, so cannot. we reset it to allow connections every time to avoid + # tests setting connections to be disabled and that state leaking into other tests. + WebMock.allow_net_connect! + + Chef.reset! + + Chef::ChefFS::FileSystemCache.instance.reset! + + Chef::Config.reset + + Chef::Log.setup! + + Chef::ServerAPIVersions.instance.reset! + + Chef::Config[:log_level] = :fatal + Chef::Log.level(Chef::Config[:log_level]) + + # By default, treat deprecation warnings as errors in tests. + Chef::Config.treat_deprecation_warnings_as_errors(true) + + # Set environment variable so the setting persists in child processes + ENV["CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS"] = "1" + + # we don't perfectly reset the priority/handler maps here, but by dup'ing the top level hash we + # throw away all the garbage resources and providers that we setup. if we mutate something like + # :package then that'll carry over from test-to-test, but the solution would be to deep-dup on every + # single test we run which is much more expensive. by throwing away the garbage top level keys we + # significantly speed up test runs. + provider_handler_map ||= Chef.provider_handler_map.send(:map).dup + resource_handler_map ||= Chef.resource_handler_map.send(:map).dup + provider_priority_map ||= Chef.provider_priority_map.send(:map).dup + resource_priority_map ||= Chef.resource_priority_map.send(:map).dup + Chef.provider_handler_map.instance_variable_set(:@map, provider_handler_map.dup) + Chef.resource_handler_map.instance_variable_set(:@map, resource_handler_map.dup) + Chef.provider_priority_map.instance_variable_set(:@map, provider_priority_map.dup) + Chef.resource_priority_map.instance_variable_set(:@map, resource_priority_map.dup) + end + + # This bit of jankiness guards against specs which accidentally drop privs when running as + # root -- which are nearly impossible to debug and so we bail out very hard if this + # condition ever happens. If a spec stubs Process.[e]uid this can throw a false positive + # which the spec must work around by unmocking Process.[e]uid to and_call_original in its + # after block. + if Process.euid == 0 && Process.uid == 0 + config.after(:each) do + if Process.uid != 0 + RSpec.configure { |c| c.fail_fast = true } + raise "rspec was invoked as root, but the last test dropped real uid to #{Process.uid}" + end + if Process.euid != 0 + RSpec.configure { |c| c.fail_fast = true } + raise "rspec was invoked as root, but the last test dropped effective uid to #{Process.euid}" + end + end + end + + # raise if anyone commits any test to CI with :focus set on it + if ENV["CI"] + config.before(:example, :focus) do + raise "This example was committed with `:focus` and should not have been" + end + end + + config.before(:suite) do + ARGV.clear + end + + # Protect Rspec from accidental exit(0) causing rspec to terminate without error + config.around(:example) do |ex| + + ex.run + rescue SystemExit => e + raise UnexpectedSystemExit.from(e) + + end +end + +require "webrick/utils" +# Webrick uses a centralized/synchronized timeout manager. It works by +# starting a thread to check for timeouts on an interval. The timeout +# checker thread cannot be stopped or canceled in any easy way, and it +# makes calls to Time.new, which fail when rspec is in the process of +# creating a method stub for that method. Since our tests don't rely on +# any timeout behavior enforced by webrick, disable the timeout manager +# via a monkey patch. +# +# Hopefully this fails loudly if the webrick code should change. As of this +# writing, the relevant code is in webrick/utils, which can be located on +# your system with: +# +# $ gem which webrick/utils +module WEBrick + module Utils + class TimeoutHandler + def initialize; end + + def register(*args); end + + def cancel(*args); end + end + end +end + +# Enough stuff needs json serialization that I'm just adding it here for equality asserts +require "chef/json_compat" diff --git a/knife/spec/tiny_server.rb b/knife/spec/tiny_server.rb new file mode 100644 index 0000000000..786130d0d5 --- /dev/null +++ b/knife/spec/tiny_server.rb @@ -0,0 +1,190 @@ +# +# Author:: Daniel DeLeo (<dan@chef.io>) +# Copyright:: Copyright (c) Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "webrick" +require "webrick/https" +require "rack" +require "singleton" +require "open-uri" +require "chef/config" + +module TinyServer + + class Manager + + # 5 == debug, 3 == warning + LOGGER = WEBrick::Log.new(STDOUT, 3) + DEFAULT_OPTIONS = { + Port: 9000, + Host: "localhost", + Logger: LOGGER, + # SSLEnable: options[:ssl], + # SSLCertName: [ [ 'CN', WEBrick::Utils::getservername ] ], + AccessLog: [], # Remove this option to enable the access log when debugging. + }.freeze + + def initialize(**options) + @options = DEFAULT_OPTIONS.merge(options) + @creator = caller.first + end + + attr_reader :options + attr_reader :creator + attr_reader :server + + def start(timeout = 5) + raise "Server already started!" if server + + # Create the server (but don't start yet) + start_queue = Queue.new + @server = create_server(StartCallback: proc { start_queue << true }) + + @server_thread = Thread.new do + # Ensure any exceptions will cause the main rspec thread to fail too + Thread.current.abort_on_exception = true + server.start + end + + # Wait for the StartCallback to tell us we've started + Timeout.timeout(timeout) do + start_queue.pop + end + end + + def stop(timeout = 5) + if server + server.shutdown + @server = nil + end + + if server_thread + begin + # Wait for a normal shutdown + server_thread.join(timeout) + rescue + # If it wouldn't shut down normally, kill it. + server_thread.kill + server_thread.join(timeout) + end + @server_thread = nil + end + end + + private + + attr_reader :server_thread + + def create_server(**extra_options) + server = WEBrick::HTTPServer.new(**options, **extra_options) + server.mount("/", Rack::Handler::WEBrick, API.instance) + server + end + end + + class API + include Singleton + + GET = "GET".freeze + PUT = "PUT".freeze + POST = "POST".freeze + DELETE = "DELETE".freeze + + attr_reader :routes + + def initialize + clear + end + + def clear + @routes = { GET => [], PUT => [], POST => [], DELETE => [] } + end + + def get(path, response_code, data = nil, headers = nil, &block) + @routes[GET] << Route.new(path, Response.new(response_code, data, headers, &block)) + end + + def put(path, response_code, data = nil, headers = nil, &block) + @routes[PUT] << Route.new(path, Response.new(response_code, data, headers, &block)) + end + + def post(path, response_code, data = nil, headers = nil, &block) + @routes[POST] << Route.new(path, Response.new(response_code, data, headers, &block)) + end + + def delete(path, response_code, data = nil, headers = nil, &block) + @routes[DELETE] << Route.new(path, Response.new(response_code, data, headers, &block)) + end + + def call(env) + if response = response_for_request(env) + response.call + else + debug_info = { message: "no data matches the request for #{env["REQUEST_URI"]}", + available_routes: @routes, request: env } + # Uncomment me for glorious debugging + # pp :not_found => debug_info + [404, { "Content-Type" => "application/json" }, [ Chef::JSONCompat.to_json(debug_info) ]] + end + end + + def response_for_request(env) + if route = @routes[env["REQUEST_METHOD"]].find { |route| route.matches_request?(env["REQUEST_URI"]) } + route.response + end + end + end + + class Route + attr_reader :response + + def initialize(path_spec, response) + @path_spec, @response = path_spec, response + end + + def matches_request?(uri) + uri = URI.parse(uri).request_uri + @path_spec === uri + end + + def to_s + "#{@path_spec} => (#{@response})" + end + + end + + class Response + HEADERS = { "Content-Type" => "application/json" }.freeze + + def initialize(response_code = 200, data = nil, headers = nil, &block) + @response_code, @data = response_code, data + @response_headers = headers ? HEADERS.merge(headers) : HEADERS + @block = block_given? ? block : nil + end + + def call + data = @data || @block.call + [@response_code, @response_headers, Array(data)] + end + + def to_s + "#{@response_code} => #{(@data || @block)}" + end + + end + +end |