diff options
Diffstat (limited to 'spec/unit/knife')
96 files changed, 0 insertions, 14645 deletions
diff --git a/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb b/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb deleted file mode 100644 index 4d36208be0..0000000000 --- a/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb +++ /dev/null @@ -1,152 +0,0 @@ -# -# Author:: Lamont Granquist <lamont@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 "spec_helper" - -describe Chef::Knife::Bootstrap::ChefVaultHandler do - - let(:stdout) { StringIO.new } - let(:stderr) { StringIO.new } - let(:stdin) { StringIO.new } - let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) } - - let(:config) { {} } - - let(:client) { Chef::ApiClient.new } - - let(:chef_vault_handler) do - chef_vault_handler = Chef::Knife::Bootstrap::ChefVaultHandler.new(config: config, ui: ui) - chef_vault_handler - end - - context "when there's no vault option" do - it "should report its not doing anything" do - expect(chef_vault_handler.doing_chef_vault?).to be false - end - - it "shouldn't do anything" do - expect(chef_vault_handler).to_not receive(:sanity_check) - expect(chef_vault_handler).to_not receive(:update_bootstrap_vault_json!) - chef_vault_handler - end - end - - context "when setting chef vault items" do - let(:bootstrap_vault_item) { double("ChefVault::Item") } - - before do - expect(chef_vault_handler).to receive(:require_chef_vault!).at_least(:once) - expect(bootstrap_vault_item).to receive(:clients).with(client).at_least(:once) - expect(bootstrap_vault_item).to receive(:save).at_least(:once) - end - - context "from config[:bootstrap_vault_item]" do - it "sets a single item as a scalar" do - config[:bootstrap_vault_item] = { "vault" => "item1" } - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets a single item as an array" do - config[:bootstrap_vault_item] = { "vault" => [ "item1" ] } - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets two items as an array" do - config[:bootstrap_vault_item] = { "vault" => %w{item1 item2} } - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets two vaults from different hash keys" do - config[:bootstrap_vault_item] = { "vault" => %w{item1 item2}, "vault2" => [ "item3" ] } - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault2", "item3").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - end - - context "from config[:bootstrap_vault_json]" do - it "sets a single item as a scalar" do - config[:bootstrap_vault_json] = '{ "vault": "item1" }' - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets a single item as an array" do - config[:bootstrap_vault_json] = '{ "vault": [ "item1" ] }' - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets two items as an array" do - config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ] }' - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets two vaults from different hash keys" do - config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ], "vault2": [ "item3" ] }' - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault2", "item3").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - end - - context "from config[:bootstrap_vault_file]" do - - def setup_file_contents(json) - stringio = StringIO.new(json) - config[:bootstrap_vault_file] = "/foo/bar/baz" - expect(File).to receive(:read).with(config[:bootstrap_vault_file]).and_return(stringio) - end - - it "sets a single item as a scalar" do - setup_file_contents('{ "vault": "item1" }') - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets a single item as an array" do - setup_file_contents('{ "vault": [ "item1" ] }') - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets two items as an array" do - setup_file_contents('{ "vault": [ "item1", "item2" ] }') - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - - it "sets two vaults from different hash keys" do - setup_file_contents('{ "vault": [ "item1", "item2" ], "vault2": [ "item3" ] }') - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item1").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault", "item2").and_return(bootstrap_vault_item) - expect(chef_vault_handler).to receive(:load_chef_bootstrap_vault_item).with("vault2", "item3").and_return(bootstrap_vault_item) - chef_vault_handler.run(client) - end - end - end -end diff --git a/spec/unit/knife/bootstrap/client_builder_spec.rb b/spec/unit/knife/bootstrap/client_builder_spec.rb deleted file mode 100644 index 10edd13882..0000000000 --- a/spec/unit/knife/bootstrap/client_builder_spec.rb +++ /dev/null @@ -1,207 +0,0 @@ -# -# Author:: Lamont Granquist <lamont@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 "spec_helper" - -describe Chef::Knife::Bootstrap::ClientBuilder do - - let(:stdout) { StringIO.new } - let(:stderr) { StringIO.new } - let(:stdin) { StringIO.new } - let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) } - - let(:config) { {} } - - let(:chef_config) { {} } - - let(:node_name) { "bevell.wat" } - - let(:rest) { double("Chef::ServerAPI") } - - let(:client_builder) do - client_builder = Chef::Knife::Bootstrap::ClientBuilder.new(config: config, chef_config: chef_config, ui: ui) - allow(client_builder).to receive(:rest).and_return(rest) - allow(client_builder).to receive(:node_name).and_return(node_name) - client_builder - end - - context "#sanity_check!" do - let(:response_404) { OpenStruct.new(code: "404") } - let(:exception_404) { Net::HTTPClientException.new("404 not found", response_404) } - - context "in cases where the prompting fails" do - before do - # should fail early in #run - expect(client_builder).to_not receive(:create_client!) - expect(client_builder).to_not receive(:create_node!) - end - - it "exits when the node exists and the user does not want to delete" do - expect(rest).to receive(:get).with("nodes/#{node_name}") - expect(ui.stdin).to receive(:readline).and_return("n") - expect { client_builder.run }.to raise_error(SystemExit) - end - - it "exits when the client exists and the user does not want to delete" do - expect(rest).to receive(:get).with("nodes/#{node_name}").and_raise(exception_404) - expect(rest).to receive(:get).with("clients/#{node_name}") - expect(ui.stdin).to receive(:readline).and_return("n") - expect { client_builder.run }.to raise_error(SystemExit) - end - end - - context "in cases where the prompting succeeds" do - before do - # mock out the rest of #run - expect(client_builder).to receive(:create_client!) - expect(client_builder).to receive(:create_node!) - end - - it "when both the client and node do not exist it succeeds" do - expect(rest).to receive(:get).with("nodes/#{node_name}").and_raise(exception_404) - expect(rest).to receive(:get).with("clients/#{node_name}").and_raise(exception_404) - expect { client_builder.run }.not_to raise_error - end - - it "when we are allowed to delete an old node" do - expect(rest).to receive(:get).with("nodes/#{node_name}") - expect(ui.stdin).to receive(:readline).and_return("y") - expect(rest).to receive(:get).with("clients/#{node_name}").and_raise(exception_404) - expect(rest).to receive(:delete).with("nodes/#{node_name}") - expect { client_builder.run }.not_to raise_error - end - - it "when we are allowed to delete an old client" do - expect(rest).to receive(:get).with("nodes/#{node_name}").and_raise(exception_404) - expect(rest).to receive(:get).with("clients/#{node_name}") - expect(ui.stdin).to receive(:readline).and_return("y") - expect(rest).to receive(:delete).with("clients/#{node_name}") - expect { client_builder.run }.not_to raise_error - end - - it "when we are are allowed to delete both an old client and node" do - expect(rest).to receive(:get).with("nodes/#{node_name}") - expect(rest).to receive(:get).with("clients/#{node_name}") - expect(ui.stdin).to receive(:readline).twice.and_return("y") - expect(rest).to receive(:delete).with("nodes/#{node_name}") - expect(rest).to receive(:delete).with("clients/#{node_name}") - expect { client_builder.run }.not_to raise_error - end - end - end - - context "#create_client!" do - let(:client) { Chef::ApiClient.new } - - before do - # mock out the rest of #run - expect(client_builder).to receive(:sanity_check) - expect(client_builder).to receive(:create_node!) - end - - it "delegates everything to Chef::ApiClient::Registration and sets client" do - reg_double = double("Chef::ApiClient::Registration") - expect(Chef::ApiClient::Registration).to receive(:new).with(node_name, client_builder.client_path, http_api: rest).and_return(reg_double) - expect(reg_double).to receive(:run).and_return(client) - client_builder.run - expect(client_builder.client).to eq(client) - end - - end - - context "#client_path" do - it "has a public API for the temporary client.pem file" do - expect(client_builder.client_path).to match(/#{node_name}.pem/) - end - end - - context "#create_node!" do - before do - # mock out the rest of #run - expect(client_builder).to receive(:sanity_check) - expect(client_builder).to receive(:create_client!) - # mock out default node building steps - expect(client_builder).to receive(:client_rest).and_return(client_rest) - expect(Chef::Node).to receive(:new).with(chef_server_rest: client_rest).and_return(node) - expect(node).to receive(:name).with(node_name) - expect(node).to receive(:save) - end - - let(:client_rest) { double("Chef::ServerAPI (client)") } - - let(:node) { double("Chef::Node") } - - it "builds a node with a default run_list of []" do - expect(node).to receive(:run_list).with([]) - client_builder.run - end - - it "does not add tags by default" do - allow(node).to receive(:run_list).with([]) - expect(node).to_not receive(:tags) - client_builder.run - end - - it "adds tags to the node when given" do - tag_receiver = [] - - config[:tags] = %w{foo bar} - allow(node).to receive(:run_list).with([]) - allow(node).to receive(:tags).and_return(tag_receiver) - client_builder.run - expect(tag_receiver).to eq %w{foo bar} - end - - it "builds a node when the run_list is a string" do - config[:run_list] = "role[base],role[app]" - expect(node).to receive(:run_list).with(["role[base]", "role[app]"]) - client_builder.run - end - - it "builds a node when the run_list is an Array" do - config[:run_list] = ["role[base]", "role[app]"] - expect(node).to receive(:run_list).with(["role[base]", "role[app]"]) - client_builder.run - end - - it "builds a node with first_boot_attributes if they're given" do - config[:first_boot_attributes] = { baz: :quux } - expect(node).to receive(:normal_attrs=).with({ baz: :quux }) - expect(node).to receive(:run_list).with([]) - client_builder.run - end - - it "builds a node with an environment if its given" do - config[:environment] = "production" - expect(node).to receive(:environment).with("production") - expect(node).to receive(:run_list).with([]) - client_builder.run - end - - it "builds a node with policy_name and policy_group when given" do - config[:policy_name] = "my-app" - config[:policy_group] = "staging" - - expect(node).to receive(:run_list).with([]) - expect(node).to receive(:policy_name=).with("my-app") - expect(node).to receive(:policy_group=).with("staging") - - client_builder.run - end - end -end diff --git a/spec/unit/knife/bootstrap/train_connector_spec.rb b/spec/unit/knife/bootstrap/train_connector_spec.rb deleted file mode 100644 index 4c384100fa..0000000000 --- a/spec/unit/knife/bootstrap/train_connector_spec.rb +++ /dev/null @@ -1,244 +0,0 @@ -# -# 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 "spec_helper" -require "ostruct" -require "chef/knife/bootstrap/train_connector" - -describe Chef::Knife::Bootstrap::TrainConnector do - let(:protocol) { "mock" } - let(:family) { "unknown" } - let(:release) { "unknown" } # version - let(:name) { "unknown" } - let(:arch) { "x86_64" } - let(:connection_opts) { {} } # connection opts - let(:host_url) { "mock://user1@example.com" } - let(:mock_connection) { true } - - subject do - # Example groups can still override by setting explicitly it in 'connection_opts' - tc = Chef::Knife::Bootstrap::TrainConnector.new(host_url, protocol, connection_opts) - tc - end - - before(:each) do - if mock_connection - subject.connect! - subject.connection.mock_os( - family: family, - name: name, - release: release, - arch: arch - ) - end - end - - describe "platform helpers" do - context "on linux" do - let(:family) { "debian" } - let(:name) { "ubuntu" } - it "reports that it is linux and unix, because that is how train classifies it" do - expect(subject.unix?).to eq true - expect(subject.linux?).to eq true - expect(subject.windows?).to eq false - end - end - context "on unix" do - let(:family) { "os" } - let(:name) { "mac_os_x" } - it "reports only a unix OS" do - expect(subject.unix?).to eq true - expect(subject.linux?).to eq false - expect(subject.windows?).to eq false - end - end - context "on windows" do - let(:family) { "windows" } - let(:name) { "windows" } - it "reports only a windows OS" do - expect(subject.unix?).to eq false - expect(subject.linux?).to eq false - expect(subject.windows?).to eq true - end - end - end - - describe "#connect!" do - it "establishes the connection to the remote host by waiting for it" do - expect(subject.connection).to receive(:wait_until_ready) - subject.connect! - end - end - - describe "#initialize" do - let(:mock_connection) { false } - - context "when provided target is a proper URL" do - let(:protocol) { "ssh" } - let(:host_url) { "mock://user1@localhost:2200" } - it "correctly configures the instance from the URL" do - expect(subject.config[:backend]).to eq "mock" - expect(subject.config[:port]).to eq 2200 - expect(subject.config[:host]).to eq "localhost" - expect(subject.config[:user]).to eq "user1" - end - - context "and conflicting options are given" do - let(:connection_opts) { { user: "user2", host: "example.com", port: 15 } } - it "resolves them from the URI" do - expect(subject.config[:backend]).to eq "mock" - expect(subject.config[:port]).to eq 2200 - expect(subject.config[:host]).to eq "localhost" - expect(subject.config[:user]).to eq "user1" - end - end - end - - context "when provided target is just a hostname" do - let(:host_url) { "localhost" } - let(:protocol) { "mock" } - it "correctly sets backend protocol from the default" do - expect(subject.config[:backend]).to eq "mock" - end - - context "and options have been provided that are supported by the transport" do - let(:protocol) { "ssh" } - let(:connection_opts) { { port: 15, user: "user2" } } - - it "sets hostname and transport from arguments and provided fields from options" do - expect(subject.config[:backend]).to eq "ssh" - expect(subject.config[:host]).to eq "localhost" - expect(subject.config[:user]).to eq "user2" - expect(subject.config[:port]).to eq 15 - end - - end - - end - - context "when provided target is just a an IP address" do - let(:host_url) { "127.0.0.1" } - let(:protocol) { "mock" } - it "correctly sets backend protocol from the default" do - expect(subject.config[:backend]).to eq "mock" - end - end - end - - describe "#temp_dir" do - context "under windows" do - let(:family) { "windows" } - let(:name) { "windows" } - - it "uses the windows command to create the temp dir" do - expected_command = Chef::Knife::Bootstrap::TrainConnector::MKTEMP_WIN_COMMAND - expect(subject).to receive(:run_command!).with(expected_command) - .and_return double("result", stdout: "C:/a/path") - expect(subject.temp_dir).to eq "C:/a/path" - end - - end - context "under linux and unix-like" do - let(:family) { "debian" } - let(:name) { "ubuntu" } - let(:random) { "wScHX6" } - let(:dir) { "/tmp/chef_#{random}" } - - before do - allow(SecureRandom).to receive(:alphanumeric).with(6).and_return(random) - end - - context "uses the *nix command to create the temp dir and sets ownership to logged-in" do - it "with sudo privilege" do - subject.config[:sudo] = true - expected_command1 = "mkdir -p '#{dir}'" - expected_command2 = "chown user1 '#{dir}'" - expect(subject).to receive(:run_command!).with(expected_command1) - .and_return double("result", stdout: "\r\n") - expect(subject).to receive(:run_command!).with(expected_command2) - .and_return double("result", stdout: "\r\n") - expect(subject.temp_dir).to eq(dir) - end - - it "without sudo privilege" do - expected_command = "mkdir -p '#{dir}'" - expect(subject).to receive(:run_command!).with(expected_command) - .and_return double("result", stdout: "\r\n") - expect(subject.temp_dir).to eq(dir) - end - end - - context "with noise in stderr" do - it "uses the *nix command to create the temp dir" do - expected_command = "mkdir -p '#{dir}'" - expect(subject).to receive(:run_command!).with(expected_command) - .and_return double("result", stdout: "sudo: unable to resolve host hostname.localhost\r\n" + "#{dir}\r\n") - expect(subject.temp_dir).to eq(dir) - end - end - end - end - context "#upload_file_content!" do - it "creates a local file with expected content and uploads it" do - expect(subject).to receive(:upload_file!) do |local_path, remote_path| - expect(File.read(local_path)).to eq "test data" - expect(remote_path).to eq "/target/path" - end - expect_any_instance_of(Tempfile).to receive(:binmode) - subject.upload_file_content!("test data", "/target/path") - end - end - - context "del_file" do - context "on windows" do - let(:family) { "windows" } - let(:name) { "windows" } - it "deletes the file with a windows command" do - expect(subject).to receive(:run_command!) do |cmd, &_handler| - expect(cmd).to match(/Test-Path "deleteme\.txt".*/) - end - subject.del_file!("deleteme.txt") - end - end - context "on unix-like" do - let(:family) { "debian" } - let(:name) { "ubuntu" } - it "deletes the file with a windows command" do - expect(subject).to receive(:run_command!) do |cmd, &_handler| - expect(cmd).to match(/rm -f "deleteme\.txt".*/) - end - subject.del_file!("deleteme.txt") - end - end - end - - context "#run_command!" do - it "raises a RemoteExecutionFailed when the remote execution failed" do - command_result = double("results", stdout: "", stderr: "failed", exit_status: 1) - expect(subject).to receive(:run_command).and_return command_result - - expect { subject.run_command!("test") }.to raise_error do |e| - expect(e.hostname).to eq subject.hostname - expect(e.class).to eq Chef::Knife::Bootstrap::RemoteExecutionFailed - expect(e.stderr).to eq "failed" - expect(e.stdout).to eq "" - expect(e.exit_status).to eq 1 - end - end - end - -end diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb deleted file mode 100644 index 15a51b7f92..0000000000 --- a/spec/unit/knife/bootstrap_spec.rb +++ /dev/null @@ -1,2193 +0,0 @@ -# -# Author:: Ian Meyer (<ianmmeyer@gmail.com>) -# Copyright:: Copyright 2010-2016, Ian Meyer -# 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 "spec_helper" - -Chef::Knife::Bootstrap.load_deps - -describe Chef::Knife::Bootstrap do - let(:bootstrap_template) { nil } - let(:stderr) { StringIO.new } - let(:bootstrap_cli_options) { [ ] } - let(:linux_test) { true } - let(:windows_test) { false } - let(:linux_test) { false } - let(:unix_test) { false } - let(:ssh_test) { false } - - let(:connection) do - double("TrainConnector", - windows?: windows_test, - linux?: linux_test, - unix?: unix_test) - end - - let(:knife) do - Chef::Log.logger = Logger.new(StringIO.new) - Chef::Config[:knife][:bootstrap_template] = bootstrap_template unless bootstrap_template.nil? - - k = Chef::Knife::Bootstrap.new(bootstrap_cli_options) - allow(k.ui).to receive(:stderr).and_return(stderr) - allow(k).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(false) - allow(k).to receive(:connection).and_return connection - k.merge_configs - k - end - - context "#check_license" do - let(:acceptor) { instance_double(LicenseAcceptance::Acceptor) } - - before do - expect(LicenseAcceptance::Acceptor).to receive(:new).and_return(acceptor) - end - - describe "when a license is not required" do - it "does not set the chef_license" do - expect(acceptor).to receive(:license_required?).and_return(false) - knife.check_license - expect(Chef::Config[:chef_license]).to eq(nil) - end - end - - describe "when a license is required" do - it "sets the chef_license" do - expect(acceptor).to receive(:license_required?).and_return(true) - expect(acceptor).to receive(:id_from_mixlib).and_return("id") - expect(acceptor).to receive(:check_and_persist) - expect(acceptor).to receive(:acceptance_value).and_return("accept-no-persist") - knife.check_license - expect(Chef::Config[:chef_license]).to eq("accept-no-persist") - end - end - end - - context "#bootstrap_template" do - it "should default to chef-full" do - expect(knife.bootstrap_template).to be_a_kind_of(String) - expect(File.basename(knife.bootstrap_template)).to eq("chef-full") - end - end - - context "#render_template - when using the chef-full default template" do - let(:rendered_template) do - knife.merge_configs - knife.render_template - end - - it "should render client.rb" do - expect(rendered_template).to match("cat > /etc/chef/client.rb <<'EOP'") - expect(rendered_template).to match("chef_server_url \"https://localhost:443\"") - expect(rendered_template).to match("validation_client_name \"chef-validator\"") - expect(rendered_template).to match("log_location STDOUT") - end - - it "should render first-boot.json" do - expect(rendered_template).to match("cat > /etc/chef/first-boot.json <<'EOP'") - expect(rendered_template).to match('{"run_list":\[\]}') - end - - context "and encrypted_data_bag_secret was provided" do - it "should render encrypted_data_bag_secret file" do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true) - expect(knife).to receive(:read_secret).and_return("secrets") - expect(rendered_template).to match("cat > /etc/chef/encrypted_data_bag_secret <<'EOP'") - expect(rendered_template).to match('{"run_list":\[\]}') - expect(rendered_template).to match(/secrets/) - end - end - end - - context "with --bootstrap-vault-item" do - let(:bootstrap_cli_options) { [ "--bootstrap-vault-item", "vault1:item1", "--bootstrap-vault-item", "vault1:item2", "--bootstrap-vault-item", "vault2:item1" ] } - it "sets the knife config cli option correctly" do - expect(knife.config[:bootstrap_vault_item]).to eq({ "vault1" => %w{item1 item2}, "vault2" => ["item1"] }) - end - end - - context "with --bootstrap-preinstall-command" do - command = "while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do\n echo 'waiting for dpkg lock';\n sleep 1;\n done;" - let(:bootstrap_cli_options) { [ "--bootstrap-preinstall-command", command ] } - let(:rendered_template) do - knife.merge_configs - knife.render_template - end - it "configures the preinstall command in the bootstrap template correctly" do - expect(rendered_template).to match(/command/) - end - end - - context "with --bootstrap-proxy" do - let(:bootstrap_cli_options) { [ "--bootstrap-proxy", "1.1.1.1" ] } - let(:rendered_template) do - knife.merge_configs - knife.render_template - end - it "configures the https_proxy environment variable in the bootstrap template correctly" do - expect(rendered_template).to match(/https_proxy="1.1.1.1" export https_proxy/) - end - end - - context "with --bootstrap-no-proxy" do - let(:bootstrap_cli_options) { [ "--bootstrap-no-proxy", "localserver" ] } - let(:rendered_template) do - knife.merge_configs - knife.render_template - end - it "configures the https_proxy environment variable in the bootstrap template correctly" do - expect(rendered_template).to match(/no_proxy="localserver" export no_proxy/) - end - end - - context "with :bootstrap_template and :template_file cli options" do - let(:bootstrap_cli_options) { [ "--bootstrap-template", "my-template", "other-template" ] } - - it "should select bootstrap template" do - expect(File.basename(knife.bootstrap_template)).to eq("my-template") - end - end - - context "when finding templates" do - context "when :bootstrap_template config is set to a file" do - context "that doesn't exist" do - let(:bootstrap_template) { "/opt/blah/not/exists/template.erb" } - - it "raises an error" do - expect { knife.find_template }.to raise_error(Errno::ENOENT) - end - end - - context "that exists" do - let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")) } - - it "loads the given file as the template" do - expect(Chef::Log).to receive(:trace) - expect(knife.find_template).to eq(File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb"))) - end - end - end - - context "when :bootstrap_template config is set to a template name" do - let(:bootstrap_template) { "example" } - - let(:builtin_template_path) { File.expand_path(File.join(__dir__, "../../../lib/chef/knife/bootstrap/templates", "example.erb")) } - - let(:chef_config_dir_template_path) { "/knife/chef/config/bootstrap/example.erb" } - - let(:env_home_template_path) { "/env/home/.chef/bootstrap/example.erb" } - - let(:gem_files_template_path) { "/Users/schisamo/.rvm/gems/ruby-1.9.2-p180@chef-0.10/gems/knife-windows-0.5.4/lib/chef/knife/bootstrap/fake-bootstrap-template.erb" } - - def configure_chef_config_dir - allow(Chef::Knife).to receive(:chef_config_dir).and_return("/knife/chef/config") - end - - def configure_env_home - allow(Chef::Util::PathHelper).to receive(:home).with(".chef", "bootstrap", "example.erb").and_yield(env_home_template_path) - end - - def configure_gem_files - allow(Gem).to receive(:find_files).and_return([ gem_files_template_path ]) - end - - before(:each) do - expect(File).to receive(:exist?).with(bootstrap_template).and_return(false) - end - - context "when file is available everywhere" do - before do - configure_chef_config_dir - configure_env_home - configure_gem_files - - expect(File).to receive(:exist?).with(builtin_template_path).and_return(true) - end - - it "should load the template from built-in templates" do - expect(knife.find_template).to eq(builtin_template_path) - end - end - - context "when file is available in chef_config_dir" do - before do - configure_chef_config_dir - configure_env_home - configure_gem_files - - expect(File).to receive(:exist?).with(builtin_template_path).and_return(false) - expect(File).to receive(:exist?).with(chef_config_dir_template_path).and_return(true) - - it "should load the template from chef_config_dir" do - knife.find_template.should eq(chef_config_dir_template_path) - end - end - end - - context "when file is available in home directory" do - before do - configure_chef_config_dir - configure_env_home - configure_gem_files - - expect(File).to receive(:exist?).with(builtin_template_path).and_return(false) - expect(File).to receive(:exist?).with(chef_config_dir_template_path).and_return(false) - expect(File).to receive(:exist?).with(env_home_template_path).and_return(true) - end - - it "should load the template from chef_config_dir" do - expect(knife.find_template).to eq(env_home_template_path) - end - end - - context "when file is available in Gem files" do - before do - configure_chef_config_dir - configure_env_home - configure_gem_files - - expect(File).to receive(:exist?).with(builtin_template_path).and_return(false) - expect(File).to receive(:exist?).with(chef_config_dir_template_path).and_return(false) - expect(File).to receive(:exist?).with(env_home_template_path).and_return(false) - expect(File).to receive(:exist?).with(gem_files_template_path).and_return(true) - end - - it "should load the template from Gem files" do - expect(knife.find_template).to eq(gem_files_template_path) - end - end - - context "when file is available in Gem files and home dir doesn't exist" do - before do - configure_chef_config_dir - configure_gem_files - allow(Chef::Util::PathHelper).to receive(:home).with(".chef", "bootstrap", "example.erb").and_return(nil) - - expect(File).to receive(:exist?).with(builtin_template_path).and_return(false) - expect(File).to receive(:exist?).with(chef_config_dir_template_path).and_return(false) - expect(File).to receive(:exist?).with(gem_files_template_path).and_return(true) - end - - it "should load the template from Gem files" do - expect(knife.find_template).to eq(gem_files_template_path) - end - end - end - end - - ["-t", "--bootstrap-template"].each do |t| - context "when #{t} option is given in the command line" do - it "sets the knife :bootstrap_template config" do - knife.parse_options([t, "blahblah"]) - knife.merge_configs - expect(knife.bootstrap_template).to eq("blahblah") - end - end - end - - context "with run_list template" do - let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")) } - - it "should return an empty run_list" do - expect(knife.render_template).to eq('{"run_list":[]}') - end - - it "should have role[base] in the run_list" do - knife.parse_options(["-r", "role[base]"]) - knife.merge_configs - expect(knife.render_template).to eq('{"run_list":["role[base]"]}') - end - - it "should have role[base] and recipe[cupcakes] in the run_list" do - knife.parse_options(["-r", "role[base],recipe[cupcakes]"]) - knife.merge_configs - expect(knife.render_template).to eq('{"run_list":["role[base]","recipe[cupcakes]"]}') - end - - context "with bootstrap_attribute options" do - let(:jsonfile) do - file = Tempfile.new (["node", ".json"]) - File.open(file.path, "w") { |f| f.puts '{"foo":{"bar":"baz"}}' } - file - end - - it "should have foo => {bar => baz} in the first_boot from cli" do - knife.parse_options(["-j", '{"foo":{"bar":"baz"}}']) - knife.merge_configs - expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}') - actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template) - expect(actual_hash).to eq(expected_hash) - end - - it "should have foo => {bar => baz} in the first_boot from file" do - knife.parse_options(["--json-attribute-file", jsonfile.path]) - knife.merge_configs - expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}') - actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template) - expect(actual_hash).to eq(expected_hash) - jsonfile.close - end - - it "raises a Chef::Exceptions::BootstrapCommandInputError with the proper error message" do - knife.parse_options(["-j", '{"foo":{"bar":"baz"}}']) - knife.parse_options(["--json-attribute-file", jsonfile.path]) - knife.merge_configs - allow(knife).to receive(:validate_name_args!) - expect(knife).to receive(:check_license) - - expect { knife.run }.to raise_error(Chef::Exceptions::BootstrapCommandInputError) - jsonfile.close - end - end - end - - context "with hints template" do - let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test-hints.erb")) } - - it "should create a hint file when told to" do - knife.parse_options(["--hint", "openstack"]) - knife.merge_configs - expect(knife.render_template).to match(%r{/etc/chef/ohai/hints/openstack.json}) - end - - it "should populate a hint file with JSON when given a file to read" do - allow(::File).to receive(:read).and_return('{ "foo" : "bar" }') - knife.parse_options(["--hint", "openstack=hints/openstack.json"]) - knife.merge_configs - expect(knife.render_template).to match(/\{\"foo\":\"bar\"\}/) - end - end - - describe "specifying no_proxy with various entries" do - subject(:knife) do - k = described_class.new - Chef::Config[:knife][:bootstrap_template] = template_file - allow(k).to receive(:connection).and_return connection - k.parse_options(options) - k.merge_configs - k - end - - let(:options) { ["--bootstrap-no-proxy", setting] } - - let(:template_file) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "no_proxy.erb")) } - - let(:rendered_template) do - knife.render_template - end - - context "via --bootstrap-no-proxy" do - let(:setting) { "api.opscode.com" } - - it "renders the client.rb with a single FQDN no_proxy entry" do - expect(rendered_template).to match(/.*no_proxy\s*"api.opscode.com".*/) - end - end - - context "via --bootstrap-no-proxy multiple" do - let(:setting) { "api.opscode.com,172.16.10.*" } - - it "renders the client.rb with comma-separated FQDN and wildcard IP address no_proxy entries" do - expect(rendered_template).to match(/.*no_proxy\s*"api.opscode.com,172.16.10.\*".*/) - end - end - - context "via --ssl-verify-mode none" do - let(:options) { ["--node-ssl-verify-mode", "none"] } - - it "renders the client.rb with ssl_verify_mode set to :verify_none" do - expect(rendered_template).to match(/ssl_verify_mode :verify_none/) - end - end - - context "via --node-ssl-verify-mode peer" do - let(:options) { ["--node-ssl-verify-mode", "peer"] } - - it "renders the client.rb with ssl_verify_mode set to :verify_peer" do - expect(rendered_template).to match(/ssl_verify_mode :verify_peer/) - end - end - - context "via --node-ssl-verify-mode all" do - let(:options) { ["--node-ssl-verify-mode", "all"] } - - it "raises error" do - expect { rendered_template }.to raise_error(RuntimeError) - end - end - - context "via --node-verify-api-cert" do - let(:options) { ["--node-verify-api-cert"] } - - it "renders the client.rb with verify_api_cert set to true" do - expect(rendered_template).to match(/verify_api_cert true/) - end - end - - context "via --no-node-verify-api-cert" do - let(:options) { ["--no-node-verify-api-cert"] } - - it "renders the client.rb with verify_api_cert set to false" do - expect(rendered_template).to match(/verify_api_cert false/) - end - end - end - - describe "specifying the encrypted data bag secret key" do - let(:secret) { "supersekret" } - let(:options) { [] } - let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "secret.erb")) } - let(:rendered_template) do - knife.parse_options(options) - knife.merge_configs - knife.render_template - end - - it "creates a secret file" do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true) - expect(knife).to receive(:read_secret).and_return(secret) - expect(rendered_template).to match(/#{secret}/) - end - - it "renders the client.rb with an encrypted_data_bag_secret entry" do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true) - expect(knife).to receive(:read_secret).and_return(secret) - expect(rendered_template).to match(%r{encrypted_data_bag_secret\s*"/etc/chef/encrypted_data_bag_secret"}) - end - - end - - describe "when transferring trusted certificates" do - let(:trusted_certs_dir) { Chef::Util::PathHelper.cleanpath(File.join(__dir__, "../../data/trusted_certs")) } - - let(:rendered_template) do - knife.merge_configs - knife.render_template - end - - before do - Chef::Config[:trusted_certs_dir] = trusted_certs_dir - allow(IO).to receive(:read).and_call_original - allow(IO).to receive(:read).with(File.expand_path(Chef::Config[:validation_key])).and_return("") - end - - def certificates - Dir[File.join(trusted_certs_dir, "*.{crt,pem}")] - end - - it "creates /etc/chef/trusted_certs" do - expect(rendered_template).to match(%r{mkdir -p /etc/chef/trusted_certs}) - end - - it "copies the certificates in the directory" do - certificates.each do |cert| - expect(IO).to receive(:read).with(File.expand_path(cert)) - end - - certificates.each do |cert| - expect(rendered_template).to match(%r{cat > /etc/chef/trusted_certs/#{File.basename(cert)} <<'EOP'}) - end - end - - context "when :trusted_cets_dir is empty" do - let(:trusted_certs_dir) { Chef::Util::PathHelper.cleanpath(File.join(__dir__, "../../data/trusted_certs_empty")) } - it "doesn't create /etc/chef/trusted_certs if :trusted_certs_dir is empty" do - expect(rendered_template).not_to match(%r{mkdir -p /etc/chef/trusted_certs}) - end - end - - end - - context "when doing fips things" do - let(:template_file) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "no_proxy.erb")) } - let(:trusted_certs_dir) { Chef::Util::PathHelper.cleanpath(File.join(__dir__, "../../data/trusted_certs")) } - - before do - Chef::Config[:knife][:bootstrap_template] = template_file - knife.merge_configs - end - - let(:rendered_template) do - knife.render_template - end - - context "when knife is in fips mode" do - before do - Chef::Config[:fips] = true - end - - it "renders 'fips true'" do - expect(rendered_template).to match("fips") - end - end - - context "when knife is not in fips mode" do - before do - # This is required because the chef-fips pipeline does - # has a default value of true for fips - Chef::Config[:fips] = false - end - - it "does not render anything about fips" do - expect(rendered_template).not_to match("fips") - end - end - end - - describe "when transferring client.d" do - - let(:rendered_template) do - knife.merge_configs - knife.render_template - end - - before do - Chef::Config[:client_d_dir] = client_d_dir - end - - context "when client_d_dir is nil" do - let(:client_d_dir) { nil } - - it "does not create /etc/chef/client.d" do - expect(rendered_template).not_to match(%r{mkdir -p /etc/chef/client\.d}) - end - end - - context "when client_d_dir is set" do - let(:client_d_dir) do - Chef::Util::PathHelper.cleanpath( - File.join(__dir__, "../../data/client.d_00") - ) - end - - it "creates /etc/chef/client.d" do - expect(rendered_template).to match("mkdir -p /etc/chef/client\.d") - end - - context "a flat directory structure" do - it "escapes single-quotes" do - expect(rendered_template).to match("cat > /etc/chef/client.d/02-strings.rb <<'EOP'") - expect(rendered_template).to match("something '\\\\''/foo/bar'\\\\''") - end - - it "creates a file 00-foo.rb" do - expect(rendered_template).to match("cat > /etc/chef/client.d/00-foo.rb <<'EOP'") - expect(rendered_template).to match("d6f9b976-289c-4149-baf7-81e6ffecf228") - end - it "creates a file bar" do - expect(rendered_template).to match("cat > /etc/chef/client.d/bar <<'EOP'") - expect(rendered_template).to match("1 / 0") - end - end - - context "a nested directory structure" do - let(:client_d_dir) do - Chef::Util::PathHelper.cleanpath( - File.join(__dir__, "../../data/client.d_01") - ) - end - it "creates a file foo/bar.rb" do - expect(rendered_template).to match("cat > /etc/chef/client.d/foo/bar.rb <<'EOP'") - expect(rendered_template).to match("1 / 0") - end - end - end - end - - describe "#connection_protocol" do - let(:host_descriptor) { "example.com" } - let(:config) { {} } - let(:knife_connection_protocol) { nil } - before do - allow(knife).to receive(:config).and_return config - allow(knife).to receive(:host_descriptor).and_return host_descriptor - if knife_connection_protocol - Chef::Config[:knife][:connection_protocol] = knife_connection_protocol - knife.merge_configs - end - end - - context "when protocol is part of the host argument" do - let(:host_descriptor) { "winrm://myhost" } - - it "returns the value provided by the host argument" do - expect(knife.connection_protocol).to eq "winrm" - end - end - - context "when protocol is provided via the CLI flag" do - let(:config) { { connection_protocol: "winrm" } } - it "returns that value" do - expect(knife.connection_protocol).to eq "winrm" - end - - end - context "when protocol is provided via the host argument and the CLI flag" do - let(:host_descriptor) { "ssh://example.com" } - let(:config) { { connection_protocol: "winrm" } } - - it "returns the value provided by the host argument" do - expect(knife.connection_protocol).to eq "ssh" - end - end - - context "when no explicit protocol is provided" do - let(:config) { {} } - let(:host_descriptor) { "example.com" } - let(:knife_connection_protocol) { "winrm" } - it "falls back to knife config" do - expect(knife.connection_protocol).to eq "winrm" - end - context "and there is no knife bootstrap_protocol" do - let(:knife_connection_protocol) { nil } - it "falls back to 'ssh'" do - expect(knife.connection_protocol).to eq "ssh" - end - end - end - - end - - describe "#validate_protocol!" do - let(:host_descriptor) { "example.com" } - let(:config) { {} } - let(:connection_protocol) { "ssh" } - before do - allow(knife).to receive(:config).and_return config - allow(knife).to receive(:connection_protocol).and_return connection_protocol - allow(knife).to receive(:host_descriptor).and_return host_descriptor - end - - context "when protocol is provided both in the URL and via --protocol" do - - context "and they do not match" do - let(:connection_protocol) { "ssh" } - let(:config) { { connection_protocol: "winrm" } } - it "outputs an error and exits" do - expect(knife.ui).to receive(:error) - expect { knife.validate_protocol! }.to raise_error SystemExit - end - end - - context "and they do match" do - let(:connection_protocol) { "winrm" } - let(:config) { { connection_protocol: "winrm" } } - it "returns true" do - expect(knife.validate_protocol!).to eq true - end - end - end - - context "and the protocol is supported" do - - Chef::Knife::Bootstrap::SUPPORTED_CONNECTION_PROTOCOLS.each do |proto| - let(:connection_protocol) { proto } - it "returns true for #{proto}" do - expect(knife.validate_protocol!).to eq true - end - end - end - - context "and the protocol is not supported" do - let(:connection_protocol) { "invalid" } - it "outputs an error and exits" do - expect(knife.ui).to receive(:error).with(/Unsupported protocol '#{connection_protocol}'/) - expect { knife.validate_protocol! }.to raise_error SystemExit - end - end - end - - describe "#validate_policy_options!" do - - context "when only policy_name is given" do - - let(:bootstrap_cli_options) { %w{ --policy-name my-app-server } } - - it "returns an error stating that policy_name and policy_group must be given together" do - expect { knife.validate_policy_options! }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: --policy-name and --policy-group must be specified together") - end - - end - - context "when only policy_group is given" do - - let(:bootstrap_cli_options) { %w{ --policy-group staging } } - - it "returns an error stating that policy_name and policy_group must be given together" do - expect { knife.validate_policy_options! }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: --policy-name and --policy-group must be specified together") - end - - end - - context "when both policy_name and policy_group are given, but run list is also given" do - - let(:bootstrap_cli_options) { %w{ --policy-name my-app --policy-group staging --run-list cookbook } } - - it "returns an error stating that policyfile and run_list are exclusive" do - expect { knife.validate_policy_options! }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: Policyfile options and --run-list are exclusive") - end - - end - - context "when policy_name and policy_group are given with no conflicting options" do - - let(:bootstrap_cli_options) { %w{ --policy-name my-app --policy-group staging } } - - it "passes options validation" do - expect { knife.validate_policy_options! }.to_not raise_error - end - - it "passes them into the bootstrap context" do - expect(knife.bootstrap_context.first_boot).to have_key(:policy_name) - expect(knife.bootstrap_context.first_boot).to have_key(:policy_group) - end - - it "ensures that run_list is not set in the bootstrap context" do - expect(knife.bootstrap_context.first_boot).to_not have_key(:run_list) - end - - end - - # https://github.com/chef/chef/issues/4131 - # Arguably a bug in the plugin: it shouldn't be setting this to nil, but it - # worked before, so make it work now. - context "when a plugin sets the run list option to nil" do - before do - knife.config[:run_list] = nil - end - - it "passes options validation" do - expect { knife.validate_policy_options! }.to_not raise_error - end - end - end - - # TODO - this is the only cli option we validate the _option_ itself - - # so we'll know if someone accidentally deletes or renames use_sudo_password - # Is this worht keeping? If so, then it seems we should expand it - # to cover all options. - context "validating use_sudo_password option" do - it "use_sudo_password contains description and long params for help" do - expect(knife.options).to(have_key(:use_sudo_password)) \ - && expect(knife.options[:use_sudo_password][:description].to_s).not_to(eq(""))\ - && expect(knife.options[:use_sudo_password][:long].to_s).not_to(eq("")) - end - end - - context "#connection_opts" do - let(:connection_protocol) { "ssh" } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - context "behavioral test: " do - let(:expected_connection_opts) do - { base_opts: true, - ssh_identity_opts: true, - ssh_opts: true, - gateway_opts: true, - host_verify_opts: true, - sudo_opts: true, - winrm_opts: true } - end - - it "queries and merges only expected configurations" do - expect(knife).to receive(:base_opts).and_return({ base_opts: true }) - expect(knife).to receive(:host_verify_opts).and_return({ host_verify_opts: true }) - expect(knife).to receive(:gateway_opts).and_return({ gateway_opts: true }) - expect(knife).to receive(:sudo_opts).and_return({ sudo_opts: true }) - expect(knife).to receive(:winrm_opts).and_return({ winrm_opts: true }) - expect(knife).to receive(:ssh_opts).and_return({ ssh_opts: true }) - expect(knife).to receive(:ssh_identity_opts).and_return({ ssh_identity_opts: true }) - expect(knife.connection_opts).to match expected_connection_opts - end - end - - context "functional test: " do - context "when protocol is winrm" do - let(:connection_protocol) { "winrm" } - # context "and neither CLI nor Chef::Config config entries have been provided" - # end - context "and all supported values are provided as Chef::Config entries" do - before do - # Set everything to easily identifiable and obviously fake values - # to verify that Chef::Config is being sourced instead of knife.config - knife.config = {} - Chef::Config[:knife][:max_wait] = 9999 - Chef::Config[:knife][:winrm_user] = "winbob" - Chef::Config[:knife][:winrm_port] = 9999 - Chef::Config[:knife][:ca_trust_file] = "trust.me" - Chef::Config[:knife][:kerberos_realm] = "realm" - Chef::Config[:knife][:kerberos_service] = "service" - Chef::Config[:knife][:winrm_auth_method] = "kerberos" # default is negotiate - Chef::Config[:knife][:winrm_basic_auth_only] = true - Chef::Config[:knife][:winrm_no_verify_cert] = true - Chef::Config[:knife][:session_timeout] = 9999 - Chef::Config[:knife][:winrm_ssl] = true - Chef::Config[:knife][:winrm_ssl_peer_fingerprint] = "ABCDEF" - end - - context "and no CLI options have been given" do - let(:expected_result) do - { - logger: Chef::Log, # not configurable - ca_trust_path: "trust.me", - max_wait_until_ready: 9999, - operation_timeout: 9999, - ssl_peer_fingerprint: "ABCDEF", - winrm_transport: "kerberos", - winrm_basic_auth_only: true, - user: "winbob", - port: 9999, - self_signed: true, - ssl: true, - kerberos_realm: "realm", - kerberos_service: "service", - } - end - - it "generates a config hash using the Chef::Config values" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - - end - - context "and some CLI options have been given" do - let(:expected_result) do - { - logger: Chef::Log, # not configurable - ca_trust_path: "no trust", - max_wait_until_ready: 9999, - operation_timeout: 9999, - ssl_peer_fingerprint: "ABCDEF", - winrm_transport: "kerberos", - winrm_basic_auth_only: true, - user: "microsoftbob", - port: 12, - self_signed: true, - ssl: true, - kerberos_realm: "realm", - kerberos_service: "service", - password: "lobster", - } - end - - before do - knife.config[:ca_trust_file] = "no trust" - knife.config[:connection_user] = "microsoftbob" - knife.config[:connection_port] = 12 - knife.config[:winrm_port] = "13" # indirectly verify we're not looking for the wrong CLI flag - knife.config[:connection_password] = "lobster" - end - - it "generates a config hash using the CLI options when available and falling back to Chef::Config values" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - - context "and all CLI options have been given" do - before do - # We'll force kerberos vi knife.config because it - # causes additional options to populate - make sure - # Chef::Config is different so we can be sure that we didn't - # pull in the Chef::Config value - Chef::Config[:knife][:winrm_auth_method] = "negotiate" - knife.config[:connection_password] = "blue" - knife.config[:max_wait] = 1000 - knife.config[:connection_user] = "clippy" - knife.config[:connection_port] = 1000 - knife.config[:winrm_port] = 1001 # We should not see this value get used - - knife.config[:ca_trust_file] = "trust.the.internet" - knife.config[:kerberos_realm] = "otherrealm" - knife.config[:kerberos_service] = "otherservice" - knife.config[:winrm_auth_method] = "kerberos" # default is negotiate - knife.config[:winrm_basic_auth_only] = false - knife.config[:winrm_no_verify_cert] = false - knife.config[:session_timeout] = 1000 - knife.config[:winrm_ssl] = false - knife.config[:winrm_ssl_peer_fingerprint] = "FEDCBA" - end - let(:expected_result) do - { - logger: Chef::Log, # not configurable - ca_trust_path: "trust.the.internet", - max_wait_until_ready: 1000, - operation_timeout: 1000, - ssl_peer_fingerprint: "FEDCBA", - winrm_transport: "kerberos", - winrm_basic_auth_only: false, - user: "clippy", - port: 1000, - self_signed: false, - ssl: false, - kerberos_realm: "otherrealm", - kerberos_service: "otherservice", - password: "blue", - } - end - it "generates a config hash using the CLI options and pulling nothing from Chef::Config" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - end # with underlying Chef::Config values - - context "and no values are provided from Chef::Config or CLI" do - before do - # We will use knife's actual config since these tests - # have assumptions based on CLI default values - end - let(:expected_result) do - { - logger: Chef::Log, - operation_timeout: 60, - self_signed: false, - ssl: false, - ssl_peer_fingerprint: nil, - winrm_basic_auth_only: false, - winrm_transport: "negotiate", - } - end - it "populates appropriate defaults" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - end # winrm - - context "when protocol is ssh" do - let(:connection_protocol) { "ssh" } - # context "and neither CLI nor Chef::Config config entries have been provided" - # end - context "and all supported values are provided as Chef::Config entries" do - before do - # Set everything to easily identifiable and obviously fake values - # to verify that Chef::Config is being sourced instead of knife.config - knife.config = {} - Chef::Config[:knife][:max_wait] = 9999 - Chef::Config[:knife][:session_timeout] = 9999 - Chef::Config[:knife][:ssh_user] = "sshbob" - Chef::Config[:knife][:ssh_port] = 9999 - Chef::Config[:knife][:host_key_verify] = false - Chef::Config[:knife][:ssh_gateway_identity] = "/gateway.pem" - Chef::Config[:knife][:ssh_gateway] = "admin@mygateway.local:1234" - Chef::Config[:knife][:ssh_identity_file] = "/identity.pem" - Chef::Config[:knife][:use_sudo_password] = false # We have no password. - end - - context "and no CLI options have been given" do - let(:expected_result) do - { - logger: Chef::Log, # not configurable - max_wait_until_ready: 9999.0, - connection_timeout: 9999, - user: "sshbob", - bastion_host: "mygateway.local", - bastion_port: 1234, - bastion_user: "admin", - forward_agent: false, - keys_only: true, - key_files: ["/identity.pem", "/gateway.pem"], - sudo: false, - verify_host_key: "always", - port: 9999, - non_interactive: true, - } - end - - it "generates a correct config hash using the Chef::Config values" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - - context "and unsupported Chef::Config options are given in Chef::Config, not in CLI" do - before do - Chef::Config[:knife][:password] = "blah" - Chef::Config[:knife][:ssh_password] = "blah" - Chef::Config[:knife][:preserve_home] = true - Chef::Config[:knife][:use_sudo] = true - Chef::Config[:knife][:ssh_forward_agent] = "blah" - end - it "does not include the corresponding option in the connection options" do - knife.merge_configs - expect(knife.connection_opts.key?(:password)).to eq false - expect(knife.connection_opts.key?(:ssh_forward_agent)).to eq false - expect(knife.connection_opts.key?(:use_sudo)).to eq false - expect(knife.connection_opts.key?(:preserve_home)).to eq false - end - end - - context "and some CLI options have been given" do - before do - knife.config = {} - knife.config[:connection_user] = "sshalice" - knife.config[:connection_port] = 12 - knife.config[:ssh_port] = "13" # canary to indirectly verify we're not looking for the wrong CLI flag - knife.config[:connection_password] = "feta cheese" - knife.config[:max_wait] = 150 - knife.config[:session_timeout] = 120 - knife.config[:use_sudo] = true - knife.config[:use_sudo_pasword] = true - knife.config[:ssh_forward_agent] = true - end - - let(:expected_result) do - { - logger: Chef::Log, # not configurable - max_wait_until_ready: 150.0, # cli - connection_timeout: 120, # cli - user: "sshalice", # cli - password: "feta cheese", # cli - bastion_host: "mygateway.local", # Config - bastion_port: 1234, # Config - bastion_user: "admin", # Config - forward_agent: true, # cli - keys_only: false, # implied false from config password present - key_files: ["/identity.pem", "/gateway.pem"], # Config - sudo: true, # ccli - verify_host_key: "always", # Config - port: 12, # cli - non_interactive: true, - } - end - - it "generates a config hash using the CLI options when available and falling back to Chef::Config values" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - - context "and all CLI options have been given" do - before do - knife.config = {} - knife.config[:max_wait] = 150 - knife.config[:session_timeout] = 120 - knife.config[:connection_user] = "sshroot" - knife.config[:connection_port] = 1000 - knife.config[:connection_password] = "blah" - knife.config[:forward_agent] = true - knife.config[:use_sudo] = true - knife.config[:use_sudo_password] = true - knife.config[:preserve_home] = true - knife.config[:use_sudo_pasword] = true - knife.config[:ssh_forward_agent] = true - knife.config[:ssh_verify_host_key] = true - knife.config[:ssh_gateway_identity] = "/gateway-identity.pem" - knife.config[:ssh_gateway] = "me@example.com:10" - knife.config[:ssh_identity_file] = "/my-identity.pem" - - # We'll set these as canaries - if one of these values shows up - # in a failed test, then the behavior of not pulling from these keys - # out of knife.config is broken: - knife.config[:ssh_user] = "do not use" - knife.config[:ssh_port] = 1001 - end - let(:expected_result) do - { - logger: Chef::Log, # not configurable - max_wait_until_ready: 150, - connection_timeout: 120, - user: "sshroot", - password: "blah", - port: 1000, - bastion_host: "example.com", - bastion_port: 10, - bastion_user: "me", - forward_agent: true, - keys_only: false, - key_files: ["/my-identity.pem", "/gateway-identity.pem"], - sudo: true, - sudo_options: "-H", - sudo_password: "blah", - verify_host_key: true, - non_interactive: true, - } - end - it "generates a config hash using the CLI options and pulling nothing from Chef::Config" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - end - context "and no values are provided from Chef::Config or CLI" do - before do - # We will use knife's actual config since these tests - # have assumptions based on CLI default values - config = {} - end - - let(:expected_result) do - { - forward_agent: false, - key_files: [], - logger: Chef::Log, - keys_only: false, - sudo: false, - verify_host_key: "always", - non_interactive: true, - connection_timeout: 60, - } - end - it "populates appropriate defaults" do - knife.merge_configs - expect(knife.connection_opts).to match expected_result - end - end - - end # ssh - end # functional tests - - end # connection_opts - - context "#base_opts" do - let(:connection_protocol) { nil } - - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for all protocols" do - context "when password is provided" do - before do - knife.config[:connection_port] = 250 - knife.config[:connection_user] = "test" - knife.config[:connection_password] = "opscode" - end - - let(:expected_opts) do - { - port: 250, - user: "test", - logger: Chef::Log, - password: "opscode", - } - end - it "generates the correct options" do - expect(knife.base_opts).to eq expected_opts - end - - end - - context "when password is not provided" do - before do - knife.config[:connection_port] = 250 - knife.config[:connection_user] = "test" - end - - let(:expected_opts) do - { - port: 250, - user: "test", - logger: Chef::Log, - } - end - it "generates the correct options" do - expect(knife.base_opts).to eq expected_opts - end - end - end - end - - context "#host_verify_opts" do - let(:connection_protocol) { nil } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for winrm" do - let(:connection_protocol) { "winrm" } - it "returns the expected configuration" do - knife.config[:winrm_no_verify_cert] = true - expect(knife.host_verify_opts).to eq( { self_signed: true } ) - end - it "provides a correct default when no option given" do - expect(knife.host_verify_opts).to eq( { self_signed: false } ) - end - end - - context "for ssh" do - let(:connection_protocol) { "ssh" } - it "returns the expected configuration" do - knife.config[:ssh_verify_host_key] = false - expect(knife.host_verify_opts).to eq( { verify_host_key: false } ) - end - it "provides a correct default when no option given" do - expect(knife.host_verify_opts).to eq( { verify_host_key: "always" } ) - end - end - end - - # TODO - test keys_only, password, config source behavior - context "#ssh_identity_opts" do - let(:connection_protocol) { nil } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for winrm" do - let(:connection_protocol) { "winrm" } - it "returns an empty hash" do - expect(knife.ssh_identity_opts).to eq({}) - end - end - - context "for ssh" do - let(:connection_protocol) { "ssh" } - context "when an identity file is specified" do - before do - knife.config[:ssh_identity_file] = "/identity.pem" - end - it "generates the expected configuration" do - expect(knife.ssh_identity_opts).to eq({ - key_files: [ "/identity.pem" ], - keys_only: true, - }) - end - context "and a password is also specified" do - before do - knife.config[:connection_password] = "blah" - end - it "generates the expected configuration (key, keys_only false)" do - expect(knife.ssh_identity_opts).to eq({ - key_files: [ "/identity.pem" ], - keys_only: false, - }) - end - end - - context "and a gateway is not specified" do - context "but a gateway identity file is specified" do - it "does not include the gateway identity file in keys" do - expect(knife.ssh_identity_opts).to eq({ - key_files: ["/identity.pem"], - keys_only: true, - }) - end - - end - - end - - context "and a gatway is specified" do - before do - knife.config[:ssh_gateway] = "example.com" - end - context "and a gateway identity file is not specified" do - it "config includes only identity file and not gateway identity" do - expect(knife.ssh_identity_opts).to eq({ - key_files: [ "/identity.pem" ], - keys_only: true, - }) - end - end - - context "and a gateway identity file is also specified" do - before do - knife.config[:ssh_gateway_identity] = "/gateway.pem" - end - - it "generates the expected configuration (both keys, keys_only true)" do - expect(knife.ssh_identity_opts).to eq({ - key_files: [ "/identity.pem", "/gateway.pem" ], - keys_only: true, - }) - end - end - end - end - - context "when no identity file is specified" do - it "generates the expected configuration (no keys, keys_only false)" do - expect(knife.ssh_identity_opts).to eq( { - key_files: [ ], - keys_only: false, - }) - end - context "and a gateway with gateway identity file is specified" do - before do - knife.config[:ssh_gateway] = "host" - knife.config[:ssh_gateway_identity] = "/gateway.pem" - end - - it "generates the expected configuration (gateway key, keys_only false)" do - expect(knife.ssh_identity_opts).to eq({ - key_files: [ "/gateway.pem" ], - keys_only: false, - }) - end - end - end - end - end - - context "#gateway_opts" do - let(:connection_protocol) { nil } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for winrm" do - let(:connection_protocol) { "winrm" } - it "returns an empty hash" do - expect(knife.gateway_opts).to eq({}) - end - end - - context "for ssh" do - let(:connection_protocol) { "ssh" } - context "and ssh_gateway with hostname, user and port provided" do - before do - knife.config[:ssh_gateway] = "testuser@gateway:9021" - end - it "returns a proper bastion host config subset" do - expect(knife.gateway_opts).to eq({ - bastion_user: "testuser", - bastion_host: "gateway", - bastion_port: 9021, - }) - end - end - context "and ssh_gateway with only hostname is given" do - before do - knife.config[:ssh_gateway] = "gateway" - end - it "returns a proper bastion host config subset" do - expect(knife.gateway_opts).to eq({ - bastion_user: nil, - bastion_host: "gateway", - bastion_port: nil, - }) - end - end - context "and ssh_gateway with hostname and user is is given" do - before do - knife.config[:ssh_gateway] = "testuser@gateway" - end - it "returns a proper bastion host config subset" do - expect(knife.gateway_opts).to eq({ - bastion_user: "testuser", - bastion_host: "gateway", - bastion_port: nil, - }) - end - end - - context "and ssh_gateway with hostname and port is is given" do - before do - knife.config[:ssh_gateway] = "gateway:11234" - end - it "returns a proper bastion host config subset" do - expect(knife.gateway_opts).to eq({ - bastion_user: nil, - bastion_host: "gateway", - bastion_port: 11234, - }) - end - end - - context "and ssh_gateway is not provided" do - it "returns an empty hash" do - expect(knife.gateway_opts).to eq({}) - end - end - end - end - - context "#sudo_opts" do - let(:connection_protocol) { nil } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for winrm" do - let(:connection_protocol) { "winrm" } - it "returns an empty hash" do - expect(knife.sudo_opts).to eq({}) - end - end - - context "for ssh" do - let(:connection_protocol) { "ssh" } - context "when use_sudo is set" do - before do - knife.config[:use_sudo] = true - end - - it "returns a config that enables sudo" do - expect(knife.sudo_opts).to eq( { sudo: true } ) - end - - context "when use_sudo_password is also set" do - before do - knife.config[:use_sudo_password] = true - knife.config[:connection_password] = "opscode" - end - it "includes :connection_password value in a sudo-enabled configuration" do - expect(knife.sudo_opts).to eq({ - sudo: true, - sudo_password: "opscode", - }) - end - end - - context "when preserve_home is set" do - before do - knife.config[:preserve_home] = true - end - it "enables sudo with sudo_option to preserve home" do - expect(knife.sudo_opts).to eq({ - sudo_options: "-H", - sudo: true, - }) - end - end - end - - context "when use_sudo is not set" do - before do - knife.config[:use_sudo_password] = true - knife.config[:preserve_home] = true - end - it "returns configuration for sudo off, ignoring other related options" do - expect(knife.sudo_opts).to eq( { sudo: false } ) - end - end - end - end - - context "#ssh_opts" do - let(:connection_protocol) { nil } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for ssh" do - let(:connection_protocol) { "ssh" } - let(:default_opts) do - { - non_interactive: true, - forward_agent: false, - connection_timeout: 60, - } - end - - context "by default" do - it "returns a configuration hash with appropriate defaults" do - expect(knife.ssh_opts).to eq default_opts - end - end - - context "when ssh_forward_agent has a value" do - before do - knife.config[:ssh_forward_agent] = true - end - it "returns a default configuration hash with forward_agent set to true" do - expect(knife.ssh_opts).to eq(default_opts.merge(forward_agent: true)) - end - end - context "when session_timeout has a value" do - before do - knife.config[:session_timeout] = 120 - end - it "returns a default configuration hash with updated timeout value." do - expect(knife.ssh_opts).to eq(default_opts.merge(connection_timeout: 120)) - end - end - - end - - context "for winrm" do - let(:connection_protocol) { "winrm" } - it "returns an empty has because ssh is not winrm" do - expect(knife.ssh_opts).to eq({}) - end - end - - end - - context "#winrm_opts" do - let(:connection_protocol) { nil } - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "for winrm" do - let(:connection_protocol) { "winrm" } - let(:expected) do - { - winrm_transport: "negotiate", - winrm_basic_auth_only: false, - ssl: false, - ssl_peer_fingerprint: nil, - operation_timeout: 60, - } - end - - it "generates a correct configuration hash with expected defaults" do - expect(knife.winrm_opts).to eq expected - end - - context "with ssl_peer_fingerprint" do - let(:ssl_peer_fingerprint_expected) do - expected.merge({ ssl_peer_fingerprint: "ABCD" }) - end - - before do - knife.config[:winrm_ssl_peer_fingerprint] = "ABCD" - end - - it "generates a correct options hash with ssl_peer_fingerprint from the config provided" do - expect(knife.winrm_opts).to eq ssl_peer_fingerprint_expected - end - end - - context "with winrm_ssl" do - let(:ssl_expected) do - expected.merge({ ssl: true }) - end - before do - knife.config[:winrm_ssl] = true - end - - it "generates a correct options hash with ssl from the config provided" do - expect(knife.winrm_opts).to eq ssl_expected - end - end - - context "with winrm_auth_method" do - let(:winrm_auth_method_expected) do - expected.merge({ winrm_transport: "freeaccess" }) - end - - before do - knife.config[:winrm_auth_method] = "freeaccess" - end - - it "generates a correct options hash with winrm_transport from the config provided" do - expect(knife.winrm_opts).to eq winrm_auth_method_expected - end - end - - context "with ca_trust_file" do - let(:ca_trust_expected) do - expected.merge({ ca_trust_path: "/trust.me" }) - end - before do - knife.config[:ca_trust_file] = "/trust.me" - end - - it "generates a correct options hash with ca_trust_file from the config provided" do - expect(knife.winrm_opts).to eq ca_trust_expected - end - end - - context "with kerberos auth" do - let(:kerberos_expected) do - expected.merge({ - kerberos_service: "testsvc", - kerberos_realm: "TESTREALM", - winrm_transport: "kerberos", - }) - end - - before do - knife.config[:winrm_auth_method] = "kerberos" - knife.config[:kerberos_service] = "testsvc" - knife.config[:kerberos_realm] = "TESTREALM" - end - - it "generates a correct options hash containing kerberos auth configuration from the config provided" do - expect(knife.winrm_opts).to eq kerberos_expected - end - end - - context "with winrm_basic_auth_only" do - before do - knife.config[:winrm_basic_auth_only] = true - end - let(:basic_auth_expected) do - expected.merge( { winrm_basic_auth_only: true } ) - end - it "generates a correct options hash containing winrm_basic_auth_only from the config provided" do - expect(knife.winrm_opts).to eq basic_auth_expected - end - end - end - - context "for ssh" do - let(:connection_protocol) { "ssh" } - it "returns an empty hash because ssh is not winrm" do - expect(knife.winrm_opts).to eq({}) - end - end - end - describe "#run" do - it "performs the steps we expect to run a bootstrap" do - expect(knife).to receive(:check_license) - expect(knife).to receive(:validate_name_args!).ordered - expect(knife).to receive(:validate_protocol!).ordered - expect(knife).to receive(:validate_first_boot_attributes!).ordered - expect(knife).to receive(:validate_winrm_transport_opts!).ordered - expect(knife).to receive(:validate_policy_options!).ordered - expect(knife).to receive(:winrm_warn_no_ssl_verification).ordered - expect(knife).to receive(:warn_on_short_session_timeout).ordered - expect(knife).to receive(:connect!).ordered - expect(knife).to receive(:register_client).ordered - expect(knife).to receive(:render_template).and_return "content" - expect(knife).to receive(:upload_bootstrap).with("content").and_return "/remote/path.sh" - expect(knife).to receive(:perform_bootstrap).with("/remote/path.sh") - expect(connection).to receive(:del_file!) # Make sure cleanup happens - - knife.run - - # Post-run verify expected state changes (not many directly in #run) - expect($stdout.sync).to eq true - end - end - - describe "#register_client" do - let(:vault_handler_mock) { double("ChefVaultHandler") } - let(:client_builder_mock) { double("ClientBuilder") } - let(:node_name) { nil } - before do - allow(knife).to receive(:chef_vault_handler).and_return vault_handler_mock - allow(knife).to receive(:client_builder).and_return client_builder_mock - knife.config[:chef_node_name] = node_name - end - - shared_examples_for "creating the client locally" do - context "when a valid node name is present" do - let(:node_name) { "test" } - before do - allow(client_builder_mock).to receive(:client).and_return "client" - allow(client_builder_mock).to receive(:client_path).and_return "/key.pem" - end - - it "runs client_builder and vault_handler" do - expect(client_builder_mock).to receive(:run) - expect(vault_handler_mock).to receive(:run).with("client") - knife.register_client - end - - it "sets the path to the client key in the bootstrap context" do - allow(client_builder_mock).to receive(:run) - allow(vault_handler_mock).to receive(:run).with("client") - knife.register_client - expect(knife.bootstrap_context.client_pem).to eq "/key.pem" - end - end - - context "when no valid node name is present" do - let(:node_name) { nil } - it "shows an error and exits" do - expect(knife.ui).to receive(:error) - expect { knife.register_client }.to raise_error(SystemExit) - end - end - end - context "when chef_vault_handler says we're using vault" do - let(:vault_handler_mock) { double("ChefVaultHandler") } - before do - allow(vault_handler_mock).to receive(:doing_chef_vault?).and_return true - end - it_behaves_like "creating the client locally" - end - - context "when an non-existant validation key is specified in chef config" do - before do - Chef::Config[:validation_key] = "/blah" - allow(vault_handler_mock).to receive(:doing_chef_vault?).and_return false - allow(File).to receive(:exist?).with(%r{/blah}).and_return false - end - it_behaves_like "creating the client locally" - end - - context "when a valid validation key is given and we're doing old-style client creation" do - before do - Chef::Config[:validation_key] = "/blah" - allow(File).to receive(:exist?).with(%r{/blah}).and_return true - allow(vault_handler_mock).to receive(:doing_chef_vault?).and_return false - end - - it "shows a warning message" do - expect(knife.ui).to receive(:warn).twice - knife.register_client - end - end - end - - describe "#perform_bootstrap" do - let(:exit_status) { 0 } - let(:result_mock) { double("result", exit_status: exit_status, stderr: "A message") } - - before do - allow(connection).to receive(:hostname).and_return "testhost" - end - it "runs the remote script and logs the output" do - expect(knife.ui).to receive(:info).with(/Bootstrapping.*/) - expect(knife).to receive(:bootstrap_command) - .with("/path.sh") - .and_return("sh /path.sh") - expect(connection) - .to receive(:run_command) - .with("sh /path.sh") - .and_yield("output here") - .and_return result_mock - - expect(knife.ui).to receive(:msg).with(/testhost/) - knife.perform_bootstrap("/path.sh") - end - context "when the remote command fails" do - let(:exit_status) { 1 } - it "shows an error and exits" do - expect(knife.ui).to receive(:info).with(/Bootstrapping.*/) - expect(knife).to receive(:bootstrap_command) - .with("/path.sh") - .and_return("sh /path.sh") - expect(connection).to receive(:run_command).with("sh /path.sh").and_return result_mock - expect { knife.perform_bootstrap("/path.sh") }.to raise_error(SystemExit) - end - end - end - - describe "#connect!" do - before do - # These are not required at run-time because train will handle its own - # protocol loading. In this case, we're simulating train failures and have to load - # them ourselves. - require "net/ssh" - require "train/transports/ssh" - end - - context "in the normal case" do - it "connects using the connection_opts and notifies the operator of progress" do - expect(knife.ui).to receive(:info).with(/Connecting to.*/) - expect(knife).to receive(:connection_opts).and_return( { opts: "here" }) - expect(knife).to receive(:do_connect).with( { opts: "here" } ) - knife.connect! - end - end - - context "when a general non-auth-failure occurs" do - let(:expected_error) { RuntimeError.new } - before do - allow(knife).to receive(:do_connect).and_raise(expected_error) - end - it "re-raises the exception" do - expect { knife.connect! }.to raise_error(expected_error) - end - end - - context "when ssh fingerprint is invalid" do - let(:expected_error) { Train::Error.new("fingerprint AA:BB is unknown for \"blah,127.0.0.1\"") } - before do - allow(knife).to receive(:do_connect).and_raise(expected_error) - end - it "warns, prompts to accept, then connects with verify_host_key of accept_new" do - expect(knife).to receive(:do_connect).and_raise(expected_error) - expect(knife.ui).to receive(:confirm) - .with(/.*host 'blah \(127.0.0.1\)'.*AA:BB.*Are you sure you want to continue.*/m) - .and_return(true) - expect(knife).to receive(:do_connect) do |opts| - expect(opts[:verify_host_key]).to eq :accept_new - end - knife.connect! - end - end - - context "when an auth failure occurs" do - let(:expected_error) do - e = Train::Error.new - actual = Net::SSH::AuthenticationFailed.new - # Simulate train's nested error - they wrap - # ssh/network errors in a TrainError. - allow(e).to receive(:cause).and_return(actual) - e - end - - let(:expected_error_password_prompt) do - e = Train::ClientError.new - reason = :no_ssh_password_or_key_available - allow(e).to receive(:reason).and_return(reason) - e - end - - let(:expected_error_password_prompt_winrm) do - e = RuntimeError.new - message = "password is a required option" - allow(e).to receive(:message).and_return(message) - e - end - - context "and password auth was used" do - before do - allow(connection).to receive(:password_auth?).and_return true - end - - it "re-raises the error so as not to resubmit the same failing password" do - expect(knife).to receive(:do_connect).and_raise(expected_error) - expect { knife.connect! }.to raise_error(expected_error) - end - end - - context "and password auth was not used" do - before do - allow(connection).to receive(:password_auth?).and_return false - allow(connection).to receive(:user).and_return "testuser" - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "when using ssh" do - let(:connection_protocol) { "ssh" } - - it "warns, prompts for password, then reconnects with a password-enabled configuration using the new password" do - expect(knife).to receive(:do_connect).and_raise(expected_error_password_prompt) - expect(knife.ui).to receive(:warn).with(/Failed to auth.*/) - expect(knife.ui).to receive(:ask).and_return("newpassword") - # Ensure that we set echo off to prevent showing password on the screen - expect(knife).to receive(:do_connect) do |opts| - expect(opts[:password]).to eq "newpassword" - end - knife.connect! - end - end - - context "when using winrm" do - let(:connection_protocol) { "winrm" } - - it "warns, prompts for password, then reconnects with a password-enabled configuration using the new password for" do - expect(knife).to receive(:do_connect).and_raise(expected_error_password_prompt_winrm) - expect(knife.ui).to receive(:warn).with(/Failed to auth.*/) - expect(knife.ui).to receive(:ask).and_return("newpassword") - # Ensure that we set echo off to prevent showing password on the screen - expect(knife).to receive(:do_connect) do |opts| - expect(opts[:password]).to eq "newpassword" - end - knife.connect! - end - end - end - end - end - - it "verifies that a server to bootstrap was given as a command line arg" do - knife.name_args = nil - expect(knife).to receive(:check_license) - expect { knife.run }.to raise_error(SystemExit) - expect(stderr.string).to match(/ERROR:.+FQDN or ip/) - end - - describe "#bootstrap_context" do - context "under Windows" do - let(:windows_test) { true } - it "creates a WindowsBootstrapContext" do - require "chef/knife/core/windows_bootstrap_context" - expect(knife.bootstrap_context.class).to eq Chef::Knife::Core::WindowsBootstrapContext - end - end - - context "under linux" do - let(:linux_test) { true } - it "creates a BootstrapContext" do - require "chef/knife/core/bootstrap_context" - expect(knife.bootstrap_context.class).to eq Chef::Knife::Core::BootstrapContext - end - end - end - - describe "#config_value" do - before do - knife.config[:test_key_a] = "a from cli" - knife.config[:test_key_b] = "b from cli" - Chef::Config[:knife][:test_key_a] = "a from Chef::Config" - Chef::Config[:knife][:test_key_c] = "c from Chef::Config" - Chef::Config[:knife][:alt_test_key_c] = "alt c from Chef::Config" - knife.merge_configs - Chef::Config[:treat_deprecation_warnings_as_errors] = false - end - - it "returns the Chef::Config value from the cli when the CLI key is set" do - expect(knife.config_value(:test_key_a, :alt_test_key_c)).to eq "a from cli" - end - - it "returns the Chef::Config value from the alternative key when the CLI key is not set" do - expect(knife.config_value(:test_key_d, :alt_test_key_c)).to eq "alt c from Chef::Config" - end - - it "returns the default value when the key is not provided by CLI or Chef::Config" do - expect(knife.config_value(:missing_key, :missing_key, "found")).to eq "found" - end - end - - describe "#upload_bootstrap" do - before do - allow(connection).to receive(:temp_dir).and_return(temp_dir) - allow(connection).to receive(:normalize_path) { |a| a } - end - - let(:content) { "bootstrap script content" } - context "under Windows" do - let(:windows_test) { true } - let(:temp_dir) { "C:/Temp/bootstrap" } - it "creates a bat file in the temp dir provided by connection, using given content" do - expect(connection).to receive(:upload_file_content!).with(content, "C:/Temp/bootstrap/bootstrap.bat") - expect(knife.upload_bootstrap(content)).to eq "C:/Temp/bootstrap/bootstrap.bat" - end - end - - context "under Linux" do - let(:linux_test) { true } - let(:temp_dir) { "/tmp/bootstrap" } - it "creates a 'sh file in the temp dir provided by connection, using given content" do - expect(connection).to receive(:upload_file_content!).with(content, "/tmp/bootstrap/bootstrap.sh") - expect(knife.upload_bootstrap(content)).to eq "/tmp/bootstrap/bootstrap.sh" - end - end - end - - describe "#bootstrap_command" do - context "under Windows" do - let(:windows_test) { true } - it "prefixes the command to run under cmd.exe" do - expect(knife.bootstrap_command("autoexec.bat")).to eq "cmd.exe /C autoexec.bat" - end - - end - context "under Linux" do - let(:linux_test) { true } - it "prefixes the command to run under sh" do - expect(knife.bootstrap_command("bootstrap")).to eq "sh bootstrap" - end - end - end - - describe "#default_bootstrap_template" do - context "under Windows" do - let(:windows_test) { true } - it "is windows-chef-client-msi" do - expect(knife.default_bootstrap_template).to eq "windows-chef-client-msi" - end - - end - context "under Linux" do - let(:linux_test) { true } - it "is chef-full" do - expect(knife.default_bootstrap_template).to eq "chef-full" - end - end - end - - describe "#do_connect" do - let(:host_descriptor) { "example.com" } - let(:connection) { double("TrainConnector") } - let(:connector_mock) { double("TargetResolver", targets: [ connection ]) } - before do - allow(knife).to receive(:host_descriptor).and_return host_descriptor - end - - it "creates a TrainConnector and connects it" do - expect(Chef::Knife::Bootstrap::TrainConnector).to receive(:new).and_return connection - expect(connection).to receive(:connect!) - knife.do_connect({}) - end - - context "when sshd configured with requiretty" do - let(:pty_err_msg) { "Sudo requires a TTY. Please see the README on how to configure sudo to allow for non-interactive usage." } - let(:expected_error) { Train::UserError.new(pty_err_msg, :sudo_no_tty) } - before do - allow(connection).to receive(:connect!).and_raise(expected_error) - end - it "retry with pty true request option" do - expect(Chef::Knife::Bootstrap::TrainConnector).to receive(:new).and_return(connection).exactly(2).times - expect(knife.ui).to receive(:warn).with("#{pty_err_msg} - trying with pty request") - expect { knife.do_connect({}) }.to raise_error(expected_error) - end - end - end - - describe "validate_winrm_transport_opts!" do - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "when using ssh" do - let(:connection_protocol) { "ssh" } - it "returns true" do - expect(knife.validate_winrm_transport_opts!).to eq true - end - end - context "when using winrm" do - let(:connection_protocol) { "winrm" } - context "with plaintext auth" do - before do - knife.config[:winrm_auth_method] = "plaintext" - end - context "with ssl" do - before do - knife.config[:winrm_ssl] = true - end - it "will not error because we won't send anything in plaintext regardless" do - expect(knife.validate_winrm_transport_opts!).to eq true - end - end - context "without ssl" do - before do - knife.config[:winrm_ssl] = false - end - context "and no validation key exists" do - before do - Chef::Config[:validation_key] = "validation_key.pem" - allow(File).to receive(:exist?).with(/.*validation_key.pem/).and_return false - end - - it "will error because we will generate and send a client key over the wire in plaintext" do - expect { knife.validate_winrm_transport_opts! }.to raise_error(SystemExit) - end - - end - context "and a validation key exists" do - before do - Chef::Config[:validation_key] = "validation_key.pem" - allow(File).to receive(:exist?).with(/.*validation_key.pem/).and_return true - end - # TODO - don't we still send validation key? - it "will not error because we don not send client key over the wire" do - expect(knife.validate_winrm_transport_opts!).to eq true - end - end - end - end - - context "with other auth" do - before do - knife.config[:winrm_auth_method] = "kerberos" - end - - context "and no validation key exists" do - before do - - Chef::Config[:validation_key] = "validation_key.pem" - allow(File).to receive(:exist?).with(/.*validation_key.pem/).and_return false - end - - it "will not error because we're not using plaintext auth" do - expect(knife.validate_winrm_transport_opts!).to eq true - end - end - context "and a validation key exists" do - before do - Chef::Config[:validation_key] = "validation_key.pem" - allow(File).to receive(:exist?).with(/.*validation_key.pem/).and_return true - end - - it "will not error because a client key won't be sent over the wire in plaintext when a validation key is present" do - expect(knife.validate_winrm_transport_opts!).to eq true - end - end - - end - - end - - end - - describe "#winrm_warn_no_ssl_verification" do - before do - allow(knife).to receive(:connection_protocol).and_return connection_protocol - end - - context "when using ssh" do - let(:connection_protocol) { "ssh" } - it "does not issue a warning" do - expect(knife.ui).to_not receive(:warn) - knife.winrm_warn_no_ssl_verification - end - end - context "when using winrm" do - let(:connection_protocol) { "winrm" } - context "winrm_no_verify_cert is set" do - before do - knife.config[:winrm_no_verify_cert] = true - end - - context "and ca_trust_file is present" do - before do - knife.config[:ca_trust_file] = "file" - end - - it "does not issue a warning" do - expect(knife.ui).to_not receive(:warn) - knife.winrm_warn_no_ssl_verification - end - end - - context "and winrm_ssl_peer_fingerprint is present" do - before do - knife.config[:winrm_ssl_peer_fingerprint] = "ABCD" - end - it "does not issue a warning" do - expect(knife.ui).to_not receive(:warn) - knife.winrm_warn_no_ssl_verification - end - end - context "and neither ca_trust_file nor winrm_ssl_peer_fingerprint is present" do - it "issues a warning" do - expect(knife.ui).to receive(:warn) - knife.winrm_warn_no_ssl_verification - end - end - end - end - end - - describe "#warn_on_short_session_timeout" do - let(:session_timeout) { 60 } - - before do - allow(knife).to receive(:session_timeout).and_return(session_timeout) - end - - context "timeout is not set at all" do - let(:session_timeout) { nil } - it "does not issue a warning" do - expect(knife.ui).to_not receive(:warn) - knife.warn_on_short_session_timeout - end - end - - context "timeout is more than 15" do - let(:session_timeout) { 16 } - it "does not issue a warning" do - expect(knife.ui).to_not receive(:warn) - knife.warn_on_short_session_timeout - end - end - context "timeout is 15 or less" do - let(:session_timeout) { 15 } - it "issues a warning" do - expect(knife.ui).to receive(:warn) - knife.warn_on_short_session_timeout - end - end - end -end diff --git a/spec/unit/knife/client_bulk_delete_spec.rb b/spec/unit/knife/client_bulk_delete_spec.rb deleted file mode 100644 index 435eb888aa..0000000000 --- a/spec/unit/knife/client_bulk_delete_spec.rb +++ /dev/null @@ -1,166 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@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 "spec_helper" - -describe Chef::Knife::ClientBulkDelete do - let(:stdout_io) { StringIO.new } - let(:stdout) { stdout_io.string } - let(:stderr_io) { StringIO.new } - let(:stderr) { stderr_io.string } - - let(:knife) do - k = Chef::Knife::ClientBulkDelete.new - k.name_args = name_args - k.config = option_args - allow(k.ui).to receive(:stdout).and_return(stdout_io) - allow(k.ui).to receive(:stderr).and_return(stderr_io) - allow(k.ui).to receive(:confirm).and_return(knife_confirm) - allow(k.ui).to receive(:confirm_without_exit).and_return(knife_confirm) - k - end - - let(:name_args) { [ "." ] } - let(:option_args) { {} } - - let(:knife_confirm) { true } - - let(:nonvalidator_client_names) { %w{tim dan stephen} } - let(:nonvalidator_clients) do - clients = {} - - nonvalidator_client_names.each do |client_name| - client = Chef::ApiClientV1.new - client.name(client_name) - allow(client).to receive(:destroy).and_return(true) - clients[client_name] = client - end - - clients - end - - let(:validator_client_names) { %w{myorg-validator} } - let(:validator_clients) do - clients = {} - - validator_client_names.each do |validator_client_name| - validator_client = Chef::ApiClientV1.new - validator_client.name(validator_client_name) - allow(validator_client).to receive(:validator).and_return(true) - allow(validator_client).to receive(:destroy).and_return(true) - clients[validator_client_name] = validator_client - end - - clients - end - - let(:client_names) { nonvalidator_client_names + validator_client_names } - let(:clients) do - nonvalidator_clients.merge(validator_clients) - end - - before(:each) do - allow(Chef::ApiClientV1).to receive(:list).and_return(clients) - end - - describe "run" do - describe "without a regex" do - let(:name_args) { [ ] } - - it "should exit if the regex is not provided" do - expect { knife.run }.to raise_error(SystemExit) - end - end - - describe "with any clients" do - it "should get the list of the clients" do - expect(Chef::ApiClientV1).to receive(:list) - knife.run - end - - it "should print the name of the clients" do - knife.run - client_names.each do |client_name| - expect(stdout).to include(client_name) - end - end - - it "should confirm you really want to delete them" do - expect(knife.ui).to receive(:confirm) - knife.run - end - - describe "without --delete-validators" do - it "should mention that validator clients wont be deleted" do - knife.run - expect(stdout).to include("The following clients are validators and will not be deleted:") - info = stdout.index "The following clients are validators and will not be deleted:" - val = stdout.index "myorg-validator" - expect(val > info).to be_truthy - end - - it "should only delete nonvalidator clients" do - nonvalidator_clients.each_value do |c| - expect(c).to receive(:destroy) - end - - validator_clients.each_value do |c| - expect(c).not_to receive(:destroy) - end - - knife.run - end - end - - describe "with --delete-validators" do - let(:option_args) { { delete_validators: true } } - - it "should mention that validator clients will be deleted" do - knife.run - expect(stdout).to include("The following validators will be deleted") - end - - it "should confirm twice" do - expect(knife.ui).to receive(:confirm).once - expect(knife.ui).to receive(:confirm_without_exit).once - knife.run - end - - it "should delete all clients" do - clients.each_value do |c| - expect(c).to receive(:destroy) - end - - knife.run - end - end - end - - describe "with some clients" do - let(:name_args) { [ "^ti" ] } - - it "should only delete clients that match the regex" do - expect(clients["tim"]).to receive(:destroy) - expect(clients["stephen"]).not_to receive(:destroy) - expect(clients["dan"]).not_to receive(:destroy) - expect(clients["myorg-validator"]).not_to receive(:destroy) - knife.run - end - end - end -end diff --git a/spec/unit/knife/client_create_spec.rb b/spec/unit/knife/client_create_spec.rb deleted file mode 100644 index d8b67de101..0000000000 --- a/spec/unit/knife/client_create_spec.rb +++ /dev/null @@ -1,169 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -Chef::Knife::ClientCreate.load_deps - -describe Chef::Knife::ClientCreate do - let(:stderr) { StringIO.new } - let(:stdout) { StringIO.new } - - let(:default_client_hash) do - { - "name" => "adam", - "validator" => false, - } - end - - let(:client) do - Chef::ApiClientV1.new - end - - let(:knife) do - k = Chef::Knife::ClientCreate.new - k.name_args = [] - allow(k).to receive(:client).and_return(client) - allow(k).to receive(:edit_hash).with(client).and_return(client) - allow(k.ui).to receive(:stderr).and_return(stderr) - allow(k.ui).to receive(:stdout).and_return(stdout) - k - end - - before do - allow(client).to receive(:to_s).and_return("client[adam]") - allow(knife).to receive(:create_client).and_return(client) - end - - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - end - - describe "run" do - context "when nothing is passed" do - # from spec/support/shared/unit/knife_shared.rb - it_should_behave_like "mandatory field missing" do - let(:name_args) { [] } - let(:fieldname) { "client name" } - end - end - - context "when clientname is passed" do - before do - knife.name_args = ["adam"] - end - - context "when public_key and prevent_keygen are passed" do - before do - knife.config[:public_key] = "some_key" - knife.config[:prevent_keygen] = true - end - - it "prints the usage" do - expect(knife).to receive(:show_usage) - expect { knife.run }.to raise_error(SystemExit) - end - - it "prints a relevant error message" do - expect { knife.run }.to raise_error(SystemExit) - expect(stderr.string).to match(/You cannot pass --public-key and --prevent-keygen/) - end - end - - it "should create the ApiClient" do - expect(knife).to receive(:create_client) - knife.run - end - - it "should print a message upon creation" do - expect(knife).to receive(:create_client) - knife.run - expect(stderr.string).to match(/Created client.*adam/i) - end - - it "should set the Client name" do - knife.run - expect(client.name).to eq("adam") - end - - it "by default it is not a validator" do - knife.run - expect(client.validator).to be_falsey - end - - it "by default it should set create_key to true" do - knife.run - expect(client.create_key).to be_truthy - end - - it "should allow you to edit the data" do - expect(knife).to receive(:edit_hash).with(client).and_return(client) - knife.run - end - - describe "with -f or --file" do - before do - client.private_key "woot" - end - - it "should write the private key to a file" do - knife.config[:file] = "/tmp/monkeypants" - filehandle = double("Filehandle") - expect(filehandle).to receive(:print).with("woot") - expect(File).to receive(:open).with("/tmp/monkeypants", "w").and_yield(filehandle) - knife.run - end - end - - describe "with -p or --public-key" do - before do - knife.config[:public_key] = "some_key" - allow(File).to receive(:read).and_return("some_key") - allow(File).to receive(:expand_path) - end - - it "sets the public key" do - knife.run - expect(client.public_key).to eq("some_key") - end - end - - describe "with -k or --prevent-keygen" do - before do - knife.config[:prevent_keygen] = true - end - - it "does not set create_key" do - knife.run - expect(client.create_key).to be_falsey - end - end - - describe "with --validator" do - before do - knife.config[:validator] = true - end - - it "should create an validator client" do - knife.run - expect(client.validator).to be_truthy - end - end - end - end -end diff --git a/spec/unit/knife/client_delete_spec.rb b/spec/unit/knife/client_delete_spec.rb deleted file mode 100644 index 41a83b05e4..0000000000 --- a/spec/unit/knife/client_delete_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::ClientDelete do - before(:each) do - @knife = Chef::Knife::ClientDelete.new - # defaults - @knife.config = { - delete_validators: false, - } - @knife.name_args = [ "adam" ] - end - - describe "run" do - it "should delete the client" do - expect(@knife).to receive(:delete_object).with(Chef::ApiClientV1, "adam", "client") - @knife.run - end - - context "receives multiple clients" do - let(:clients) { %w{ adam ben charlie } } - - before(:each) do - @knife.name_args = clients - end - - it "deletes all clients" do - clients.each do |client| - expect(@knife).to receive(:delete_object).with(Chef::ApiClientV1, client, "client") - end - - @knife.run - end - end - - it "should print usage and exit when a client name is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - end - - describe "with a validator" do - before(:each) do - allow(Chef::Knife::UI).to receive(:confirm).and_return(true) - allow(@knife).to receive(:confirm).and_return(true) - @client = Chef::ApiClientV1.new - expect(Chef::ApiClientV1).to receive(:load).and_return(@client) - end - - it "should delete non-validator client if --delete-validators is not set" do - @knife.config[:delete_validators] = false - expect(@client).to receive(:destroy).and_return(@client) - expect(@knife).to receive(:msg) - - @knife.run - end - - it "should delete non-validator client if --delete-validators is set" do - @knife.config[:delete_validators] = true - expect(@client).to receive(:destroy).and_return(@client) - expect(@knife).to receive(:msg) - - @knife.run - end - - it "should not delete validator client if --delete-validators is not set" do - @client.validator(true) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should delete validator client if --delete-validators is set" do - @knife.config[:delete_validators] = true - expect(@client).to receive(:destroy).and_return(@client) - expect(@knife).to receive(:msg) - - @knife.run - end - end -end diff --git a/spec/unit/knife/client_edit_spec.rb b/spec/unit/knife/client_edit_spec.rb deleted file mode 100644 index e7c9030883..0000000000 --- a/spec/unit/knife/client_edit_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" -require "chef/api_client_v1" - -describe Chef::Knife::ClientEdit do - before(:each) do - @knife = Chef::Knife::ClientEdit.new - @knife.name_args = [ "adam" ] - @knife.config[:disable_editing] = true - end - - describe "run" do - let(:data) do - { - "name" => "adam", - "validator" => false, - "admin" => false, - "chef_type" => "client", - "create_key" => true, - } - end - - it "should edit the client" do - allow(Chef::ApiClientV1).to receive(:load).with("adam").and_return(data) - expect(@knife).to receive(:edit_hash).with(data).and_return(data) - @knife.run - end - - it "should print usage and exit when a client name is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - end -end diff --git a/spec/unit/knife/client_list_spec.rb b/spec/unit/knife/client_list_spec.rb deleted file mode 100644 index d1b379a787..0000000000 --- a/spec/unit/knife/client_list_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::ClientList do - before(:each) do - @knife = Chef::Knife::ClientList.new - @knife.name_args = [ "adam" ] - end - - describe "run" do - it "should list the clients" do - expect(Chef::ApiClientV1).to receive(:list) - expect(@knife).to receive(:format_list_for_display) - @knife.run - end - end -end diff --git a/spec/unit/knife/client_reregister_spec.rb b/spec/unit/knife/client_reregister_spec.rb deleted file mode 100644 index 6b6519d44f..0000000000 --- a/spec/unit/knife/client_reregister_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::ClientReregister do - before(:each) do - @knife = Chef::Knife::ClientReregister.new - @knife.name_args = [ "adam" ] - @client_mock = double("client_mock", private_key: "foo_key") - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - context "when no client name is given on the command line" do - before do - @knife.name_args = [] - end - - it "should print usage and exit when a client name is not provided" do - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - end - - context "when not configured for file output" do - it "reregisters the client and prints the key" do - expect(Chef::ApiClientV1).to receive(:reregister).with("adam").and_return(@client_mock) - @knife.run - expect(@stdout.string).to match( /foo_key/ ) - end - end - - context "when configured for file output" do - it "should write the private key to a file" do - expect(Chef::ApiClientV1).to receive(:reregister).with("adam").and_return(@client_mock) - - @knife.config[:file] = "/tmp/monkeypants" - filehandle = StringIO.new - expect(File).to receive(:open).with("/tmp/monkeypants", "w").and_yield(filehandle) - @knife.run - expect(filehandle.string).to eq("foo_key") - end - end - -end diff --git a/spec/unit/knife/client_show_spec.rb b/spec/unit/knife/client_show_spec.rb deleted file mode 100644 index 47b4b6ccb0..0000000000 --- a/spec/unit/knife/client_show_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::ClientShow do - before(:each) do - @knife = Chef::Knife::ClientShow.new - @knife.name_args = [ "adam" ] - @client_mock = double("client_mock") - end - - describe "run" do - it "should list the client" do - expect(Chef::ApiClientV1).to receive(:load).with("adam").and_return(@client_mock) - expect(@knife).to receive(:format_for_display).with(@client_mock) - @knife.run - end - - it "should pretty print json" do - @knife.config[:format] = "json" - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - fake_client_contents = { "foo" => "bar", "baz" => "qux" } - expect(Chef::ApiClientV1).to receive(:load).with("adam").and_return(fake_client_contents) - @knife.run - expect(@stdout.string).to eql("{\n \"foo\": \"bar\",\n \"baz\": \"qux\"\n}\n") - end - - it "should print usage and exit when a client name is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - end -end diff --git a/spec/unit/knife/configure_client_spec.rb b/spec/unit/knife/configure_client_spec.rb deleted file mode 100644 index b104718c89..0000000000 --- a/spec/unit/knife/configure_client_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::ConfigureClient do - before do - @knife = Chef::Knife::ConfigureClient.new - Chef::Config[:chef_server_url] = "https://chef.example.com" - Chef::Config[:validation_client_name] = "chef-validator" - Chef::Config[:validation_key] = "/etc/chef/validation.pem" - - @stderr = StringIO.new - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - end - - describe "run" do - it "should print usage and exit when a directory is not provided" do - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal).with(/must provide the directory/) - expect do - @knife.run - end.to raise_error SystemExit - end - - describe "when specifing a directory" do - before do - @knife.name_args = ["/home/bob/.chef"] - @client_file = StringIO.new - @validation_file = StringIO.new - expect(File).to receive(:open).with("/home/bob/.chef/client.rb", "w") - .and_yield(@client_file) - expect(File).to receive(:open).with("/home/bob/.chef/validation.pem", "w") - .and_yield(@validation_file) - expect(IO).to receive(:read).and_return("foo_bar_baz") - end - - it "should recursively create the directory" do - expect(FileUtils).to receive(:mkdir_p).with("/home/bob/.chef") - @knife.run - end - - it "should write out the config file" do - allow(FileUtils).to receive(:mkdir_p) - @knife.run - expect(@client_file.string).to match %r{chef_server_url\s+'https\://chef\.example\.com'} - expect(@client_file.string).to match(/validation_client_name\s+'chef-validator'/) - end - - it "should write out the validation.pem file" do - allow(FileUtils).to receive(:mkdir_p) - @knife.run - expect(@validation_file.string).to match(/foo_bar_baz/) - end - - it "should print information on what is being configured" do - allow(FileUtils).to receive(:mkdir_p) - @knife.run - expect(@stderr.string).to match(/creating client configuration/i) - expect(@stderr.string).to match(/writing client\.rb/i) - expect(@stderr.string).to match(/writing validation\.pem/i) - end - end - end - -end diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb deleted file mode 100644 index 7d6c840d1f..0000000000 --- a/spec/unit/knife/configure_spec.rb +++ /dev/null @@ -1,190 +0,0 @@ -require "spec_helper" - -describe Chef::Knife::Configure do - before do - Chef::Log.logger = Logger.new(StringIO.new) - - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::Configure.new - @rest_client = double("null rest client", post: { result: :true }) - allow(@knife).to receive(:rest).and_return(@rest_client) - - @out = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@out) - @knife.config[:config_file] = "/home/you/.chef/knife.rb" - - @in = StringIO.new("\n" * 7) - allow(@knife.ui).to receive(:stdin).and_return(@in) - - @err = StringIO.new - allow(@knife.ui).to receive(:stderr).and_return(@err) - - allow(Ohai::System).to receive(:new).and_return(ohai) - end - - let(:fqdn) { "foo.example.org" } - - let(:ohai) do - o = {} - allow(o).to receive(:all_plugins).with(%w{ os hostname fqdn }) - o[:fqdn] = fqdn - o - end - - let(:default_admin_key) { "/etc/chef-server/admin.pem" } - let(:default_admin_key_win32) { File.expand_path(default_admin_key) } - - let(:default_validator_key) { "/etc/chef-server/chef-validator.pem" } - let(:default_validator_key_win32) { File.expand_path(default_validator_key) } - - let(:default_server_url) { "https://#{fqdn}/organizations/myorg" } - - it "asks the user for the URL of the chef server" do - @knife.ask_user_for_config - expect(@out.string).to match(Regexp.escape("Please enter the chef server URL: [#{default_server_url}]")) - expect(@knife.chef_server).to eq(default_server_url) - end - - it "asks the user for the clientname they want for the new client if -i is specified" do - @knife.config[:initial] = true - allow(Etc).to receive(:getlogin).and_return("a-new-user") - @knife.ask_user_for_config - expect(@out.string).to match(Regexp.escape("Please enter a name for the new user: [a-new-user]")) - expect(@knife.new_client_name).to eq(Etc.getlogin) - end - - it "should not ask the user for the clientname they want for the new client if -i and --node_name are specified" do - @knife.config[:initial] = true - @knife.config[:node_name] = "testnode" - allow(Etc).to receive(:getlogin).and_return("a-new-user") - @knife.ask_user_for_config - expect(@out.string).not_to match(Regexp.escape("Please enter a name for the new user")) - expect(@knife.new_client_name).to eq("testnode") - end - - it "asks the user for the existing API username or clientname if -i is not specified" do - allow(Etc).to receive(:getlogin).and_return("a-new-user") - @knife.ask_user_for_config - expect(@out.string).to match(Regexp.escape("Please enter an existing username or clientname for the API: [a-new-user]")) - expect(@knife.new_client_name).to eq(Etc.getlogin) - end - - it "asks the user for the existing admin client's name if -i is specified" do - @knife.config[:initial] = true - @knife.ask_user_for_config - expect(@out.string).to match(Regexp.escape("Please enter the existing admin name: [admin]")) - expect(@knife.admin_client_name).to eq("admin") - end - - it "should not ask the user for the existing admin client's name if -i and --admin-client_name are specified" do - @knife.config[:initial] = true - @knife.config[:admin_client_name] = "my-webui" - @knife.ask_user_for_config - expect(@out.string).not_to match(Regexp.escape("Please enter the existing admin:")) - expect(@knife.admin_client_name).to eq("my-webui") - end - - it "should not ask the user for the existing admin client's name if -i is not specified" do - @knife.ask_user_for_config - expect(@out.string).not_to match(Regexp.escape("Please enter the existing admin: [admin]")) - expect(@knife.admin_client_name).not_to eq("admin") - end - - it "asks the user for the location of the existing admin key if -i is specified" do - @knife.config[:initial] = true - @knife.ask_user_for_config - expect(@out.string).to match(Regexp.escape("Please enter the location of the existing admin's private key: [#{default_admin_key}]")) - if windows? - expect(@knife.admin_client_key.capitalize).to eq(default_admin_key_win32.capitalize) - else - expect(@knife.admin_client_key).to eq(default_admin_key) - end - end - - it "should not ask the user for the location of the existing admin key if -i and --admin_client_key are specified" do - @knife.config[:initial] = true - @knife.config[:admin_client_key] = "/home/you/.chef/my-webui.pem" - @knife.ask_user_for_config - expect(@out.string).not_to match(Regexp.escape("Please enter the location of the existing admin client's private key:")) - if windows? - expect(@knife.admin_client_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-webui\.pem$} - else - expect(@knife.admin_client_key).to eq("/home/you/.chef/my-webui.pem") - end - end - - it "should not ask the user for the location of the existing admin key if -i is not specified" do - @knife.ask_user_for_config - expect(@out.string).not_to match(Regexp.escape("Please enter the location of the existing admin client's private key: [#{default_admin_key}]")) - if windows? - expect(@knife.admin_client_key).not_to eq(default_admin_key_win32) - else - expect(@knife.admin_client_key).not_to eq(default_admin_key) - end - end - - it "should not ask the user for anything if -i and all other properties are specified" do - @knife.config[:initial] = true - @knife.config[:chef_server_url] = "http://localhost:5000" - @knife.config[:node_name] = "testnode" - @knife.config[:admin_client_name] = "my-webui" - @knife.config[:admin_client_key] = "/home/you/.chef/my-webui.pem" - @knife.config[:client_key] = "/home/you/a-new-user.pem" - allow(Etc).to receive(:getlogin).and_return("a-new-user") - - @knife.ask_user_for_config - expect(@out.string).to match(/\s*/) - - expect(@knife.new_client_name).to eq("testnode") - expect(@knife.chef_server).to eq("http://localhost:5000") - expect(@knife.admin_client_name).to eq("my-webui") - if windows? - expect(@knife.admin_client_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-webui\.pem$} - expect(@knife.new_client_key).to match %r{^[A-Za-z]:/home/you/a-new-user\.pem$} - else - expect(@knife.admin_client_key).to eq("/home/you/.chef/my-webui.pem") - expect(@knife.new_client_key).to eq("/home/you/a-new-user.pem") - end - end - - it "writes the new data to a config file" do - allow(Chef::Util::PathHelper).to receive(:home).with(".chef").and_return("/home/you/.chef") - allow(File).to receive(:expand_path).with("/home/you/.chef/credentials").and_return("/home/you/.chef/credentials") - allow(File).to receive(:expand_path).with("/home/you/.chef/#{Etc.getlogin}.pem").and_return("/home/you/.chef/#{Etc.getlogin}.pem") - allow(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key) - expect(FileUtils).to receive(:mkdir_p).with("/home/you/.chef") - config_file = StringIO.new - expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w").and_yield config_file - @knife.config[:repository] = "/home/you/chef-repo" - @knife.run - expect(config_file.string).to match(/^client_name\s+=\s+'#{Etc.getlogin}'$/) - expect(config_file.string).to match(%r{^client_key\s+=\s+'/home/you/.chef/#{Etc.getlogin}.pem'$}) - expect(config_file.string).to match(/^chef_server_url\s+=\s+'#{default_server_url}'$/) - end - - it "creates a new client when given the --initial option" do - allow(Chef::Util::PathHelper).to receive(:home).with(".chef").and_return("/home/you/.chef") - expect(File).to receive(:expand_path).with("/home/you/.chef/credentials").and_return("/home/you/.chef/credentials") - expect(File).to receive(:expand_path).with("/home/you/.chef/a-new-user.pem").and_return("/home/you/.chef/a-new-user.pem") - allow(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key) - Chef::Config[:node_name] = "webmonkey.example.com" - - user_command = Chef::Knife::UserCreate.new - expect(user_command).to receive(:run) - - allow(Etc).to receive(:getlogin).and_return("a-new-user") - - allow(Chef::Knife::UserCreate).to receive(:new).and_return(user_command) - expect(FileUtils).to receive(:mkdir_p).with("/home/you/.chef") - expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w") - @knife.config[:initial] = true - @knife.config[:user_password] = "blah" - @knife.run - expect(user_command.name_args).to eq(Array("a-new-user")) - expect(user_command.config[:user_password]).to eq("blah") - expect(user_command.config[:admin]).to be_truthy - expect(user_command.config[:file]).to eq("/home/you/.chef/a-new-user.pem") - expect(user_command.config[:yes]).to be_truthy - expect(user_command.config[:disable_editing]).to be_truthy - end -end diff --git a/spec/unit/knife/cookbook_bulk_delete_spec.rb b/spec/unit/knife/cookbook_bulk_delete_spec.rb deleted file mode 100644 index 3527d39bd8..0000000000 --- a/spec/unit/knife/cookbook_bulk_delete_spec.rb +++ /dev/null @@ -1,87 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@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 "spec_helper" - -describe Chef::Knife::CookbookBulkDelete do - before(:each) do - Chef::Log.logger = Logger.new(StringIO.new) - - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::CookbookBulkDelete.new - @knife.config = { print_after: nil } - @knife.name_args = ["."] - @stdout = StringIO.new - @stderr = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - allow(@knife.ui).to receive(:confirm).and_return(true) - @cookbooks = {} - %w{cheezburger pizza lasagna}.each do |cookbook_name| - cookbook = Chef::CookbookVersion.new(cookbook_name) - @cookbooks[cookbook_name] = cookbook - end - @rest = double("Chef::ServerAPI") - allow(@rest).to receive(:get).and_return(@cookbooks) - allow(@rest).to receive(:delete).and_return(true) - allow(@knife).to receive(:rest).and_return(@rest) - allow(Chef::CookbookVersion).to receive(:list).and_return(@cookbooks) - - end - - describe "when there are several cookbooks on the server" do - before do - @cheezburger = { "cheezburger" => { "url" => "file:///dev/null", "versions" => [{ "url" => "file:///dev/null-cheez", "version" => "1.0.0" }] } } - allow(@rest).to receive(:get).with("cookbooks/cheezburger").and_return(@cheezburger) - @pizza = { "pizza" => { "url" => "file:///dev/null", "versions" => [{ "url" => "file:///dev/null-pizza", "version" => "2.0.0" }] } } - allow(@rest).to receive(:get).with("cookbooks/pizza").and_return(@pizza) - @lasagna = { "lasagna" => { "url" => "file:///dev/null", "versions" => [{ "url" => "file:///dev/null-lasagna", "version" => "3.0.0" }] } } - allow(@rest).to receive(:get).with("cookbooks/lasagna").and_return(@lasagna) - end - - it "should print the cookbooks you are about to delete" do - expected = @knife.ui.list(@cookbooks.keys.sort, :columns_down) - @knife.run - expect(@stdout.string).to match(/#{expected}/) - end - - it "should confirm you really want to delete them" do - expect(@knife.ui).to receive(:confirm) - @knife.run - end - - it "should delete each cookbook" do - { "cheezburger" => "1.0.0", "pizza" => "2.0.0", "lasagna" => "3.0.0" }.each do |cookbook_name, version| - expect(@rest).to receive(:delete).with("cookbooks/#{cookbook_name}/#{version}") - end - @knife.run - end - - it "should only delete cookbooks that match the regex" do - @knife.name_args = ["cheezburger"] - expect(@rest).to receive(:delete).with("cookbooks/cheezburger/1.0.0") - @knife.run - end - end - - it "should exit if the regex is not provided" do - @knife.name_args = [] - expect { @knife.run }.to raise_error(SystemExit) - end - -end diff --git a/spec/unit/knife/cookbook_delete_spec.rb b/spec/unit/knife/cookbook_delete_spec.rb deleted file mode 100644 index f2aa7e1be0..0000000000 --- a/spec/unit/knife/cookbook_delete_spec.rb +++ /dev/null @@ -1,239 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::CookbookDelete do - before(:each) do - @knife = Chef::Knife::CookbookDelete.new - @knife.name_args = ["foobar"] - @knife.cookbook_name = "foobar" - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - @stderr = StringIO.new - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - end - - describe "run" do - it "should print usage and exit when a cookbook name is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "when specifying a cookbook name" do - it "should delete the cookbook without a specific version" do - expect(@knife).to receive(:delete_without_explicit_version) - @knife.run - end - - describe "and a version" do - it "should delete the specific version of the cookbook" do - @knife.name_args << "1.0.0" - expect(@knife).to receive(:delete_explicit_version) - @knife.run - end - end - - describe "with -a or --all" do - it "should delete all versions of the cookbook" do - @knife.config[:all] = true - expect(@knife).to receive(:delete_all_versions) - @knife.run - end - end - - describe "with -p or --purge" do - it "should prompt to purge the files" do - @knife.config[:purge] = true - expect(@knife).to receive(:confirm) - .with(/.+Are you sure you want to purge files.+/) - expect(@knife).to receive(:delete_without_explicit_version) - @knife.run - end - end - end - end - - describe "delete_explicit_version" do - it "should delete the specific cookbook version" do - @knife.cookbook_name = "foobar" - @knife.version = "1.0.0" - expect(@knife).to receive(:delete_object).with(Chef::CookbookVersion, - "foobar version 1.0.0", - "cookbook").and_yield - expect(@knife).to receive(:delete_request).with("cookbooks/foobar/1.0.0") - @knife.delete_explicit_version - end - end - - describe "delete_all_versions" do - it "should prompt to delete all versions of the cookbook" do - @knife.cookbook_name = "foobar" - expect(@knife).to receive(:confirm).with("Do you really want to delete all versions of foobar") - expect(@knife).to receive(:delete_all_without_confirmation) - @knife.delete_all_versions - end - end - - describe "delete_all_without_confirmation" do - it "should delete all versions without confirmation" do - versions = ["1.0.0", "1.1.0"] - expect(@knife).to receive(:available_versions).and_return(versions) - versions.each do |v| - expect(@knife).to receive(:delete_version_without_confirmation).with(v) - end - @knife.delete_all_without_confirmation - end - end - - describe "delete_without_explicit_version" do - it "should exit if there are no available versions" do - expect(@knife).to receive(:available_versions).and_return(nil) - expect { @knife.delete_without_explicit_version }.to raise_error(SystemExit) - end - - it "should delete the version if only one is found" do - expect(@knife).to receive(:available_versions).at_least(:once).and_return(["1.0.0"]) - expect(@knife).to receive(:delete_explicit_version) - @knife.delete_without_explicit_version - end - - it "should ask which version(s) to delete if multiple are found" do - expect(@knife).to receive(:available_versions).at_least(:once).and_return(["1.0.0", "1.1.0"]) - expect(@knife).to receive(:ask_which_versions_to_delete).and_return(["1.0.0", "1.1.0"]) - expect(@knife).to receive(:delete_versions_without_confirmation).with(["1.0.0", "1.1.0"]) - @knife.delete_without_explicit_version - end - end - - describe "available_versions" do - before(:each) do - @rest_mock = double("rest") - expect(@knife).to receive(:rest).and_return(@rest_mock) - @cookbook_data = { "foobar" => { "versions" => [{ "version" => "1.0.0" }, - { "version" => "1.1.0" }, - { "version" => "2.0.0" } ] }, - } - end - - it "should return the list of versions of the cookbook" do - expect(@rest_mock).to receive(:get).with("cookbooks/foobar").and_return(@cookbook_data) - expect(@knife.available_versions).to eq(["1.0.0", "1.1.0", "2.0.0"]) - end - - it "should raise if an error other than HTTP 404 is returned" do - exception = Net::HTTPClientException.new("500 Internal Server Error", "500") - expect(@rest_mock).to receive(:get).and_raise(exception) - expect { @knife.available_versions }.to raise_error Net::HTTPClientException - end - - describe "if the cookbook can't be found" do - before(:each) do - expect(@rest_mock).to receive(:get) - .and_raise(Net::HTTPClientException.new("404 Not Found", "404")) - end - - it "should print an error" do - @knife.available_versions - expect(@stderr.string).to match(/error.+cannot find a cookbook named foobar/i) - end - - it "should return nil" do - expect(@knife.available_versions).to eq(nil) - end - end - end - - describe "ask_which_version_to_delete" do - before(:each) do - allow(@knife).to receive(:available_versions).and_return(["1.0.0", "1.1.0", "2.0.0"]) - end - - it "should prompt the user to select a version" do - prompt = /Which version\(s\) do you want to delete\?.+1\. foobar 1\.0\.0.+2\. foobar 1\.1\.0.+3\. foobar 2\.0\.0.+4\. All versions.+/m - expect(@knife).to receive(:ask_question).with(prompt).and_return("1") - @knife.ask_which_versions_to_delete - end - - it "should print an error and exit if a version wasn't specified" do - expect(@knife).to receive(:ask_question).and_return("") - expect(@knife.ui).to receive(:error).with(/no versions specified/i) - expect { @knife.ask_which_versions_to_delete }.to raise_error(SystemExit) - end - - it "should print an error if an invalid choice was selected" do - expect(@knife).to receive(:ask_question).and_return("100") - expect(@knife.ui).to receive(:error).with(/100 is not a valid choice/i) - @knife.ask_which_versions_to_delete - end - - it "should return the selected versions" do - expect(@knife).to receive(:ask_question).and_return("1, 3") - expect(@knife.ask_which_versions_to_delete).to eq(["1.0.0", "2.0.0"]) - end - - it "should return all of the versions if 'all' was selected" do - expect(@knife).to receive(:ask_question).and_return("4") - expect(@knife.ask_which_versions_to_delete).to eq([:all]) - end - end - - describe "delete_version_without_confirmation" do - it "should delete the cookbook version" do - expect(@knife).to receive(:delete_request).with("cookbooks/foobar/1.0.0") - @knife.delete_version_without_confirmation("1.0.0") - end - - it "should output that the cookbook was deleted" do - allow(@knife).to receive(:delete_request) - @knife.delete_version_without_confirmation("1.0.0") - expect(@stderr.string).to match(/deleted cookbook\[foobar\]\[1.0.0\]/im) - end - - describe "with --print-after" do - it "should display the cookbook data" do - object = "" - @knife.config[:print_after] = true - allow(@knife).to receive(:delete_request).and_return(object) - expect(@knife).to receive(:format_for_display).with(object) - @knife.delete_version_without_confirmation("1.0.0") - end - end - end - - describe "delete_versions_without_confirmation" do - it "should delete each version without confirmation" do - versions = ["1.0.0", "1.1.0"] - versions.each do |v| - expect(@knife).to receive(:delete_version_without_confirmation).with(v) - end - @knife.delete_versions_without_confirmation(versions) - end - - describe "with -a or --all" do - it "should delete all versions without confirmation" do - versions = [:all] - expect(@knife).to receive(:delete_all_without_confirmation) - @knife.delete_versions_without_confirmation(versions) - end - end - end - -end diff --git a/spec/unit/knife/cookbook_download_spec.rb b/spec/unit/knife/cookbook_download_spec.rb deleted file mode 100644 index c8903dea5b..0000000000 --- a/spec/unit/knife/cookbook_download_spec.rb +++ /dev/null @@ -1,255 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::CookbookDownload do - before(:each) do - @knife = Chef::Knife::CookbookDownload.new - @stderr = StringIO.new - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - end - - describe "run" do - it "should print usage and exit when a cookbook name is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal).with(/must specify a cookbook name/) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should exit with a fatal error when there is no cookbook on the server" do - @knife.name_args = ["foobar", nil] - expect(@knife).to receive(:determine_version).and_return(nil) - expect(@knife.ui).to receive(:fatal).with("No such cookbook found") - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "with a cookbook name" do - before(:each) do - @knife.name_args = ["foobar"] - @knife.config[:download_directory] = "/var/tmp/chef" - @rest_mock = double("rest") - allow(@knife).to receive(:rest).and_return(@rest_mock) - - expect(Chef::CookbookVersion).to receive(:load).with("foobar", "1.0.0") - .and_return(cookbook) - end - - let(:manifest_data) do - { - all_files: [ - { - "path" => "recipes/foo.rb", - "name" => "recipes/foo.rb", - "url" => "http://example.org/files/foo.rb", - }, - { - "path" => "recipes/bar.rb", - "name" => "recipes/bar.rb", - "url" => "http://example.org/files/bar.rb", - }, - { - "path" => "templates/default/foo.erb", - "name" => "templates/foo.erb", - "url" => "http://example.org/files/foo.erb", - }, - { - "path" => "templates/default/bar.erb", - "name" => "templates/bar.erb", - "url" => "http://example.org/files/bar.erb", - }, - { - "path" => "attributes/default.rb", - "name" => "attributes/default.rb", - "url" => "http://example.org/files/default.rb", - }, - ], - } - end - - let(:cookbook) do - cb = Chef::CookbookVersion.new("foobar") - cb.version = "1.0.0" - cb.manifest = manifest_data - cb - end - - describe "and no version" do - let(:manifest_data) { { all_files: [] } } - it "should determine which version to download" do - expect(@knife).to receive(:determine_version).and_return("1.0.0") - expect(File).to receive(:exist?).with("/var/tmp/chef/foobar-1.0.0").and_return(false) - @knife.run - end - end - - describe "and a version" do - before(:each) do - @knife.name_args << "1.0.0" - @files = manifest_data.values.map { |v| v.map { |i| i["path"] } }.flatten.uniq - @files_mocks = {} - @files.map { |f| File.basename(f) }.flatten.uniq.each do |f| - @files_mocks[f] = double("#{f}_mock") - allow(@files_mocks[f]).to receive(:path).and_return("/var/tmp/#{f}") - end - end - - it "should print an error and exit if the cookbook download directory already exists" do - expect(File).to receive(:exist?).with("/var/tmp/chef/foobar-1.0.0").and_return(true) - expect(@knife.ui).to receive(:fatal).with(%r{/var/tmp/chef/foobar-1\.0\.0 exists}i) - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "when downloading the cookbook" do - before(:each) do - @files.map { |f| File.dirname(f) }.flatten.uniq.each do |dir| - expect(FileUtils).to receive(:mkdir_p).with("/var/tmp/chef/foobar-1.0.0/#{dir}") - .at_least(:once) - end - - @files_mocks.each_pair do |file, mock| - expect(@rest_mock).to receive(:streaming_request).with("http://example.org/files/#{file}") - .and_return(mock) - end - - @files.each do |f| - expect(FileUtils).to receive(:mv) - .with("/var/tmp/#{File.basename(f)}", "/var/tmp/chef/foobar-1.0.0/#{f}") - end - end - - it "should download the cookbook when the cookbook download directory doesn't exist" do - expect(File).to receive(:exist?).with("/var/tmp/chef/foobar-1.0.0").and_return(false) - @knife.run - %w{attributes recipes templates}.each do |segment| - expect(@stderr.string).to match(/downloading #{segment}/im) - end - expect(@stderr.string).to match(/downloading foobar cookbook version 1\.0\.0/im) - expect(@stderr.string).to match %r{cookbook downloaded to /var/tmp/chef/foobar-1\.0\.0}im - end - - describe "with -f or --force" do - it "should remove the existing the cookbook download directory if it exists" do - @knife.config[:force] = true - expect(File).to receive(:exist?).with("/var/tmp/chef/foobar-1.0.0").and_return(true) - expect(FileUtils).to receive(:rm_rf).with("/var/tmp/chef/foobar-1.0.0") - @knife.run - end - end - end - - end - end - - end - - describe "determine_version" do - - it "should return nil if there are no versions" do - expect(@knife).to receive(:available_versions).and_return(nil) - expect(@knife.determine_version).to eq(nil) - expect(@knife.version).to eq(nil) - end - - it "should return and set the version if there is only one version" do - expect(@knife).to receive(:available_versions).at_least(:once).and_return(["1.0.0"]) - expect(@knife.determine_version).to eq("1.0.0") - expect(@knife.version).to eq("1.0.0") - end - - it "should ask which version to download and return it if there is more than one" do - expect(@knife).to receive(:available_versions).at_least(:once).and_return(["1.0.0", "2.0.0"]) - expect(@knife).to receive(:ask_which_version).and_return("1.0.0") - expect(@knife.determine_version).to eq("1.0.0") - end - - describe "with -N or --latest" do - it "should return and set the version to the latest version" do - @knife.config[:latest] = true - expect(@knife).to receive(:available_versions).at_least(:once) - .and_return(["1.0.0", "1.1.0", "2.0.0"]) - @knife.determine_version - expect(@knife.version.to_s).to eq("2.0.0") - end - end - end - - describe "available_versions" do - before(:each) do - @knife.cookbook_name = "foobar" - end - - it "should return nil if there are no versions" do - expect(Chef::CookbookVersion).to receive(:available_versions) - .with("foobar") - .and_return(nil) - expect(@knife.available_versions).to eq(nil) - end - - it "should return the available versions" do - expect(Chef::CookbookVersion).to receive(:available_versions) - .with("foobar") - .and_return(["1.1.0", "2.0.0", "1.0.0"]) - expect(@knife.available_versions).to eq([Chef::Version.new("1.0.0"), - Chef::Version.new("1.1.0"), - Chef::Version.new("2.0.0")]) - end - - it "should avoid multiple API calls to the server" do - expect(Chef::CookbookVersion).to receive(:available_versions) - .once - .with("foobar") - .and_return(["1.1.0", "2.0.0", "1.0.0"]) - @knife.available_versions - @knife.available_versions - end - end - - describe "ask_which_version" do - before(:each) do - @knife.cookbook_name = "foobar" - allow(@knife).to receive(:available_versions).and_return(["1.0.0", "1.1.0", "2.0.0"]) - end - - it "should prompt the user to select a version" do - prompt = /Which version do you want to download\?.+1\. foobar 1\.0\.0.+2\. foobar 1\.1\.0.+3\. foobar 2\.0\.0.+/m - expect(@knife).to receive(:ask_question).with(prompt).and_return("1") - @knife.ask_which_version - end - - it "should set the version to the user's selection" do - expect(@knife).to receive(:ask_question).and_return("1") - @knife.ask_which_version - expect(@knife.version).to eq("1.0.0") - end - - it "should print an error and exit if a version wasn't specified" do - expect(@knife).to receive(:ask_question).and_return("") - expect(@knife.ui).to receive(:error).with(/is not a valid value/i) - expect { @knife.ask_which_version }.to raise_error(SystemExit) - end - - it "should print an error if an invalid choice was selected" do - expect(@knife).to receive(:ask_question).and_return("100") - expect(@knife.ui).to receive(:error).with(/'100' is not a valid value/i) - expect { @knife.ask_which_version }.to raise_error(SystemExit) - end - end - -end diff --git a/spec/unit/knife/cookbook_list_spec.rb b/spec/unit/knife/cookbook_list_spec.rb deleted file mode 100644 index 4cf806c6f0..0000000000 --- a/spec/unit/knife/cookbook_list_spec.rb +++ /dev/null @@ -1,88 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::CookbookList do - before do - @knife = Chef::Knife::CookbookList.new - @rest_mock = double("rest") - allow(@knife).to receive(:rest).and_return(@rest_mock) - @cookbook_names = %w{apache2 mysql} - @base_url = "https://server.example.com/cookbooks" - @cookbook_data = {} - @cookbook_names.each do |item| - @cookbook_data[item] = { "url" => "#{@base_url}/#{item}", - "versions" => [{ "version" => "1.0.1", - "url" => "#{@base_url}/#{item}/1.0.1" }] } - end - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should display the latest version of the cookbooks" do - expect(@rest_mock).to receive(:get).with("/cookbooks?num_versions=1") - .and_return(@cookbook_data) - @knife.run - @cookbook_names.each do |item| - expect(@stdout.string).to match(/#{item}\s+1\.0\.1/) - end - end - - it "should query cookbooks for the configured environment" do - @knife.config[:environment] = "production" - expect(@rest_mock).to receive(:get) - .with("/environments/production/cookbooks?num_versions=1") - .and_return(@cookbook_data) - @knife.run - end - - describe "with -w or --with-uri" do - it "should display the cookbook uris" do - @knife.config[:with_uri] = true - allow(@rest_mock).to receive(:get).and_return(@cookbook_data) - @knife.run - @cookbook_names.each do |item| - pattern = /#{Regexp.escape(@cookbook_data[item]['versions'].first['url'])}/ - expect(@stdout.string).to match pattern - end - end - end - - describe "with -a or --all" do - before do - @cookbook_names.each do |item| - @cookbook_data[item]["versions"] << { "version" => "1.0.0", - "url" => "#{@base_url}/#{item}/1.0.0" } - end - end - - it "should display all versions of the cookbooks" do - @knife.config[:all_versions] = true - expect(@rest_mock).to receive(:get).with("/cookbooks?num_versions=all") - .and_return(@cookbook_data) - @knife.run - @cookbook_names.each do |item| - expect(@stdout.string).to match(/#{item}\s+1\.0\.1\s+1\.0\.0/) - end - end - end - - end -end diff --git a/spec/unit/knife/cookbook_metadata_from_file_spec.rb b/spec/unit/knife/cookbook_metadata_from_file_spec.rb deleted file mode 100644 index f9bbffae2d..0000000000 --- a/spec/unit/knife/cookbook_metadata_from_file_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Matthew Kent (<mkent@magoazul.com>) -# Copyright:: Copyright (c) Chef Software Inc. -# 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 "spec_helper" - -describe Chef::Knife::CookbookMetadataFromFile do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @src = File.expand_path(File.join(CHEF_SPEC_DATA, "metadata", "quick_start", "metadata.rb")) - @tgt = File.expand_path(File.join(CHEF_SPEC_DATA, "metadata", "quick_start", "metadata.json")) - @knife = Chef::Knife::CookbookMetadataFromFile.new - @knife.name_args = [ @src ] - allow(@knife).to receive(:to_json_pretty).and_return(true) - @md = Chef::Cookbook::Metadata.new - allow(Chef::Cookbook::Metadata).to receive(:new).and_return(@md) - allow($stdout).to receive(:write) - end - - after do - if File.exist?(@tgt) - File.unlink(@tgt) - end - end - - describe "run" do - it "should print usage and exit when a FILE is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal).with(/You must specify the FILE./) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should determine cookbook name from path" do - expect(@md).to receive(:name).with(no_args) - expect(@md).to receive(:name).with("quick_start") - @knife.run - end - - it "should load the metadata source" do - expect(@md).to receive(:from_file).with(@src) - @knife.run - end - - it "should write out the metadata to the correct location" do - expect(File).to receive(:open).with(@tgt, "w") - @knife.run - end - - it "should generate json from the metadata" do - expect(Chef::JSONCompat).to receive(:to_json_pretty).with(@md) - @knife.run - end - - end -end diff --git a/spec/unit/knife/cookbook_metadata_spec.rb b/spec/unit/knife/cookbook_metadata_spec.rb deleted file mode 100644 index 732cf78421..0000000000 --- a/spec/unit/knife/cookbook_metadata_spec.rb +++ /dev/null @@ -1,182 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2011-2016, Thomas Bishop -# 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 "spec_helper" - -describe Chef::Knife::CookbookMetadata do - let(:knife) do - knife = Chef::Knife::CookbookMetadata.new - knife.name_args = ["foobar"] - knife - end - - let(:cookbook_dir) { Dir.mktmpdir } - - let(:stdout) { StringIO.new } - - let(:stderr) { StringIO.new } - - before(:each) do - allow(knife.ui).to receive(:stdout).and_return(stdout) - allow(knife.ui).to receive(:stderr).and_return(stderr) - end - - def create_metadata_rb(**kwargs) - name = kwargs[:name] - Dir.mkdir("#{cookbook_dir}/#{name}") - File.open("#{cookbook_dir}/#{name}/metadata.rb", "w+") do |f| - kwargs.each do |key, value| - if value.is_a?(Array) - f.puts "#{key} #{value.map { |v| "\"#{v}\"" }.join(", ")}" - else - f.puts "#{key} \"#{value}\"" - end - end - end - end - - def create_metadata_json(**kwargs) - name = kwargs[:name] - Dir.mkdir("#{cookbook_dir}/#{name}") - File.open("#{cookbook_dir}/#{name}/metadata.json", "w+") do |f| - f.write(FFI_Yajl::Encoder.encode(kwargs)) - end - end - - def create_invalid_json - Dir.mkdir("#{cookbook_dir}/foobar") - File.open("#{cookbook_dir}/foobar/metadata.json", "w+") do |f| - f.write <<-EOH - { "version": "1.0.0", {ImInvalid}} - EOH - end - end - - describe "run" do - it "should print an error and exit if a cookbook name was not provided" do - knife.name_args = [] - expect(knife.ui).to receive(:error).with(/you must specify the cookbook.+use the --all/i) - expect { knife.run }.to raise_error(SystemExit) - end - - it "should print an error and exit if an empty cookbook name was provided" do - knife.name_args = [""] - expect(knife.ui).to receive(:error).with(/you must specify the cookbook.+use the --all/i) - expect { knife.run }.to raise_error(SystemExit) - end - - it "should generate the metadata for the cookbook" do - expect(knife).to receive(:generate_metadata).with("foobar") - knife.run - end - - describe "with -a or --all" do - before(:each) do - Chef::Config[:cookbook_path] = cookbook_dir - knife.config[:all] = true - create_metadata_rb(name: "foo", version: "1.0.0") - create_metadata_rb(name: "bar", version: "2.0.0") - expect(knife).to receive(:generate_metadata).with("foo").and_call_original - expect(knife).to receive(:generate_metadata).with("bar").and_call_original - end - - it "should generate the metadata for each cookbook" do - expect(Chef::CookbookLoader).to receive(:new).with(cookbook_dir).and_call_original - knife.run - expect(stderr.string).to match %r{generating metadata for foo from #{cookbook_dir}/foo/metadata\.rb}im - expect(stderr.string).to match %r{generating metadata for bar from #{cookbook_dir}/bar/metadata\.rb}im - end - - it "with -o or --cookbook_path should look in the provided path and generate cookbook metadata" do - Chef::Config[:cookbook_path] = "/dev/null" - knife.config[:cookbook_path] = cookbook_dir - expect(Chef::CookbookLoader).to receive(:new).with(cookbook_dir).and_call_original - knife.run - expect(stderr.string).to match %r{generating metadata for foo from #{cookbook_dir}/foo/metadata\.rb}im - expect(stderr.string).to match %r{generating metadata for bar from #{cookbook_dir}/bar/metadata\.rb}im - end - end - - end - - describe "generate_metadata" do - before(:each) do - Chef::Config[:cookbook_path] = cookbook_dir - end - - it "should generate the metadata from metadata.rb if it exists" do - create_metadata_rb(name: "foobar", version: "1.0.0") - expect(knife).to receive(:generate_metadata_from_file).with("foobar", "#{cookbook_dir}/foobar/metadata.rb").and_call_original - knife.run - expect(File.exist?("#{cookbook_dir}/foobar/metadata.json")).to be true - json = FFI_Yajl::Parser.parse(IO.read("#{cookbook_dir}/foobar/metadata.json")) - expect(json["name"]).to eql("foobar") - expect(json["version"]).to eql("1.0.0") - end - - it "should validate the metadata json if metadata.rb does not exist" do - create_metadata_json(name: "foobar", version: "1.0.0") - expect(knife).to receive(:validate_metadata_json).with(cookbook_dir, "foobar").and_call_original - knife.run - end - end - - describe "validation errors" do - before(:each) do - Chef::Config[:cookbook_path] = cookbook_dir - end - - it "should fail for obsolete operators in metadata.rb" do - create_metadata_rb(name: "foobar", version: "1.0.0", depends: [ "foo:bar", ">> 0.2" ]) - expect(Chef::Cookbook::Metadata).not_to receive(:validate_json) - expect { knife.run }.to raise_error(SystemExit) - expect(stderr.string).to match(/error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im) - end - - it "should fail for obsolete format in metadata.rb (sadly)" do - create_metadata_rb(name: "foobar", version: "1.0.0", depends: [ "foo:bar", "> 0.2", "< 1.0" ]) - expect(Chef::Cookbook::Metadata).not_to receive(:validate_json) - expect { knife.run }.to raise_error(SystemExit) - expect(stderr.string).to match(/error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im) - end - - it "should fail for obsolete operators in metadata.json" do - create_metadata_json(name: "foobar", version: "1.0.0", dependencies: { "foo:bar" => ">> 0.2" }) - expect { knife.run }.to raise_error(SystemExit) - expect(stderr.string).to match(/error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im) - end - - it "should not fail for unknown field in metadata.rb" do - create_metadata_rb(name: "sounders", version: "2.0.0", beats: "toronto") - expect(Chef::Cookbook::Metadata).not_to receive(:validate_json) - expect { knife.run }.not_to raise_error - expect(stderr.string).to eql("") - end - - it "should not fail for unknown field in metadata.json" do - create_metadata_json(name: "sounders", version: "2.0.0", beats: "toronto") - expect { knife.run }.not_to raise_error - expect(stderr.string).to eql("") - end - - it "should fail on unparsable json" do - create_invalid_json - expect { knife.run }.to raise_error(Chef::Exceptions::JSON::ParseError) - end - end -end diff --git a/spec/unit/knife/cookbook_show_spec.rb b/spec/unit/knife/cookbook_show_spec.rb deleted file mode 100644 index defc243de3..0000000000 --- a/spec/unit/knife/cookbook_show_spec.rb +++ /dev/null @@ -1,253 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::CookbookShow do - before do - Chef::Config[:node_name] = "webmonkey.example.com" - allow(knife).to receive(:rest).and_return(rest) - allow(knife).to receive(:pretty_print).and_return(true) - allow(knife).to receive(:output).and_return(true) - allow(Chef::CookbookVersion).to receive(:load).and_return(cb) - end - - let(:knife) do - knife = Chef::Knife::CookbookShow.new - knife.config = {} - knife.name_args = [ "cookbook_name" ] - knife - end - - let(:cb) do - cb = Chef::CookbookVersion.new("cookbook_name") - cb.manifest = manifest - cb - end - - let(:rest) { double(Chef::ServerAPI) } - - let(:content) { "Example recipe text" } - - let(:manifest) do - { - "all_files" => [ - { - name: "recipes/default.rb", - path: "recipes/default.rb", - checksum: "1234", - url: "http://example.org/files/default.rb", - }, - ], - } - end - - describe "run" do - describe "with 0 arguments: help" do - it "should should print usage and exit when given no arguments" do - knife.name_args = [] - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end - end - - describe "with 1 argument: versions" do - let(:response) do - { - "cookbook_name" => { - "url" => "http://url/cookbooks/cookbook_name", - "versions" => [ - { "version" => "0.10.0", "url" => "http://url/cookbooks/cookbook_name/0.10.0" }, - { "version" => "0.9.0", "url" => "http://url/cookbookx/cookbook_name/0.9.0" }, - { "version" => "0.8.0", "url" => "http://url/cookbooks/cookbook_name/0.8.0" }, - ], - }, - } - end - - it "should show the raw cookbook data" do - expect(rest).to receive(:get).with("cookbooks/cookbook_name").and_return(response) - expect(knife).to receive(:format_cookbook_list_for_display).with(response) - knife.run - end - - it "should respect the user-supplied environment" do - knife.config[:environment] = "foo" - expect(rest).to receive(:get).with("environments/foo/cookbooks/cookbook_name").and_return(response) - expect(knife).to receive(:format_cookbook_list_for_display).with(response) - knife.run - end - end - - describe "with 2 arguments: name and version" do - before do - knife.name_args << "0.1.0" - end - - let(:output) do - { "cookbook_name" => "cookbook_name", - "name" => "cookbook_name-0.0.0", - "frozen?" => false, - "version" => "0.0.0", - "metadata" => { - "name" => nil, - "description" => "", - "eager_load_libraries" => true, - "long_description" => "", - "maintainer" => "", - "maintainer_email" => "", - "license" => "All rights reserved", - "platforms" => {}, - "dependencies" => {}, - "providing" => {}, - "recipes" => {}, - "version" => "0.0.0", - "source_url" => "", - "issues_url" => "", - "privacy" => false, - "chef_versions" => [], - "ohai_versions" => [], - "gems" => [], - }, - "recipes" => - [{ "name" => "recipes/default.rb", - "path" => "recipes/default.rb", - "checksum" => "1234", - "url" => "http://example.org/files/default.rb" }], - } - end - - it "should show the specific part of a cookbook" do - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(knife).to receive(:output).with(output) - knife.run - end - end - - describe "with 3 arguments: name, version, and segment" do - before(:each) do - knife.name_args = [ "cookbook_name", "0.1.0", "recipes" ] - end - - it "should print the json of the part" do - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(knife).to receive(:output).with(cb.files_for("recipes")) - knife.run - end - end - - describe "with 4 arguments: name, version, segment and filename" do - before(:each) do - knife.name_args = [ "cookbook_name", "0.1.0", "recipes", "default.rb" ] - end - - it "should print the raw result of the request (likely a file!)" do - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(rest).to receive(:streaming_request).with("http://example.org/files/default.rb").and_return(StringIO.new(content)) - expect(knife).to receive(:pretty_print).with(content) - knife.run - end - end - - describe "with 4 arguments: name, version, segment and filename -- with specificity" do - before(:each) do - knife.name_args = [ "cookbook_name", "0.1.0", "files", "afile.rb" ] - cb.manifest = { - "all_files" => [ - { - name: "files/afile.rb", - path: "files/host-examplehost.example.org/afile.rb", - checksum: "1111", - specificity: "host-examplehost.example.org", - url: "http://example.org/files/1111", - }, - { - name: "files/afile.rb", - path: "files/ubuntu-9.10/afile.rb", - checksum: "2222", - specificity: "ubuntu-9.10", - url: "http://example.org/files/2222", - }, - { - name: "files/afile.rb", - path: "files/ubuntu/afile.rb", - checksum: "3333", - specificity: "ubuntu", - url: "http://example.org/files/3333", - }, - { - name: "files/afile.rb", - path: "files/default/afile.rb", - checksum: "4444", - specificity: "default", - url: "http://example.org/files/4444", - }, - ], - } - - end - - describe "with --fqdn" do - it "should pass the fqdn" do - knife.config[:platform] = "example_platform" - knife.config[:platform_version] = "1.0" - knife.config[:fqdn] = "examplehost.example.org" - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(rest).to receive(:streaming_request).with("http://example.org/files/1111").and_return(StringIO.new(content)) - expect(knife).to receive(:pretty_print).with(content) - knife.run - end - end - - describe "and --platform" do - it "should pass the platform" do - knife.config[:platform] = "ubuntu" - knife.config[:platform_version] = "1.0" - knife.config[:fqdn] = "differenthost.example.org" - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(rest).to receive(:streaming_request).with("http://example.org/files/3333").and_return(StringIO.new(content)) - expect(knife).to receive(:pretty_print).with(content) - knife.run - end - end - - describe "and --platform-version" do - it "should pass the platform" do - knife.config[:platform] = "ubuntu" - knife.config[:platform_version] = "9.10" - knife.config[:fqdn] = "differenthost.example.org" - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(rest).to receive(:streaming_request).with("http://example.org/files/2222").and_return(StringIO.new(content)) - expect(knife).to receive(:pretty_print).with(content) - knife.run - end - end - - describe "with none of the arguments, it should use the default" do - it "should pass them all" do - expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb) - expect(rest).to receive(:streaming_request).with("http://example.org/files/4444").and_return(StringIO.new(content)) - expect(knife).to receive(:pretty_print).with(content) - knife.run - end - end - - end - end -end diff --git a/spec/unit/knife/cookbook_upload_spec.rb b/spec/unit/knife/cookbook_upload_spec.rb deleted file mode 100644 index dbed8b8a67..0000000000 --- a/spec/unit/knife/cookbook_upload_spec.rb +++ /dev/null @@ -1,364 +0,0 @@ -# -# Author:: Matthew Kent (<mkent@magoazul.com>) -# Author:: Steven Danna (<steve@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 "spec_helper" - -require "chef/cookbook_uploader" -require "timeout" - -describe Chef::Knife::CookbookUpload do - let(:cookbook) do - cookbook = Chef::CookbookVersion.new("test_cookbook", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(true) - allow(cookbook.metadata).to receive(:name).and_return(cookbook.name) - cookbook - end - - let(:cookbooks_by_name) do - { cookbook.name => cookbook } - end - - let(:cookbook_loader) do - cookbook_loader = cookbooks_by_name.dup - allow(cookbook_loader).to receive(:merged_cookbooks).and_return([]) - allow(cookbook_loader).to receive(:load_cookbooks).and_return(cookbook_loader) - allow(cookbook_loader).to receive(:compile_metadata).and_return(nil) - allow(cookbook_loader).to receive(:freeze_versions).and_return(nil) - cookbook_loader - end - - let(:cookbook_uploader) { double(upload_cookbooks: nil) } - - let(:output) { StringIO.new } - - let(:name_args) { ["test_cookbook"] } - - let(:knife) do - k = Chef::Knife::CookbookUpload.new - k.name_args = name_args - allow(k.ui).to receive(:stdout).and_return(output) - allow(k.ui).to receive(:stderr).and_return(output) - k - end - - before(:each) do - allow(Chef::CookbookLoader).to receive(:new).and_return(cookbook_loader) - allow(Chef::CookbookLoader).to receive(:copy_to_tmp_dir_from_array).and_yield(cookbook_loader) - end - - describe "with --concurrency" do - it "should upload cookbooks with predefined concurrency" do - allow(Chef::CookbookVersion).to receive(:list_all_versions).and_return({}) - knife.config[:concurrency] = 3 - test_cookbook = Chef::CookbookVersion.new("test_cookbook", "/tmp/blah") - allow(cookbook_loader).to receive(:each).and_yield("test_cookbook", test_cookbook) - allow(cookbook_loader).to receive(:cookbook_names).and_return(["test_cookbook"]) - expect(Chef::CookbookUploader).to receive(:new) - .with( kind_of(Array), { force: nil, concurrency: 3 }) - .and_return(double("Chef::CookbookUploader", upload_cookbooks: true)) - knife.run - end - end - - describe "run" do - before(:each) do - allow(Chef::CookbookUploader).to receive_messages(new: cookbook_uploader) - allow(Chef::CookbookVersion).to receive(:list_all_versions).and_return({}) - end - - it "should print usage and exit when a cookbook name is not provided" do - knife.name_args = [] - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end - - describe "when specifying cookbook without metadata.rb or metadata.json" do - let(:name_args) { ["test_cookbook1"] } - let(:cookbook) do - cookbook = Chef::CookbookVersion.new("test_cookbook1", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(false) - cookbook - end - - it "should upload the cookbook" do - expect { knife.run }.to raise_error(Chef::Exceptions::MetadataNotFound) - end - end - - describe "when name attribute in metadata not set" do - let(:name_args) { ["test_cookbook1"] } - - let(:cookbook) do - cookbook = Chef::CookbookVersion.new("test_cookbook1", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(true) - allow(cookbook.metadata).to receive(:name).and_return(nil) - cookbook - end - - it "should upload the cookbook" do - expect { knife.run }.to raise_error(Chef::Exceptions::MetadataNotValid) - end - end - - describe "when specifying a cookbook name" do - it "should upload the cookbook" do - expect(knife).to receive(:upload).once - knife.run - end - - it "should report on success" do - expect(knife).to receive(:upload).once - expect(knife.ui).to receive(:info).with(/Uploaded 1 cookbook/) - knife.run - end - end - - describe "when specifying the same cookbook name twice" do - it "should upload the cookbook only once" do - knife.name_args = %w{test_cookbook test_cookbook} - expect(knife).to receive(:upload).once - knife.run - end - end - - describe "when specifying a cookbook name among many" do - let(:name_args) { ["test_cookbook1"] } - - let(:cookbook) do - cookbook = Chef::CookbookVersion.new("test_cookbook1", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(true) - allow(cookbook.metadata).to receive(:name).and_return(cookbook.name) - cookbook - end - - let(:cookbooks_by_name) do - { cookbook.name => cookbook } - end - - it "should read only one cookbook" do - expect(cookbook_loader).to receive(:[]).once.with("test_cookbook1").and_call_original - knife.run - end - - it "should not read all cookbooks" do - expect(cookbook_loader).to receive(:load_cookbooks) - knife.run - end - - it "should upload only one cookbook" do - expect(knife).to receive(:upload).exactly(1).times - knife.run - end - end - - # This is testing too much. We should break it up. - describe "when specifying a cookbook name with dependencies" do - let(:name_args) { ["test_cookbook2"] } - - let(:test_cookbook1) do - cookbook = Chef::CookbookVersion.new("test_cookbook1", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(true) - allow(cookbook.metadata).to receive(:name).and_return(cookbook.name) - cookbook - end - - let(:test_cookbook2) do - c = Chef::CookbookVersion.new("test_cookbook2") - c.metadata.depends("test_cookbook3") - allow(c).to receive(:has_metadata_file?).and_return(true) - allow(c.metadata).to receive(:name).and_return(c.name) - c - end - - let(:test_cookbook3) do - c = Chef::CookbookVersion.new("test_cookbook3") - c.metadata.depends("test_cookbook1") - c.metadata.depends("test_cookbook2") - allow(c).to receive(:has_metadata_file?).and_return(true) - allow(c.metadata).to receive(:name).and_return(c.name) - c - end - - let(:cookbooks_by_name) do - { "test_cookbook1" => test_cookbook1, - "test_cookbook2" => test_cookbook2, - "test_cookbook3" => test_cookbook3 } - end - - it "should upload all dependencies once" do - knife.config[:depends] = true - allow(knife).to receive(:cookbook_names).and_return(%w{test_cookbook1 test_cookbook2 test_cookbook3}) - expect(knife).to receive(:upload).exactly(3).times - expect do - Timeout.timeout(5) do - knife.run - end - end.not_to raise_error - end - end - - describe "when specifying a cookbook name with missing dependencies" do - let(:cookbook_dependency) { Chef::CookbookVersion.new("dependency", "/tmp/blah") } - - before(:each) do - cookbook.metadata.depends("dependency") - allow(cookbook_loader).to receive(:[]) do |ckbk| - { "test_cookbook" => cookbook, - "dependency" => cookbook_dependency }[ckbk] - end - allow(knife).to receive(:cookbook_names).and_return(%w{cookbook_dependency test_cookbook}) - @stdout, @stderr, @stdin = StringIO.new, StringIO.new, StringIO.new - knife.ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {}) - end - - it "should exit and not upload the cookbook" do - expect(cookbook_loader).to receive(:[]).once.with("test_cookbook") - expect(cookbook_uploader).not_to receive(:upload_cookbooks) - expect { knife.run }.to raise_error(SystemExit) - end - - it "should output a message for a single missing dependency" do - expect { knife.run }.to raise_error(SystemExit) - expect(@stderr.string).to include("Cookbook test_cookbook depends on cookbooks which are not currently") - expect(@stderr.string).to include("being uploaded and cannot be found on the server.") - expect(@stderr.string).to include("The missing cookbook(s) are: 'dependency' version '>= 0.0.0'") - end - - it "should output a message for a multiple missing dependencies which are concatenated" do - cookbook_dependency2 = Chef::CookbookVersion.new("dependency2") - cookbook.metadata.depends("dependency2") - allow(cookbook_loader).to receive(:[]) do |ckbk| - { "test_cookbook" => cookbook, - "dependency" => cookbook_dependency, - "dependency2" => cookbook_dependency2 }[ckbk] - end - allow(knife).to receive(:cookbook_names).and_return(%w{dependency dependency2 test_cookbook}) - expect { knife.run }.to raise_error(SystemExit) - expect(@stderr.string).to include("Cookbook test_cookbook depends on cookbooks which are not currently") - expect(@stderr.string).to include("being uploaded and cannot be found on the server.") - expect(@stderr.string).to include("The missing cookbook(s) are:") - expect(@stderr.string).to include("'dependency' version '>= 0.0.0'") - expect(@stderr.string).to include("'dependency2' version '>= 0.0.0'") - end - end - - it "should freeze the version of the cookbooks if --freeze is specified" do - knife.config[:freeze] = true - expect(cookbook_loader).to receive(:freeze_versions).once - knife.run - end - - describe "with -a or --all" do - before(:each) do - knife.config[:all] = true - end - - context "when cookbooks exist in the cookbook path" do - let(:test_cookbook1) do - cookbook = Chef::CookbookVersion.new("test_cookbook1", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(true) - allow(cookbook.metadata).to receive(:name).and_return(cookbook.name) - cookbook - end - - let(:test_cookbook2) do - cookbook = Chef::CookbookVersion.new("test_cookbook2", "/tmp/blah") - allow(cookbook).to receive(:has_metadata_file?).and_return(true) - allow(cookbook.metadata).to receive(:name).and_return(cookbook.name) - cookbook - end - - before(:each) do - allow(cookbook_loader).to receive(:each).and_yield("test_cookbook1", test_cookbook1).and_yield("test_cookbook2", test_cookbook2) - allow(cookbook_loader).to receive(:cookbook_names).and_return(%w{test_cookbook1 test_cookbook2}) - end - - it "should upload all cookbooks" do - expect(knife).to receive(:upload).once - knife.run - end - - it "should report on success" do - expect(knife).to receive(:upload).once - expect(knife.ui).to receive(:info).with(/Uploaded all cookbooks/) - knife.run - end - - it "should update the version constraints for an environment" do - allow(knife).to receive(:assert_environment_valid!).and_return(true) - knife.config[:environment] = "production" - expect(knife).to receive(:update_version_constraints).once - knife.run - end - end - - context "when no cookbooks exist in the cookbook path" do - before(:each) do - allow(cookbook_loader).to receive(:each) - end - - it "should not upload any cookbooks" do - expect(knife).to_not receive(:upload) - knife.run - end - - context "when cookbook path is an array" do - it "should warn users that no cookbooks exist" do - cookbook_path = windows? ? "C:/chef-repo/cookbooks" : "/chef-repo/cookbooks" - knife.config[:cookbook_path] = [cookbook_path, "/home/user/cookbooks"] - expect(knife.ui).to receive(:warn).with("Could not find any cookbooks in your cookbook path: '#{knife.config[:cookbook_path].join(", ")}'. Use --cookbook-path to specify the desired path.") - knife.run - end - end - - context "when cookbook path is a string" do - it "should warn users that no cookbooks exist" do - knife.config[:cookbook_path] = windows? ? "C:/chef-repo/cookbooks" : "/chef-repo/cookbooks" - expect(knife.ui).to receive(:warn).with( - "Could not find any cookbooks in your cookbook path: '#{knife.config[:cookbook_path]}'. Use --cookbook-path to specify the desired path." - ) - knife.run - end - end - end - end - - describe "when a frozen cookbook exists on the server" do - it "should fail to replace it" do - exception = Chef::Exceptions::CookbookFrozen.new - expect(cookbook_uploader).to receive(:upload_cookbooks) - .and_raise(exception) - allow(knife.ui).to receive(:error) - expect(knife.ui).to receive(:error).with(exception) - expect { knife.run }.to raise_error(SystemExit) - end - - it "should not update the version constraints for an environment" do - allow(knife).to receive(:assert_environment_valid!).and_return(true) - knife.config[:environment] = "production" - allow(knife).to receive(:upload).and_raise(Chef::Exceptions::CookbookFrozen) - expect(knife.ui).to receive(:error).with(/Failed to upload 1 cookbook/) - expect(knife.ui).to receive(:warn).with(/Not updating version constraints/) - expect(knife).not_to receive(:update_version_constraints) - expect { knife.run }.to raise_error(SystemExit) - end - end - end # run -end diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb deleted file mode 100644 index a55047a739..0000000000 --- a/spec/unit/knife/core/bootstrap_context_spec.rb +++ /dev/null @@ -1,287 +0,0 @@ -# -# 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 "spec_helper" -require "chef/knife/core/bootstrap_context" - -describe Chef::Knife::Core::BootstrapContext do - let(:config) { { foo: :bar, color: true } } - let(:run_list) { Chef::RunList.new("recipe[tmux]", "role[base]") } - let(:chef_config) do - { - config_log_level: "info", - config_log_location: "/tmp/log", - validation_key: File.join(CHEF_SPEC_DATA, "ssl", "private_key.pem"), - chef_server_url: "http://chef.example.com:4444", - validation_client_name: "chef-validator-testing", - } - end - - let(:secret) { nil } - - subject(:bootstrap_context) { described_class.new(config, run_list, chef_config, secret) } - - it "initializes with Chef 11 parameters" do - expect { described_class.new(config, run_list, chef_config) }.not_to raise_error - end - - it "runs chef with the first-boot.json with no environment" do - expect(bootstrap_context.start_chef).to eq "chef-client -j /etc/chef/first-boot.json" - end - - describe "when in verbosity mode" do - let(:config) { { verbosity: 2, color: true } } - it "adds '-l debug' when verbosity is >= 2" do - expect(bootstrap_context.start_chef).to eq "chef-client -j /etc/chef/first-boot.json -l debug" - end - end - - describe "when no color value has been set in config" do - let(:config) { { color: false } } - it "adds '--no-color' when color is false" do - expect(bootstrap_context.start_chef).to eq "chef-client -j /etc/chef/first-boot.json --no-color" - end - end - - it "reads the validation key" do - expect(bootstrap_context.validation_key).to eq IO.read(File.join(CHEF_SPEC_DATA, "ssl", "private_key.pem")) - end - - it "generates the config file data" do - expected = <<~EXPECTED - chef_server_url "http://chef.example.com:4444" - validation_client_name "chef-validator-testing" - log_level :info - log_location "/tmp/log" - # Using default node name (fqdn) - EXPECTED - expect(bootstrap_context.config_content).to eq expected - end - - describe "when chef_license is set" do - let(:chef_config) { { chef_license: "accept-no-persist" } } - it "sets chef_license in the generated config file" do - expect(bootstrap_context.config_content).to include("chef_license \"accept-no-persist\"") - end - end - - describe "when file_cache_path is set" do - let(:chef_config) { { file_cache_path: "/home/opscode/cache" } } - it "sets file_cache_path in the generated config file" do - expect(bootstrap_context.config_content).to include("file_cache_path \"/home/opscode/cache\"") - end - end - - describe "when file_backup_path is set" do - let(:chef_config) { { file_backup_path: "/home/opscode/backup" } } - it "sets file_backup_path in the generated config file" do - expect(bootstrap_context.config_content).to include("file_backup_path \"/home/opscode/backup\"") - end - end - - describe "alternate chef-client path" do - let(:chef_config) { { chef_client_path: "/usr/local/bin/chef-client" } } - it "runs chef-client from another path when specified" do - expect(bootstrap_context.start_chef).to eq "/usr/local/bin/chef-client -j /etc/chef/first-boot.json" - end - end - - describe "validation key path that contains a ~" do - let(:chef_config) { { validation_key: "~/my.key" } } - it "reads the validation key when it contains a ~" do - expect(File).to receive(:exist?).with(File.expand_path("my.key", ENV["HOME"])).and_return(true) - expect(IO).to receive(:read).with(File.expand_path("my.key", ENV["HOME"])) - bootstrap_context.validation_key - end - end - - describe "when an explicit node name is given" do - let(:config) { { chef_node_name: "foobar.example.com" } } - it "sets the node name in the client.rb" do - expect(bootstrap_context.config_content).to match(/node_name "foobar\.example\.com"/) - end - end - - describe "when bootstrapping into a specific environment" do - let(:config) { { environment: "prodtastic", color: true } } - it "starts chef in the configured environment" do - expect(bootstrap_context.start_chef).to eq("chef-client -j /etc/chef/first-boot.json -E prodtastic") - end - end - - describe "when tags are given" do - let(:config) { { tags: [ "unicorn" ] } } - it "adds the attributes to first_boot" do - expect(Chef::JSONCompat.to_json(bootstrap_context.first_boot)).to eq(Chef::JSONCompat.to_json({ run_list: run_list, tags: ["unicorn"] })) - end - end - - describe "when JSON attributes are given" do - let(:config) { { first_boot_attributes: { baz: :quux } } } - it "adds the attributes to first_boot" do - expect(Chef::JSONCompat.to_json(bootstrap_context.first_boot)).to eq(Chef::JSONCompat.to_json({ baz: :quux, run_list: run_list })) - end - end - - describe "when JSON attributes are NOT given" do - it "sets first_boot equal to run_list" do - expect(Chef::JSONCompat.to_json(bootstrap_context.first_boot)).to eq(Chef::JSONCompat.to_json({ run_list: run_list })) - end - end - - describe "when policy_name and policy_group are present in config" do - - let(:config) { { policy_name: "my_app_server", policy_group: "staging" } } - - it "includes them in the first_boot data and excludes run_list" do - expect(Chef::JSONCompat.to_json(bootstrap_context.first_boot)).to eq(Chef::JSONCompat.to_json({ policy_name: "my_app_server", policy_group: "staging" })) - end - - end - - describe "when an encrypted_data_bag_secret is provided" do - let(:secret) { "supersekret" } - it "reads the encrypted_data_bag_secret" do - expect(bootstrap_context.encrypted_data_bag_secret).to eq "supersekret" - end - end - - describe "to support compatibility with existing templates" do - it "sets the @config instance variable" do - expect(bootstrap_context.instance_variable_get(:@config)).to eq config - end - - it "sets the @run_list instance variable" do - expect(bootstrap_context.instance_variable_get(:@run_list)).to eq run_list - end - end - - describe "ssl_verify_mode" do - it "isn't set in the config_content by default" do - expect(bootstrap_context.config_content).not_to include("ssl_verify_mode") - end - - describe "when configured via the config hash" do - let(:config) { { node_ssl_verify_mode: "none" } } - - it "uses the config value" do - expect(bootstrap_context.config_content).to include("ssl_verify_mode :verify_none") - end - end - end - - describe "fips mode" do - before do - chef_config[:fips] = true - end - - it "sets fips mode in the client.rb" do - expect(bootstrap_context.config_content).to match(/fips true/) - end - end - - describe "verify_api_cert" do - it "isn't set in the config_content by default" do - expect(bootstrap_context.config_content).not_to include("verify_api_cert") - end - - describe "when configured via the config hash" do - let(:config) { { node_verify_api_cert: true } } - - it "uses config value" do - expect(bootstrap_context.config_content).to include("verify_api_cert true") - end - end - end - - describe "#config_log_location" do - context "when config_log_location is nil" do - let(:chef_config) { { config_log_location: nil } } - it "sets the default config_log_location in the client.rb" do - expect(bootstrap_context.get_log_location).to eq "STDOUT" - end - end - - context "when config_log_location is empty" do - let(:chef_config) { { config_log_location: "" } } - it "sets the default config_log_location in the client.rb" do - expect(bootstrap_context.get_log_location).to eq "STDOUT" - end - end - - context "when config_log_location is :win_evt" do - let(:chef_config) { { config_log_location: :win_evt } } - it "raise error when config_log_location is :win_evt " do - expect { bootstrap_context.get_log_location }.to raise_error("The value :win_evt is not supported for config_log_location on Linux Platforms \n") - end - end - - context "when config_log_location is :syslog" do - let(:chef_config) { { config_log_location: :syslog } } - it "sets the config_log_location value as :syslog in the client.rb" do - expect(bootstrap_context.get_log_location).to eq ":syslog" - end - end - - context "When config_log_location is STDOUT" do - let(:chef_config) { { config_log_location: STDOUT } } - it "Sets the config_log_location value as STDOUT in the client.rb" do - expect(bootstrap_context.get_log_location).to eq "STDOUT" - end - end - - context "when config_log_location is STDERR" do - let(:chef_config) { { config_log_location: STDERR } } - it "sets the config_log_location value as STDERR in the client.rb" do - expect(bootstrap_context.get_log_location).to eq "STDERR" - end - end - - context "when config_log_location is a path" do - let(:chef_config) { { config_log_location: "/tmp/ChefLogFile" } } - it "sets the config_log_location path in the client.rb" do - expect(bootstrap_context.get_log_location).to eq "\"/tmp/ChefLogFile\"" - end - end - - end - - describe "#version_to_install" do - context "when bootstrap_version is provided" do - let(:config) { { bootstrap_version: "awesome" } } - - it "returns bootstrap_version" do - expect(bootstrap_context.version_to_install).to eq "awesome" - end - end - - context "when bootstrap_version is not provided" do - let(:config) { { channel: "stable" } } - it "returns the currently running major version out of Chef::VERSION" do - expect(bootstrap_context.version_to_install).to eq Chef::VERSION.split(".").first - end - end - - context "and channel is other than stable" do - let(:config) { { channel: "unstable" } } - it "returns the version string 'latest'" do - expect(bootstrap_context.version_to_install).to eq "latest" - end - end - end -end diff --git a/spec/unit/knife/core/cookbook_scm_repo_spec.rb b/spec/unit/knife/core/cookbook_scm_repo_spec.rb deleted file mode 100644 index 316cbdfaa6..0000000000 --- a/spec/unit/knife/core/cookbook_scm_repo_spec.rb +++ /dev/null @@ -1,187 +0,0 @@ -# -# 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 "spec_helper" -require "chef/knife/core/cookbook_scm_repo" - -describe Chef::Knife::CookbookSCMRepo do - before do - @repo_path = File.join(CHEF_SPEC_DATA, "cookbooks") - @stdout, @stderr, @stdin = StringIO.new, StringIO.new, StringIO.new - @ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {}) - @cookbook_repo = Chef::Knife::CookbookSCMRepo.new(@repo_path, @ui, default_branch: "master") - - @branch_list = Mixlib::ShellOut.new - @branch_list.stdout.replace(<<-BRANCHES) - chef-vendor-apache2 - chef-vendor-build-essential - chef-vendor-dynomite - chef-vendor-ganglia - chef-vendor-graphite - chef-vendor-python - chef-vendor-absent-new - BRANCHES - end - - it "has a path to the cookbook repo" do - expect(@cookbook_repo.repo_path).to eq(@repo_path) - end - - it "has a default branch" do - expect(@cookbook_repo.default_branch).to eq("master") - end - - describe "when sanity checking the repo" do - it "exits when the directory does not exist" do - expect(::File).to receive(:directory?).with(@repo_path).and_return(false) - expect { @cookbook_repo.sanity_check }.to raise_error(SystemExit) - end - - describe "and the repo dir exists" do - before do - allow(::File).to receive(:directory?).with(@repo_path).and_return(true) - end - - it "exits when there is no git repo" do - allow(::File).to receive(:directory?).with(/.*\.git/).and_return(false) - expect { @cookbook_repo.sanity_check }.to raise_error(SystemExit) - end - - describe "and the repo is a git repo" do - before do - allow(::File).to receive(:directory?).with(File.join(@repo_path, ".git")).and_return(true) - end - - it "exits when the default branch doesn't exist" do - @nobranches = Mixlib::ShellOut.new.tap { |s| s.stdout.replace "\n" } - expect(@cookbook_repo).to receive(:shell_out!).with("git branch --no-color", cwd: @repo_path).and_return(@nobranches) - expect { @cookbook_repo.sanity_check }.to raise_error(SystemExit) - end - - describe "and the default branch exists" do - before do - @master_branch = Mixlib::ShellOut.new - @master_branch.stdout.replace "* master\n" - expect(@cookbook_repo).to receive(:shell_out!).with("git branch --no-color", cwd: @repo_path).and_return(@master_branch) - end - - it "exits when the git repo is dirty" do - @dirty_status = Mixlib::ShellOut.new - @dirty_status.stdout.replace(<<-DIRTY) - M chef/lib/chef/knife/cookbook_site_install.rb - DIRTY - expect(@cookbook_repo).to receive(:shell_out!).with("git status --porcelain", cwd: @repo_path).and_return(@dirty_status) - expect { @cookbook_repo.sanity_check }.to raise_error(SystemExit) - end - - describe "and the repo is clean" do - before do - @clean_status = Mixlib::ShellOut.new.tap { |s| s.stdout.replace("\n") } - allow(@cookbook_repo).to receive(:shell_out!).with("git status --porcelain", cwd: @repo_path).and_return(@clean_status) - end - - it "passes the sanity check" do - @cookbook_repo.sanity_check - end - - end - end - end - end - end - - it "resets to default state by checking out the default branch" do - expect(@cookbook_repo).to receive(:shell_out!).with("git checkout master", cwd: @repo_path) - @cookbook_repo.reset_to_default_state - end - - it "determines if a the pristine copy branch exists" do - expect(@cookbook_repo).to receive(:shell_out!).with("git branch --no-color", cwd: @repo_path).and_return(@branch_list) - expect(@cookbook_repo.branch_exists?("chef-vendor-apache2")).to be_truthy - expect(@cookbook_repo).to receive(:shell_out!).with("git branch --no-color", cwd: @repo_path).and_return(@branch_list) - expect(@cookbook_repo.branch_exists?("chef-vendor-nginx")).to be_falsey - end - - it "determines if a the branch not exists correctly without substring search" do - expect(@cookbook_repo).to receive(:shell_out!).twice.with("git branch --no-color", cwd: @repo_path).and_return(@branch_list) - expect(@cookbook_repo).not_to be_branch_exists("chef-vendor-absent") - expect(@cookbook_repo).to be_branch_exists("chef-vendor-absent-new") - end - - describe "when the pristine copy branch does not exist" do - it "prepares for import by creating the pristine copy branch" do - expect(@cookbook_repo).to receive(:shell_out!).with("git branch --no-color", cwd: @repo_path).and_return(@branch_list) - expect(@cookbook_repo).to receive(:shell_out!).with("git checkout -b chef-vendor-nginx", cwd: @repo_path) - @cookbook_repo.prepare_to_import("nginx") - end - end - - describe "when the pristine copy branch does exist" do - it "prepares for import by checking out the pristine copy branch" do - expect(@cookbook_repo).to receive(:shell_out!).with("git branch --no-color", cwd: @repo_path).and_return(@branch_list) - expect(@cookbook_repo).to receive(:shell_out!).with("git checkout chef-vendor-apache2", cwd: @repo_path) - @cookbook_repo.prepare_to_import("apache2") - end - end - - describe "when the pristine copy branch was not updated by the changes" do - before do - @updates = Mixlib::ShellOut.new - @updates.stdout.replace("\n") - allow(@cookbook_repo).to receive(:shell_out!).with("git status --porcelain -- apache2", cwd: @repo_path).and_return(@updates) - end - - it "shows no changes in the pristine copy" do - expect(@cookbook_repo.updated?("apache2")).to be_falsey - end - - it "does nothing to finalize the updates" do - expect(@cookbook_repo.finalize_updates_to("apache2", "1.2.3")).to be_falsey - end - end - - describe "when the pristine copy branch was updated by the changes" do - before do - @updates = Mixlib::ShellOut.new - @updates.stdout.replace(" M cookbooks/apache2/recipes/default.rb\n") - allow(@cookbook_repo).to receive(:shell_out!).with("git status --porcelain -- apache2", cwd: @repo_path).and_return(@updates) - end - - it "shows changes in the pristine copy" do - expect(@cookbook_repo.updated?("apache2")).to be_truthy - end - - it "commits the changes to the repo and tags the commit" do - expect(@cookbook_repo).to receive(:shell_out!).with("git add apache2", cwd: @repo_path) - expect(@cookbook_repo).to receive(:shell_out!).with("git commit -m \"Import apache2 version 1.2.3\" -- apache2", cwd: @repo_path) - expect(@cookbook_repo).to receive(:shell_out!).with("git tag -f cookbook-site-imported-apache2-1.2.3", cwd: @repo_path) - expect(@cookbook_repo.finalize_updates_to("apache2", "1.2.3")).to be_truthy - end - end - - describe "when a custom default branch is specified" do - before do - @cookbook_repo = Chef::Knife::CookbookSCMRepo.new(@repo_path, @ui, default_branch: "develop") - end - - it "resets to default state by checking out the default branch" do - expect(@cookbook_repo).to receive(:shell_out!).with("git checkout develop", cwd: @repo_path) - @cookbook_repo.reset_to_default_state - end - end -end diff --git a/spec/unit/knife/core/gem_glob_loader_spec.rb b/spec/unit/knife/core/gem_glob_loader_spec.rb deleted file mode 100644 index b7ff3ae96e..0000000000 --- a/spec/unit/knife/core/gem_glob_loader_spec.rb +++ /dev/null @@ -1,209 +0,0 @@ -# -# 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 "spec_helper" - -describe Chef::Knife::SubcommandLoader::GemGlobLoader do - let(:loader) { Chef::Knife::SubcommandLoader::GemGlobLoader.new(File.join(CHEF_SPEC_DATA, "knife-site-subcommands")) } - let(:home) { File.join(CHEF_SPEC_DATA, "knife-home") } - let(:plugin_dir) { File.join(home, ".chef", "plugins", "knife") } - - before do - allow(ChefUtils).to receive(:windows?) { false } - Chef::Util::PathHelper.class_variable_set(:@@home_dir, home) - end - - after do - Chef::Util::PathHelper.class_variable_set(:@@home_dir, nil) - end - - it "builds a list of the core subcommand file require paths" do - expect(loader.subcommand_files).not_to be_empty - loader.subcommand_files.each do |require_path| - expect(require_path).to match(%r{chef/knife/.*|plugins/knife/.*}) - end - end - - it "finds files installed via rubygems" do - expect(loader.find_subcommands_via_rubygems).to include("chef/knife/node_create") - loader.find_subcommands_via_rubygems.each_value { |abs_path| expect(abs_path).to match(%r{chef/knife/.+}) } - end - - it "finds files from latest version of installed gems" do - gems = [ double("knife-ec2-0.5.12") ] - gem_files = [ - "/usr/lib/ruby/gems/knife-ec2-0.5.12/lib/chef/knife/ec2_base.rb", - "/usr/lib/ruby/gems/knife-ec2-0.5.12/lib/chef/knife/ec2_otherstuff.rb", - ] - expect($LOAD_PATH).to receive(:map).and_return([]) - if Gem::Specification.respond_to? :latest_specs - expect(Gem::Specification).to receive(:latest_specs).with(true).and_return(gems) - expect(gems[0]).to receive(:matches_for_glob).with(%r{chef/knife/\*\.rb\{(.*),\.rb,(.*)\}}).and_return(gem_files) - else - expect(Gem.source_index).to receive(:latest_specs).with(true).and_return(gems) - expect(gems[0]).to receive(:require_paths).twice.and_return(["lib"]) - expect(gems[0]).to receive(:full_gem_path).and_return("/usr/lib/ruby/gems/knife-ec2-0.5.12") - expect(Dir).to receive(:[]).with("/usr/lib/ruby/gems/knife-ec2-0.5.12/lib/chef/knife/*.rb").and_return(gem_files) - end - expect(loader).to receive(:find_subcommands_via_dirglob).and_return({}) - expect(loader.subcommand_files.select { |file| file =~ /knife-ec2/ }.sort).to eq(gem_files) - end - - it "finds files using a dirglob when rubygems is not available" do - expect(loader.find_subcommands_via_dirglob).to include("chef/knife/node_create") - loader.find_subcommands_via_dirglob.each_value { |abs_path| expect(abs_path).to match(%r{chef/knife/.+}) } - end - - it "finds user-specific subcommands in the user's ~/.chef directory" do - expected_command = File.join(home, ".chef", "plugins", "knife", "example_home_subcommand.rb") - expect(loader.site_subcommands).to include(expected_command) - end - - it "finds repo specific subcommands by searching for a .chef directory" do - expected_command = File.join(CHEF_SPEC_DATA, "knife-site-subcommands", "plugins", "knife", "example_subcommand.rb") - expect(loader.site_subcommands).to include(expected_command) - end - - # https://github.com/chef/chef-dk/issues/227 - # - # `knife` in ChefDK isn't from a gem install, it's directly run from a clone - # of the source, but there can be one or more versions of chef also installed - # as a gem. If the gem install contains a command that doesn't exist in the - # source tree of the "primary" chef install, it can be loaded and cause an - # error. We also want to ensure that we only load builtin commands from the - # "primary" chef install. - context "when a different version of chef is also installed as a gem" do - - let(:all_found_commands) do - [ - "/opt/chefdk/embedded/apps/chef/lib/chef/knife/bootstrap.rb", - "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_bulk_delete.rb", - "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_create.rb", - - # We use the fake version 1.0.0 because that version doesn't exist, - # which ensures it won't ever equal "chef-#{Chef::VERSION}" - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/bootstrap.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/client_bulk_delete.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/client_create.rb", - - # Test that we don't accept a version number that is different only in - # trailing characters, e.g. we are running Chef 12.0.0 but there is a - # Chef 12.0.0.rc.0 gem also: - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.rc.0/lib/chef/knife/thing.rb", - - # Test that we ignore the platform suffix when checking for different - # gem versions. - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-x86-mingw32/lib/chef/knife/valid.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-i386-mingw64/lib/chef/knife/valid-too.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-mswin32/lib/chef/knife/also-valid.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-universal-mingw32/lib/chef/knife/universal-is-valid.rb", - # ...but don't ignore the .rc / .dev parts in the case when we have - # platform suffixes - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.rc.0-x86-mingw32/lib/chef/knife/invalid.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.dev-mswin32/lib/chef/knife/invalid-too.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.dev.0-x86-mingw64/lib/chef/knife/still-invalid.rb", - - # This command is "extra" compared to what's in the embedded/apps/chef install: - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/data_bag_secret_options.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-vault-2.2.4/lib/chef/knife/decrypt.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/knife-spork-1.4.1/lib/chef/knife/spork-bump.rb", - - # These are fake commands that have names designed to test that the - # regex is strict enough - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-foo-#{Chef::VERSION}/lib/chef/knife/chef-foo.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/foo-chef-#{Chef::VERSION}/lib/chef/knife/foo-chef.rb", - - # In a real scenario, we'd use rubygems APIs to only select the most - # recent gem, but for this test we want to check that we're doing the - # right thing both when the plugin version matches and does not match - # the current chef version. Looking at - # `SubcommandLoader::MATCHES_THIS_CHEF_GEM` and - # `SubcommandLoader::MATCHES_CHEF_GEM` should make it clear why we want - # to test these two cases. - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-bar-1.0.0/lib/chef/knife/chef-bar.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/bar-chef-1.0.0/lib/chef/knife/bar-chef.rb", - ] - end - - let(:expected_valid_commands) do - [ - "/opt/chefdk/embedded/apps/chef/lib/chef/knife/bootstrap.rb", - "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_bulk_delete.rb", - "/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_create.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-x86-mingw32/lib/chef/knife/valid.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-i386-mingw64/lib/chef/knife/valid-too.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-mswin32/lib/chef/knife/also-valid.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-universal-mingw32/lib/chef/knife/universal-is-valid.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-vault-2.2.4/lib/chef/knife/decrypt.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/knife-spork-1.4.1/lib/chef/knife/spork-bump.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-foo-#{Chef::VERSION}/lib/chef/knife/chef-foo.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/foo-chef-#{Chef::VERSION}/lib/chef/knife/foo-chef.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-bar-1.0.0/lib/chef/knife/chef-bar.rb", - "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/bar-chef-1.0.0/lib/chef/knife/bar-chef.rb", - ] - end - - before do - expect(loader).to receive(:find_files_latest_gems).with("chef/knife/*.rb").and_return(all_found_commands) - expect(loader).to receive(:find_subcommands_via_dirglob).and_return({}) - end - - it "ignores commands from the non-matching gem install" do - expect(loader.find_subcommands_via_rubygems.values).to eq(expected_valid_commands) - end - - end - - describe "finding 3rd party plugins" do - let(:env_home) { "/home/alice" } - let(:manifest_path) { env_home + "/.chef/plugin_manifest.json" } - - before do - env_dup = ENV.to_hash - allow(ENV).to receive(:[]) { |key| env_dup[key] } - allow(ENV).to receive(:[]).with("HOME").and_return(env_home) - end - - it "searches rubygems for plugins" do - if Gem::Specification.respond_to?(:latest_specs) - expect(Gem::Specification).to receive(:latest_specs).and_call_original - else - expect(Gem.source_index).to receive(:latest_specs).and_call_original - end - loader.subcommand_files.each do |require_path| - expect(require_path).to match(%r{chef/knife/.*|plugins/knife/.*}) - end - end - - context "and HOME environment variable is not set" do - before do - allow(ENV).to receive(:[]).with("HOME").and_return(nil) - end - - it "searches rubygems for plugins" do - if Gem::Specification.respond_to?(:latest_specs) - expect(Gem::Specification).to receive(:latest_specs).and_call_original - else - expect(Gem.source_index).to receive(:latest_specs).and_call_original - end - loader.subcommand_files.each do |require_path| - expect(require_path).to match(%r{chef/knife/.*|plugins/knife/.*}) - end - end - end - end -end diff --git a/spec/unit/knife/core/hashed_command_loader_spec.rb b/spec/unit/knife/core/hashed_command_loader_spec.rb deleted file mode 100644 index c88656945b..0000000000 --- a/spec/unit/knife/core/hashed_command_loader_spec.rb +++ /dev/null @@ -1,112 +0,0 @@ -# -# 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 "spec_helper" - -describe Chef::Knife::SubcommandLoader::HashedCommandLoader do - before do - allow(ChefUtils).to receive(:windows?) { false } - end - - let(:plugin_manifest) do - { - "_autogenerated_command_paths" => { - "plugins_paths" => { - "cool_a" => ["/file/for/plugin/a"], - "cooler_b" => ["/file/for/plugin/b"], - }, - "plugins_by_category" => { - "cool" => [ - "cool_a", - ], - "cooler" => [ - "cooler_b", - ], - }, - }, - } - end - - let(:loader) do - Chef::Knife::SubcommandLoader::HashedCommandLoader.new( - File.join(CHEF_SPEC_DATA, "knife-site-subcommands"), - plugin_manifest - ) - end - - describe "#list_commands" do - before do - allow(File).to receive(:exist?).and_return(true) - end - - it "lists all commands by category when no argument is given" do - expect(loader.list_commands).to eq({ "cool" => ["cool_a"], "cooler" => ["cooler_b"] }) - end - - it "lists only commands in the given category when a category is given" do - expect(loader.list_commands("cool")).to eq({ "cool" => ["cool_a"] }) - end - - context "when the plugin path is invalid" do - before do - expect(File).to receive(:exist?).with("/file/for/plugin/b").and_return(false) - end - - it "lists all commands by category when no argument is given" do - expect(Chef::Log).to receive(:error).with(/There are plugin files specified in the knife cache that cannot be found/) - expect(Chef::Log).to receive(:error).with("Missing files:\n\t/file/for/plugin/b") - expect(loader.list_commands).to eq({}) - end - end - end - - describe "#subcommand_files" do - it "lists all the files" do - expect(loader.subcommand_files).to eq(["/file/for/plugin/a", "/file/for/plugin/b"]) - end - end - - describe "#load_commands" do - before do - allow(Kernel).to receive(:load).and_return(true) - end - - it "returns false for non-existant commands" do - expect(loader.load_command(["nothere"])).to eq(false) - end - - it "loads the correct file and returns true if the command exists" do - allow(File).to receive(:exist?).and_return(true) - expect(Kernel).to receive(:load).with("/file/for/plugin/a").and_return(true) - expect(loader.load_command(["cool_a"])).to eq(true) - end - end - - describe "#subcommand_for_args" do - it "returns the subcommands for an exact match" do - expect(loader.subcommand_for_args(["cooler_b"])).to eq("cooler_b") - end - - it "finds the right subcommand even when _'s are elided" do - expect(loader.subcommand_for_args(%w{cooler b})).to eq("cooler_b") - end - - it "returns nil if the the subcommand isn't in our manifest" do - expect(loader.subcommand_for_args(["cooler c"])).to eq(nil) - end - end -end diff --git a/spec/unit/knife/core/node_editor_spec.rb b/spec/unit/knife/core/node_editor_spec.rb deleted file mode 100644 index 4eac07c313..0000000000 --- a/spec/unit/knife/core/node_editor_spec.rb +++ /dev/null @@ -1,211 +0,0 @@ -# -# Author:: Jordan Running (<jr@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 "spec_helper" -require "chef/knife/core/node_editor" - -describe Chef::Knife::NodeEditor do - let(:node_data) do - { "name" => "test_node", - "chef_environment" => "production", - "automatic" => { "foo" => "bar" }, - "default" => { "alpha" => { "bravo" => "charlie", "delta" => "echo" } }, - "normal" => { "alpha" => { "bravo" => "hotel" }, "tags" => [] }, - "override" => { "alpha" => { "bravo" => "foxtrot", "delta" => "golf" } }, - "policy_name" => nil, - "policy_group" => nil, - "run_list" => %w{role[comedy] role[drama] recipe[mystery]}, - } - end - - let(:node) { Chef::Node.from_hash(node_data) } - - let(:ui) { double "ui" } - let(:base_config) { { editor: "cat" } } - let(:config) { base_config.merge(all_attributes: false) } - - subject { described_class.new(node, ui, config) } - - describe "#view" do - it "returns a Hash with only the name, chef_environment, normal, " + - "policy_name, policy_group, and run_list properties" do - expected = node_data.select do |key,| - %w{ name chef_environment normal - policy_name policy_group run_list }.include?(key) - end - - expect(subject.view).to eq(expected) - end - - context "when config[:all_attributes] == true" do - let(:config) { base_config.merge(all_attributes: true) } - - it "returns a Hash with all of the node's properties" do - expect(subject.view).to eq(node_data) - end - end - end - - describe "#apply_updates" do - context "when the node name is changed" do - before(:each) do - allow(ui).to receive(:warn) - allow(ui).to receive(:confirm).and_return(true) - end - - it "emits a warning and prompts for confirmation" do - data = subject.view.merge("name" => "foo_new_name_node") - updated_node = subject.apply_updates(data) - - expect(ui).to have_received(:warn) - .with "Changing the name of a node results in a new node being " + - "created, test_node will not be modified or removed." - - expect(ui).to have_received(:confirm) - .with("Proceed with creation of new node") - - expect(updated_node).to be_a(Chef::Node) - end - end - - context "when config[:all_attributes] == false" do - let(:config) { base_config.merge(all_attributes: false) } - - let(:updated_data) do - subject.view.merge( - "normal" => { "alpha" => { "bravo" => "hotel2" }, "tags" => [ "xyz" ] }, - "policy_name" => "mypolicy", - "policy_group" => "prod", - "run_list" => %w{role[drama] recipe[mystery]} - ) - end - - it "returns a node with run_list and normal_attrs changed" do - updated_node = subject.apply_updates(updated_data) - expect(updated_node).to be_a(Chef::Node) - - # Expected to have been changed - expect(updated_node.normal_attrs).to eql(updated_data["normal"]) - expect(updated_node.policy_name).to eql(updated_data["policy_name"]) - expect(updated_node.policy_group).to eql(updated_data["policy_group"]) - expect(updated_node.chef_environment).to eql(updated_data["policy_group"]) - expect(updated_node.run_list.map(&:to_s)).to eql(updated_data["run_list"]) - - # Expected not to have changed - expect(updated_node.default_attrs).to eql(node.default_attrs) - expect(updated_node.override_attrs).to eql(node.override_attrs) - expect(updated_node.automatic_attrs).to eql(node.automatic_attrs) - end - end - - context "when config[:all_attributes] == true" do - let(:config) { base_config.merge(all_attributes: true) } - - let(:updated_data) do - subject.view.merge( - "default" => { "alpha" => { "bravo" => "charlie2", "delta" => "echo2" } }, - "normal" => { "alpha" => { "bravo" => "hotel2" }, "tags" => [ "xyz" ] }, - "override" => { "alpha" => { "bravo" => "foxtrot2", "delta" => "golf2" } }, - "policy_name" => "mypolicy", - "policy_group" => "prod", - "run_list" => %w{role[drama] recipe[mystery]} - ) - end - - it "returns a node with all editable properties changed" do - updated_node = subject.apply_updates(updated_data) - expect(updated_node).to be_a(Chef::Node) - - expect(updated_node.chef_environment).to eql(updated_data["policy_group"]) - expect(updated_node.automatic_attrs).to eql(updated_data["automatic"]) - expect(updated_node.normal_attrs).to eql(updated_data["normal"]) - expect(updated_node.default_attrs).to eql(updated_data["default"]) - expect(updated_node.override_attrs).to eql(updated_data["override"]) - expect(updated_node.policy_name).to eql(updated_data["policy_name"]) - expect(updated_node.policy_group).to eql(updated_data["policy_group"]) - expect(updated_node.run_list.map(&:to_s)).to eql(updated_data["run_list"]) - end - end - end - - describe "#updated?" do - context "before the node has been edited" do - it "returns false" do - expect(subject.updated?).to be false - end - end - - context "after the node has been edited" do - context "and changes were made" do - let(:updated_data) do - subject.view.merge( - "default" => { "alpha" => { "bravo" => "charlie2", "delta" => "echo2" } }, - "normal" => { "alpha" => { "bravo" => "hotel2" }, "tags" => [ "xyz" ] }, - "override" => { "alpha" => { "bravo" => "foxtrot2", "delta" => "golf2" } }, - "policy_name" => "mypolicy", - "policy_group" => "prod", - "run_list" => %w{role[drama] recipe[mystery]} - ) - end - - context "and changes affect only editable properties" do - before(:each) do - allow(ui).to receive(:edit_hash) - .with(subject.view) - .and_return(updated_data) - - subject.edit_node - end - - it "returns an array of the changed property names" do - expect(subject.updated?).to eql %w{ chef_environment normal policy_name policy_group run_list } - end - end - - context "and the changes include non-editable properties" do - before(:each) do - data = updated_data.merge("bad_property" => "bad_value") - - allow(ui).to receive(:edit_hash) - .with(subject.view) - .and_return(data) - - subject.edit_node - end - - it "returns an array of property names that doesn't include " + - "the non-editable properties" do - expect(subject.updated?).to eql %w{ chef_environment normal policy_name policy_group run_list } - end - end - end - - context "and changes were not made" do - before(:each) do - allow(ui).to receive(:edit_hash) - .with(subject.view) - .and_return(subject.view.dup) - - subject.edit_node - end - - it { is_expected.not_to be_updated } - end - end - end -end diff --git a/spec/unit/knife/core/object_loader_spec.rb b/spec/unit/knife/core/object_loader_spec.rb deleted file mode 100644 index 0dcabff46d..0000000000 --- a/spec/unit/knife/core/object_loader_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@chef.io>) -# Author:: Juanje Ojeda (<juanje.ojeda@gmail.com>) -# 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 "spec_helper" -require "chef/knife/core/object_loader" - -describe Chef::Knife::Core::ObjectLoader do - before(:each) do - @knife = Chef::Knife.new - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - Dir.chdir(File.join(CHEF_SPEC_DATA, "object_loader")) - end - - shared_examples_for "Chef object" do |chef_class| - it "should create a #{chef_class} object" do - expect(@object).to be_a_kind_of(chef_class) - end - - it "should has a attribute 'name'" do - expect(@object.name).to eql("test") - end - end - - { - "nodes" => Chef::Node, - "roles" => Chef::Role, - "environments" => Chef::Environment, - }.each do |repo_location, chef_class| - - describe "when the file is a #{chef_class}" do - before do - @loader = Chef::Knife::Core::ObjectLoader.new(chef_class, @knife.ui) - end - - describe "when the file is a Ruby" do - before do - @object = @loader.load_from(repo_location, "test.rb") - end - - it_behaves_like "Chef object", chef_class - end - - # NOTE: This is check for the bug described at CHEF-2352 - describe "when the file is a JSON" do - describe "and it has defined 'json_class'" do - before do - @object = @loader.load_from(repo_location, "test_json_class.json") - end - - it_behaves_like "Chef object", chef_class - end - - describe "and it has not defined 'json_class'" do - before do - @object = @loader.load_from(repo_location, "test.json") - end - - it_behaves_like "Chef object", chef_class - end - end - end - end - -end diff --git a/spec/unit/knife/core/subcommand_loader_spec.rb b/spec/unit/knife/core/subcommand_loader_spec.rb deleted file mode 100644 index e8bc045946..0000000000 --- a/spec/unit/knife/core/subcommand_loader_spec.rb +++ /dev/null @@ -1,64 +0,0 @@ -# -# 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 "spec_helper" - -describe Chef::Knife::SubcommandLoader do - let(:loader) { Chef::Knife::SubcommandLoader.new(File.join(CHEF_SPEC_DATA, "knife-site-subcommands")) } - let(:home) { File.join(CHEF_SPEC_DATA, "knife-home") } - let(:plugin_dir) { File.join(home, ".chef", "plugins", "knife") } - - before do - allow(ChefUtils).to receive(:windows?) { false } - Chef::Util::PathHelper.class_variable_set(:@@home_dir, home) - end - - after do - Chef::Util::PathHelper.class_variable_set(:@@home_dir, nil) - end - - let(:config_dir) { File.join(CHEF_SPEC_DATA, "knife-site-subcommands") } - - describe "#for_config" do - context "when ~/.chef/plugin_manifest.json exists" do - before do - allow(File).to receive(:exist?).with(File.join(home, ".chef", "plugin_manifest.json")).and_return(true) - end - - it "creates a HashedCommandLoader with the manifest has _autogenerated_command_paths" do - allow(File).to receive(:read).with(File.join(home, ".chef", "plugin_manifest.json")).and_return("{ \"_autogenerated_command_paths\": {}}") - expect(Chef::Knife::SubcommandLoader.for_config(config_dir)).to be_a Chef::Knife::SubcommandLoader::HashedCommandLoader - end - end - - context "when ~/.chef/plugin_manifest.json does not exist" do - before do - allow(File).to receive(:exist?).with(File.join(home, ".chef", "plugin_manifest.json")).and_return(false) - end - - it "creates a GemGlobLoader" do - expect(Chef::Knife::SubcommandLoader.for_config(config_dir)).to be_a Chef::Knife::SubcommandLoader::GemGlobLoader - end - end - end - - describe "#gem_glob_loader" do - it "always creates a GemGlobLoader" do - expect(Chef::Knife::SubcommandLoader.gem_glob_loader(config_dir)).to be_a Chef::Knife::SubcommandLoader::GemGlobLoader - end - end -end diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb deleted file mode 100644 index 3bbe799267..0000000000 --- a/spec/unit/knife/core/ui_spec.rb +++ /dev/null @@ -1,656 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Tim Hinderliter (<tim@chef.io>) -# Author:: Daniel DeLeo (<dan@chef.io>) -# Author:: John Keiser (<jkeiser@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 "spec_helper" - -describe Chef::Knife::UI do - before do - @out, @err, @in = StringIO.new, StringIO.new, StringIO.new - @config = { - verbosity: 0, - yes: nil, - format: "summary", - field_separator: ".", - } - @ui = Chef::Knife::UI.new(@out, @err, @in, @config) - end - - class TestObject < OpenStruct - def self.from_hash(hsh) - new(hsh) - end - end - - describe "edit" do - ruby_for_json = { "foo" => "bar" } - ruby_from_json = TestObject.from_hash(ruby_for_json) - json_from_ruby = "{\n \"foo\": \"bar\"\n}" - json_from_editor = "{\n \"bar\": \"foo\"\n}" - ruby_from_editor = TestObject.from_hash({ "bar" => "foo" }) - my_editor = "veeeye" - temp_path = "/tmp/bar/baz" - - let(:subject) { @ui.edit_data(ruby_for_json, parse_output, object_class: klass) } - let(:parse_output) { false } - let(:klass) { nil } - - context "when editing is disabled" do - before do - @ui.config[:disable_editing] = true - stub_const("Tempfile", double) # Tempfiles should never be invoked - end - context "when parse_output is false" do - it "returns pretty json string" do - expect(subject).to eql(json_from_ruby) - end - end - context "when parse_output is true" do - let(:parse_output) { true } - let(:klass) { TestObject } - it "returns a ruby object" do - expect(subject).to eql(ruby_from_json) - end - context "but no object class is provided" do - let(:klass) { nil } - it "raises an error" do - expect { subject }.to raise_error ArgumentError, - /Please pass in the object class to hydrate or use #edit_hash/ - end - end - end - end - - context "when editing is enabled" do - before do - @ui.config[:disable_editing] = false - @ui.config[:editor] = my_editor - @mock = double("Tempfile") - expect(@mock).to receive(:sync=).with(true) - expect(@mock).to receive(:puts).with(json_from_ruby) - expect(@mock).to receive(:close) - expect(@mock).to receive(:path).at_least(:once).and_return(temp_path) - expect(Tempfile).to receive(:open).with([ "knife-edit-", ".json" ]).and_yield(@mock) - end - context "and the editor works" do - before do - expect(@ui).to receive(:system).with("#{my_editor} #{temp_path}").and_return(true) - expect(IO).to receive(:read).with(temp_path).and_return(json_from_editor) - end - - context "when parse_output is false" do - it "returns an edited pretty json string" do - expect(subject).to eql(json_from_editor) - end - end - context "when parse_output is true" do - let(:parse_output) { true } - let(:klass) { TestObject } - it "returns an edited ruby object" do - expect(subject).to eql(ruby_from_editor) - end - end - end - context "when running the editor fails with nil" do - before do - expect(@ui).to receive(:system).with("#{my_editor} #{temp_path}").and_return(nil) - expect(IO).not_to receive(:read) - end - it "throws an exception" do - expect { subject }.to raise_error(RuntimeError) - end - end - context "when running the editor fails with false" do - before do - expect(@ui).to receive(:system).with("#{my_editor} #{temp_path}").and_return(false) - expect(IO).not_to receive(:read) - end - it "throws an exception" do - expect { subject }.to raise_error(RuntimeError) - end - end - end - context "when editing and not stubbing Tempfile (semi-functional test)" do - before do - @ui.config[:disable_editing] = false - @ui.config[:editor] = my_editor - @tempfile = Tempfile.new([ "knife-edit-", ".json" ]) - expect(Tempfile).to receive(:open).with([ "knife-edit-", ".json" ]).and_yield(@tempfile) - end - - context "and the editor works" do - before do - expect(@ui).to receive(:system).with("#{my_editor} #{@tempfile.path}").and_return(true) - expect(IO).to receive(:read).with(@tempfile.path).and_return(json_from_editor) - end - - context "when parse_output is false" do - it "returns an edited pretty json string" do - expect(subject).to eql(json_from_editor) - end - it "the tempfile should have mode 0600", :unix_only do - # XXX: this looks odd because we're really testing Tempfile.new here - expect(File.stat(@tempfile.path).mode & 0777).to eql(0600) - expect(subject).to eql(json_from_editor) - end - end - - context "when parse_output is true" do - let(:parse_output) { true } - let(:klass) { TestObject } - it "returns an edited ruby object" do - expect(subject).to eql(ruby_from_editor) - end - it "the tempfile should have mode 0600", :unix_only do - # XXX: this looks odd because we're really testing Tempfile.new here - expect(File.stat(@tempfile.path).mode & 0777).to eql(0600) - expect(subject).to eql(ruby_from_editor) - end - end - end - end - end - - describe "format_list_for_display" do - it "should print the full hash if --with-uri is true" do - @ui.config[:with_uri] = true - expect(@ui.format_list_for_display({ marcy: :playground })).to eq({ marcy: :playground }) - end - - it "should print only the keys if --with-uri is false" do - @ui.config[:with_uri] = false - expect(@ui.format_list_for_display({ marcy: :playground })).to eq([ :marcy ]) - end - end - - shared_examples "an output mehthod handling IO exceptions" do |method| - it "should throw Errno::EIO exceptions" do - allow(@out).to receive(:puts).and_raise(Errno::EIO) - allow(@err).to receive(:puts).and_raise(Errno::EIO) - expect { @ui.send(method, "hi") }.to raise_error(Errno::EIO) - end - - it "should ignore Errno::EPIPE exceptions (CHEF-3516)" do - allow(@out).to receive(:puts).and_raise(Errno::EPIPE) - allow(@err).to receive(:puts).and_raise(Errno::EPIPE) - expect { @ui.send(method, "hi") }.to raise_error(SystemExit) - end - - it "should throw Errno::EPIPE exceptions with -VV (CHEF-3516)" do - @config[:verbosity] = 2 - allow(@out).to receive(:puts).and_raise(Errno::EPIPE) - allow(@err).to receive(:puts).and_raise(Errno::EPIPE) - expect { @ui.send(method, "hi") }.to raise_error(Errno::EPIPE) - end - end - - describe "output" do - it_behaves_like "an output mehthod handling IO exceptions", :output - - it "formats strings appropriately" do - @ui.output("hi") - expect(@out.string).to eq("hi\n") - end - - it "formats hashes appropriately" do - @ui.output({ "hi" => "a", "lo" => "b" }) - expect(@out.string).to eq <<~EOM - hi: a - lo: b - EOM - end - - it "formats empty hashes appropriately" do - @ui.output({}) - expect(@out.string).to eq("\n") - end - - it "formats arrays appropriately" do - @ui.output(%w{a b}) - expect(@out.string).to eq <<~EOM - a - b - EOM - end - - it "formats empty arrays appropriately" do - @ui.output([ ]) - expect(@out.string).to eq("\n") - end - - it "formats single-member arrays appropriately" do - @ui.output([ "a" ]) - expect(@out.string).to eq("a\n") - end - - it "formats nested single-member arrays appropriately" do - @ui.output([ [ "a" ] ]) - expect(@out.string).to eq("a\n") - end - - it "formats nested arrays appropriately" do - @ui.output([ %w{a b}, %w{c d}]) - expect(@out.string).to eq <<~EOM - a - b - - c - d - EOM - end - - it "formats nested arrays with single- and empty subarrays appropriately" do - @ui.output([ %w{a b}, [ "c" ], [], %w{d e}]) - expect(@out.string).to eq <<~EOM - a - b - - c - - - d - e - EOM - end - - it "formats arrays of hashes with extra lines in between for readability" do - @ui.output([ { "a" => "b", "c" => "d" }, { "x" => "y" }, { "m" => "n", "o" => "p" }]) - expect(@out.string).to eq <<~EOM - a: b - c: d - - x: y - - m: n - o: p - EOM - end - - it "formats hashes with empty array members appropriately" do - @ui.output({ "a" => [], "b" => "c" }) - expect(@out.string).to eq <<~EOM - a: - b: c - EOM - end - - it "formats hashes with single-member array values appropriately" do - @ui.output({ "a" => [ "foo" ], "b" => "c" }) - expect(@out.string).to eq <<~EOM - a: foo - b: c - EOM - end - - it "formats hashes with array members appropriately" do - @ui.output({ "a" => %w{foo bar}, "b" => "c" }) - expect(@out.string).to eq <<~EOM - a: - foo - bar - b: c - EOM - end - - it "formats hashes with single-member nested array values appropriately" do - @ui.output({ "a" => [ [ "foo" ] ], "b" => "c" }) - expect(@out.string).to eq <<~EOM - a: - foo - b: c - EOM - end - - it "formats hashes with nested array values appropriately" do - @ui.output({ "a" => [ %w{foo bar}, %w{baz bjork} ], "b" => "c" }) - # XXX: using a HEREDOC at this point results in a line with required spaces which auto-whitespace removal settings - # on editors will remove and will break this test. - expect(@out.string).to eq("a:\n foo\n bar\n \n baz\n bjork\nb: c\n") - end - - it "formats hashes with hash values appropriately" do - @ui.output({ "a" => { "aa" => "bb", "cc" => "dd" }, "b" => "c" }) - expect(@out.string).to eq <<~EOM - a: - aa: bb - cc: dd - b: c - EOM - end - - it "formats hashes with empty hash values appropriately" do - @ui.output({ "a" => {}, "b" => "c" }) - expect(@out.string).to eq <<~EOM - a: - b: c - EOM - end - end - - describe "warn" do - it_behaves_like "an output mehthod handling IO exceptions", :warn - end - - describe "error" do - it_behaves_like "an output mehthod handling IO exceptions", :warn - end - - describe "fatal" do - it_behaves_like "an output mehthod handling IO exceptions", :warn - end - - describe "format_for_display" do - it "should return the raw data" do - input = { gi: :go } - expect(@ui.format_for_display(input)).to eq(input) - end - - describe "with --attribute passed" do - it "should return the deeply nested attribute" do - input = { "gi" => { "go" => "ge" }, "id" => "sample-data-bag-item" } - @ui.config[:attribute] = "gi.go" - expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "gi.go" => "ge" } }) - end - - it "should return multiple attributes" do - input = { "gi" => "go", "hi" => "ho", "id" => "sample-data-bag-item" } - @ui.config[:attribute] = %w{gi hi} - expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "gi" => "go", "hi" => "ho" } }) - end - - it "should handle attributes named the same as methods" do - input = { "keys" => "values", "hi" => "ho", "id" => "sample-data-bag-item" } - @ui.config[:attribute] = "keys" - expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "keys" => "values" } }) - end - - it "should handle nested attributes named the same as methods" do - input = { "keys" => { "keys" => "values" }, "hi" => "ho", "id" => "sample-data-bag-item" } - @ui.config[:attribute] = "keys.keys" - expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "keys.keys" => "values" } }) - end - - it "should return the name attribute" do - input = Chef::Node.new - input.name("chef.localdomain") - @ui.config[:attribute] = "name" - expect(@ui.format_for_display(input)).to eq( { "chef.localdomain" => { "name" => "chef.localdomain" } }) - end - - it "should return a 'class' attribute and not the node.class" do - input = Chef::Node.new - input.default["class"] = "classy!" - @ui.config[:attribute] = "class" - expect(@ui.format_for_display(input)).to eq( { nil => { "class" => "classy!" } } ) - end - - it "should return the chef_environment attribute" do - input = Chef::Node.new - input.chef_environment = "production-partner-load-integration-preview-testing" - @ui.config[:attribute] = "chef_environment" - expect(@ui.format_for_display(input)).to eq( { nil => { "chef_environment" => "production-partner-load-integration-preview-testing" } } ) - end - - it "works with arrays" do - input = Chef::Node.new - input.default["array"] = %w{zero one two} - @ui.config[:attribute] = "array.1" - expect(@ui.format_for_display(input)).to eq( { nil => { "array.1" => "one" } } ) - end - - it "returns nil when given an attribute path that isn't a name or attribute" do - input = { "keys" => { "keys" => "values" }, "hi" => "ho", "id" => "sample-data-bag-item" } - non_existing_path = "nope.nada.nothingtoseehere" - @ui.config[:attribute] = non_existing_path - expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { non_existing_path => nil } }) - end - - describe "when --field-separator is passed" do - it "honors that separator" do - input = { "keys" => { "with spaces" => { "open" => { "doors" => { "with many.dots" => "when asked" } } } } } - @ui.config[:field_separator] = ";" - @ui.config[:attribute] = "keys;with spaces;open;doors;with many.dots" - expect(@ui.format_for_display(input)).to eq({ nil => { "keys;with spaces;open;doors;with many.dots" => "when asked" } }) - end - end - end - - describe "with --run-list passed" do - it "should return the run list" do - input = Chef::Node.new - input.name("sample-node") - input.run_list("role[monkey]", "role[churchmouse]") - @ui.config[:run_list] = true - response = @ui.format_for_display(input) - expect(response["sample-node"]["run_list"][0]).to eq("role[monkey]") - expect(response["sample-node"]["run_list"][1]).to eq("role[churchmouse]") - end - end - end - - describe "format_cookbook_list_for_display" do - before(:each) do - @item = { - "cookbook_name" => { - "url" => "http://url/cookbooks/cookbook", - "versions" => [ - { "version" => "3.0.0", "url" => "http://url/cookbooks/3.0.0" }, - { "version" => "2.0.0", "url" => "http://url/cookbooks/2.0.0" }, - { "version" => "1.0.0", "url" => "http://url/cookbooks/1.0.0" }, - ], - }, - } - end - - it "should return an array of the cookbooks with versions" do - expected_response = [ "cookbook_name 3.0.0 2.0.0 1.0.0" ] - response = @ui.format_cookbook_list_for_display(@item) - expect(response).to eq(expected_response) - end - - describe "with --with-uri" do - it "should return the URIs" do - response = { - "cookbook_name" => { - "1.0.0" => "http://url/cookbooks/1.0.0", - "2.0.0" => "http://url/cookbooks/2.0.0", - "3.0.0" => "http://url/cookbooks/3.0.0" }, - } - @ui.config[:with_uri] = true - expect(@ui.format_cookbook_list_for_display(@item)).to eq(response) - end - end - - context "when running on Windows" do - before(:each) do - stdout = double("StringIO", tty?: true) - allow(@ui).to receive(:stdout).and_return(stdout) - allow(ChefUtils).to receive(:windows?) { true } - Chef::Config.reset - end - - after(:each) do - Chef::Config.reset - end - - it "should have color set to true if knife config has color explicitly set to true" do - Chef::Config[:color] = true - @ui.config[:color] = true - expect(@ui.color?).to eql(true) - end - - it "should have color set to false if knife config has color explicitly set to false" do - Chef::Config[:color] = false - expect(@ui.color?).to eql(false) - end - - it "should not have color set to false by default" do - expect(@ui.color?).to eql(false) - end - end - end - - describe "color" do - context "when ui.color? => true" do - it "returns colored output" do - skip "doesn't work on systems that don't correctly have terminals setup for color" - expect(@ui).to receive(:color?).and_return(true) - expect(@ui.color("a_bus_is", :yellow)).to eql("\e[33ma_bus_is\e[0m") - end - end - - context "when ui.color? => false" do - it "returns plain output" do - expect(@ui).to receive(:color?).and_return(false) - expect(@ui.color("a_bus_is", :yellow)).to eql("a_bus_is") - end - end - end - - describe "confirm" do - let(:stdout) { StringIO.new } - let(:output) { stdout.string } - - let(:question) { "monkeys rule" } - let(:answer) { "y" } - - let(:default_choice) { nil } - let(:append_instructions) { true } - - def run_confirm - allow(@ui).to receive(:stdout).and_return(stdout) - allow(@ui.stdin).to receive(:readline).and_return(answer) - @ui.confirm(question, append_instructions, default_choice) - end - - def run_confirm_without_exit - allow(@ui).to receive(:stdout).and_return(stdout) - allow(@ui.stdin).to receive(:readline).and_return(answer) - @ui.confirm_without_exit(question, append_instructions, default_choice) - end - - shared_examples_for "confirm with positive answer" do - it "confirm should return true" do - expect(run_confirm).to be_truthy - end - - it "confirm_without_exit should return true" do - expect(run_confirm_without_exit).to be_truthy - end - end - - shared_examples_for "confirm with negative answer" do - it "confirm should exit 3" do - expect do - run_confirm - end.to raise_error(SystemExit) { |e| expect(e.status).to eq(3) } - end - - it "confirm_without_exit should return false" do - expect(run_confirm_without_exit).to be_falsey - end - end - - describe "with default choice set to true" do - let(:default_choice) { true } - - it "should show 'Y/n' in the instructions" do - run_confirm - expect(output).to include("Y/n") - end - - describe "with empty answer" do - let(:answer) { "" } - - it_behaves_like "confirm with positive answer" - end - - describe "with answer N " do - let(:answer) { "N" } - - it_behaves_like "confirm with negative answer" - end - end - - describe "with default choice set to false" do - let(:default_choice) { false } - - it "should show 'y/N' in the instructions" do - run_confirm - expect(output).to include("y/N") - end - - describe "with empty answer" do - let(:answer) { "" } - - it_behaves_like "confirm with negative answer" - end - - describe "with answer N " do - let(:answer) { "Y" } - - it_behaves_like "confirm with positive answer" - end - end - - %w{Y y}.each do |answer| - describe "with answer #{answer}" do - let(:answer) { answer } - - it_behaves_like "confirm with positive answer" - end - end - - %w{N n}.each do |answer| - describe "with answer #{answer}" do - let(:answer) { answer } - - it_behaves_like "confirm with negative answer" - end - end - - describe "with --y or --yes passed" do - it "should return true" do - @ui.config[:yes] = true - expect(run_confirm).to be_truthy - expect(output).to eq("") - end - end - end - - describe "when asking for free-form user input" do - it "asks a question and returns the answer provided by the user" do - out = StringIO.new - allow(@ui).to receive(:stdout).and_return(out) - allow(@ui).to receive(:stdin).and_return(StringIO.new("http://mychefserver.example.com\n")) - expect(@ui.ask_question("your chef server URL?")).to eq("http://mychefserver.example.com") - expect(out.string).to eq("your chef server URL?") - end - - it "suggests a default setting and returns the default when the user's response only contains whitespace" do - out = StringIO.new - allow(@ui).to receive(:stdout).and_return(out) - allow(@ui).to receive(:stdin).and_return(StringIO.new(" \n")) - expect(@ui.ask_question("your chef server URL? ", default: "http://localhost:4000")).to eq("http://localhost:4000") - expect(out.string).to eq("your chef server URL? [http://localhost:4000] ") - end - end - -end diff --git a/spec/unit/knife/core/windows_bootstrap_context_spec.rb b/spec/unit/knife/core/windows_bootstrap_context_spec.rb deleted file mode 100644 index 76b90c955e..0000000000 --- a/spec/unit/knife/core/windows_bootstrap_context_spec.rb +++ /dev/null @@ -1,238 +0,0 @@ -# -# Author:: Bryan McLellan <btm@loftninjas.org> -# 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 "spec_helper" -require "chef/knife/core/windows_bootstrap_context" -describe Chef::Knife::Core::WindowsBootstrapContext do - let(:config) { {} } - let(:chef_config) { Chef::Config.save } # "dup" to a hash - let(:bootstrap_context) { Chef::Knife::Core::WindowsBootstrapContext.new(config, nil, chef_config, nil) } - - describe "fips" do - context "when fips is set" do - before do - chef_config[:fips] = true - end - - it "sets fips mode in the client.rb" do - expect(bootstrap_context.config_content).to match(/fips true/) - end - end - - context "when fips is not set" do - before do - chef_config[:fips] = false - end - - it "sets fips mode in the client.rb" do - expect(bootstrap_context.config_content).not_to match(/fips true/) - end - end - end - - describe "trusted_certs_script" do - let(:mock_cert_dir) { ::File.absolute_path(::File.join("spec", "assets", "fake_trusted_certs")) } - let(:script_output) { bootstrap_context.trusted_certs_script } - let(:crt_files) { ::Dir.glob(::File.join(mock_cert_dir, "*.crt")) } - let(:pem_files) { ::Dir.glob(::File.join(mock_cert_dir, "*.pem")) } - let(:other_files) { ::Dir.glob(::File.join(mock_cert_dir, "*")) - crt_files - pem_files } - - before do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(trusted_certs_dir: mock_cert_dir)) - end - - it "should echo every .crt file in the trusted_certs directory" do - crt_files.each do |f| - echo_file = ::File.read(f).gsub(/^/, "echo.") - expect(script_output).to include(::File.join("trusted_certs", ::File.basename(f))) - expect(script_output).to include(echo_file) - end - end - - it "should echo every .pem file in the trusted_certs directory" do - pem_files.each do |f| - echo_file = ::File.read(f).gsub(/^/, "echo.") - expect(script_output).to include(::File.join("trusted_certs", ::File.basename(f))) - expect(script_output).to include(echo_file) - end - end - - it "should not echo files which aren't .crt or .pem files" do - other_files.each do |f| - echo_file = ::File.read(f).gsub(/^/, "echo.") - expect(script_output).to_not include(::File.join("trusted_certs", ::File.basename(f))) - expect(script_output).to_not include(echo_file) - end - end - end - - describe "validation_key" do - before do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(validation_key: "C:\\chef\\key.pem")) - end - - it "should return false if validation_key does not exist" do - allow(::File).to receive(:expand_path).with("C:\\chef\\key.pem").and_call_original - allow(::File).to receive(:exist?).and_return(false) - expect(bootstrap_context.validation_key).to eq(false) - end - end - - describe "#get_log_location" do - - context "when config_log_location value is nil" do - it "sets STDOUT in client.rb as default" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: nil)) - expect(bootstrap_context.get_log_location).to eq("STDOUT\n") - end - end - - context "when config_log_location value is empty" do - it "sets STDOUT in client.rb as default" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: "")) - expect(bootstrap_context.get_log_location).to eq("STDOUT\n") - end - end - - context "when config_log_location value is STDOUT" do - it "sets STDOUT in client.rb" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: STDOUT)) - expect(bootstrap_context.get_log_location).to eq("STDOUT\n") - end - end - - context "when config_log_location value is STDERR" do - it "sets STDERR in client.rb" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: STDERR)) - expect(bootstrap_context.get_log_location).to eq("STDERR\n") - end - end - - context "when config_log_location value is path to a file" do - it "sets file path in client.rb" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: "C:\\chef\\chef.log")) - expect(bootstrap_context.get_log_location).to eq("\"C:\\chef\\chef.log\"\n") - end - end - - context "when config_log_location value is :win_evt" do - it "sets :win_evt in client.rb" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: :win_evt)) - expect(bootstrap_context.get_log_location).to eq(":win_evt\n") - end - end - - context "when config_log_location value is :syslog" do - it "raise error with message and exit" do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(config_log_location: :syslog)) - expect { bootstrap_context.get_log_location }.to raise_error("syslog is not supported for log_location on Windows OS\n") - end - end - - end - - describe "#config_content" do - before do - bootstrap_context.instance_variable_set( - :@chef_config, Mash.new( - config_log_level: :info, - config_log_location: STDOUT, - chef_server_url: "http://chef.example.com:4444", - validation_client_name: "chef-validator-testing", - file_cache_path: "c:/chef/cache", - file_backup_path: "c:/chef/backup", - cache_options: ({ path: "c:/chef/cache/checksums", skip_expires: true }) - ) - ) - end - - it "generates the config file data" do - expected = <<~EXPECTED - echo.chef_server_url "http://chef.example.com:4444" - echo.validation_client_name "chef-validator-testing" - echo.file_cache_path "C:\\\\chef\\\\cache" - echo.file_backup_path "C:\\\\chef\\\\backup" - echo.cache_options ^({:path =^> "C:\\\\chef\\\\cache\\\\checksums", :skip_expires =^> true}^) - echo.# Using default node name ^(fqdn^) - echo.log_level :auto - echo.log_location STDOUT - EXPECTED - expect(bootstrap_context.config_content).to eq expected - end - - describe "when chef_license is set" do - before do - bootstrap_context.instance_variable_set(:@chef_config, Mash.new(chef_license: "accept-no-persist")) - end - it "sets chef_license in the generated config file" do - expect(bootstrap_context.config_content).to include("chef_license \"accept-no-persist\"") - end - end - end - - describe "#start_chef" do - it "returns the expected string" do - expect(bootstrap_context.start_chef).to eq( - <<~EOH - SET "PATH=%SYSTEM32%;%SystemRoot%;%SYSTEM32%\\Wbem;%SYSTEM32%\\WindowsPowerShell\\v1.0\\;C:\\ruby\\bin;C:\\opscode\\chef\\bin;C:\\opscode\\chef\\embedded\\bin;%PATH%" - chef-client -c C:\\chef\\client.rb -j C:\\chef\\first-boot.json - EOH - ) - end - end - - describe "msi_url" do - context "when msi_url config option is not set" do - let(:config) { { channel: "stable" } } - before do - expect(bootstrap_context).to receive(:version_to_install).and_return("something") - end - - it "returns a chef.io msi url with minimal url parameters" do - reference_url = "https://www.chef.io/chef/download?p=windows&channel=stable&v=something" - expect(bootstrap_context.msi_url).to eq(reference_url) - end - - it "returns a chef.io msi url with provided url parameters substituted" do - reference_url = "https://www.chef.io/chef/download?p=windows&pv=machine&m=arch&DownloadContext=ctx&channel=stable&v=something" - expect(bootstrap_context.msi_url("machine", "arch", "ctx")).to eq(reference_url) - end - - context "when a channel is provided in config" do - let(:config) { { channel: "current" } } - it "returns a chef.io msi url with the requested channel" do - reference_url = "https://www.chef.io/chef/download?p=windows&channel=current&v=something" - expect(bootstrap_context.msi_url).to eq(reference_url) - end - end - end - - context "when msi_url config option is set" do - let(:custom_url) { "file://something" } - let(:config) { { msi_url: custom_url, install: true } } - - it "returns the overridden url" do - expect(bootstrap_context.msi_url).to eq(custom_url) - end - - it "doesn't introduce any unnecessary query parameters if provided by the template" do - expect(bootstrap_context.msi_url("machine", "arch", "ctx")).to eq(custom_url) - end - end - end -end diff --git a/spec/unit/knife/data_bag_create_spec.rb b/spec/unit/knife/data_bag_create_spec.rb deleted file mode 100644 index 93082c190e..0000000000 --- a/spec/unit/knife/data_bag_create_spec.rb +++ /dev/null @@ -1,175 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@chef.io>) -# Author:: Seth Falcon (<seth@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 "spec_helper" -require "tempfile" - -describe Chef::Knife::DataBagCreate do - let(:knife) do - k = Chef::Knife::DataBagCreate.new - allow(k).to receive(:rest).and_return(rest) - allow(k.ui).to receive(:stdout).and_return(stdout) - k - end - - let(:rest) { double("Chef::ServerAPI") } - let(:stdout) { StringIO.new } - - let(:bag_name) { "sudoing_admins" } - let(:item_name) { "ME" } - - let(:secret) { "abc123SECRET" } - - let(:raw_hash) { { "login_name" => "alphaomega", "id" => item_name } } - - let(:config) { {} } - - before do - Chef::Config[:node_name] = "webmonkey.example.com" - knife.name_args = [bag_name, item_name] - allow(knife).to receive(:config).and_return(config) - end - - context "when data_bag already exists" do - it "doesn't create a data bag" do - expect(knife).to receive(:create_object).and_yield(raw_hash) - expect(rest).to receive(:get).with("data/#{bag_name}") - expect(rest).to_not receive(:post).with("data", { "name" => bag_name }) - expect(knife.ui).to receive(:info).with("Data bag #{bag_name} already exists") - - knife.run - end - end - - context "when data_bag doesn't exist" do - before do - # Data bag doesn't exist by default so we mock the GET request to return 404 - exception = double("404 error", code: "404") - allow(rest).to receive(:get) - .with("data/#{bag_name}") - .and_raise(Net::HTTPClientException.new("404", exception)) - end - - it "tries to create a data bag with an invalid name when given one argument" do - knife.name_args = ["invalid&char"] - expect(Chef::DataBag).to receive(:validate_name!).with(knife.name_args[0]).and_raise(Chef::Exceptions::InvalidDataBagName) - expect { knife.run }.to exit_with_code(1) - end - - it "won't create a data bag with a reserved name for search" do - %w{node role client environment}.each do |name| - knife.name_args = [name] - expect(Chef::DataBag).to receive(:validate_name!).with(knife.name_args[0]).and_raise(Chef::Exceptions::InvalidDataBagName) - expect { knife.run }.to exit_with_code(1) - end - end - - context "when part of the name is a reserved name" do - before do - exception = double("404 error", code: "404") - %w{node role client environment}.each do |name| - allow(rest).to receive(:get) - .with("data/sudoing_#{name}_admins") - .and_raise(Net::HTTPClientException.new("404", exception)) - end - end - - it "will create a data bag containing a reserved word" do - %w{node role client environment}.each do |name| - knife.name_args = ["sudoing_#{name}_admins"] - expect(rest).to receive(:post).with("data", { "name" => knife.name_args[0] }) - expect(knife.ui).to receive(:info).with("Created data_bag[#{knife.name_args[0]}]") - - knife.run - end - end - end - - context "when given one argument" do - before do - knife.name_args = [bag_name] - end - - it "creates a data bag" do - expect(rest).to receive(:post).with("data", { "name" => bag_name }) - expect(knife.ui).to receive(:info).with("Created data_bag[#{bag_name}]") - - knife.run - end - end - - context "when given a data bag name partially matching a reserved name for search" do - %w{xnode rolex xenvironmentx xclientx}.each do |name| - let(:bag_name) { name } - - before do - knife.name_args = [bag_name] - end - - it "creates a data bag named '#{name}'" do - expect(rest).to receive(:post).with("data", { "name" => bag_name }) - expect(knife.ui).to receive(:info).with("Created data_bag[#{bag_name}]") - - knife.run - end - end - end - - context "no secret is specified for encryption" do - let(:item) do - item = Chef::DataBagItem.from_hash(raw_hash) - item.data_bag(bag_name) - item - end - - it "creates a data bag item" do - expect(knife).to receive(:create_object).and_yield(raw_hash) - expect(knife).to receive(:encryption_secret_provided?).and_return(false) - expect(rest).to receive(:post).with("data", { "name" => bag_name }).ordered - expect(rest).to receive(:post).with("data/#{bag_name}", item).ordered - - knife.run - end - end - - context "a secret is specified for encryption" do - let(:encoded_data) { Chef::EncryptedDataBagItem.encrypt_data_bag_item(raw_hash, secret) } - - let(:item) do - item = Chef::DataBagItem.from_hash(encoded_data) - item.data_bag(bag_name) - item - end - - it "creates an encrypted data bag item" do - expect(knife).to receive(:create_object).and_yield(raw_hash) - expect(knife).to receive(:encryption_secret_provided?).and_return(true) - expect(knife).to receive(:read_secret).and_return(secret) - expect(Chef::EncryptedDataBagItem) - .to receive(:encrypt_data_bag_item) - .with(raw_hash, secret) - .and_return(encoded_data) - expect(rest).to receive(:post).with("data", { "name" => bag_name }).ordered - expect(rest).to receive(:post).with("data/#{bag_name}", item).ordered - - knife.run - end - end - end -end diff --git a/spec/unit/knife/data_bag_edit_spec.rb b/spec/unit/knife/data_bag_edit_spec.rb deleted file mode 100644 index 6ebcaf4945..0000000000 --- a/spec/unit/knife/data_bag_edit_spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -# -# Author:: Seth Falcon (<seth@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 "spec_helper" -require "tempfile" - -describe Chef::Knife::DataBagEdit do - before do - Chef::Config[:node_name] = "webmonkey.example.com" - knife.name_args = [bag_name, item_name] - allow(knife).to receive(:config).and_return(config) - end - - let(:knife) do - k = Chef::Knife::DataBagEdit.new - allow(k).to receive(:rest).and_return(rest) - allow(k.ui).to receive(:stdout).and_return(stdout) - k - end - - let(:raw_hash) { { "login_name" => "alphaomega", "id" => "item_name" } } - let(:db) { Chef::DataBagItem.from_hash(raw_hash) } - let(:raw_edited_hash) { { "login_name" => "rho", "id" => "item_name", "new_key" => "new_value" } } - - let(:rest) { double("Chef::ServerAPI") } - let(:stdout) { StringIO.new } - - let(:bag_name) { "sudoing_admins" } - let(:item_name) { "ME" } - - let(:secret) { "abc123SECRET" } - - let(:config) { {} } - - let(:is_encrypted?) { false } - let(:transmitted_hash) { raw_edited_hash } - let(:data_to_edit) { db.raw_data } - shared_examples_for "editing a data bag" do - it "correctly edits then uploads the data bag" do - expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(db) - expect(knife).to receive(:encrypted?).with(db.raw_data).and_return(is_encrypted?) - expect(knife).to receive(:edit_hash).with(data_to_edit).and_return(raw_edited_hash) - expect(rest).to receive(:put).with("data/#{bag_name}/#{item_name}", transmitted_hash).ordered - - knife.run - end - end - - it "requires data bag and item arguments" do - knife.name_args = [] - expect(stdout).to receive(:puts).twice.with(anything) - expect { knife.run }.to exit_with_code(1) - expect(stdout.string).to eq("") - end - - context "when no secret is provided" do - include_examples "editing a data bag" - end - - context "when config[:print_after] is set" do - let(:config) { { print_after: true } } - before do - expect(knife.ui).to receive(:output).with(raw_edited_hash) - end - - include_examples "editing a data bag" - end - - context "when a secret is provided" do - let!(:enc_raw_hash) { Chef::EncryptedDataBagItem.encrypt_data_bag_item(raw_hash, secret) } - let!(:enc_edited_hash) { Chef::EncryptedDataBagItem.encrypt_data_bag_item(raw_edited_hash, secret) } - let(:transmitted_hash) { enc_edited_hash } - - before(:each) do - expect(knife).to receive(:read_secret).at_least(1).times.and_return(secret) - expect(Chef::EncryptedDataBagItem).to receive(:encrypt_data_bag_item).with(raw_edited_hash, secret).and_return(enc_edited_hash) - end - - context "the data bag starts encrypted" do - let(:is_encrypted?) { true } - let(:db) { Chef::DataBagItem.from_hash(enc_raw_hash) } - # If the data bag is encrypted, it gets passed to `edit` as a hash. Otherwise, it gets passed as a DataBag - let(:data_to_edit) { raw_hash } - - before(:each) do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true) - end - - include_examples "editing a data bag" - end - - context "the data bag starts unencrypted" do - before(:each) do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).exactly(0).times - expect(knife).to receive(:encryption_secret_provided?).and_return(true) - end - - include_examples "editing a data bag" - end - end - - it "fails to edit an encrypted data bag if the secret is missing" do - expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(db) - expect(knife).to receive(:encrypted?).with(db.raw_data).and_return(true) - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(false) - - expect(knife.ui).to receive(:fatal).with("You cannot edit an encrypted data bag without providing the secret.") - expect { knife.run }.to exit_with_code(1) - end - -end diff --git a/spec/unit/knife/data_bag_from_file_spec.rb b/spec/unit/knife/data_bag_from_file_spec.rb deleted file mode 100644 index 12211eede3..0000000000 --- a/spec/unit/knife/data_bag_from_file_spec.rb +++ /dev/null @@ -1,174 +0,0 @@ -# -# Author:: Seth Falcon (<seth@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 "spec_helper" - -require "chef/data_bag_item" -require "chef/encrypted_data_bag_item" -require "tempfile" - -Chef::Knife::DataBagFromFile.load_deps - -describe Chef::Knife::DataBagFromFile do - before :each do - allow(ChefUtils).to receive(:windows?) { false } - Chef::Config[:node_name] = "webmonkey.example.com" - FileUtils.mkdir_p([db_folder, db_folder2]) - db_file.write(Chef::JSONCompat.to_json(plain_data)) - db_file.flush - allow(knife).to receive(:config).and_return(config) - allow(Chef::Knife::Core::ObjectLoader).to receive(:new).and_return(loader) - end - - # We have to explicitly clean up Tempfile on Windows because it said so. - after :each do - db_file.close - db_file2.close - db_file3.close - FileUtils.rm_rf(db_folder) - FileUtils.rm_rf(db_folder2) - FileUtils.remove_entry_secure tmp_dir - end - - let(:knife) do - k = Chef::Knife::DataBagFromFile.new - allow(k).to receive(:rest).and_return(rest) - allow(k.ui).to receive(:stdout).and_return(stdout) - k - end - - let(:tmp_dir) { make_canonical_temp_directory } - let(:db_folder) { File.join(tmp_dir, data_bags_path, bag_name) } - let(:db_file) { Tempfile.new(["data_bag_from_file_test", ".json"], db_folder) } - let(:db_file2) { Tempfile.new(["data_bag_from_file_test2", ".json"], db_folder) } - let(:db_folder2) { File.join(tmp_dir, data_bags_path, bag_name2) } - let(:db_file3) { Tempfile.new(["data_bag_from_file_test3", ".json"], db_folder2) } - - def new_bag_expects(b = bag_name, d = plain_data) - data_bag = double - expect(data_bag).to receive(:data_bag).with(b) - expect(data_bag).to receive(:raw_data=).with(d) - expect(data_bag).to receive(:save) - expect(data_bag).to receive(:data_bag) - expect(data_bag).to receive(:id) - data_bag - end - - let(:loader) { double("Knife::Core::ObjectLoader") } - - let(:data_bags_path) { "data_bags" } - let(:plain_data) do - { - "id" => "item_name", - "greeting" => "hello", - "nested" => { "a1" => [1, 2, 3], "a2" => { "b1" => true } }, - } - end - let(:enc_data) { Chef::EncryptedDataBagItem.encrypt_data_bag_item(plain_data, secret) } - - let(:rest) { double("Chef::ServerAPI") } - let(:stdout) { StringIO.new } - - let(:bag_name) { "sudoing_admins" } - let(:bag_name2) { "sudoing_admins2" } - let(:item_name) { "ME" } - - let(:secret) { "abc123SECRET" } - - let(:config) { {} } - - it "loads from a file and saves" do - knife.name_args = [bag_name, db_file.path] - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, db_file.path).and_return(plain_data) - expect(Chef::DataBagItem).to receive(:new).and_return(new_bag_expects) - - knife.run - end - - it "loads all from multiple files and saves" do - knife.name_args = [ bag_name, db_file.path, db_file2.path ] - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, db_file.path).and_return(plain_data) - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, db_file2.path).and_return(plain_data) - expect(Chef::DataBagItem).to receive(:new).twice.and_return(new_bag_expects, new_bag_expects) - - knife.run - end - - it "loads all from a folder and saves" do - knife.name_args = [ bag_name, db_folder ] - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, db_file.path).and_return(plain_data) - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, db_file2.path).and_return(plain_data) - expect(Chef::DataBagItem).to receive(:new).twice.and_return(new_bag_expects, new_bag_expects) - - knife.run - end - - describe "loading all data bags" do - - it "loads all data bags when -a or --all options is provided" do - knife.name_args = [] - config[:all] = true - expect(loader).to receive(:find_all_object_dirs).with("./#{data_bags_path}").and_return([bag_name, bag_name2]) - expect(loader).to receive(:find_all_objects).with("./#{data_bags_path}/#{bag_name}").and_return([File.basename(db_file.path), File.basename(db_file2.path)]) - expect(loader).to receive(:find_all_objects).with("./#{data_bags_path}/#{bag_name2}").and_return([File.basename(db_file3.path)]) - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, File.basename(db_file.path)).and_return(plain_data) - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, File.basename(db_file2.path)).and_return(plain_data) - expect(loader).to receive(:load_from).with(data_bags_path, bag_name2, File.basename(db_file3.path)).and_return(plain_data) - expect(Chef::DataBagItem).to receive(:new).exactly(3).times.and_return(new_bag_expects, new_bag_expects, new_bag_expects(bag_name2)) - - knife.run - end - - it "loads all data bags items when -a or --all options is provided" do - knife.name_args = [bag_name2] - config[:all] = true - expect(loader).to receive(:find_all_objects).with("./#{data_bags_path}/#{bag_name2}").and_return([File.basename(db_file3.path)]) - expect(loader).to receive(:load_from).with(data_bags_path, bag_name2, File.basename(db_file3.path)).and_return(plain_data) - expect(Chef::DataBagItem).to receive(:new).and_return(new_bag_expects(bag_name2)) - - knife.run - end - - end - - describe "encrypted data bag items" do - before(:each) do - expect(knife).to receive(:encryption_secret_provided?).and_return(true) - expect(knife).to receive(:read_secret).and_return(secret) - expect(Chef::EncryptedDataBagItem).to receive(:encrypt_data_bag_item).with(plain_data, secret).and_return(enc_data) - end - - it "encrypts values when given --secret" do - knife.name_args = [bag_name, db_file.path] - expect(loader).to receive(:load_from).with(data_bags_path, bag_name, db_file.path).and_return(plain_data) - expect(Chef::DataBagItem).to receive(:new).and_return(new_bag_expects(bag_name, enc_data)) - - knife.run - end - - end - - describe "command line parsing" do - it "prints help if given no arguments" do - knife.name_args = [bag_name] - expect { knife.run }.to exit_with_code(1) - expect(stdout.string).to start_with("knife data bag from file BAG FILE|FOLDER [FILE|FOLDER..] (options)") - end - end - -end diff --git a/spec/unit/knife/data_bag_secret_options_spec.rb b/spec/unit/knife/data_bag_secret_options_spec.rb deleted file mode 100644 index e8f99c3f79..0000000000 --- a/spec/unit/knife/data_bag_secret_options_spec.rb +++ /dev/null @@ -1,173 +0,0 @@ -# -# Author:: Tyler Ball (<tball@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 "spec_helper" -require "chef/knife" -require "chef/config" -require "tempfile" - -class ExampleDataBagCommand < Chef::Knife - include Chef::Knife::DataBagSecretOptions -end - -describe Chef::Knife::DataBagSecretOptions do - let(:example_db) do - k = ExampleDataBagCommand.new - allow(k.ui).to receive(:stdout).and_return(stdout) - k - end - - let(:stdout) { StringIO.new } - - let(:secret) { "abc123SECRET" } - let(:secret_file) do - sfile = Tempfile.new("encrypted_data_bag_secret") - sfile.puts(secret) - sfile.flush - sfile - end - - after do - secret_file.close - secret_file.unlink - end - - describe "#validate_secrets" do - - it "throws an error when provided with both --secret and --secret-file on the CL" do - example_db.config[:cl_secret_file] = secret_file.path - example_db.config[:cl_secret] = secret - expect(example_db).to receive(:exit).with(1) - expect(example_db.ui).to receive(:fatal).with("Please specify only one of --secret, --secret-file") - - example_db.validate_secrets - end - - it "throws an error when provided with `secret` and `secret_file` in knife.rb" do - Chef::Config[:knife][:secret_file] = secret_file.path - Chef::Config[:knife][:secret] = secret - example_db.merge_configs - expect(example_db).to receive(:exit).with(1) - expect(example_db.ui).to receive(:fatal).with("Please specify only one of 'secret' or 'secret_file' in your config file") - - example_db.validate_secrets - end - - end - - describe "#read_secret" do - - it "returns the secret first" do - example_db.config[:cl_secret] = secret - Chef::Config[:knife][:secret] = secret - example_db.merge_configs - expect(example_db.read_secret).to eq(secret) - end - - it "returns the secret_file only if secret does not exist" do - example_db.config[:cl_secret_file] = secret_file.path - Chef::Config[:knife][:secret_file] = secret_file.path - example_db.merge_configs - expect(Chef::EncryptedDataBagItem).to receive(:load_secret).with(secret_file.path).and_return("secret file contents") - expect(example_db.read_secret).to eq("secret file contents") - end - - it "returns the secret from the knife.rb config" do - Chef::Config[:knife][:secret_file] = secret_file.path - Chef::Config[:knife][:secret] = secret - example_db.merge_configs - expect(example_db.read_secret).to eq(secret) - end - - it "returns the secret_file from the knife.rb config only if the secret does not exist" do - Chef::Config[:knife][:secret_file] = secret_file.path - example_db.merge_configs - expect(Chef::EncryptedDataBagItem).to receive(:load_secret).with(secret_file.path).and_return("secret file contents") - expect(example_db.read_secret).to eq("secret file contents") - end - - end - - describe "#encryption_secret_provided?" do - - it "returns true if the secret is passed on the CL" do - example_db.config[:cl_secret] = secret - expect(example_db.encryption_secret_provided?).to eq(true) - end - - it "returns true if the secret_file is passed on the CL" do - example_db.config[:cl_secret_file] = secret_file.path - expect(example_db.encryption_secret_provided?).to eq(true) - end - - it "returns true if --encrypt is passed on the CL and :secret is in config" do - example_db.config[:encrypt] = true - Chef::Config[:knife][:secret] = secret - example_db.merge_configs - expect(example_db.encryption_secret_provided?).to eq(true) - end - - it "returns true if --encrypt is passed on the CL and :secret_file is in config" do - example_db.config[:encrypt] = true - Chef::Config[:knife][:secret_file] = secret_file.path - example_db.merge_configs - expect(example_db.encryption_secret_provided?).to eq(true) - end - - it "throws an error if --encrypt is passed and there is not :secret or :secret_file in the config" do - example_db.config[:encrypt] = true - expect(example_db).to receive(:exit).with(1) - expect(example_db.ui).to receive(:fatal).with("No secret or secret_file specified in config, unable to encrypt item.") - example_db.encryption_secret_provided? - end - - it "returns false if no secret is passed" do - expect(example_db.encryption_secret_provided?).to eq(false) - end - - it "returns false if --encrypt is not provided and :secret is in the config" do - Chef::Config[:knife][:secret] = secret - example_db.merge_configs - expect(example_db.encryption_secret_provided?).to eq(false) - end - - it "returns false if --encrypt is not provided and :secret_file is in the config" do - Chef::Config[:knife][:secret_file] = secret_file.path - example_db.merge_configs - expect(example_db.encryption_secret_provided?).to eq(false) - end - - it "returns true if --encrypt is not provided, :secret is in the config and need_encrypt_flag is false" do - Chef::Config[:knife][:secret] = secret - example_db.merge_configs - expect(example_db.encryption_secret_provided_ignore_encrypt_flag?).to eq(true) - end - - it "returns true if --encrypt is not provided, :secret_file is in the config and need_encrypt_flag is false" do - Chef::Config[:knife][:secret_file] = secret_file.path - example_db.merge_configs - expect(example_db.encryption_secret_provided_ignore_encrypt_flag?).to eq(true) - end - - it "returns false if --encrypt is not provided and need_encrypt_flag is false" do - expect(example_db.encryption_secret_provided_ignore_encrypt_flag?).to eq(false) - end - - end - -end diff --git a/spec/unit/knife/data_bag_show_spec.rb b/spec/unit/knife/data_bag_show_spec.rb deleted file mode 100644 index 2b806b8a65..0000000000 --- a/spec/unit/knife/data_bag_show_spec.rb +++ /dev/null @@ -1,139 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Seth Falcon (<seth@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 "spec_helper" - -require "chef/data_bag_item" -require "chef/encrypted_data_bag_item" -require "chef/json_compat" -require "tempfile" - -describe Chef::Knife::DataBagShow do - - before do - Chef::Config[:node_name] = "webmonkey.example.com" - knife.name_args = [bag_name, item_name] - allow(knife).to receive(:config).and_return(config) - end - - let(:knife) do - k = Chef::Knife::DataBagShow.new - allow(k).to receive(:rest).and_return(rest) - allow(k.ui).to receive(:stdout).and_return(stdout) - k - end - - let(:rest) { double("Chef::ServerAPI") } - let(:stdout) { StringIO.new } - - let(:bag_name) { "sudoing_admins" } - let(:item_name) { "ME" } - - let(:data_bag_contents) do - { "id" => "id", "baz" => "http://localhost:4000/data/bag_o_data/baz", - "qux" => "http://localhost:4000/data/bag_o_data/qux" } - end - let(:enc_hash) { Chef::EncryptedDataBagItem.encrypt_data_bag_item(data_bag_contents, secret) } - let(:data_bag) { Chef::DataBagItem.from_hash(data_bag_contents) } - let(:data_bag_with_encoded_hash) { Chef::DataBagItem.from_hash(enc_hash) } - let(:enc_data_bag) { Chef::EncryptedDataBagItem.new(enc_hash, secret) } - - let(:secret) { "abc123SECRET" } - # - # let(:raw_hash) {{ "login_name" => "alphaomega", "id" => item_name }} - # - let(:config) { { format: "json" } } - - context "Data bag to show is encrypted" do - before do - allow(knife).to receive(:encrypted?).and_return(true) - end - - it "decrypts and displays the encrypted data bag when the secret is provided" do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true) - expect(knife).to receive(:read_secret).and_return(secret) - expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(data_bag_with_encoded_hash) - expect(knife.ui).to receive(:info).with("Encrypted data bag detected, decrypting with provided secret.") - expect(Chef::EncryptedDataBagItem).to receive(:load).with(bag_name, item_name, secret).and_return(enc_data_bag) - - expected = %q{baz: http://localhost:4000/data/bag_o_data/baz -id: id -qux: http://localhost:4000/data/bag_o_data/qux} - knife.run - expect(stdout.string.strip).to eq(expected) - end - - it "displays the encrypted data bag when the secret is not provided" do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(false) - expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(data_bag_with_encoded_hash) - expect(knife.ui).to receive(:warn).with("Encrypted data bag detected, but no secret provided for decoding. Displaying encrypted data.") - - knife.run - expect(stdout.string.strip).to include("baz", "qux", "cipher") - end - end - - context "Data bag to show is not encrypted" do - before do - allow(knife).to receive(:encrypted?).and_return(false) - end - - it "displays the data bag" do - expect(knife).to receive(:read_secret).exactly(0).times - expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(data_bag) - - expected = %q{baz: http://localhost:4000/data/bag_o_data/baz -id: id -qux: http://localhost:4000/data/bag_o_data/qux} - knife.run - expect(stdout.string.strip).to eq(expected) - end - - context "when a secret is given" do - it "displays the data bag" do - expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true) - expect(knife).to receive(:read_secret).and_return(secret) - expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(data_bag) - expect(knife.ui).to receive(:warn).with("Unencrypted data bag detected, ignoring any provided secret options.") - - expected = %q{baz: http://localhost:4000/data/bag_o_data/baz -id: id -qux: http://localhost:4000/data/bag_o_data/qux} - knife.run - expect(stdout.string.strip).to eq(expected) - end - end - end - - it "displays the list of items in the data bag when only one @name_arg is provided" do - knife.name_args = [bag_name] - expect(Chef::DataBag).to receive(:load).with(bag_name).and_return({}) - - knife.run - expect(stdout.string.strip).to eq("") - end - - it "raises an error when no @name_args are provided" do - knife.name_args = [] - - expect { knife.run }.to exit_with_code(1) - expect(stdout.string).to start_with("knife data bag show BAG [ITEM] (options)") - end - -end diff --git a/spec/unit/knife/environment_compare_spec.rb b/spec/unit/knife/environment_compare_spec.rb deleted file mode 100644 index bfaeed0c82..0000000000 --- a/spec/unit/knife/environment_compare_spec.rb +++ /dev/null @@ -1,112 +0,0 @@ -# -# Author:: Sander Botman (<sbotman@schubergphilis.com>) -# Copyright:: Copyright 2013-2016, Sander Botman. -# 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 "spec_helper" - -describe Chef::Knife::EnvironmentCompare do - before(:each) do - @knife = Chef::Knife::EnvironmentCompare.new - - @environments = { - "cita" => "http://localhost:4000/environments/cita", - "citm" => "http://localhost:4000/environments/citm", - } - - allow(@knife).to receive(:environment_list).and_return(@environments) - - @constraints = { - "cita" => { "foo" => "= 1.0.1", "bar" => "= 0.0.4" }, - "citm" => { "foo" => "= 1.0.1", "bar" => "= 0.0.2" }, - } - - allow(@knife).to receive(:constraint_list).and_return(@constraints) - - @cookbooks = { "foo" => "= 1.0.1", "bar" => "= 0.0.1" } - - allow(@knife).to receive(:cookbook_list).and_return(@cookbooks) - - @rest_double = double("rest") - allow(@knife).to receive(:rest).and_return(@rest_double) - @cookbook_names = %w{apache2 mysql foo bar dummy chef_handler} - @base_url = "https://server.example.com/cookbooks" - @cookbook_data = {} - @cookbook_names.each do |item| - @cookbook_data[item] = { "url" => "#{@base_url}/#{item}", - "versions" => [{ "version" => "1.0.1", - "url" => "#{@base_url}/#{item}/1.0.1" }] } - end - - allow(@rest_double).to receive(:get).with("/cookbooks?num_versions=1").and_return(@cookbook_data) - - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should display only cookbooks with version constraints" do - @knife.config[:format] = "summary" - @knife.run - @environments.each_key do |item| - expect(@stdout.string).to(match(/#{item}/)) && expect(@stdout.string.lines.count).to(be 4) - end - end - - it "should display 4 number of lines" do - @knife.config[:format] = "summary" - @knife.run - expect(@stdout.string.lines.count).to be 4 - end - end - - describe "with -m or --mismatch" do - it "should display only cookbooks that have mismatching version constraints" do - @knife.config[:format] = "summary" - @knife.config[:mismatch] = true - @knife.run - @constraints.each_value do |ver| - expect(@stdout.string).to match(/#{ver[1]}/) - end - end - - it "should display 3 number of lines" do - @knife.config[:format] = "summary" - @knife.config[:mismatch] = true - @knife.run - expect(@stdout.string.lines.count).to be 3 - end - end - - describe "with -a or --all" do - it "should display all cookbooks" do - @knife.config[:format] = "summary" - @knife.config[:all] = true - @knife.run - @constraints.each_value do |ver| - expect(@stdout.string).to match(/#{ver[1]}/) - end - end - - it "should display 8 number of lines" do - @knife.config[:format] = "summary" - @knife.config[:all] = true - @knife.run - expect(@stdout.string.lines.count).to be 8 - end - end - -end diff --git a/spec/unit/knife/environment_create_spec.rb b/spec/unit/knife/environment_create_spec.rb deleted file mode 100644 index d54cab8dc9..0000000000 --- a/spec/unit/knife/environment_create_spec.rb +++ /dev/null @@ -1,91 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@ospcode.com>) -# 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 "spec_helper" - -describe Chef::Knife::EnvironmentCreate do - before(:each) do - @knife = Chef::Knife::EnvironmentCreate.new - allow(@knife).to receive(:msg).and_return true - allow(@knife).to receive(:output).and_return true - allow(@knife).to receive(:show_usage).and_return true - @knife.name_args = [ "production" ] - - @environment = Chef::Environment.new - allow(@environment).to receive(:save) - - allow(Chef::Environment).to receive(:new).and_return @environment - allow(@knife).to receive(:edit_data).and_return @environment - end - - describe "run" do - it "should create a new environment" do - expect(Chef::Environment).to receive(:new) - @knife.run - end - - it "should set the environment name" do - expect(@environment).to receive(:name).with("production") - @knife.run - end - - it "should not print the environment" do - expect(@knife).not_to receive(:output) - @knife.run - end - - it "should prompt you to edit the data" do - expect(@knife).to receive(:edit_data).with(@environment, object_class: Chef::Environment) - @knife.run - end - - it "should save the environment" do - expect(@environment).to receive(:save) - @knife.run - end - - it "should show usage and exit when no environment name is provided" do - @knife.name_args = [ ] - expect(@knife.ui).to receive(:fatal) - expect(@knife).to receive(:show_usage) - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "with --description" do - before(:each) do - @knife.config[:description] = "This is production" - end - - it "should set the description" do - expect(@environment).to receive(:description).with("This is production") - @knife.run - end - end - - describe "with --print-after" do - before(:each) do - @knife.config[:print_after] = true - end - - it "should pretty print the environment, formatted for display" do - expect(@knife).to receive(:output).with(@environment) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/environment_delete_spec.rb b/spec/unit/knife/environment_delete_spec.rb deleted file mode 100644 index 643bf1cc13..0000000000 --- a/spec/unit/knife/environment_delete_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@ospcode.com>) -# 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 "spec_helper" - -describe Chef::Knife::EnvironmentDelete do - before(:each) do - @knife = Chef::Knife::EnvironmentDelete.new - allow(@knife).to receive(:msg).and_return true - allow(@knife).to receive(:output).and_return true - allow(@knife).to receive(:show_usage).and_return true - allow(@knife).to receive(:confirm).and_return true - @knife.name_args = [ "production" ] - - @environment = Chef::Environment.new - @environment.name("production") - @environment.description("Please delete me") - allow(@environment).to receive(:destroy).and_return true - allow(Chef::Environment).to receive(:load).and_return @environment - end - - it "should confirm that you want to delete" do - expect(@knife).to receive(:confirm) - @knife.run - end - - it "should load the environment" do - expect(Chef::Environment).to receive(:load).with("production") - @knife.run - end - - it "should delete the environment" do - expect(@environment).to receive(:destroy) - @knife.run - end - - it "should not print the environment" do - expect(@knife).not_to receive(:output) - @knife.run - end - - it "should show usage and exit when no environment name is provided" do - @knife.name_args = [] - expect(@knife.ui).to receive(:fatal) - expect(@knife).to receive(:show_usage) - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "with --print-after" do - it "should pretty print the environment, formatted for display" do - @knife.config[:print_after] = true - expect(@knife).to receive(:output).with(@environment) - @knife.run - end - end -end diff --git a/spec/unit/knife/environment_edit_spec.rb b/spec/unit/knife/environment_edit_spec.rb deleted file mode 100644 index 1feb1c05fd..0000000000 --- a/spec/unit/knife/environment_edit_spec.rb +++ /dev/null @@ -1,79 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@ospcode.com>) -# 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 "spec_helper" - -describe Chef::Knife::EnvironmentEdit do - before(:each) do - @knife = Chef::Knife::EnvironmentEdit.new - allow(@knife.ui).to receive(:msg).and_return true - allow(@knife.ui).to receive(:output).and_return true - allow(@knife.ui).to receive(:show_usage).and_return true - @knife.name_args = [ "production" ] - - @environment = Chef::Environment.new - @environment.name("production") - @environment.description("Please edit me") - allow(@environment).to receive(:save).and_return true - allow(Chef::Environment).to receive(:load).and_return @environment - allow(@knife.ui).to receive(:edit_data).and_return @environment - end - - it "should load the environment" do - expect(Chef::Environment).to receive(:load).with("production") - @knife.run - end - - it "should let you edit the environment" do - expect(@knife.ui).to receive(:edit_data).with(@environment, object_class: Chef::Environment) - @knife.run - end - - it "should save the edited environment data" do - pansy = Chef::Environment.new - - @environment.name("new_environment_name") - expect(@knife.ui).to receive(:edit_data).with(@environment, object_class: Chef::Environment).and_return(pansy) - expect(pansy).to receive(:save) - @knife.run - end - - it "should not save the unedited environment data" do - expect(@environment).not_to receive(:save) - @knife.run - end - - it "should not print the environment" do - expect(@knife).not_to receive(:output) - @knife.run - end - - it "should show usage and exit when no environment name is provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "with --print-after" do - it "should pretty print the environment, formatted for display" do - @knife.config[:print_after] = true - expect(@knife.ui).to receive(:output).with(@environment) - @knife.run - end - end -end diff --git a/spec/unit/knife/environment_from_file_spec.rb b/spec/unit/knife/environment_from_file_spec.rb deleted file mode 100644 index 2090ec7bbd..0000000000 --- a/spec/unit/knife/environment_from_file_spec.rb +++ /dev/null @@ -1,90 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@ospcode.com>) -# Author:: Seth Falcon (<seth@ospcode.com>) -# 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 "spec_helper" - -Chef::Knife::EnvironmentFromFile.load_deps - -describe Chef::Knife::EnvironmentFromFile do - before(:each) do - allow(ChefUtils).to receive(:windows?) { false } - @knife = Chef::Knife::EnvironmentFromFile.new - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - @knife.name_args = [ "spec.rb" ] - - @environment = Chef::Environment.new - @environment.name("spec") - @environment.description("runs the unit tests") - @environment.cookbook_versions({ "apt" => "= 1.2.3" }) - allow(@environment).to receive(:save).and_return true - allow(@knife.loader).to receive(:load_from).and_return @environment - end - - describe "run" do - it "loads the environment data from a file and saves it" do - expect(@knife.loader).to receive(:load_from).with("environments", "spec.rb").and_return(@environment) - expect(@environment).to receive(:save) - @knife.run - end - - context "when handling multiple environments" do - before(:each) do - @env_apple = @environment.dup - @env_apple.name("apple") - allow(@knife.loader).to receive(:load_from).with("apple.rb").and_return @env_apple - end - - it "loads multiple environments if given" do - @knife.name_args = [ "spec.rb", "apple.rb" ] - expect(@environment).to receive(:save).twice - @knife.run - end - - it "loads all environments with -a" do - allow(File).to receive(:expand_path).with("./environments/").and_return("/tmp/environments") - allow(Dir).to receive(:glob).with("/tmp/environments/*.{json,rb}").and_return(["spec.rb", "apple.rb"]) - @knife.name_args = [] - allow(@knife).to receive(:config).and_return({ all: true }) - expect(@environment).to receive(:save).twice - @knife.run - end - end - - it "should not print the environment" do - expect(@knife).not_to receive(:output) - @knife.run - end - - it "should show usage and exit if not filename is provided" do - @knife.name_args = [] - expect(@knife.ui).to receive(:fatal) - expect(@knife).to receive(:show_usage) - expect { @knife.run }.to raise_error(SystemExit) - end - - describe "with --print-after" do - it "should pretty print the environment, formatted for display" do - @knife.config[:print_after] = true - expect(@knife).to receive(:output) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/environment_list_spec.rb b/spec/unit/knife/environment_list_spec.rb deleted file mode 100644 index 7bb0e723aa..0000000000 --- a/spec/unit/knife/environment_list_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@ospcode.com>) -# 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 "spec_helper" - -describe Chef::Knife::EnvironmentList do - before(:each) do - @knife = Chef::Knife::EnvironmentList.new - allow(@knife).to receive(:msg).and_return true - allow(@knife).to receive(:output).and_return true - allow(@knife).to receive(:show_usage).and_return true - - @environments = { - "production" => "http://localhost:4000/environments/production", - "development" => "http://localhost:4000/environments/development", - "testing" => "http://localhost:4000/environments/testing", - } - allow(Chef::Environment).to receive(:list).and_return @environments - end - - it "should make an api call to list the environments" do - expect(Chef::Environment).to receive(:list) - @knife.run - end - - it "should print the environment names in a sorted list" do - names = @environments.keys.sort { |a, b| a <=> b } - expect(@knife).to receive(:output).with(names) - @knife.run - end - - describe "with --with-uri" do - it "should print and unsorted list of the environments and their URIs" do - @knife.config[:with_uri] = true - expect(@knife).to receive(:output).with(@environments) - @knife.run - end - end -end diff --git a/spec/unit/knife/environment_show_spec.rb b/spec/unit/knife/environment_show_spec.rb deleted file mode 100644 index 8f67e593bc..0000000000 --- a/spec/unit/knife/environment_show_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@ospcode.com>) -# 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 "spec_helper" - -describe Chef::Knife::EnvironmentShow do - before(:each) do - @knife = Chef::Knife::EnvironmentShow.new - allow(@knife).to receive(:msg).and_return true - allow(@knife).to receive(:output).and_return true - allow(@knife).to receive(:show_usage).and_return true - @knife.name_args = [ "production" ] - - @environment = Chef::Environment.new - @environment.name("production") - @environment.description("Look at me!") - allow(Chef::Environment).to receive(:load).and_return @environment - end - - it "should load the environment" do - expect(Chef::Environment).to receive(:load).with("production") - @knife.run - end - - it "should pretty print the environment, formatted for display" do - expect(@knife).to receive(:format_for_display).with(@environment) - expect(@knife).to receive(:output) - @knife.run - end - - it "should show usage and exit when no environment name is provided" do - @knife.name_args = [] - expect(@knife.ui).to receive(:fatal) - expect(@knife).to receive(:show_usage) - expect { @knife.run }.to raise_error(SystemExit) - end -end diff --git a/spec/unit/knife/key_create_spec.rb b/spec/unit/knife/key_create_spec.rb deleted file mode 100644 index 12826ae7e2..0000000000 --- a/spec/unit/knife/key_create_spec.rb +++ /dev/null @@ -1,223 +0,0 @@ -# -# Author:: Tyler Cloke (<tyler@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 "spec_helper" -require "chef/knife/user_key_create" -require "chef/knife/client_key_create" -require "chef/knife/key_create" -require "chef/key" - -describe "key create commands that inherit knife" do - shared_examples_for "a key create command" do - let(:stderr) { StringIO.new } - let(:params) { [] } - let(:service_object) { instance_double(Chef::Knife::KeyCreate) } - let(:command) do - c = described_class.new([]) - c.ui.config[:disable_editing] = true - allow(c.ui).to receive(:stderr).and_return(stderr) - allow(c.ui).to receive(:stdout).and_return(stderr) - allow(c).to receive(:show_usage) - c - end - - context "after apply_params! is called with valid args" do - let(:params) { ["charmander"] } - before do - command.apply_params!(params) - end - - context "when the service object is called" do - it "creates a new instance of Chef::Knife::KeyCreate with the correct args" do - expect(Chef::Knife::KeyCreate).to receive(:new) - .with("charmander", command.actor_field_name, command.ui, command.config) - .and_return(service_object) - command.service_object - end - end # when the service object is called - end # after apply_params! is called with valid args - end # a key create command - - describe Chef::Knife::UserKeyCreate do - it_should_behave_like "a key create command" - # defined in key_helper.rb - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyCreate) } - let(:params) { ["charmander"] } - end - end - - describe Chef::Knife::ClientKeyCreate do - it_should_behave_like "a key create command" - # defined in key_helper.rb - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyCreate) } - let(:params) { ["charmander"] } - end - end -end - -describe Chef::Knife::KeyCreate do - let(:public_key) do - "-----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvPo+oNPB7uuNkws0fC02 -KxSwdyqPLu0fhI1pOweNKAZeEIiEz2PkybathHWy8snSXGNxsITkf3eyvIIKa8OZ -WrlqpI3yv/5DOP8HTMCxnFuMJQtDwMcevlqebX4bCxcByuBpNYDcAHjjfLGSfMjn -E5lZpgYWwnpic4kSjYcL9ORK9nYvlWV9P/kCYmRhIjB4AhtpWRiOfY/TKi3P2LxT -IjSmiN/ihHtlhV/VSnBJ5PzT/lRknlrJ4kACoz7Pq9jv+aAx5ft/xE9yDa2DYs0q -Tfuc9dUYsFjptWYrV6pfEQ+bgo1OGBXORBFcFL+2D7u9JYquKrMgosznHoEkQNLo -0wIDAQAB ------END PUBLIC KEY-----" - end - let(:config) { {} } - let(:actor) { "charmander" } - let(:ui) { instance_double("Chef::Knife::UI") } - - shared_examples_for "key create run command" do - let(:key_create_object) do - described_class.new(actor, actor_field_name, ui, config) - end - - context "when public_key and key_name weren't passed" do - it "raises a Chef::Exceptions::KeyCommandInputError with the proper error message" do - expect { key_create_object.run }.to raise_error(Chef::Exceptions::KeyCommandInputError, key_create_object.public_key_or_key_name_error_msg) - end - end - - context "when the command is run" do - let(:expected_hash) do - { - actor_field_name => "charmander", - } - end - - before do - allow(File).to receive(:read).and_return(public_key) - allow(File).to receive(:expand_path) - - allow(key_create_object).to receive(:output_private_key_to_file) - allow(key_create_object).to receive(:display_private_key) - allow(key_create_object).to receive(:edit_hash).and_return(expected_hash) - allow(key_create_object).to receive(:create_key_from_hash).and_return(Chef::Key.from_hash(expected_hash)) - allow(key_create_object).to receive(:display_info) - end - - context "when a valid hash is passed" do - let(:key_name) { "charmander-key" } - let(:valid_expiration_date) { "2020-12-24T21:00:00Z" } - let(:expected_hash) do - { - actor_field_name => "charmander", - "public_key" => public_key, - "expiration_date" => valid_expiration_date, - "key_name" => key_name, - } - end - before do - key_create_object.config[:public_key] = "public_key_path" - key_create_object.config[:expiration_Date] = valid_expiration_date, - key_create_object.config[:key_name] = key_name - end - - it "creates the proper hash" do - expect(key_create_object).to receive(:create_key_from_hash).with(expected_hash) - key_create_object.run - end - end - - context "when public_key is passed" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "public_key" => public_key, - } - end - before do - key_create_object.config[:public_key] = "public_key_path" - end - - it "calls File.expand_path with the public_key input" do - expect(File).to receive(:expand_path).with("public_key_path") - key_create_object.run - end - end # when public_key is passed - - context "when public_key isn't passed and key_name is" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "name" => "charmander-key", - "create_key" => true, - } - end - before do - key_create_object.config[:key_name] = "charmander-key" - end - - it "should set create_key to true" do - expect(key_create_object).to receive(:create_key_from_hash).with(expected_hash) - key_create_object.run - end - end - - context "when the server returns a private key" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "public_key" => public_key, - "private_key" => "super_private", - } - end - - before do - key_create_object.config[:public_key] = "public_key_path" - end - - context "when file is not passed" do - it "calls display_private_key with the private_key" do - expect(key_create_object).to receive(:display_private_key).with("super_private") - key_create_object.run - end - end - - context "when file is passed" do - before do - key_create_object.config[:file] = "/fake/file" - end - - it "calls output_private_key_to_file with the private_key" do - expect(key_create_object).to receive(:output_private_key_to_file).with("super_private") - key_create_object.run - end - end - end # when the server returns a private key - end # when the command is run - end # key create run command" - - context "when actor_field_name is 'user'" do - it_should_behave_like "key create run command" do - let(:actor_field_name) { "user" } - end - end - - context "when actor_field_name is 'client'" do - it_should_behave_like "key create run command" do - let(:actor_field_name) { "client" } - end - end -end diff --git a/spec/unit/knife/key_delete_spec.rb b/spec/unit/knife/key_delete_spec.rb deleted file mode 100644 index fd39c7381a..0000000000 --- a/spec/unit/knife/key_delete_spec.rb +++ /dev/null @@ -1,133 +0,0 @@ -# -# Author:: Tyler Cloke (<tyler@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 "spec_helper" -require "chef/knife/user_key_delete" -require "chef/knife/client_key_delete" -require "chef/knife/key_delete" -require "chef/key" - -describe "key delete commands that inherit knife" do - shared_examples_for "a key delete command" do - let(:stderr) { StringIO.new } - let(:params) { [] } - let(:service_object) { instance_double(Chef::Knife::KeyDelete) } - let(:command) do - c = described_class.new([]) - c.ui.config[:disable_editing] = true - allow(c.ui).to receive(:stderr).and_return(stderr) - allow(c.ui).to receive(:stdout).and_return(stderr) - allow(c).to receive(:show_usage) - c - end - - context "after apply_params! is called with valid args" do - let(:params) { %w{charmander charmander-key} } - before do - command.apply_params!(params) - end - - context "when the service object is called" do - it "creates a new instance of Chef::Knife::KeyDelete with the correct args" do - expect(Chef::Knife::KeyDelete).to receive(:new) - .with("charmander-key", "charmander", command.actor_field_name, command.ui) - .and_return(service_object) - command.service_object - end - end # when the service object is called - end # after apply_params! is called with valid args - end # a key delete command - - describe Chef::Knife::UserKeyDelete do - it_should_behave_like "a key delete command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command with a keyname as the second arg" - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyDelete) } - let(:params) { %w{charmander charmander-key} } - end - end - - describe Chef::Knife::ClientKeyDelete do - it_should_behave_like "a key delete command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command with a keyname as the second arg" - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyDelete) } - let(:params) { %w{charmander charmander-key} } - end - end -end - -describe Chef::Knife::KeyDelete do - let(:actor) { "charmander" } - let(:keyname) { "charmander-key" } - let(:ui) { instance_double("Chef::Knife::UI") } - - shared_examples_for "key delete run command" do - let(:key_delete_object) do - described_class.new(keyname, actor, actor_field_name, ui) - end - - before do - allow_any_instance_of(Chef::Key).to receive(:destroy) - allow(key_delete_object).to receive(:print_destroyed) - allow(key_delete_object).to receive(:confirm!) - end - - context "when the command is run" do - it "calls Chef::Key.new with the proper input" do - expect(Chef::Key).to receive(:new).with(actor, actor_field_name).and_call_original - key_delete_object.run - end - - it "calls name on the Chef::Key instance with the proper input" do - expect_any_instance_of(Chef::Key).to receive(:name).with(keyname) - key_delete_object.run - end - - it "calls destroy on the Chef::Key instance" do - expect_any_instance_of(Chef::Key).to receive(:destroy).once - key_delete_object.run - end - - it "calls confirm!" do - expect(key_delete_object).to receive(:confirm!) - key_delete_object.run - end - - it "calls print_destroyed" do - expect(key_delete_object).to receive(:print_destroyed) - key_delete_object.run - end - end # when the command is run - - end # key delete run command - - context "when actor_field_name is 'user'" do - it_should_behave_like "key delete run command" do - let(:actor_field_name) { "user" } - end - end - - context "when actor_field_name is 'client'" do - it_should_behave_like "key delete run command" do - let(:actor_field_name) { "client" } - end - end -end diff --git a/spec/unit/knife/key_edit_spec.rb b/spec/unit/knife/key_edit_spec.rb deleted file mode 100644 index b42503af59..0000000000 --- a/spec/unit/knife/key_edit_spec.rb +++ /dev/null @@ -1,264 +0,0 @@ -# -# Author:: Tyler Cloke (<tyler@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 "spec_helper" -require "chef/knife/user_key_edit" -require "chef/knife/client_key_edit" -require "chef/knife/key_edit" -require "chef/key" - -describe "key edit commands that inherit knife" do - shared_examples_for "a key edit command" do - let(:stderr) { StringIO.new } - let(:params) { [] } - let(:service_object) { instance_double(Chef::Knife::KeyEdit) } - let(:command) do - c = described_class.new([]) - c.ui.config[:disable_editing] = true - allow(c.ui).to receive(:stderr).and_return(stderr) - allow(c.ui).to receive(:stdout).and_return(stderr) - allow(c).to receive(:show_usage) - c - end - - context "after apply_params! is called with valid args" do - let(:params) { %w{charmander charmander-key} } - before do - command.apply_params!(params) - end - - context "when the service object is called" do - it "creates a new instance of Chef::Knife::KeyEdit with the correct args" do - expect(Chef::Knife::KeyEdit).to receive(:new) - .with("charmander-key", "charmander", command.actor_field_name, command.ui, command.config) - .and_return(service_object) - command.service_object - end - end # when the service object is called - end # after apply_params! is called with valid args - end # a key edit command - - describe Chef::Knife::UserKeyEdit do - it_should_behave_like "a key edit command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command with a keyname as the second arg" - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyEdit) } - let(:params) { %w{charmander charmander-key} } - end - end - - describe Chef::Knife::ClientKeyEdit do - it_should_behave_like "a key edit command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command with a keyname as the second arg" - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyEdit) } - let(:params) { %w{charmander charmander-key} } - end - end -end - -describe Chef::Knife::KeyEdit do - let(:public_key) do - "-----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvPo+oNPB7uuNkws0fC02 -KxSwdyqPLu0fhI1pOweNKAZeEIiEz2PkybathHWy8snSXGNxsITkf3eyvIIKa8OZ -WrlqpI3yv/5DOP8HTMCxnFuMJQtDwMcevlqebX4bCxcByuBpNYDcAHjjfLGSfMjn -E5lZpgYWwnpic4kSjYcL9ORK9nYvlWV9P/kCYmRhIjB4AhtpWRiOfY/TKi3P2LxT -IjSmiN/ihHtlhV/VSnBJ5PzT/lRknlrJ4kACoz7Pq9jv+aAx5ft/xE9yDa2DYs0q -Tfuc9dUYsFjptWYrV6pfEQ+bgo1OGBXORBFcFL+2D7u9JYquKrMgosznHoEkQNLo -0wIDAQAB ------END PUBLIC KEY-----" - end - let(:config) { {} } - let(:actor) { "charmander" } - let(:keyname) { "charmander-key" } - let(:ui) { instance_double("Chef::Knife::UI") } - - shared_examples_for "key edit run command" do - let(:key_edit_object) do - described_class.new(keyname, actor, actor_field_name, ui, config) - end - - context "when the command is run" do - let(:expected_hash) do - { - actor_field_name => "charmander", - } - end - let(:new_keyname) { "charizard-key" } - - before do - allow(File).to receive(:read).and_return(public_key) - allow(File).to receive(:expand_path) - - allow(key_edit_object).to receive(:output_private_key_to_file) - allow(key_edit_object).to receive(:display_private_key) - allow(key_edit_object).to receive(:edit_hash).and_return(expected_hash) - allow(key_edit_object).to receive(:display_info) - end - - context "when public_key and create_key are passed" do - before do - key_edit_object.config[:public_key] = "public_key_path" - key_edit_object.config[:create_key] = true - end - - it "raises a Chef::Exceptions::KeyCommandInputError with the proper error message" do - expect { key_edit_object.run }.to raise_error(Chef::Exceptions::KeyCommandInputError, key_edit_object.public_key_and_create_key_error_msg) - end - end - - context "when key_name is passed" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "name" => new_keyname, - } - end - before do - key_edit_object.config[:key_name] = new_keyname - allow_any_instance_of(Chef::Key).to receive(:update) - end - - it "update_key_from_hash gets passed a hash with new key name" do - expect(key_edit_object).to receive(:update_key_from_hash).with(expected_hash).and_return(Chef::Key.from_hash(expected_hash)) - key_edit_object.run - end - - it "Chef::Key.update is passed a string containing the original keyname" do - expect_any_instance_of(Chef::Key).to receive(:update).with(/#{keyname}/).and_return(Chef::Key.from_hash(expected_hash)) - key_edit_object.run - end - - it "Chef::Key.update is not passed a string containing the new keyname" do - expect_any_instance_of(Chef::Key).not_to receive(:update).with(/#{new_keyname}/) - allow_any_instance_of(Chef::Key).to receive(:update).and_return(Chef::Key.from_hash(expected_hash)) - key_edit_object.run - end - end - - context "when public_key, key_name, and expiration_date are passed" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "public_key" => public_key, - "name" => new_keyname, - "expiration_date" => "infinity", - } - end - before do - key_edit_object.config[:public_key] = "this-public-key" - key_edit_object.config[:key_name] = new_keyname - key_edit_object.config[:expiration_date] = "infinity" - allow(key_edit_object).to receive(:update_key_from_hash).and_return(Chef::Key.from_hash(expected_hash)) - end - - it "passes the right hash to update_key_from_hash" do - expect(key_edit_object).to receive(:update_key_from_hash).with(expected_hash) - key_edit_object.run - end - end - - context "when create_key is passed" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "create_key" => true, - } - end - - before do - key_edit_object.config[:create_key] = true - allow(key_edit_object).to receive(:update_key_from_hash).and_return(Chef::Key.from_hash(expected_hash)) - end - - it "passes the right hash to update_key_from_hash" do - expect(key_edit_object).to receive(:update_key_from_hash).with(expected_hash) - key_edit_object.run - end - end - - context "when public_key is passed" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "public_key" => public_key, - } - end - before do - allow(key_edit_object).to receive(:update_key_from_hash).and_return(Chef::Key.from_hash(expected_hash)) - key_edit_object.config[:public_key] = "public_key_path" - end - - it "calls File.expand_path with the public_key input" do - expect(File).to receive(:expand_path).with("public_key_path") - key_edit_object.run - end - end # when public_key is passed - - context "when the server returns a private key" do - let(:expected_hash) do - { - actor_field_name => "charmander", - "public_key" => public_key, - "private_key" => "super_private", - } - end - - before do - allow(key_edit_object).to receive(:update_key_from_hash).and_return(Chef::Key.from_hash(expected_hash)) - key_edit_object.config[:public_key] = "public_key_path" - end - - context "when file is not passed" do - it "calls display_private_key with the private_key" do - expect(key_edit_object).to receive(:display_private_key).with("super_private") - key_edit_object.run - end - end - - context "when file is passed" do - before do - key_edit_object.config[:file] = "/fake/file" - end - - it "calls output_private_key_to_file with the private_key" do - expect(key_edit_object).to receive(:output_private_key_to_file).with("super_private") - key_edit_object.run - end - end - end # when the server returns a private key - - end # when the command is run - - end # key edit run command - - context "when actor_field_name is 'user'" do - it_should_behave_like "key edit run command" do - let(:actor_field_name) { "user" } - end - end - - context "when actor_field_name is 'client'" do - it_should_behave_like "key edit run command" do - let(:actor_field_name) { "client" } - end - end -end diff --git a/spec/unit/knife/key_helper.rb b/spec/unit/knife/key_helper.rb deleted file mode 100644 index 6dbfb567f4..0000000000 --- a/spec/unit/knife/key_helper.rb +++ /dev/null @@ -1,74 +0,0 @@ -# -# Author:: Tyler Cloke (<tyler@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 "spec_helper" - -shared_examples_for "a knife key command" do - let(:stderr) { StringIO.new } - let(:params) { [] } - let(:command) do - c = described_class.new([]) - c.ui.config[:disable_editing] = true - allow(c.ui).to receive(:stderr).and_return(stderr) - allow(c.ui).to receive(:stdout).and_return(stderr) - allow(c).to receive(:show_usage) - c - end - - context "before apply_params! is called" do - context "when apply_params! is called with invalid args" do - it "shows the usage" do - expect(command).to receive(:show_usage) - expect { command.apply_params!(params) }.to exit_with_code(1) - end - - it "outputs the proper error" do - expect { command.apply_params!(params) }.to exit_with_code(1) - expect(stderr.string).to include(command.actor_missing_error) - end - - it "exits 1" do - expect { command.apply_params!(params) }.to exit_with_code(1) - end - end - end # before apply_params! is called - - context "after apply_params! is called with valid args" do - let(:params) { ["charmander"] } - before do - command.apply_params!(params) - end - - it "properly defines the actor" do - expect(command.actor).to eq("charmander") - end - end # after apply_params! is called with valid args - - context "when the command is run" do - before do - allow(command).to receive(:service_object).and_return(service_object) - allow(command).to receive(:name_args).and_return(["charmander"]) - end - - context "when the command is successful" do - before do - expect(service_object).to receive(:run) - end - end - end -end # a knife key command diff --git a/spec/unit/knife/key_list_spec.rb b/spec/unit/knife/key_list_spec.rb deleted file mode 100644 index 51ed73b64f..0000000000 --- a/spec/unit/knife/key_list_spec.rb +++ /dev/null @@ -1,216 +0,0 @@ -# -# Author:: Tyler Cloke (<tyler@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 "spec_helper" -require "chef/knife/user_key_list" -require "chef/knife/client_key_list" -require "chef/knife/key_list" -require "chef/key" - -describe "key list commands that inherit knife" do - shared_examples_for "a key list command" do - let(:stderr) { StringIO.new } - let(:params) { [] } - let(:service_object) { instance_double(Chef::Knife::KeyList) } - let(:command) do - c = described_class.new([]) - c.ui.config[:disable_editing] = true - allow(c.ui).to receive(:stderr).and_return(stderr) - allow(c.ui).to receive(:stdout).and_return(stderr) - allow(c).to receive(:show_usage) - c - end - - context "after apply_params! is called with valid args" do - let(:params) { ["charmander"] } - before do - command.apply_params!(params) - end - - context "when the service object is called" do - it "creates a new instance of Chef::Knife::KeyList with the correct args" do - expect(Chef::Knife::KeyList).to receive(:new) - .with("charmander", command.list_method, command.ui, command.config) - .and_return(service_object) - command.service_object - end - end # when the service object is called - end # after apply_params! is called with valid args - end # a key list command - - describe Chef::Knife::UserKeyList do - it_should_behave_like "a key list command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyList) } - let(:params) { ["charmander"] } - end - end - - describe Chef::Knife::ClientKeyList do - it_should_behave_like "a key list command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyList) } - let(:params) { ["charmander"] } - end - end -end - -describe Chef::Knife::KeyList do - let(:config) { {} } - let(:actor) { "charmander" } - let(:ui) { instance_double("Chef::Knife::UI") } - - shared_examples_for "key list run command" do - let(:key_list_object) do - described_class.new(actor, list_method, ui, config) - end - - before do - allow(Chef::Key).to receive(list_method).and_return(http_response) - allow(key_list_object).to receive(:display_info) - # simply pass the string though that colorize takes in - allow(key_list_object).to receive(:colorize).with(kind_of(String)) do |input| - input - end - end - - context "when only_expired and only_non_expired were both passed" do - before do - key_list_object.config[:only_expired] = true - key_list_object.config[:only_non_expired] = true - end - - it "raises a Chef::Exceptions::KeyCommandInputError with the proper error message" do - expect { key_list_object.run }.to raise_error(Chef::Exceptions::KeyCommandInputError, key_list_object.expired_and_non_expired_msg) - end - end - - context "when the command is run" do - before do - key_list_object.config[:only_expired] = false - key_list_object.config[:only_non_expired] = false - key_list_object.config[:with_details] = false - end - - it "calls Chef::Key with the proper list command and input" do - expect(Chef::Key).to receive(list_method).with(actor) - key_list_object.run - end - - it "displays all the keys" do - expect(key_list_object).to receive(:display_info).with(/non-expired/).twice - expect(key_list_object).to receive(:display_info).with(/out-of-date/).once - key_list_object.run - end - - context "when only_expired is called" do - before do - key_list_object.config[:only_expired] = true - end - - it "excludes displaying non-expired keys" do - expect(key_list_object).to receive(:display_info).with(/non-expired/).exactly(0).times - key_list_object.run - end - - it "displays the expired keys" do - expect(key_list_object).to receive(:display_info).with(/out-of-date/).once - key_list_object.run - end - end # when only_expired is called - - context "when only_non_expired is called" do - before do - key_list_object.config[:only_non_expired] = true - end - - it "excludes displaying expired keys" do - expect(key_list_object).to receive(:display_info).with(/out-of-date/).exactly(0).times - key_list_object.run - end - - it "displays the non-expired keys" do - expect(key_list_object).to receive(:display_info).with(/non-expired/).twice - key_list_object.run - end - end # when only_expired is called - - context "when with_details is false" do - before do - key_list_object.config[:with_details] = false - end - - it "does not display the uri" do - expect(key_list_object).to receive(:display_info).with(/https/).exactly(0).times - key_list_object.run - end - - it "does not display the expired status" do - expect(key_list_object).to receive(:display_info).with(/\(expired\)/).exactly(0).times - key_list_object.run - end - end # when with_details is false - - context "when with_details is true" do - before do - key_list_object.config[:with_details] = true - end - - it "displays the uri" do - expect(key_list_object).to receive(:display_info).with(/https/).exactly(3).times - key_list_object.run - end - - it "displays the expired status" do - expect(key_list_object).to receive(:display_info).with(/\(expired\)/).once - key_list_object.run - end - end # when with_details is true - - end # when the command is run - - end # key list run command - - context "when list_method is :list_by_user" do - it_should_behave_like "key list run command" do - let(:list_method) { :list_by_user } - let(:http_response) do - [ - { "uri" => "https://api.opscode.piab/users/charmander/keys/non-expired1", "name" => "non-expired1", "expired" => false }, - { "uri" => "https://api.opscode.piab/users/charmander/keys/non-expired2", "name" => "non-expired2", "expired" => false }, - { "uri" => "https://api.opscode.piab/users/mary/keys/out-of-date", "name" => "out-of-date", "expired" => true }, - ] - end - end - end - - context "when list_method is :list_by_client" do - it_should_behave_like "key list run command" do - let(:list_method) { :list_by_client } - let(:http_response) do - [ - { "uri" => "https://api.opscode.piab/organizations/pokemon/clients/charmander/keys/non-expired1", "name" => "non-expired1", "expired" => false }, - { "uri" => "https://api.opscode.piab/organizations/pokemon/clients/charmander/keys/non-expired2", "name" => "non-expired2", "expired" => false }, - { "uri" => "https://api.opscode.piab/organizations/pokemon/clients/mary/keys/out-of-date", "name" => "out-of-date", "expired" => true }, - ] - end - end - end -end diff --git a/spec/unit/knife/key_show_spec.rb b/spec/unit/knife/key_show_spec.rb deleted file mode 100644 index 6d1ca2ccc7..0000000000 --- a/spec/unit/knife/key_show_spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -# -# Author:: Tyler Cloke (<tyler@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 "spec_helper" -require "chef/knife/user_key_show" -require "chef/knife/client_key_show" -require "chef/knife/key_show" -require "chef/key" - -describe "key show commands that inherit knife" do - shared_examples_for "a key show command" do - let(:stderr) { StringIO.new } - let(:params) { [] } - let(:service_object) { instance_double(Chef::Knife::KeyShow) } - let(:command) do - c = described_class.new([]) - c.ui.config[:disable_editing] = true - allow(c.ui).to receive(:stderr).and_return(stderr) - allow(c.ui).to receive(:stdout).and_return(stderr) - allow(c).to receive(:show_usage) - c - end - - context "after apply_params! is called with valid args" do - let(:params) { %w{charmander charmander-key} } - before do - command.apply_params!(params) - end - - context "when the service object is called" do - it "creates a new instance of Chef::Knife::KeyShow with the correct args" do - expect(Chef::Knife::KeyShow).to receive(:new) - .with("charmander-key", "charmander", command.load_method, command.ui) - .and_return(service_object) - command.service_object - end - end # when the service object is called - end # after apply_params! is called with valid args - end # a key show command - - describe Chef::Knife::UserKeyShow do - it_should_behave_like "a key show command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command with a keyname as the second arg" - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyShow) } - let(:params) { %w{charmander charmander-key} } - end - end - - describe Chef::Knife::ClientKeyShow do - it_should_behave_like "a key show command" - # defined in key_helpers.rb - it_should_behave_like "a knife key command with a keyname as the second arg" - it_should_behave_like "a knife key command" do - let(:service_object) { instance_double(Chef::Knife::KeyShow) } - let(:params) { %w{charmander charmander-key} } - end - end -end - -describe Chef::Knife::KeyShow do - let(:actor) { "charmander" } - let(:keyname) { "charmander" } - let(:ui) { instance_double("Chef::Knife::UI") } - let(:expected_hash) do - { - actor_field_name => "charmander", - "name" => "charmander-key", - "public_key" => "some-public-key", - "expiration_date" => "infinity", - } - end - - shared_examples_for "key show run command" do - let(:key_show_object) do - described_class.new(keyname, actor, load_method, ui) - end - - before do - allow(key_show_object).to receive(:display_output) - allow(Chef::Key).to receive(load_method).and_return(Chef::Key.from_hash(expected_hash)) - end - - context "when the command is run" do - it "loads the key using the proper method and args" do - expect(Chef::Key).to receive(load_method).with(actor, keyname) - key_show_object.run - end - - it "displays the key" do - expect(key_show_object).to receive(:display_output) - key_show_object.run - end - end - end - - context "when load_method is :load_by_user" do - it_should_behave_like "key show run command" do - let(:load_method) { :load_by_user } - let(:actor_field_name) { "user" } - end - end - - context "when load_method is :load_by_client" do - it_should_behave_like "key show run command" do - let(:load_method) { :load_by_client } - let(:actor_field_name) { "user" } - end - end -end diff --git a/spec/unit/knife/node_bulk_delete_spec.rb b/spec/unit/knife/node_bulk_delete_spec.rb deleted file mode 100644 index e23f286999..0000000000 --- a/spec/unit/knife/node_bulk_delete_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::NodeBulkDelete do - before(:each) do - Chef::Log.logger = Logger.new(StringIO.new) - - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeBulkDelete.new - @knife.name_args = ["."] - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - allow(@knife.ui).to receive(:confirm).and_return(true) - @nodes = {} - %w{adam brent jacob}.each do |node_name| - @nodes[node_name] = "http://localhost:4000/nodes/#{node_name}" - end - end - - describe "when creating the list of nodes" do - it "fetches the node list" do - expected = @nodes.inject({}) do |inflatedish, (name, uri)| - inflatedish[name] = Chef::Node.new.tap { |n| n.name(name) } - inflatedish - end - expect(Chef::Node).to receive(:list).and_return(@nodes) - # I hate not having == defined for anything :( - actual = @knife.all_nodes - expect(actual.keys).to match_array(expected.keys) - expect(actual.values.map(&:name)).to match_array(%w{adam brent jacob}) - end - end - - describe "run" do - before do - @inflatedish_list = @nodes.keys.inject({}) do |nodes_by_name, name| - node = Chef::Node.new - node.name(name) - allow(node).to receive(:destroy).and_return(true) - nodes_by_name[name] = node - nodes_by_name - end - allow(@knife).to receive(:all_nodes).and_return(@inflatedish_list) - end - - it "should print the nodes you are about to delete" do - @knife.run - expect(@stdout.string).to match(/#{@knife.ui.list(@nodes.keys.sort, :columns_down)}/) - end - - it "should confirm you really want to delete them" do - expect(@knife.ui).to receive(:confirm) - @knife.run - end - - it "should delete each node" do - @inflatedish_list.each_value do |n| - expect(n).to receive(:destroy) - end - @knife.run - end - - it "should only delete nodes that match the regex" do - @knife.name_args = ["adam"] - expect(@inflatedish_list["adam"]).to receive(:destroy) - expect(@inflatedish_list["brent"]).not_to receive(:destroy) - expect(@inflatedish_list["jacob"]).not_to receive(:destroy) - @knife.run - end - - it "should exit if the regex is not provided" do - @knife.name_args = [] - expect { @knife.run }.to raise_error(SystemExit) - end - - end -end diff --git a/spec/unit/knife/node_delete_spec.rb b/spec/unit/knife/node_delete_spec.rb deleted file mode 100644 index e6c677c041..0000000000 --- a/spec/unit/knife/node_delete_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::NodeDelete do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeDelete.new - @knife.config = { - print_after: nil, - } - @knife.name_args = %w{ adam ben } - allow(@knife).to receive(:output).and_return(true) - allow(@knife).to receive(:confirm).and_return(true) - - @adam_node = Chef::Node.new - @ben_node = Chef::Node.new - allow(@ben_node).to receive(:destroy).and_return(true) - allow(@adam_node).to receive(:destroy).and_return(true) - allow(Chef::Node).to receive(:load).with("adam").and_return(@adam_node) - allow(Chef::Node).to receive(:load).with("ben").and_return(@ben_node) - - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should confirm that you want to delete" do - expect(@knife).to receive(:confirm) - @knife.run - end - - it "should load the nodes" do - expect(Chef::Node).to receive(:load).with("adam").and_return(@adam_node) - expect(Chef::Node).to receive(:load).with("ben").and_return(@ben_node) - @knife.run - end - - it "should delete the nodes" do - expect(@adam_node).to receive(:destroy).and_return(@adam_node) - expect(@ben_node).to receive(:destroy).and_return(@ben_node) - @knife.run - end - - it "should not print the node" do - expect(@knife).not_to receive(:output).with("poop") - @knife.run - end - - describe "with -p or --print-after" do - it "should pretty print the node, formatted for display" do - @knife.config[:print_after] = true - expect(@knife).to receive(:format_for_display).with(@adam_node).and_return("adam") - expect(@knife).to receive(:format_for_display).with(@ben_node).and_return("ben") - expect(@knife).to receive(:output).with("adam") - expect(@knife).to receive(:output).with("ben") - @knife.run - end - end - end -end diff --git a/spec/unit/knife/node_edit_spec.rb b/spec/unit/knife/node_edit_spec.rb deleted file mode 100644 index 7b2ebb5b2c..0000000000 --- a/spec/unit/knife/node_edit_spec.rb +++ /dev/null @@ -1,116 +0,0 @@ -# -# 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. -# - -require "spec_helper" -Chef::Knife::NodeEdit.load_deps - -describe Chef::Knife::NodeEdit do - - # helper to convert the view from Chef objects into Ruby objects representing JSON - def deserialized_json_view - Chef::JSONCompat.from_json(Chef::JSONCompat.to_json_pretty(@knife.node_editor.send(:view))) - end - - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeEdit.new - @knife.config = { - editor: "cat", - attribute: nil, - print_after: nil, - } - @knife.name_args = [ "adam" ] - @node = Chef::Node.new - end - - it "should load the node" do - expect(Chef::Node).to receive(:load).with("adam").and_return(@node) - @knife.node - end - - describe "after loading the node" do - before do - @knife.config[:all_attributes] = false - - allow(@knife).to receive(:node).and_return(@node) - @node.automatic_attrs = { go: :away } - @node.default_attrs = { hide: :me } - @node.override_attrs = { dont: :show } - @node.normal_attrs = { do_show: :these } - @node.chef_environment("prod") - @node.run_list("recipe[foo]") - end - - it "creates a view of the node without attributes from roles or ohai" do - actual = deserialized_json_view - expect(actual).not_to have_key("automatic") - expect(actual).not_to have_key("override") - expect(actual).not_to have_key("default") - expect(actual["normal"]).to eq({ "do_show" => "these" }) - expect(actual["run_list"]).to eq(["recipe[foo]"]) - expect(actual["chef_environment"]).to eq("prod") - end - - it "shows the extra attributes when given the --all option" do - @knife.config[:all_attributes] = true - - actual = deserialized_json_view - expect(actual["automatic"]).to eq({ "go" => "away" }) - expect(actual["override"]).to eq({ "dont" => "show" }) - expect(actual["default"]).to eq({ "hide" => "me" }) - expect(actual["normal"]).to eq({ "do_show" => "these" }) - expect(actual["run_list"]).to eq(["recipe[foo]"]) - expect(actual["chef_environment"]).to eq("prod") - end - - it "does not consider unedited data updated" do - view = deserialized_json_view - @knife.node_editor.send(:apply_updates, view) - expect(@knife.node_editor).not_to be_updated - end - - it "considers edited data updated" do - view = deserialized_json_view - view["run_list"] << "role[fuuu]" - @knife.node_editor.send(:apply_updates, view) - expect(@knife.node_editor).to be_updated - end - - end - - describe "edit_node" do - - before do - allow(@knife).to receive(:node).and_return(@node) - end - - let(:subject) { @knife.node_editor.edit_node } - - it "raises an exception when editing is disabled" do - @knife.config[:disable_editing] = true - expect { subject }.to raise_error(SystemExit) - end - - it "raises an exception when the editor is not set" do - @knife.config[:editor] = nil - expect { subject }.to raise_error(SystemExit) - end - - end - -end diff --git a/spec/unit/knife/node_environment_set_spec.rb b/spec/unit/knife/node_environment_set_spec.rb deleted file mode 100644 index 6a6d48cc2f..0000000000 --- a/spec/unit/knife/node_environment_set_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -# -# Author:: Jimmy McCrory (<jimmy.mccrory@gmail.com>) -# Copyright:: Copyright 2014-2016, Jimmy McCrory -# 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 "spec_helper" - -describe Chef::Knife::NodeEnvironmentSet do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeEnvironmentSet.new - @knife.name_args = %w{adam bar} - allow(@knife).to receive(:output).and_return(true) - @node = Chef::Node.new - @node.name("knifetest-node") - @node.chef_environment << "foo" - allow(@node).to receive(:save).and_return(true) - allow(Chef::Node).to receive(:load).and_return(@node) - end - - describe "run" do - it "should load the node" do - expect(Chef::Node).to receive(:load).with("adam") - @knife.run - end - - it "should update the environment" do - @knife.run - expect(@node.chef_environment).to eq("bar") - end - - it "should save the node" do - expect(@node).to receive(:save) - @knife.run - end - - it "sets the environment to config for display" do - @knife.run - expect(@knife.config[:environment]).to eq("bar") - end - - it "should print the environment" do - expect(@knife).to receive(:output).and_return(true) - @knife.run - end - - end -end diff --git a/spec/unit/knife/node_from_file_spec.rb b/spec/unit/knife/node_from_file_spec.rb deleted file mode 100644 index 00d6dd5d1a..0000000000 --- a/spec/unit/knife/node_from_file_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -Chef::Knife::NodeFromFile.load_deps - -describe Chef::Knife::NodeFromFile do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeFromFile.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "adam.rb" ] - allow(@knife).to receive(:output).and_return(true) - allow(@knife).to receive(:confirm).and_return(true) - @node = Chef::Node.new - allow(@node).to receive(:save) - allow(@knife.loader).to receive(:load_from).and_return(@node) - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should load from a file" do - expect(@knife.loader).to receive(:load_from).with("nodes", "adam.rb").and_return(@node) - @knife.run - end - - it "should not print the Node" do - expect(@knife).not_to receive(:output) - @knife.run - end - - describe "with -p or --print-after" do - it "should print the Node" do - @knife.config[:print_after] = true - expect(@knife).to receive(:output) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/node_list_spec.rb b/spec/unit/knife/node_list_spec.rb deleted file mode 100644 index d594fffc14..0000000000 --- a/spec/unit/knife/node_list_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::NodeList do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - Chef::Config[:environment] = nil # reset this value each time, as it is not reloaded - @knife = Chef::Knife::NodeList.new - allow(@knife).to receive(:output).and_return(true) - @list = { - "foo" => "http://example.com/foo", - "bar" => "http://example.com/foo", - } - allow(Chef::Node).to receive(:list).and_return(@list) - allow(Chef::Node).to receive(:list_by_environment).and_return(@list) - end - - describe "run" do - it "should list all of the nodes if -E is not specified" do - expect(Chef::Node).to receive(:list).and_return(@list) - @knife.run - end - - it "should pretty print the list" do - expect(Chef::Node).to receive(:list).and_return(@list) - expect(@knife).to receive(:output).with(%w{bar foo}) - @knife.run - end - - it "should list nodes in the specific environment if -E ENVIRONMENT is specified" do - Chef::Config[:environment] = "prod" - expect(Chef::Node).to receive(:list_by_environment).with("prod").and_return(@list) - @knife.run - end - - describe "with -w or --with-uri" do - it "should pretty print the hash" do - @knife.config[:with_uri] = true - expect(Chef::Node).to receive(:list).and_return(@list) - expect(@knife).to receive(:output).with(@list) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/node_policy_set_spec.rb b/spec/unit/knife/node_policy_set_spec.rb deleted file mode 100644 index 40b1d2617d..0000000000 --- a/spec/unit/knife/node_policy_set_spec.rb +++ /dev/null @@ -1,122 +0,0 @@ -# -# Author:: Piyush Awasthi (<piyush.awasthi@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 "spec_helper" - -describe Chef::Knife::NodePolicySet do - let(:node) do - node = Chef::Node.new - node.name("adam") - node.run_list = ["role[base]"] - node - end - - let(:knife) do - Chef::Log.logger = Logger.new(StringIO.new) - Chef::Config[:knife][:bootstrap_template] = bootstrap_template unless bootstrap_template.nil? - knife_obj = Chef::Knife::NodePolicySet.new(bootstrap_cli_options) - knife_obj.merge_configs - allow(knife_obj.ui).to receive(:stderr).and_return(stderr) - allow(knife_obj).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(false) - knife_obj - end - - let(:stderr) { StringIO.new } - let(:bootstrap_template) { nil } - let(:bootstrap_cli_options) { [ ] } - - describe "#run" do - context "when node_name is not given" do - let(:bootstrap_cli_options) { %w{ } } - it "returns an error that you must specify a node name" do - expect { knife.send(:validate_node!) }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: You must specify a node name") - end - end - - context "when node is given" do - let(:bootstrap_cli_options) { %w{ adam staging my-app } } - it "should load the node" do - expect(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node) - allow(node).to receive(:save).and_return(true) - knife.run - end - end - - context "when node not saved" do - let(:bootstrap_cli_options) { %w{ adam staging my-app } } - it "returns an error node not updated successfully" do - allow(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node) - allow(node).to receive(:save).and_return(false) - knife.run - expect(stderr.string.strip).to eq("Error in updating node #{node.name}") - end - end - - context "when the policy is set successfully on the node" do - let(:bootstrap_cli_options) { %w{ adam staging my-app } } - it "returns node updated successfully" do - allow(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node) - allow(node).to receive(:save).and_return(true) - knife.run - expect(stderr.string.strip).to eq("Successfully set the policy on node #{node.name}") - end - end - end - - describe "handling policy options" do - context "when policy_group and policy_name is not given" do - let(:bootstrap_cli_options) { %w{ } } - it "returns an error stating that policy_name and policy_group must be given together" do - expect { knife.send(:validate_options!) }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: Policy group and name must be specified together") - end - end - - context "when only policy_name is given" do - let(:bootstrap_cli_options) { %w{ adam staging } } - it "returns an error stating that policy_name and policy_group must be given together" do - expect { knife.send(:validate_options!) }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: Policy group and name must be specified together") - end - end - - context "when only policy_group is given" do - let(:bootstrap_cli_options) { %w{ adam my-app } } - it "returns an error stating that policy_name and policy_group must be given together" do - expect { knife.send(:validate_options!) }.to raise_error(SystemExit) - expect(stderr.string).to include("ERROR: Policy group and name must be specified together") - end - end - - context "when policy_name and policy_group are given with no conflicting options" do - let(:bootstrap_cli_options) { %w{ adam staging my-app } } - it "passes options validation" do - expect { knife.send(:validate_options!) }.to_not raise_error - end - - it "returns value set in config" do - allow(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node) - allow(node).to receive(:save).and_return(false) - knife.run - expect(node.policy_name).to eq("my-app") - expect(node.policy_group).to eq("staging") - end - end - end -end diff --git a/spec/unit/knife/node_run_list_add_spec.rb b/spec/unit/knife/node_run_list_add_spec.rb deleted file mode 100644 index 0148711fac..0000000000 --- a/spec/unit/knife/node_run_list_add_spec.rb +++ /dev/null @@ -1,145 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::NodeRunListAdd do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeRunListAdd.new - @knife.config = { - after: nil, - } - @knife.name_args = [ "adam", "role[monkey]" ] - allow(@knife).to receive(:output).and_return(true) - @node = Chef::Node.new - allow(@node).to receive(:save).and_return(true) - allow(Chef::Node).to receive(:load).and_return(@node) - end - - describe "run" do - it "should load the node" do - expect(Chef::Node).to receive(:load).with("adam") - @knife.run - end - - it "should add to the run list" do - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - end - - it "should save the node" do - expect(@node).to receive(:save) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.run - end - - describe "with -a or --after specified" do - it "should add to the run list after the specified entry" do - @node.run_list << "role[acorns]" - @node.run_list << "role[barn]" - @knife.config[:after] = "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[monkey]") - expect(@node.run_list[2]).to eq("role[barn]") - end - end - - describe "with -b or --before specified" do - it "should add to the run list before the specified entry" do - @node.run_list << "role[acorns]" - @node.run_list << "role[barn]" - @knife.config[:before] = "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - expect(@node.run_list[1]).to eq("role[acorns]") - expect(@node.run_list[2]).to eq("role[barn]") - end - end - - describe "with both --after and --before specified" do - it "exits with an error" do - @node.run_list << "role[acorns]" - @node.run_list << "role[barn]" - @knife.config[:before] = "role[acorns]" - @knife.config[:after] = "role[acorns]" - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - end - - describe "with more than one role or recipe" do - it "should add to the run list all the entries" do - @knife.name_args = [ "adam", "role[monkey],role[duck]" ] - @node.run_list << "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[monkey]") - expect(@node.run_list[2]).to eq("role[duck]") - end - end - - describe "with more than one role or recipe with space between items" do - it "should add to the run list all the entries" do - @knife.name_args = [ "adam", "role[monkey], role[duck]" ] - @node.run_list << "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[monkey]") - expect(@node.run_list[2]).to eq("role[duck]") - end - end - - describe "with more than one role or recipe as different arguments" do - it "should add to the run list all the entries" do - @knife.name_args = [ "adam", "role[monkey]", "role[duck]" ] - @node.run_list << "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[monkey]") - expect(@node.run_list[2]).to eq("role[duck]") - end - end - - describe "with more than one role or recipe as different arguments and list separated by commas" do - it "should add to the run list all the entries" do - @knife.name_args = [ "adam", "role[monkey]", "role[duck],recipe[bird::fly]" ] - @node.run_list << "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[monkey]") - expect(@node.run_list[2]).to eq("role[duck]") - end - end - - describe "with one role or recipe but with an extraneous comma" do - it "should add to the run list one item" do - @knife.name_args = [ "adam", "role[monkey]," ] - @node.run_list << "role[acorns]" - @knife.run - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[monkey]") - end - end - end -end diff --git a/spec/unit/knife/node_run_list_remove_spec.rb b/spec/unit/knife/node_run_list_remove_spec.rb deleted file mode 100644 index 1974821728..0000000000 --- a/spec/unit/knife/node_run_list_remove_spec.rb +++ /dev/null @@ -1,106 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::NodeRunListRemove do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeRunListRemove.new - @knife.config[:print_after] = nil - @knife.name_args = [ "adam", "role[monkey]" ] - @node = Chef::Node.new - @node.name("knifetest-node") - @node.run_list << "role[monkey]" - allow(@node).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:output).and_return(true) - allow(@knife.ui).to receive(:confirm).and_return(true) - - allow(Chef::Node).to receive(:load).and_return(@node) - end - - describe "run" do - it "should load the node" do - expect(Chef::Node).to receive(:load).with("adam").and_return(@node) - @knife.run - end - - it "should remove the item from the run list" do - @knife.run - expect(@node.run_list[0]).not_to eq("role[monkey]") - end - - it "should save the node" do - expect(@node).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - @knife.config[:print_after] = true - expect(@knife.ui).to receive(:output).with({ "knifetest-node" => { "run_list" => [] } }) - @knife.run - end - - describe "run with a list of roles and recipes" do - it "should remove the items from the run list" do - @node.run_list << "role[monkey]" - @node.run_list << "recipe[duck::type]" - @knife.name_args = [ "adam", "role[monkey],recipe[duck::type]" ] - @knife.run - expect(@node.run_list).not_to include("role[monkey]") - expect(@node.run_list).not_to include("recipe[duck::type]") - end - - it "should remove the items from the run list when name args contains whitespace" do - @node.run_list << "role[monkey]" - @node.run_list << "recipe[duck::type]" - @knife.name_args = [ "adam", "role[monkey], recipe[duck::type]" ] - @knife.run - expect(@node.run_list).not_to include("role[monkey]") - expect(@node.run_list).not_to include("recipe[duck::type]") - end - - it "should remove the items from the run list when name args contains multiple run lists" do - @node.run_list << "role[blah]" - @node.run_list << "recipe[duck::type]" - @knife.name_args = [ "adam", "role[monkey], recipe[duck::type]", "role[blah]" ] - @knife.run - expect(@node.run_list).not_to include("role[monkey]") - expect(@node.run_list).not_to include("recipe[duck::type]") - end - - it "should warn when the thing to remove is not in the runlist" do - @node.run_list << "role[blah]" - @node.run_list << "recipe[duck::type]" - @knife.name_args = [ "adam", "role[blork]" ] - expect(@knife.ui).to receive(:warn).with("role[blork] is not in the run list") - @knife.run - end - - it "should warn even more when the thing to remove is not in the runlist and unqualified" do - @node.run_list << "role[blah]" - @node.run_list << "recipe[duck::type]" - @knife.name_args = %w{adam blork} - expect(@knife.ui).to receive(:warn).with("blork is not in the run list") - expect(@knife.ui).to receive(:warn).with(/did you forget recipe\[\] or role\[\]/) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/node_run_list_set_spec.rb b/spec/unit/knife/node_run_list_set_spec.rb deleted file mode 100644 index 6246dfce6a..0000000000 --- a/spec/unit/knife/node_run_list_set_spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -# -# Author:: Mike Fiedler (<miketheman@gmail.com>) -# Copyright:: Copyright 2013-2016, Mike Fiedler -# 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 "spec_helper" - -describe Chef::Knife::NodeRunListSet do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::NodeRunListSet.new - @knife.config = {} - @knife.name_args = [ "adam", "role[monkey]" ] - allow(@knife).to receive(:output).and_return(true) - @node = Chef::Node.new - allow(@node).to receive(:save).and_return(true) - allow(Chef::Node).to receive(:load).and_return(@node) - end - - describe "run" do - it "should load the node" do - expect(Chef::Node).to receive(:load).with("adam") - @knife.run - end - - it "should set the run list" do - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - end - - it "should save the node" do - expect(@node).to receive(:save) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.run - end - - describe "with more than one role or recipe" do - it "should set the run list to all the entries" do - @knife.name_args = [ "adam", "role[monkey],role[duck]" ] - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - expect(@node.run_list[1]).to eq("role[duck]") - end - end - - describe "with more than one role or recipe with space between items" do - it "should set the run list to all the entries" do - @knife.name_args = [ "adam", "role[monkey], role[duck]" ] - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - expect(@node.run_list[1]).to eq("role[duck]") - end - end - - describe "with more than one role or recipe as different arguments" do - it "should set the run list to all the entries" do - @knife.name_args = [ "adam", "role[monkey]", "role[duck]" ] - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - expect(@node.run_list[1]).to eq("role[duck]") - end - end - - describe "with more than one role or recipe as different arguments and list separated by comas" do - it "should add to the run list all the entries" do - @knife.name_args = [ "adam", "role[monkey]", "role[duck],recipe[bird::fly]" ] - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - expect(@node.run_list[1]).to eq("role[duck]") - end - end - - describe "with one role or recipe but with an extraneous comma" do - it "should add to the run list one item" do - @knife.name_args = [ "adam", "role[monkey]," ] - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - end - end - - describe "with an existing run list" do - it "should overwrite any existing run list items" do - @node.run_list << "role[acorns]" - @node.run_list << "role[zebras]" - expect(@node.run_list[0]).to eq("role[acorns]") - expect(@node.run_list[1]).to eq("role[zebras]") - expect(@node.run_list.run_list_items.size).to eq(2) - - @knife.name_args = [ "adam", "role[monkey]", "role[duck]" ] - @knife.run - expect(@node.run_list[0]).to eq("role[monkey]") - expect(@node.run_list[1]).to eq("role[duck]") - expect(@node.run_list.run_list_items.size).to eq(2) - end - end - - end -end diff --git a/spec/unit/knife/node_show_spec.rb b/spec/unit/knife/node_show_spec.rb deleted file mode 100644 index 037672501e..0000000000 --- a/spec/unit/knife/node_show_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::NodeShow do - - let(:node) do - node = Chef::Node.new - node.name("adam") - node.run_list = ["role[base]"] - node - end - - let(:knife) do - knife = Chef::Knife::NodeShow.new - knife.name_args = [ "adam" ] - knife - end - - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - end - - describe "run" do - it "should load the node" do - expect(Chef::Node).to receive(:load).with("adam").and_return(node) - allow(knife).to receive(:output).and_return(true) - knife.run - end - - it "should pretty print the node, formatted for display" do - knife.config[:format] = nil - stdout = StringIO.new - allow(knife.ui).to receive(:stdout).and_return(stdout) - allow(Chef::Node).to receive(:load).and_return(node) - knife.run - expect(stdout.string).to eql("Node Name: adam\nEnvironment: _default\nFQDN: \nIP: \nRun List: \nRoles: \nRecipes: \nPlatform: \nTags: \n") - end - - it "should pretty print json" do - knife.config[:format] = "json" - stdout = StringIO.new - allow(knife.ui).to receive(:stdout).and_return(stdout) - expect(Chef::Node).to receive(:load).with("adam").and_return(node) - knife.run - expect(stdout.string).to eql("{\n \"name\": \"adam\",\n \"chef_environment\": \"_default\",\n \"run_list\": [\n\n]\n,\n \"normal\": {\n\n }\n}\n") - end - end -end diff --git a/spec/unit/knife/raw_spec.rb b/spec/unit/knife/raw_spec.rb deleted file mode 100644 index 1f88195e65..0000000000 --- a/spec/unit/knife/raw_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# -# Author:: Steven Danna (<steve@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 "spec_helper" - -describe Chef::Knife::Raw do - let(:rest) do - r = double("Chef::Knife::Raw::RawInputServerAPI") - allow(Chef::Knife::Raw::RawInputServerAPI).to receive(:new).and_return(r) - r - end - - let(:knife) do - k = Chef::Knife::Raw.new - k.config[:method] = "GET" - k.name_args = [ "/nodes" ] - k - end - - describe "run" do - it "should set the x-ops-request-source header when --proxy-auth is set" do - knife.config[:proxy_auth] = true - expect(rest).to receive(:request).with(:GET, "/nodes", - { "Content-Type" => "application/json", - "x-ops-request-source" => "web" }, false) - knife.run - end - end -end diff --git a/spec/unit/knife/role_bulk_delete_spec.rb b/spec/unit/knife/role_bulk_delete_spec.rb deleted file mode 100644 index 5af7c51584..0000000000 --- a/spec/unit/knife/role_bulk_delete_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@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 "spec_helper" - -describe Chef::Knife::RoleBulkDelete do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::RoleBulkDelete.new - @knife.config = { - print_after: nil, - } - @knife.name_args = ["."] - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - allow(@knife.ui).to receive(:confirm).and_return(true) - @roles = {} - %w{dev staging production}.each do |role_name| - role = Chef::Role.new - role.name(role_name) - allow(role).to receive(:destroy).and_return(true) - @roles[role_name] = role - end - allow(Chef::Role).to receive(:list).and_return(@roles) - end - - describe "run" do - - it "should get the list of the roles" do - expect(Chef::Role).to receive(:list).and_return(@roles) - @knife.run - end - - it "should print the roles you are about to delete" do - @knife.run - expect(@stdout.string).to match(/#{@knife.ui.list(@roles.keys.sort, :columns_down)}/) - end - - it "should confirm you really want to delete them" do - expect(@knife.ui).to receive(:confirm) - @knife.run - end - - it "should delete each role" do - @roles.each_value do |r| - expect(r).to receive(:destroy) - end - @knife.run - end - - it "should only delete roles that match the regex" do - @knife.name_args = ["dev"] - expect(@roles["dev"]).to receive(:destroy) - expect(@roles["staging"]).not_to receive(:destroy) - expect(@roles["production"]).not_to receive(:destroy) - @knife.run - end - - it "should exit if the regex is not provided" do - @knife.name_args = [] - expect { @knife.run }.to raise_error(SystemExit) - end - - end -end diff --git a/spec/unit/knife/role_create_spec.rb b/spec/unit/knife/role_create_spec.rb deleted file mode 100644 index 0d563e40dd..0000000000 --- a/spec/unit/knife/role_create_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::RoleCreate do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::RoleCreate.new - @knife.config = { - description: nil, - } - @knife.name_args = [ "adam" ] - allow(@knife).to receive(:output).and_return(true) - @role = Chef::Role.new - allow(@role).to receive(:save) - allow(Chef::Role).to receive(:new).and_return(@role) - allow(@knife).to receive(:edit_data).and_return(@role) - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should create a new role" do - expect(Chef::Role).to receive(:new).and_return(@role) - @knife.run - end - - it "should set the role name" do - expect(@role).to receive(:name).with("adam") - @knife.run - end - - it "should not print the role" do - expect(@knife).not_to receive(:output) - @knife.run - end - - it "should allow you to edit the data" do - expect(@knife).to receive(:edit_data).with(@role, object_class: Chef::Role) - @knife.run - end - - it "should save the role" do - expect(@role).to receive(:save) - @knife.run - end - - describe "with -d or --description" do - it "should set the description" do - @knife.config[:description] = "All is bob" - expect(@role).to receive(:description).with("All is bob") - @knife.run - end - end - - describe "with -p or --print-after" do - it "should pretty print the node, formatted for display" do - @knife.config[:print_after] = true - expect(@knife).to receive(:output).with(@role) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/role_delete_spec.rb b/spec/unit/knife/role_delete_spec.rb deleted file mode 100644 index d43f99689d..0000000000 --- a/spec/unit/knife/role_delete_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::RoleDelete do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::RoleDelete.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "adam" ] - allow(@knife).to receive(:output).and_return(true) - allow(@knife).to receive(:confirm).and_return(true) - @role = Chef::Role.new - allow(@role).to receive(:destroy).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should confirm that you want to delete" do - expect(@knife).to receive(:confirm) - @knife.run - end - - it "should load the Role" do - expect(Chef::Role).to receive(:load).with("adam").and_return(@role) - @knife.run - end - - it "should delete the Role" do - expect(@role).to receive(:destroy).and_return(@role) - @knife.run - end - - it "should not print the Role" do - expect(@knife).not_to receive(:output) - @knife.run - end - - describe "with -p or --print-after" do - it "should pretty print the Role, formatted for display" do - @knife.config[:print_after] = true - expect(@knife).to receive(:output) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/role_edit_spec.rb b/spec/unit/knife/role_edit_spec.rb deleted file mode 100644 index faf9cf7d84..0000000000 --- a/spec/unit/knife/role_edit_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::RoleEdit do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::RoleEdit.new - @knife.config[:print_after] = nil - @knife.name_args = [ "adam" ] - allow(@knife.ui).to receive(:output).and_return(true) - @role = Chef::Role.new - allow(@role).to receive(:save) - allow(Chef::Role).to receive(:load).and_return(@role) - allow(@knife.ui).to receive(:edit_data).and_return(@role) - allow(@knife.ui).to receive(:msg) - end - - describe "run" do - it "should load the role" do - expect(Chef::Role).to receive(:load).with("adam").and_return(@role) - @knife.run - end - - it "should edit the role data" do - expect(@knife.ui).to receive(:edit_data).with(@role, object_class: Chef::Role) - @knife.run - end - - it "should save the edited role data" do - pansy = Chef::Role.new - - @role.name("new_role_name") - expect(@knife.ui).to receive(:edit_data).with(@role, object_class: Chef::Role).and_return(pansy) - expect(pansy).to receive(:save) - @knife.run - end - - it "should not save the unedited role data" do - pansy = Chef::Role.new - - expect(@knife.ui).to receive(:edit_data).with(@role, object_class: Chef::Role).and_return(pansy) - expect(pansy).not_to receive(:save) - @knife.run - - end - - it "should not print the role" do - expect(@knife.ui).not_to receive(:output) - @knife.run - end - - describe "with -p or --print-after" do - it "should pretty print the role, formatted for display" do - @knife.config[:print_after] = true - expect(@knife.ui).to receive(:output).with(@role) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/role_env_run_list_add_spec.rb b/spec/unit/knife/role_env_run_list_add_spec.rb deleted file mode 100644 index 13a05db33e..0000000000 --- a/spec/unit/knife/role_env_run_list_add_spec.rb +++ /dev/null @@ -1,217 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleEnvRunListAdd do - before(:each) do - # Chef::Config[:role_name] = "websimian" - # Chef::Config[:env_name] = "QA" - @knife = Chef::Knife::RoleEnvRunListAdd.new - @knife.config = { - after: nil, - } - @knife.name_args = [ "will", "QA", "role[monkey]" ] - allow(@knife).to receive(:output).and_return(true) - @role = Chef::Role.new - allow(@role).to receive(:save).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should have an empty default run list" do - @knife.run - expect(@role.run_list[0]).to be_nil - end - - it "should have a QA environment" do - @knife.run - expect(@role.active_run_list_for("QA")).to eq("QA") - end - - it "should load the role named will" do - expect(Chef::Role).to receive(:load).with("will") - @knife.run - end - - it "should be able to add an environment specific run list" do - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - end - - it "should save the role" do - expect(@role).to receive(:save) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.run - end - - describe "with -a or --after specified" do - it "should not create a change if the specified 'after' never comes" do - @role.run_list_for("_default") << "role[acorns]" - @role.run_list_for("_default") << "role[barn]" - @knife.config[:after] = "role[acorns]" - @knife.name_args = [ "will", "QA", "role[pad]" ] - @knife.run - expect(@role.run_list_for("QA")[0]).to be_nil - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[barn]") - expect(@role.run_list[2]).to be_nil - end - - it "should add to the run list after the specified entries in the QA run list" do - # Setup - @role.run_list_for("_default") << "role[acorns]" - @role.run_list_for("_default") << "role[barn]" - @knife.run - @role.run_list_for("QA") << "role[pencil]" - @role.run_list_for("QA") << "role[pen]" - # Configuration we are testing - @knife.config[:after] = "role[pencil]" - @knife.name_args = [ "will", "QA", "role[pad]", "role[whackadoo]" ] - @knife.run - # The actual tests - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to eq("role[pencil]") - expect(@role.run_list_for("QA")[2]).to eq("role[pad]") - expect(@role.run_list_for("QA")[3]).to eq("role[whackadoo]") - expect(@role.run_list_for("QA")[4]).to eq("role[pen]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[barn]") - expect(@role.run_list[2]).to be_nil - end - end - - describe "with more than one role or recipe" do - it "should add to the QA run list all the entries" do - @knife.name_args = [ "will", "QA", "role[monkey],role[duck]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to eq("role[duck]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - describe "with more than one role or recipe with space between items" do - it "should add to the run list all the entries" do - @knife.name_args = [ "will", "QA", "role[monkey], role[duck]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to eq("role[duck]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - describe "with more than one role or recipe as different arguments" do - it "should add to the run list all the entries" do - @knife.name_args = [ "will", "QA", "role[monkey]", "role[duck]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to eq("role[duck]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - describe "with more than one role or recipe as different arguments and list separated by comas" do - it "should add to the run list all the entries" do - @knife.name_args = [ "will", "QA", "role[monkey]", "role[duck],recipe[bird::fly]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to eq("role[duck]") - expect(@role.run_list_for("QA")[2]).to eq("recipe[bird::fly]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - describe "Recipe with version number is allowed" do - it "should add to the run list all the entries including the versioned recipe" do - @knife.name_args = [ "will", "QA", "role[monkey]", "role[duck],recipe[bird::fly@1.1.3]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to eq("role[duck]") - expect(@role.run_list_for("QA")[2]).to eq("recipe[bird::fly@1.1.3]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - describe "with one role or recipe but with an extraneous comma" do - it "should add to the run list one item" do - @role.run_list_for("_default") << "role[acorns]" - @knife.name_args = [ "will", "QA", "role[monkey]," ] - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[monkey]") - expect(@role.run_list_for("QA")[1]).to be_nil - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - describe "with more than one command" do - it "should be able to the environment run list by running multiple knife commands" do - @knife.name_args = [ "will", "QA", "role[blue]," ] - @knife.run - @knife.name_args = [ "will", "QA", "role[black]," ] - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[blue]") - expect(@role.run_list_for("QA")[1]).to eq("role[black]") - expect(@role.run_list[0]).to be_nil - end - end - - describe "with more than one environment" do - it "should add to the run list a second environment in the specific run list" do - @role.run_list_for("_default") << "role[acorns]" - @knife.name_args = [ "will", "QA", "role[blue]," ] - @knife.run - @role.run_list_for("QA") << "role[walnuts]" - - @knife.name_args = [ "will", "PRD", "role[ball]," ] - @knife.run - @role.run_list_for("PRD") << "role[pen]" - - expect(@role.run_list_for("QA")[0]).to eq("role[blue]") - expect(@role.run_list_for("PRD")[0]).to eq("role[ball]") - expect(@role.run_list_for("QA")[1]).to eq("role[walnuts]") - expect(@role.run_list_for("PRD")[1]).to eq("role[pen]") - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to be_nil - end - end - - end -end diff --git a/spec/unit/knife/role_env_run_list_clear_spec.rb b/spec/unit/knife/role_env_run_list_clear_spec.rb deleted file mode 100644 index d4b9625550..0000000000 --- a/spec/unit/knife/role_env_run_list_clear_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleEnvRunListClear do - before(:each) do - Chef::Config[:role_name] = "will" - Chef::Config[:env_name] = "QA" - @setup = Chef::Knife::RoleEnvRunListAdd.new - @setup.name_args = [ "will", "QA", "role[monkey]", "role[person]" ] - - @knife = Chef::Knife::RoleEnvRunListClear.new - @knife.config = { - print_after: nil, - } - @knife.name_args = %w{will QA} - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should remove the item from the run list" do - @setup.run - @knife.run - expect(@role.run_list_for("QA")[0]).to be_nil - expect(@role.run_list[0]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "should clear an environmental run list of roles and recipes" do - it "should remove the items from the run list" do - @setup.name_args = [ "will", "QA", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @setup.name_args = [ "will", "PRD", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = %w{will QA} - @knife.run - expect(@role.run_list_for("QA")[0]).to be_nil - expect(@role.run_list_for("PRD")[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list_for("PRD")[1]).to eq("role[monkey]") - expect(@role.run_list_for("PRD")[2]).to eq("recipe[duck::type]") - expect(@role.run_list_for("PRD")[3]).to eq("role[person]") - expect(@role.run_list_for("PRD")[4]).to eq("role[bird]") - expect(@role.run_list_for("PRD")[5]).to eq("role[town]") - end - end - end -end diff --git a/spec/unit/knife/role_env_run_list_remove_spec.rb b/spec/unit/knife/role_env_run_list_remove_spec.rb deleted file mode 100644 index 7f9b41475c..0000000000 --- a/spec/unit/knife/role_env_run_list_remove_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleEnvRunListRemove do - before(:each) do - Chef::Config[:role_name] = "will" - Chef::Config[:env_name] = "QA" - @setup = Chef::Knife::RoleEnvRunListAdd.new - @setup.name_args = [ "will", "QA", "role[monkey]", "role[person]" ] - - @knife = Chef::Knife::RoleEnvRunListRemove.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will", "QA", "role[monkey]" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should remove the item from the run list" do - @setup.run - @knife.run - expect(@role.run_list_for("QA")[0]).not_to eq("role[monkey]") - expect(@role.run_list_for("QA")[0]).to eq("role[person]") - expect(@role.run_list[0]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "run with a list of roles and recipes" do - it "should remove the items from the run list" do - @setup.name_args = [ "will", "QA", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @setup.name_args = [ "will", "PRD", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will", "QA", "role[monkey]" ] - @knife.run - @knife.name_args = [ "will", "QA", "recipe[duck::type]" ] - @knife.run - expect(@role.run_list_for("QA")).not_to include("role[monkey]") - expect(@role.run_list_for("QA")).not_to include("recipe[duck::type]") - expect(@role.run_list_for("QA")[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list_for("QA")[1]).to eq("role[person]") - expect(@role.run_list_for("QA")[2]).to eq("role[bird]") - expect(@role.run_list_for("QA")[3]).to eq("role[town]") - expect(@role.run_list_for("PRD")[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list_for("PRD")[1]).to eq("role[monkey]") - expect(@role.run_list_for("PRD")[2]).to eq("recipe[duck::type]") - expect(@role.run_list_for("PRD")[3]).to eq("role[person]") - expect(@role.run_list_for("PRD")[4]).to eq("role[bird]") - expect(@role.run_list_for("PRD")[5]).to eq("role[town]") - end - end - end -end diff --git a/spec/unit/knife/role_env_run_list_replace_spec.rb b/spec/unit/knife/role_env_run_list_replace_spec.rb deleted file mode 100644 index 93b233efdc..0000000000 --- a/spec/unit/knife/role_env_run_list_replace_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleEnvRunListReplace do - before(:each) do - Chef::Config[:role_name] = "will" - Chef::Config[:env_name] = "QA" - @setup = Chef::Knife::RoleEnvRunListAdd.new - @setup.name_args = [ "will", "QA", "role[monkey]", "role[dude]", "role[fixer]" ] - - @knife = Chef::Knife::RoleEnvRunListReplace.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will", "QA", "role[dude]", "role[person]" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should remove the item from the run list" do - @setup.run - @knife.run - expect(@role.run_list_for("QA")[1]).not_to eq("role[dude]") - expect(@role.run_list_for("QA")[1]).to eq("role[person]") - expect(@role.run_list[0]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "run with a list of roles and recipes" do - it "should replace the items from the run list" do - @setup.name_args = [ "will", "QA", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @setup.name_args = [ "will", "PRD", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will", "QA", "role[monkey]", "role[gibbon]" ] - @knife.run - @knife.name_args = [ "will", "QA", "recipe[duck::type]", "recipe[duck::mallard]" ] - @knife.run - expect(@role.run_list_for("QA")).not_to include("role[monkey]") - expect(@role.run_list_for("QA")).not_to include("recipe[duck::type]") - expect(@role.run_list_for("QA")[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list_for("QA")[1]).to eq("role[gibbon]") - expect(@role.run_list_for("QA")[2]).to eq("recipe[duck::mallard]") - expect(@role.run_list_for("QA")[3]).to eq("role[person]") - expect(@role.run_list_for("QA")[4]).to eq("role[bird]") - expect(@role.run_list_for("QA")[5]).to eq("role[town]") - expect(@role.run_list_for("PRD")[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list_for("PRD")[1]).to eq("role[monkey]") - expect(@role.run_list_for("PRD")[2]).to eq("recipe[duck::type]") - expect(@role.run_list_for("PRD")[3]).to eq("role[person]") - expect(@role.run_list_for("PRD")[4]).to eq("role[bird]") - expect(@role.run_list_for("PRD")[5]).to eq("role[town]") - expect(@role.run_list[0]).to be_nil - end - end - end -end diff --git a/spec/unit/knife/role_env_run_list_set_spec.rb b/spec/unit/knife/role_env_run_list_set_spec.rb deleted file mode 100644 index d35e4dbb17..0000000000 --- a/spec/unit/knife/role_env_run_list_set_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleEnvRunListSet do - before(:each) do - Chef::Config[:role_name] = "will" - Chef::Config[:env_name] = "QA" - @setup = Chef::Knife::RoleEnvRunListAdd.new - @setup.name_args = [ "will", "QA", "role[monkey]", "role[person]", "role[bucket]" ] - - @knife = Chef::Knife::RoleEnvRunListSet.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will", "QA", "role[owen]", "role[mauntel]" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should replace all the items in the runlist with what is specified" do - @setup.run - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[owen]") - expect(@role.run_list_for("QA")[1]).to eq("role[mauntel]") - expect(@role.run_list_for("QA")[2]).to be_nil - expect(@role.run_list[0]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "should clear an environmental run list of roles and recipes" do - it "should remove the items from the run list" do - @setup.name_args = [ "will", "QA", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @setup.name_args = [ "will", "PRD", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will", "QA", "role[coke]", "role[pepsi]" ] - @knife.run - expect(@role.run_list_for("QA")[0]).to eq("role[coke]") - expect(@role.run_list_for("QA")[1]).to eq("role[pepsi]") - expect(@role.run_list_for("QA")[2]).to be_nil - expect(@role.run_list_for("PRD")[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list_for("PRD")[1]).to eq("role[monkey]") - expect(@role.run_list_for("PRD")[2]).to eq("recipe[duck::type]") - expect(@role.run_list_for("PRD")[3]).to eq("role[person]") - expect(@role.run_list_for("PRD")[4]).to eq("role[bird]") - expect(@role.run_list_for("PRD")[5]).to eq("role[town]") - expect(@role.run_list[0]).to be_nil - end - end - end -end diff --git a/spec/unit/knife/role_from_file_spec.rb b/spec/unit/knife/role_from_file_spec.rb deleted file mode 100644 index 51e94d31e3..0000000000 --- a/spec/unit/knife/role_from_file_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -Chef::Knife::RoleFromFile.load_deps - -describe Chef::Knife::RoleFromFile do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::RoleFromFile.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "adam.rb" ] - allow(@knife).to receive(:output).and_return(true) - allow(@knife).to receive(:confirm).and_return(true) - @role = Chef::Role.new - allow(@role).to receive(:save) - allow(@knife.loader).to receive(:load_from).and_return(@role) - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - it "should load from a file" do - expect(@knife.loader).to receive(:load_from).with("roles", "adam.rb").and_return(@role) - @knife.run - end - - it "should not print the role" do - expect(@knife).not_to receive(:output) - @knife.run - end - - describe "with -p or --print-after" do - it "should print the role" do - @knife.config[:print_after] = true - expect(@knife).to receive(:output) - @knife.run - end - end - end - - describe "run with multiple arguments" do - it "should load each file" do - @knife.name_args = [ "adam.rb", "caleb.rb" ] - expect(@knife.loader).to receive(:load_from).with("roles", "adam.rb").and_return(@role) - expect(@knife.loader).to receive(:load_from).with("roles", "caleb.rb").and_return(@role) - @knife.run - end - end - -end diff --git a/spec/unit/knife/role_list_spec.rb b/spec/unit/knife/role_list_spec.rb deleted file mode 100644 index dea2e874a4..0000000000 --- a/spec/unit/knife/role_list_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -# -# 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. -# - -require "spec_helper" - -describe Chef::Knife::RoleList do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::RoleList.new - allow(@knife).to receive(:output).and_return(true) - @list = { - "foo" => "http://example.com/foo", - "bar" => "http://example.com/foo", - } - allow(Chef::Role).to receive(:list).and_return(@list) - end - - describe "run" do - it "should list the roles" do - expect(Chef::Role).to receive(:list).and_return(@list) - @knife.run - end - - it "should pretty print the list" do - expect(Chef::Role).to receive(:list).and_return(@list) - expect(@knife).to receive(:output).with(%w{bar foo}) - @knife.run - end - - describe "with -w or --with-uri" do - it "should pretty print the hash" do - @knife.config[:with_uri] = true - expect(Chef::Role).to receive(:list).and_return(@list) - expect(@knife).to receive(:output).with(@list) - @knife.run - end - end - end -end diff --git a/spec/unit/knife/role_run_list_add_spec.rb b/spec/unit/knife/role_run_list_add_spec.rb deleted file mode 100644 index 6f222ee80a..0000000000 --- a/spec/unit/knife/role_run_list_add_spec.rb +++ /dev/null @@ -1,179 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleRunListAdd do - before(:each) do - # Chef::Config[:role_name] = "websimian" - # Chef::Config[:env_name] = "QA" - @knife = Chef::Knife::RoleRunListAdd.new - @knife.config = { - after: nil, - } - @knife.name_args = [ "will", "role[monkey]" ] - allow(@knife).to receive(:output).and_return(true) - @role = Chef::Role.new - allow(@role).to receive(:save).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should have a run list with the monkey role" do - @knife.run - expect(@role.run_list[0]).to eq("role[monkey]") - end - - it "should load the role named will" do - expect(Chef::Role).to receive(:load).with("will") - @knife.run - end - - it "should save the role" do - expect(@role).to receive(:save) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.run - end - - describe "with -a or --after specified" do - it "should not create a change if the specified 'after' never comes" do - @role.run_list_for("_default") << "role[acorns]" - @role.run_list_for("_default") << "role[barn]" - @knife.config[:after] = "role[tree]" - @knife.name_args = [ "will", "role[pad]" ] - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[barn]") - expect(@role.run_list[2]).to be_nil - end - - it "should add to the run list after the specified entries in the default run list" do - # Setup - @role.run_list_for("_default") << "role[acorns]" - @role.run_list_for("_default") << "role[barn]" - # Configuration we are testing - @knife.config[:after] = "role[acorns]" - @knife.name_args = [ "will", "role[pad]", "role[whackadoo]" ] - @knife.run - # The actual tests - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[pad]") - expect(@role.run_list[2]).to eq("role[whackadoo]") - expect(@role.run_list[3]).to eq("role[barn]") - expect(@role.run_list[4]).to be_nil - end - end - - describe "with more than one role or recipe" do - it "should add to the QA run list all the entries" do - @knife.name_args = [ "will", "role[monkey],role[duck]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[monkey]") - expect(@role.run_list[2]).to eq("role[duck]") - expect(@role.run_list[3]).to be_nil - end - end - - describe "with more than one role or recipe with space between items" do - it "should add to the run list all the entries" do - @knife.name_args = [ "will", "role[monkey], role[duck]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[monkey]") - expect(@role.run_list[2]).to eq("role[duck]") - expect(@role.run_list[3]).to be_nil - end - end - - describe "with more than one role or recipe as different arguments" do - it "should add to the run list all the entries" do - @knife.name_args = [ "will", "role[monkey]", "role[duck]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[monkey]") - expect(@role.run_list[2]).to eq("role[duck]") - expect(@role.run_list[3]).to be_nil - end - end - - describe "with more than one role or recipe as different arguments and list separated by comas" do - it "should add to the run list all the entries" do - @knife.name_args = [ "will", "role[monkey]", "role[duck],recipe[bird::fly]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[monkey]") - expect(@role.run_list[2]).to eq("role[duck]") - expect(@role.run_list[3]).to eq("recipe[bird::fly]") - expect(@role.run_list[4]).to be_nil - end - end - - describe "Recipe with version number is allowed" do - it "should add to the run list all the entries including the versioned recipe" do - @knife.name_args = [ "will", "role[monkey]", "role[duck],recipe[bird::fly@1.1.3]" ] - @role.run_list_for("_default") << "role[acorns]" - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[monkey]") - expect(@role.run_list[2]).to eq("role[duck]") - expect(@role.run_list[3]).to eq("recipe[bird::fly@1.1.3]") - expect(@role.run_list[4]).to be_nil - end - end - - describe "with one role or recipe but with an extraneous comma" do - it "should add to the run list one item" do - @role.run_list_for("_default") << "role[acorns]" - @knife.name_args = [ "will", "role[monkey]," ] - @knife.run - expect(@role.run_list[0]).to eq("role[acorns]") - expect(@role.run_list[1]).to eq("role[monkey]") - expect(@role.run_list[2]).to be_nil - end - end - - describe "with more than one command" do - it "should be able to the environment run list by running multiple knife commands" do - @knife.name_args = [ "will", "role[blue]," ] - @knife.run - @knife.name_args = [ "will", "role[black]," ] - @knife.run - expect(@role.run_list[0]).to eq("role[blue]") - expect(@role.run_list[1]).to eq("role[black]") - expect(@role.run_list[2]).to be_nil - end - end - - end -end diff --git a/spec/unit/knife/role_run_list_clear_spec.rb b/spec/unit/knife/role_run_list_clear_spec.rb deleted file mode 100644 index 327a9979b0..0000000000 --- a/spec/unit/knife/role_run_list_clear_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleRunListClear do - before(:each) do - Chef::Config[:role_name] = "will" - @setup = Chef::Knife::RoleRunListAdd.new - @setup.name_args = [ "will", "role[monkey]", "role[person]" ] - - @knife = Chef::Knife::RoleRunListClear.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should remove the item from the run list" do - @setup.run - @knife.run - expect(@role.run_list[0]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "should clear an environmental run list of roles and recipes" do - it "should remove the items from the run list" do - @setup.name_args = [ "will", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will" ] - @knife.run - expect(@role.run_list[0]).to be_nil - end - end - end -end diff --git a/spec/unit/knife/role_run_list_remove_spec.rb b/spec/unit/knife/role_run_list_remove_spec.rb deleted file mode 100644 index 200a559c08..0000000000 --- a/spec/unit/knife/role_run_list_remove_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleRunListRemove do - before(:each) do - Chef::Config[:role_name] = "will" - @setup = Chef::Knife::RoleRunListAdd.new - @setup.name_args = [ "will", "role[monkey]", "role[person]" ] - - @knife = Chef::Knife::RoleRunListRemove.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will", "role[monkey]" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should remove the item from the run list" do - @setup.run - @knife.run - expect(@role.run_list[0]).to eq("role[person]") - expect(@role.run_list[1]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "run with a list of roles and recipes" do - it "should remove the items from the run list" do - @setup.name_args = [ "will", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will", "role[monkey]" ] - @knife.run - @knife.name_args = [ "will", "recipe[duck::type]" ] - @knife.run - expect(@role.run_list).not_to include("role[monkey]") - expect(@role.run_list).not_to include("recipe[duck::type]") - expect(@role.run_list[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list[1]).to eq("role[person]") - expect(@role.run_list[2]).to eq("role[bird]") - expect(@role.run_list[3]).to eq("role[town]") - end - end - end -end diff --git a/spec/unit/knife/role_run_list_replace_spec.rb b/spec/unit/knife/role_run_list_replace_spec.rb deleted file mode 100644 index 1957403fb1..0000000000 --- a/spec/unit/knife/role_run_list_replace_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleRunListReplace do - before(:each) do - Chef::Config[:role_name] = "will" - @setup = Chef::Knife::RoleRunListAdd.new - @setup.name_args = [ "will", "role[monkey]", "role[dude]", "role[fixer]" ] - - @knife = Chef::Knife::RoleRunListReplace.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will", "role[dude]", "role[person]" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should remove the item from the run list" do - @setup.run - @knife.run - expect(@role.run_list[0]).to eq("role[monkey]") - expect(@role.run_list[1]).not_to eq("role[dude]") - expect(@role.run_list[1]).to eq("role[person]") - expect(@role.run_list[2]).to eq("role[fixer]") - expect(@role.run_list[3]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "run with a list of roles and recipes" do - it "should replace the items from the run list" do - @setup.name_args = [ "will", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will", "role[monkey]", "role[gibbon]" ] - @knife.run - @knife.name_args = [ "will", "recipe[duck::type]", "recipe[duck::mallard]" ] - @knife.run - expect(@role.run_list).not_to include("role[monkey]") - expect(@role.run_list).not_to include("recipe[duck::type]") - expect(@role.run_list[0]).to eq("recipe[orange::chicken]") - expect(@role.run_list[1]).to eq("role[gibbon]") - expect(@role.run_list[2]).to eq("recipe[duck::mallard]") - expect(@role.run_list[3]).to eq("role[person]") - expect(@role.run_list[4]).to eq("role[bird]") - expect(@role.run_list[5]).to eq("role[town]") - expect(@role.run_list[6]).to be_nil - end - end - end -end diff --git a/spec/unit/knife/role_run_list_set_spec.rb b/spec/unit/knife/role_run_list_set_spec.rb deleted file mode 100644 index 06098c585e..0000000000 --- a/spec/unit/knife/role_run_list_set_spec.rb +++ /dev/null @@ -1,89 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Will Albenzi (<walbenzi@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::RoleRunListSet do - before(:each) do - Chef::Config[:role_name] = "will" - @setup = Chef::Knife::RoleRunListAdd.new - @setup.name_args = [ "will", "role[monkey]", "role[person]", "role[bucket]" ] - - @knife = Chef::Knife::RoleRunListSet.new - @knife.config = { - print_after: nil, - } - @knife.name_args = [ "will", "role[owen]", "role[mauntel]" ] - allow(@knife).to receive(:output).and_return(true) - - @role = Chef::Role.new - @role.name("will") - allow(@role).to receive(:save).and_return(true) - - allow(@knife.ui).to receive(:confirm).and_return(true) - allow(Chef::Role).to receive(:load).and_return(@role) - - end - - describe "run" do - - # it "should display all the things" do - # @knife.run - # @role.to_json.should == 'show all the things' - # end - - it "should load the node" do - expect(Chef::Role).to receive(:load).with("will").and_return(@role) - @knife.run - end - - it "should replace all the items in the runlist with what is specified" do - @setup.run - @knife.run - expect(@role.run_list[0]).to eq("role[owen]") - expect(@role.run_list[1]).to eq("role[mauntel]") - expect(@role.run_list[2]).to be_nil - end - - it "should save the node" do - expect(@role).to receive(:save).and_return(true) - @knife.run - end - - it "should print the run list" do - expect(@knife).to receive(:output).and_return(true) - @knife.config[:print_after] = true - @setup.run - @knife.run - end - - describe "should clear an environmental run list of roles and recipes" do - it "should remove the items from the run list" do - @setup.name_args = [ "will", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ] - @setup.run - @knife.name_args = [ "will", "role[coke]", "role[pepsi]" ] - @knife.run - expect(@role.run_list[0]).to eq("role[coke]") - expect(@role.run_list[1]).to eq("role[pepsi]") - expect(@role.run_list[2]).to be_nil - expect(@role.run_list[3]).to be_nil - end - end - end -end diff --git a/spec/unit/knife/role_show_spec.rb b/spec/unit/knife/role_show_spec.rb deleted file mode 100644 index fe48e2f940..0000000000 --- a/spec/unit/knife/role_show_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -# -# Author:: Lamont Granquist (<lamont@chef.io>) -# Copyright:: Copyright 2014-2016, Lamont Granquist -# 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 "spec_helper" - -describe Chef::Knife::RoleShow do - let(:role) { "base" } - - let(:knife) do - knife = Chef::Knife::RoleShow.new - knife.name_args = [ role ] - knife - end - - let(:role_mock) { double("role_mock") } - - describe "run" do - it "should list the role" do - expect(Chef::Role).to receive(:load).with("base").and_return(role_mock) - expect(knife).to receive(:format_for_display).with(role_mock) - knife.run - end - - it "should pretty print json" do - knife.config[:format] = "json" - stdout = StringIO.new - allow(knife.ui).to receive(:stdout).and_return(stdout) - fake_role_contents = { "foo" => "bar", "baz" => "qux" } - expect(Chef::Role).to receive(:load).with("base").and_return(fake_role_contents) - knife.run - expect(stdout.string).to eql("{\n \"foo\": \"bar\",\n \"baz\": \"qux\"\n}\n") - end - - context "without a role name" do - let(:role) {} - - it "should print usage and exit when a role name is not provided" do - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end - end - end -end diff --git a/spec/unit/knife/ssh_spec.rb b/spec/unit/knife/ssh_spec.rb deleted file mode 100644 index 8606045e8c..0000000000 --- a/spec/unit/knife/ssh_spec.rb +++ /dev/null @@ -1,403 +0,0 @@ -# -# Author:: Bryan McLellan <btm@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 "spec_helper" -require "net/ssh" -require "net/ssh/multi" - -describe Chef::Knife::Ssh do - let(:query_result) { double("chef search results") } - - before do - Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem" - @knife = Chef::Knife::Ssh.new - @knife.merge_configs - @node_foo = {} - @node_foo["fqdn"] = "foo.example.org" - @node_foo["ipaddress"] = "10.0.0.1" - @node_foo["cloud"] = {} - - @node_bar = {} - @node_bar["fqdn"] = "bar.example.org" - @node_bar["ipaddress"] = "10.0.0.2" - @node_bar["cloud"] = {} - - end - - describe "#configure_session" do - context "manual is set to false (default)" do - before do - @knife.config[:manual] = false - allow(query_result).to receive(:search).with(any_args).and_yield(@node_foo).and_yield(@node_bar) - allow(Chef::Search::Query).to receive(:new).and_return(query_result) - end - - def self.should_return_specified_attributes - it "returns an array of the attributes specified on the command line OR config file, if only one is set" do - @node_bar["target"] = "10.0.0.2" - @node_foo["target"] = "10.0.0.1" - @node_bar["prefix"] = "bar" - @node_foo["prefix"] = "foo" - @knife.config[:ssh_attribute] = "ipaddress" - @knife.config[:prefix_attribute] = "name" - Chef::Config[:knife][:ssh_attribute] = "ipaddress" # this value will be in the config file - Chef::Config[:knife][:prefix_attribute] = "name" # this value will be in the config file - expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil, "foo"], ["10.0.0.2", nil, "bar"]]) - @knife.configure_session - end - - it "returns an array of the attributes specified on the command line even when a config value is set" do - @node_bar["target"] = "10.0.0.2" - @node_foo["target"] = "10.0.0.1" - @node_bar["prefix"] = "bar" - @node_foo["prefix"] = "foo" - Chef::Config[:knife][:ssh_attribute] = "config_file" # this value will be in the config file - Chef::Config[:knife][:prefix_attribute] = "config_file" # this value will be in the config file - @knife.config[:ssh_attribute] = "ipaddress" # this is the value of the command line via #configure_attribute - @knife.config[:prefix_attribute] = "name" # this is the value of the command line via #configure_attribute - expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil, "foo"], ["10.0.0.2", nil, "bar"]]) - @knife.configure_session - end - end - - it "searches for and returns an array of fqdns" do - expect(@knife).to receive(:session_from_list).with([ - ["foo.example.org", nil, nil], - ["bar.example.org", nil, nil], - ]) - @knife.configure_session - end - - should_return_specified_attributes - - context "when cloud hostnames are available" do - before do - @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com" - @node_bar["cloud"]["public_hostname"] = "ec2-10-0-0-2.compute-1.amazonaws.com" - end - it "returns an array of cloud public hostnames" do - expect(@knife).to receive(:session_from_list).with([ - ["ec2-10-0-0-1.compute-1.amazonaws.com", nil, nil], - ["ec2-10-0-0-2.compute-1.amazonaws.com", nil, nil], - ]) - @knife.configure_session - end - - should_return_specified_attributes - end - - context "when cloud hostnames are available but empty" do - before do - @node_foo["cloud"]["public_hostname"] = "" - @node_bar["cloud"]["public_hostname"] = "" - end - - it "returns an array of fqdns" do - expect(@knife).to receive(:session_from_list).with([ - ["foo.example.org", nil, nil], - ["bar.example.org", nil, nil], - ]) - @knife.configure_session - end - - should_return_specified_attributes - end - - it "should raise an error if no host are found" do - allow(query_result).to receive(:search).with(any_args) - expect(@knife.ui).to receive(:fatal) - expect(@knife).to receive(:exit).with(10) - @knife.configure_session - end - - context "when there are some hosts found but they do not have an attribute to connect with" do - before do - @node_foo["fqdn"] = nil - @node_bar["fqdn"] = nil - end - - it "should raise a specific error (CHEF-3402)" do - expect(@knife.ui).to receive(:fatal).with(/^2 nodes found/) - expect(@knife).to receive(:exit).with(10) - @knife.configure_session - end - end - - context "when there are some hosts found but IPs duplicated if duplicated_fqdns option sets :fatal" do - before do - @knife.config[:duplicated_fqdns] = :fatal - @node_foo["fqdn"] = "foo.example.org" - @node_bar["fqdn"] = "foo.example.org" - end - - it "should raise a specific error" do - expect(@knife.ui).to receive(:fatal).with(/^SSH node is duplicated: foo\.example\.org/) - expect(@knife).to receive(:exit).with(10) - expect(@knife).to receive(:session_from_list).with([ - ["foo.example.org", nil, nil], - ["foo.example.org", nil, nil], - ]) - @knife.configure_session - end - end - end - - context "manual is set to true" do - before do - @knife.config[:manual] = true - end - - it "returns an array of provided values" do - @knife.instance_variable_set(:@name_args, ["foo.example.org bar.example.org"]) - expect(@knife).to receive(:session_from_list).with(["foo.example.org", "bar.example.org"]) - @knife.configure_session - end - end - end - - describe "#get_prefix_attribute" do - # Order of precedence for prefix - # 1) config value (cli or knife config) - # 2) nil - before do - Chef::Config[:knife][:prefix_attribute] = nil - @knife.config[:prefix_attribute] = nil - @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com" - @node_bar["cloud"]["public_hostname"] = "" - end - - it "should return nil by default" do - expect(@knife.get_prefix_attribute({})).to eq(nil) - end - - it "should favor config over nil" do - @node_foo["prefix"] = "config" - expect( @knife.get_prefix_attribute(@node_foo)).to eq("config") - end - end - - describe "#get_ssh_attribute" do - # Order of precedence for ssh target - # 1) config value (cli or knife config) - # 2) cloud attribute - # 3) fqdn - before do - Chef::Config[:knife][:ssh_attribute] = nil - @knife.config[:ssh_attribute] = nil - @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com" - @node_bar["cloud"]["public_hostname"] = "" - end - - it "should return fqdn by default" do - expect(@knife.get_ssh_attribute({ "fqdn" => "fqdn" })).to eq("fqdn") - end - - it "should return cloud.public_hostname attribute if available" do - expect(@knife.get_ssh_attribute(@node_foo)).to eq("ec2-10-0-0-1.compute-1.amazonaws.com") - end - - it "should favor config over cloud and default" do - @node_foo["target"] = "config" - expect( @knife.get_ssh_attribute(@node_foo)).to eq("config") - end - - it "should return fqdn if cloud.hostname is empty" do - expect( @knife.get_ssh_attribute(@node_bar)).to eq("bar.example.org") - end - end - - describe "#session_from_list" do - before :each do - @knife.instance_variable_set(:@longest, 0) - ssh_config = { timeout: 50, user: "locutus", port: 23, keepalive: true, keepalive_interval: 60 } - allow(Net::SSH).to receive(:configuration_for).with("the.b.org", true).and_return(ssh_config) - end - - it "uses the port from an ssh config file" do - @knife.session_from_list([["the.b.org", nil, nil]]) - expect(@knife.session.servers[0].port).to eq(23) - end - - it "uses the port from a cloud attr" do - @knife.session_from_list([["the.b.org", 123, nil]]) - expect(@knife.session.servers[0].port).to eq(123) - end - - it "uses the prefix from list" do - @knife.session_from_list([["the.b.org", nil, "b-team"]]) - expect(@knife.session.servers[0][:prefix]).to eq("b-team") - end - - it "defaults to a prefix of host" do - @knife.session_from_list([["the.b.org", nil, nil]]) - expect(@knife.session.servers[0][:prefix]).to eq("the.b.org") - end - - it "defaults to a timeout of 120 seconds" do - @knife.session_from_list([["the.b.org", nil, nil]]) - expect(@knife.session.servers[0].options[:timeout]).to eq(120) - end - - it "uses the timeout from the CLI" do - @knife.config = {} - Chef::Config[:knife][:ssh_timeout] = nil - @knife.config[:ssh_timeout] = 5 - @knife.session_from_list([["the.b.org", nil, nil]]) - @knife.merge_configs - expect(@knife.session.servers[0].options[:timeout]).to eq(5) - end - - it "uses the timeout from knife config" do - @knife.config = {} - Chef::Config[:knife][:ssh_timeout] = 6 - @knife.merge_configs - @knife.session_from_list([["the.b.org", nil, nil]]) - expect(@knife.session.servers[0].options[:timeout]).to eq(6) - end - - it "uses the user from an ssh config file" do - @knife.session_from_list([["the.b.org", 123, nil]]) - expect(@knife.session.servers[0].user).to eq("locutus") - end - - it "uses keepalive settings from an ssh config file" do - @knife.session_from_list([["the.b.org", 123, nil]]) - expect(@knife.session.servers[0].options[:keepalive]).to be true - expect(@knife.session.servers[0].options[:keepalive_interval]).to eq 60 - end - end - - describe "#ssh_command" do - let(:execution_channel) { double(:execution_channel, on_data: nil, on_extended_data: nil) } - let(:session_channel) { double(:session_channel, request_pty: nil) } - - let(:execution_channel2) { double(:execution_channel, on_data: nil, on_extended_data: nil) } - let(:session_channel2) { double(:session_channel, request_pty: nil) } - - let(:session) { double(:session, loop: nil) } - - let(:command) { "false" } - - before do - expect(execution_channel) - .to receive(:on_request) - .and_yield(nil, double(:data_stream, read_long: exit_status)) - - expect(session_channel) - .to receive(:exec) - .with(command) - .and_yield(execution_channel, true) - - expect(execution_channel2) - .to receive(:on_request) - .and_yield(nil, double(:data_stream, read_long: exit_status2)) - - expect(session_channel2) - .to receive(:exec) - .with(command) - .and_yield(execution_channel2, true) - - expect(session) - .to receive(:open_channel) - .and_yield(session_channel) - .and_yield(session_channel2) - end - - context "both connections return 0" do - let(:exit_status) { 0 } - let(:exit_status2) { 0 } - - it "returns a 0 exit code" do - expect(@knife.ssh_command(command, session)).to eq(0) - end - end - - context "the first connection returns 1 and the second returns 0" do - let(:exit_status) { 1 } - let(:exit_status2) { 0 } - - it "returns a non-zero exit code" do - expect(@knife.ssh_command(command, session)).to eq(1) - end - end - - context "the first connection returns 1 and the second returns 2" do - let(:exit_status) { 1 } - let(:exit_status2) { 2 } - - it "returns a non-zero exit code" do - expect(@knife.ssh_command(command, session)).to eq(2) - end - end - end - - describe "#tmux" do - before do - ssh_config = { timeout: 50, user: "locutus", port: 23, keepalive: true, keepalive_interval: 60 } - allow(Net::SSH).to receive(:configuration_for).with("foo.example.org", true).and_return(ssh_config) - @query = Chef::Search::Query.new - expect(@query).to receive(:search).and_yield(@node_foo) - allow(Chef::Search::Query).to receive(:new).and_return(@query) - allow(@knife).to receive(:exec).and_return(0) - end - - it "filters out invalid characters from tmux session name" do - @knife.name_args = ["name:foo.example.org", "tmux"] - expect(@knife).to receive(:shell_out!).with("tmux new-session -d -s 'knife ssh name=foo-example-org' -n 'foo.example.org' 'ssh locutus@foo.example.org' ") - @knife.run - end - end - - describe "#run" do - - it "should print usage and exit when a SEARCH QUERY is not provided" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal).with(/You must specify the SEARCH QUERY./) - expect { @knife.run }.to raise_error(SystemExit) - end - - context "exit" do - before do - @query = Chef::Search::Query.new - expect(@query).to receive(:search).and_yield(@node_foo) - allow(Chef::Search::Query).to receive(:new).and_return(@query) - allow(@knife).to receive(:ssh_command).and_return(exit_code) - @knife.name_args = ["*:*", "false"] - end - - context "with an error" do - let(:exit_code) { 1 } - - it "should exit with a non-zero exit code" do - expect(@knife).to receive(:exit).with(exit_code) - @knife.run - end - end - - context "with no error" do - let(:exit_code) { 0 } - - it "should not exit" do - expect(@knife).not_to receive(:exit) - @knife.run - end - end - end - end -end diff --git a/spec/unit/knife/ssl_check_spec.rb b/spec/unit/knife/ssl_check_spec.rb deleted file mode 100644 index 1165da4539..0000000000 --- a/spec/unit/knife/ssl_check_spec.rb +++ /dev/null @@ -1,256 +0,0 @@ -# -# 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 "spec_helper" -require "stringio" - -describe Chef::Knife::SslCheck do - - let(:name_args) { [] } - let(:stdout_io) { StringIO.new } - let(:stderr_io) { StringIO.new } - - def stderr - stderr_io.string - end - - def stdout - stdout_io.string - end - - subject(:ssl_check) do - s = Chef::Knife::SslCheck.new - allow(s.ui).to receive(:stdout).and_return(stdout_io) - allow(s.ui).to receive(:stderr).and_return(stderr_io) - s.name_args = name_args - s - end - - before do - Chef::Config.chef_server_url = "https://example.com:8443/chef-server" - end - - context "when no arguments are given" do - it "uses the chef_server_url as the host to check" do - expect(ssl_check.host).to eq("example.com") - expect(ssl_check.port).to eq(8443) - end - end - - context "when a specific URI is given" do - let(:name_args) { %w{https://example.test:10443/foo} } - - it "checks the SSL configuration against the given host" do - expect(ssl_check.host).to eq("example.test") - expect(ssl_check.port).to eq(10443) - end - end - - context "when an invalid URI is given" do - - let(:name_args) { %w{foo.test} } - - it "prints an error and exits" do - expect { ssl_check.run }.to raise_error(SystemExit) - expected_stdout = <<~E - USAGE: knife ssl check [URL] (options) - E - expected_stderr = <<~E - ERROR: Given URI: `foo.test' is invalid - E - expect(stdout_io.string).to eq(expected_stdout) - expect(stderr_io.string).to eq(expected_stderr) - end - - context "and its malformed enough to make URI.parse barf" do - - let(:name_args) { %w{ftp://lkj\\blah:example.com/blah} } - - it "prints an error and exits" do - expect { ssl_check.run }.to raise_error(SystemExit) - expected_stdout = <<~E - USAGE: knife ssl check [URL] (options) - E - expected_stderr = <<~E - ERROR: Given URI: `#{name_args[0]}' is invalid - E - expect(stdout_io.string).to eq(expected_stdout) - expect(stderr_io.string).to eq(expected_stderr) - end - end - end - - describe "verifying trusted certificate X509 properties" do - let(:name_args) { %w{https://foo.example.com:8443} } - - let(:trusted_certs_dir) { File.join(CHEF_SPEC_DATA, "trusted_certs") } - let(:trusted_cert_file) { File.join(trusted_certs_dir, "example.crt") } - - let(:store) { OpenSSL::X509::Store.new } - let(:certificate) { OpenSSL::X509::Certificate.new(IO.read(trusted_cert_file)) } - - before do - Chef::Config[:trusted_certs_dir] = trusted_certs_dir - allow(ssl_check).to receive(:trusted_certificates).and_return([trusted_cert_file]) - allow(store).to receive(:add_cert).with(certificate) - allow(OpenSSL::X509::Store).to receive(:new).and_return(store) - allow(OpenSSL::X509::Certificate).to receive(:new).with(IO.read(trusted_cert_file)).and_return(certificate) - allow(ssl_check).to receive(:verify_cert).and_return(true) - allow(ssl_check).to receive(:verify_cert_host).and_return(true) - end - - context "when the trusted certificates directory is not glob escaped", :windows_only do - let(:trusted_certs_dir) { File.join(CHEF_SPEC_DATA.tr("/", "\\"), "trusted_certs") } - - before do - allow(ssl_check).to receive(:trusted_certificates).and_call_original - allow(store).to receive(:verify).with(certificate).and_return(true) - end - - it "escpaes the trusted certificates directory" do - expect(Dir).to receive(:glob) - .with("#{ChefConfig::PathHelper.escape_glob_dir(trusted_certs_dir)}/*.{crt,pem}") - .and_return([trusted_cert_file]) - ssl_check.run - end - end - - context "when the trusted certificates have valid X509 properties" do - before do - allow(store).to receive(:verify).with(certificate).and_return(true) - end - - it "does not generate any X509 warnings" do - expect(ssl_check.ui).not_to receive(:warn).with(/There are invalid certificates in your trusted_certs_dir/) - ssl_check.run - end - end - - context "when the trusted certificates have invalid X509 properties" do - before do - allow(store).to receive(:verify).with(certificate).and_return(false) - allow(store).to receive(:error_string).and_return("unable to get local issuer certificate") - end - - it "generates a warning message with invalid certificate file names" do - expect(ssl_check.ui).to receive(:warn).with(/#{trusted_cert_file}: unable to get local issuer certificate/) - ssl_check.run - end - end - end - - describe "verifying the remote certificate" do - let(:name_args) { %w{https://foo.example.com:8443} } - - let(:tcp_socket) { double(TCPSocket) } - let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket) } - - before do - expect(ssl_check).to receive(:proxified_socket).with("foo.example.com", 8443).and_return(tcp_socket) - expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(tcp_socket, ssl_check.verify_peer_ssl_context).and_return(ssl_socket) - end - - def run - ssl_check.run - rescue Exception - # puts "OUT: #{stdout_io.string}" - # puts "ERR: #{stderr_io.string}" - raise - end - - context "when the remote host's certificate is valid" do - - before do - expect(ssl_check).to receive(:verify_X509).and_return(true) # X509 valid certs (no warn) - expect(ssl_socket).to receive(:connect) # no error - expect(ssl_socket).to receive(:post_connection_check).with("foo.example.com") # no error - expect(ssl_socket).to receive(:hostname=).with("foo.example.com") # no error - end - - it "prints a success message" do - ssl_check.run - expect(stdout_io.string).to include("Successfully verified certificates from `foo.example.com'") - end - end - - describe "and the certificate is not valid" do - - let(:tcp_socket_for_debug) { double(TCPSocket) } - let(:ssl_socket_for_debug) { double(OpenSSL::SSL::SSLSocket) } - - let(:self_signed_crt_path) { File.join(CHEF_SPEC_DATA, "trusted_certs", "example.crt") } - let(:self_signed_crt) { OpenSSL::X509::Certificate.new(File.read(self_signed_crt_path)) } - - before do - @old_signal = trap(:INT, "DEFAULT") - - expect(ssl_check).to receive(:proxified_socket) - .with("foo.example.com", 8443) - .and_return(tcp_socket_for_debug) - expect(OpenSSL::SSL::SSLSocket).to receive(:new) - .with(tcp_socket_for_debug, ssl_check.noverify_peer_ssl_context) - .and_return(ssl_socket_for_debug) - end - - after do - trap(:INT, @old_signal) - end - - context "when the certificate's CN does not match the hostname" do - before do - expect(ssl_check).to receive(:verify_X509).and_return(true) # X509 valid certs - expect(ssl_socket).to receive(:connect) # no error - expect(ssl_socket).to receive(:post_connection_check) - .with("foo.example.com") - .and_raise(OpenSSL::SSL::SSLError) - expect(ssl_socket).to receive(:hostname=).with("foo.example.com") # no error - expect(ssl_socket_for_debug).to receive(:connect) - expect(ssl_socket_for_debug).to receive(:peer_cert).and_return(self_signed_crt) - end - - it "shows the CN used by the certificate and prints an error" do - expect { run }.to raise_error(SystemExit) - expect(stderr).to include("The SSL cert is signed by a trusted authority but is not valid for the given hostname") - expect(stderr).to include("You are attempting to connect to: 'foo.example.com'") - expect(stderr).to include("The server's certificate belongs to 'example.local'") - end - - end - - context "when the cert is not signed by any trusted authority" do - before do - expect(ssl_check).to receive(:verify_X509).and_return(true) # X509 valid certs - expect(ssl_socket).to receive(:connect) - .and_raise(OpenSSL::SSL::SSLError) - expect(ssl_socket).to receive(:hostname=) - .with("foo.example.com") # no error - expect(ssl_socket_for_debug).to receive(:connect) - expect(ssl_socket_for_debug).to receive(:peer_cert).and_return(self_signed_crt) - end - - it "shows the CN used by the certificate and prints an error" do - expect { run }.to raise_error(SystemExit) - expect(stderr).to include("The SSL certificate of foo.example.com could not be verified") - end - - end - end - - end - -end diff --git a/spec/unit/knife/ssl_fetch_spec.rb b/spec/unit/knife/ssl_fetch_spec.rb deleted file mode 100644 index 2184994dc0..0000000000 --- a/spec/unit/knife/ssl_fetch_spec.rb +++ /dev/null @@ -1,222 +0,0 @@ -# -# 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 "spec_helper" -require "chef/knife/ssl_fetch" - -describe Chef::Knife::SslFetch do - - let(:name_args) { [] } - let(:stdout_io) { StringIO.new } - let(:stderr_io) { StringIO.new } - - def stderr - stderr_io.string - end - - def stdout - stdout_io.string - end - - subject(:ssl_fetch) do - s = Chef::Knife::SslFetch.new - s.name_args = name_args - allow(s.ui).to receive(:stdout).and_return(stdout_io) - allow(s.ui).to receive(:stderr).and_return(stderr_io) - s - end - - context "when no arguments are given" do - - before do - Chef::Config.chef_server_url = "https://example.com:8443/chef-server" - end - - it "uses the chef_server_url as the host to fetch" do - expect(ssl_fetch.host).to eq("example.com") - expect(ssl_fetch.port).to eq(8443) - end - end - - context "when a specific URI is given" do - let(:name_args) { %w{https://example.test:10443/foo} } - - it "fetches the SSL configuration against the given host" do - expect(ssl_fetch.host).to eq("example.test") - expect(ssl_fetch.port).to eq(10443) - end - end - - context "when an invalid URI is given" do - - let(:name_args) { %w{foo.test} } - - it "prints an error and exits" do - expect { ssl_fetch.run }.to raise_error(SystemExit) - expected_stdout = <<~E - USAGE: knife ssl fetch [URL] (options) - E - expected_stderr = <<~E - ERROR: Given URI: `foo.test' is invalid - E - expect(stdout_io.string).to eq(expected_stdout) - expect(stderr_io.string).to eq(expected_stderr) - end - - context "and its malformed enough to make URI.parse barf" do - - let(:name_args) { %w{ftp://lkj\\blah:example.com/blah} } - - it "prints an error and exits" do - expect { ssl_fetch.run }.to raise_error(SystemExit) - expected_stdout = <<~E - USAGE: knife ssl fetch [URL] (options) - E - expected_stderr = <<~E - ERROR: Given URI: `#{name_args[0]}' is invalid - E - expect(stdout_io.string).to eq(expected_stdout) - expect(stderr_io.string).to eq(expected_stderr) - end - end - end - - describe "normalizing CNs for use as paths" do - - it "normalizes '*' to 'wildcard'" do - expect(ssl_fetch.normalize_cn("*.example.com")).to eq("wildcard_example_com") - end - - it "normalizes non-alnum and hyphen characters to underscores" do - expect(ssl_fetch.normalize_cn("Billy-Bob's Super Awesome CA!")).to eq("Billy-Bob_s_Super_Awesome_CA_") - end - - end - - describe "#cn_of" do - let(:certificate) { double("Certificate", subject: subject) } - - describe "when the certificate has a common name" do - let(:subject) { [["CN", "common name"]] } - it "returns the common name" do - expect(ssl_fetch.cn_of(certificate)).to eq("common name") - end - end - - describe "when the certificate does not have a common name" do - let(:subject) { [] } - it "returns nil" do - expect(ssl_fetch.cn_of(certificate)).to eq(nil) - end - end - end - - describe "fetching the remote cert chain" do - - let(:name_args) { %w{https://foo.example.com:8443} } - - let(:tcp_socket) { double(TCPSocket) } - let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket) } - - let(:self_signed_crt_path) { File.join(CHEF_SPEC_DATA, "trusted_certs", "example.crt") } - let(:self_signed_crt) { OpenSSL::X509::Certificate.new(File.read(self_signed_crt_path)) } - - let(:trusted_certs_dir) { Dir.mktmpdir } - - def run - ssl_fetch.run - rescue Exception - puts "OUT: #{stdout_io.string}" - puts "ERR: #{stderr_io.string}" - raise - end - - before do - Chef::Config.trusted_certs_dir = trusted_certs_dir - end - - after do - FileUtils.rm_rf(trusted_certs_dir) - end - - context "when the TLS connection is successful" do - - before do - expect(ssl_fetch).to receive(:proxified_socket).with("foo.example.com", 8443).and_return(tcp_socket) - expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(tcp_socket, ssl_fetch.noverify_peer_ssl_context).and_return(ssl_socket) - expect(ssl_socket).to receive(:connect) - expect(ssl_socket).to receive(:peer_cert_chain).and_return([self_signed_crt]) - end - - it "fetches the cert chain and writes the certs to the trusted_certs_dir" do - run - stored_cert_path = File.join(trusted_certs_dir, "example_local.crt") - expect(File).to exist(stored_cert_path) - expect(File.read(stored_cert_path)).to eq(File.read(self_signed_crt_path)) - end - - end - - context "when connecting to a non-SSL service (like HTTP)" do - - let(:name_args) { %w{http://foo.example.com} } - - let(:unknown_protocol_error) { OpenSSL::SSL::SSLError.new("SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol") } - - before do - expect(ssl_fetch).to receive(:proxified_socket).with("foo.example.com", 80).and_return(tcp_socket) - expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(tcp_socket, ssl_fetch.noverify_peer_ssl_context).and_return(ssl_socket) - expect(ssl_socket).to receive(:connect).and_raise(unknown_protocol_error) - - expect(ssl_fetch).to receive(:exit).with(1) - end - - it "tells the user their URL is for a non-ssl service" do - expected_error_text = <<~ERROR_TEXT - ERROR: The service at the given URI (http://foo.example.com) does not accept SSL connections - ERROR: Perhaps you meant to connect to 'https://foo.example.com'? - ERROR_TEXT - - run - expect(stderr).to include(expected_error_text) - end - - end - - describe "when the certificate does not have a CN" do - let(:self_signed_crt_path) { File.join(CHEF_SPEC_DATA, "trusted_certs", "example_no_cn.crt") } - let(:self_signed_crt) { OpenSSL::X509::Certificate.new(File.read(self_signed_crt_path)) } - - before do - expect(ssl_fetch).to receive(:proxified_socket).with("foo.example.com", 8443).and_return(tcp_socket) - expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(tcp_socket, ssl_fetch.noverify_peer_ssl_context).and_return(ssl_socket) - expect(ssl_socket).to receive(:connect) - expect(ssl_socket).to receive(:peer_cert_chain).and_return([self_signed_crt]) - expect(Time).to receive(:new).and_return(1) - end - - it "fetches the certificate and writes it to a file in the trusted_certs_dir" do - run - stored_cert_path = File.join(trusted_certs_dir, "foo.example.com_1.crt") - expect(File).to exist(stored_cert_path) - expect(File.read(stored_cert_path)).to eq(File.read(self_signed_crt_path)) - end - end - - end -end diff --git a/spec/unit/knife/status_spec.rb b/spec/unit/knife/status_spec.rb deleted file mode 100644 index 838e4c9600..0000000000 --- a/spec/unit/knife/status_spec.rb +++ /dev/null @@ -1,112 +0,0 @@ -# -# Author:: Sahil Muthoo (<sahil.muthoo@gmail.com>) -# 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 "spec_helper" - -describe Chef::Knife::Status do - before(:each) do - node = Chef::Node.new.tap do |n| - n.automatic_attrs["fqdn"] = "foobar" - n.automatic_attrs["ohai_time"] = 1343845969 - n.automatic_attrs["platform"] = "mac_os_x" - n.automatic_attrs["platform_version"] = "10.12.5" - end - allow(Time).to receive(:now).and_return(Time.at(1428573420)) - @query = double("Chef::Search::Query") - allow(@query).to receive(:search).and_yield(node) - allow(Chef::Search::Query).to receive(:new).and_return(@query) - @knife = Chef::Knife::Status.new - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - let(:opts) do - { filter_result: - { name: ["name"], ipaddress: ["ipaddress"], ohai_time: ["ohai_time"], - cloud: ["cloud"], run_list: ["run_list"], platform: ["platform"], - platform_version: ["platform_version"], chef_environment: ["chef_environment"] } } - end - - it "should default to searching for everything" do - expect(@query).to receive(:search).with(:node, "*:*", opts) - @knife.run - end - - it "should filter by nodes older than some mins" do - @knife.config[:hide_by_mins] = 59 - expect(@query).to receive(:search).with(:node, "NOT ohai_time:[1428569880 TO 1428573420]", opts) - @knife.run - end - - it "should filter by environment" do - @knife.config[:environment] = "production" - expect(@query).to receive(:search).with(:node, "chef_environment:production", opts) - @knife.run - end - - it "should filter by environment and nodes older than some mins" do - @knife.config[:environment] = "production" - @knife.config[:hide_by_mins] = 59 - expect(@query).to receive(:search).with(:node, "chef_environment:production NOT ohai_time:[1428569880 TO 1428573420]", opts) - @knife.run - end - - it "should not use partial search with long output" do - @knife.config[:long_output] = true - expect(@query).to receive(:search).with(:node, "*:*", {}) - @knife.run - end - - context "with a custom query" do - before :each do - @knife.instance_variable_set(:@name_args, ["name:my_custom_name"]) - end - - it "should allow a custom query to be specified" do - expect(@query).to receive(:search).with(:node, "name:my_custom_name", opts) - @knife.run - end - - it "should filter by nodes older than some mins with nodename specified" do - @knife.config[:hide_by_mins] = 59 - expect(@query).to receive(:search).with(:node, "name:my_custom_name NOT ohai_time:[1428569880 TO 1428573420]", opts) - @knife.run - end - - it "should filter by environment with nodename specified" do - @knife.config[:environment] = "production" - expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production", opts) - @knife.run - end - - it "should filter by environment and nodes older than some mins with nodename specified" do - @knife.config[:environment] = "production" - @knife.config[:hide_by_mins] = 59 - expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production NOT ohai_time:[1428569880 TO 1428573420]", opts) - @knife.run - end - end - - it "should not colorize output unless it's writing to a tty" do - @knife.run - expect(@stdout.string.match(/foobar/)).not_to be_nil - expect(@stdout.string.match(/\e.*ago/)).to be_nil - end - end -end diff --git a/spec/unit/knife/supermarket_download_spec.rb b/spec/unit/knife/supermarket_download_spec.rb deleted file mode 100644 index 5d15e74966..0000000000 --- a/spec/unit/knife/supermarket_download_spec.rb +++ /dev/null @@ -1,152 +0,0 @@ -# -# Author:: Thomas Bishop (<bishop.thomas@gmail.com>) -# Copyright:: Copyright 2012-2016, Thomas Bishop -# 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 "chef/knife/supermarket_download" -require "spec_helper" - -describe Chef::Knife::SupermarketDownload do - - describe "run" do - before do - @knife = Chef::Knife::SupermarketDownload.new - @knife.name_args = ["apache2"] - @noauth_rest = double("no auth rest") - @stderr = StringIO.new - @cookbook_api_url = "https://supermarket.chef.io/api/v1/cookbooks" - @version = "1.0.2" - @version_us = @version.tr ".", "_" - @current_data = { "deprecated" => false, - "latest_version" => "#{@cookbook_api_url}/apache2/versions/#{@version_us}", - "replacement" => "other_apache2" } - - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - allow(@knife).to receive(:noauth_rest).and_return(@noauth_rest) - expect(@noauth_rest).to receive(:get) - .with("#{@cookbook_api_url}/apache2") - .and_return(@current_data) - @knife.configure_chef - end - - context "when the cookbook is deprecated and not forced" do - before do - @current_data["deprecated"] = true - end - - it "should warn with info about the replacement" do - expect(@knife.ui).to receive(:warn) - .with(/.+deprecated.+replaced by other_apache2.+/i) - expect(@knife.ui).to receive(:warn) - .with(/use --force.+download.+/i) - @knife.run - end - end - - context "when" do - before do - @cookbook_data = { "version" => @version, - "file" => "http://example.com/apache2_#{@version_us}.tgz" } - @temp_file = double( path: "/tmp/apache2_#{@version_us}.tgz" ) - @file = File.join(Dir.pwd, "apache2-#{@version}.tar.gz") - end - - context "downloading the latest version" do - before do - expect(@noauth_rest).to receive(:get) - .with(@current_data["latest_version"]) - .and_return(@cookbook_data) - expect(@noauth_rest).to receive(:streaming_request) - .with(@cookbook_data["file"]) - .and_return(@temp_file) - end - - context "and it is deprecated and with --force" do - before do - @current_data["deprecated"] = true - @knife.config[:force] = true - end - - it "should download the latest version" do - expect(@knife.ui).to receive(:warn) - .with(/.+deprecated.+replaced by other_apache2.+/i) - expect(FileUtils).to receive(:cp).with(@temp_file.path, @file) - @knife.run - expect(@stderr.string).to match(/downloading apache2.+version.+#{Regexp.escape(@version)}/i) - expect(@stderr.string).to match(/cookbook save.+#{Regexp.escape(@file)}/i) - end - - end - - it "should download the latest version" do - expect(FileUtils).to receive(:cp).with(@temp_file.path, @file) - @knife.run - expect(@stderr.string).to match(/downloading apache2.+version.+#{Regexp.escape(@version)}/i) - expect(@stderr.string).to match(/cookbook save.+#{Regexp.escape(@file)}/i) - end - - context "with -f or --file" do - before do - @file = "/opt/chef/cookbooks/apache2.tar.gz" - @knife.config[:file] = @file - expect(FileUtils).to receive(:cp).with(@temp_file.path, @file) - end - - it "should download the cookbook to the desired file" do - @knife.run - expect(@stderr.string).to match(/downloading apache2.+version.+#{Regexp.escape(@version)}/i) - expect(@stderr.string).to match(/cookbook save.+#{Regexp.escape(@file)}/i) - end - end - - it "should provide an accessor to the version" do - allow(FileUtils).to receive(:cp).and_return(true) - expect(@knife.version).to eq(@version) - @knife.run - end - end - - context "downloading a cookbook of a specific version" do - before do - @version = "1.0.1" - @version_us = @version.tr ".", "_" - @cookbook_data = { "version" => @version, - "file" => "http://example.com/apache2_#{@version_us}.tgz" } - @temp_file = double(path: "/tmp/apache2_#{@version_us}.tgz") - @file = File.join(Dir.pwd, "apache2-#{@version}.tar.gz") - @knife.name_args << @version - end - - it "should download the desired version" do - expect(@noauth_rest).to receive(:get) - .with("#{@cookbook_api_url}/apache2/versions/#{@version_us}") - .and_return(@cookbook_data) - expect(@noauth_rest).to receive(:streaming_request) - .with(@cookbook_data["file"]) - .and_return(@temp_file) - expect(FileUtils).to receive(:cp).with(@temp_file.path, @file) - @knife.run - expect(@stderr.string).to match(/downloading apache2.+version.+#{Regexp.escape(@version)}/i) - expect(@stderr.string).to match(/cookbook save.+#{Regexp.escape(@file)}/i) - end - end - - end - - end - -end diff --git a/spec/unit/knife/supermarket_install_spec.rb b/spec/unit/knife/supermarket_install_spec.rb deleted file mode 100644 index 03cc5d1992..0000000000 --- a/spec/unit/knife/supermarket_install_spec.rb +++ /dev/null @@ -1,202 +0,0 @@ -# -# Author:: Steven Danna (<steve@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 "spec_helper" -require "chef/knife/supermarket_install" - -describe Chef::Knife::SupermarketInstall do - let(:knife) { Chef::Knife::SupermarketInstall.new } - let(:stdout) { StringIO.new } - let(:stderr) { StringIO.new } - let(:downloader) { {} } - let(:archive) { double(Mixlib::Archive, extract: true) } - let(:repo) do - double(sanity_check: true, reset_to_default_state: true, - prepare_to_import: true, finalize_updates_to: true, - merge_updates_from: true) - end - let(:install_path) do - if ChefUtils.windows? - "C:/tmp/chef" - else - "/var/tmp/chef" - end - end - - before(:each) do - require "chef/knife/core/cookbook_scm_repo" - - allow(knife.ui).to receive(:stdout).and_return(stdout) - knife.config = {} - knife.config[:cookbook_path] = [ install_path ] - - allow(knife).to receive(:stderr).and_return(stderr) - allow(knife).to receive(:stdout).and_return(stdout) - - # Assume all external commands would have succeed. :( - allow(File).to receive(:unlink) - allow(File).to receive(:rmtree) - allow(knife).to receive(:shell_out!).and_return(true) - allow(Mixlib::Archive).to receive(:new).and_return(archive) - - # SupermarketDownload Setup - allow(knife).to receive(:download_cookbook_to).and_return(downloader) - allow(downloader).to receive(:version) do - if knife.name_args.size == 2 - knife.name_args[1] - else - "0.3.0" - end - end - - # Stubs for CookbookSCMRepo - allow(Chef::Knife::CookbookSCMRepo).to receive(:new).and_return(repo) - end - - describe "run" do - it "raises an error if a cookbook name is not provided" do - knife.name_args = [] - expect(knife.ui).to receive(:error).with("Please specify a cookbook to download and install.") - expect { knife.run }.to raise_error(SystemExit) - end - - it "raises an error if more than two arguments are given" do - knife.name_args = %w{foo bar baz} - expect(knife.ui).to receive(:error).with("Installing multiple cookbooks at once is not supported.") - expect { knife.run }.to raise_error(SystemExit) - end - - it "raises an error if the second argument is not a version" do - knife.name_args = %w{getting-started 1pass} - expect(knife.ui).to receive(:error).with("Installing multiple cookbooks at once is not supported.") - expect { knife.run }.to raise_error(SystemExit) - end - - it "raises an error if the second argument is a four-digit version" do - knife.name_args = ["getting-started", "0.0.0.1"] - expect(knife.ui).to receive(:error).with("Installing multiple cookbooks at once is not supported.") - expect { knife.run }.to raise_error(SystemExit) - end - - it "raises an error if the second argument is a one-digit version" do - knife.name_args = %w{getting-started 1} - expect(knife.ui).to receive(:error).with("Installing multiple cookbooks at once is not supported.") - expect { knife.run }.to raise_error(SystemExit) - end - - it "installs the specified version if second argument is a three-digit version" do - knife.name_args = ["getting-started", "0.1.0"] - knife.config[:no_deps] = true - upstream_file = File.join(install_path, "getting-started.tar.gz") - expect(knife).to receive(:download_cookbook_to).with(upstream_file) - expect(knife).to receive(:extract_cookbook).with(upstream_file, "0.1.0") - expect(knife).to receive(:clear_existing_files).with(File.join(install_path, "getting-started")) - expect(repo).to receive(:merge_updates_from).with("getting-started", "0.1.0") - knife.run - end - - it "installs the specified version if second argument is a two-digit version" do - knife.name_args = ["getting-started", "0.1"] - knife.config[:no_deps] = true - upstream_file = File.join(install_path, "getting-started.tar.gz") - expect(knife).to receive(:download_cookbook_to).with(upstream_file) - expect(knife).to receive(:extract_cookbook).with(upstream_file, "0.1") - expect(knife).to receive(:clear_existing_files).with(File.join(install_path, "getting-started")) - expect(repo).to receive(:merge_updates_from).with("getting-started", "0.1") - knife.run - end - - it "installs the latest version if only a cookbook name is given" do - knife.name_args = ["getting-started"] - knife.config[:no_deps] = true - upstream_file = File.join(install_path, "getting-started.tar.gz") - expect(knife).to receive(:download_cookbook_to).with(upstream_file) - expect(knife).to receive(:extract_cookbook).with(upstream_file, "0.3.0") - expect(knife).to receive(:clear_existing_files).with(File.join(install_path, "getting-started")) - expect(repo).to receive(:merge_updates_from).with("getting-started", "0.3.0") - knife.run - end - - it "does not create/reset git branches if use_current_branch is set" do - knife.name_args = ["getting-started"] - knife.config[:use_current_branch] = true - knife.config[:no_deps] = true - upstream_file = File.join(install_path, "getting-started.tar.gz") - expect(repo).not_to receive(:prepare_to_import) - expect(repo).not_to receive(:reset_to_default_state) - knife.run - end - - it "does not raise an error if cookbook_path is a string" do - knife.config[:cookbook_path] = install_path - knife.config[:no_deps] = true - knife.name_args = ["getting-started"] - upstream_file = File.join(install_path, "getting-started.tar.gz") - expect(knife).to receive(:download_cookbook_to).with(upstream_file) - expect(knife).to receive(:extract_cookbook).with(upstream_file, "0.3.0") - expect(knife).to receive(:clear_existing_files).with(File.join(install_path, "getting-started")) - expect(repo).to receive(:merge_updates_from).with("getting-started", "0.3.0") - expect { knife.run }.not_to raise_error - end - end # end of run - - let(:metadata) { Chef::Cookbook::Metadata.new } - let(:rb_metadata_path) { File.join(install_path, "post-punk-kitchen", "metadata.rb") } - let(:json_metadata_path) { File.join(install_path, "post-punk-kitchen", "metadata.json") } - - describe "preferred_metadata" do - before do - allow(Chef::Cookbook::Metadata).to receive(:new).and_return(metadata) - allow(File).to receive(:exist?).and_return(false) - knife.instance_variable_set(:@cookbook_name, "post-punk-kitchen") - knife.instance_variable_set(:@install_path, install_path) - end - - it "returns a populated Metadata object if metadata.rb exists" do - allow(File).to receive(:exist?).with(rb_metadata_path).and_return(true) - expect(metadata).to receive(:from_file).with(rb_metadata_path) - knife.preferred_metadata - end - - it "returns a populated Metadata object if metadata.json exists" do - allow(File).to receive(:exist?).with(json_metadata_path).and_return(true) - # expect(IO).to receive(:read).with(json_metadata_path) - allow(IO).to receive(:read) - expect(metadata).to receive(:from_json) - knife.preferred_metadata - end - - it "prefers metadata.rb over metadata.json" do - allow(File).to receive(:exist?).with(rb_metadata_path).and_return(true) - allow(File).to receive(:exist?).with(json_metadata_path).and_return(true) - allow(IO).to receive(:read) - expect(metadata).to receive(:from_file).with(rb_metadata_path) - expect(metadata).not_to receive(:from_json) - knife.preferred_metadata - end - - it "rasies an error if it finds no metadata file" do - expect { knife.preferred_metadata }.to raise_error { |error| - expect(error).to be_a(Chef::Exceptions::MetadataNotFound) - expect(error.cookbook_name).to eq("post-punk-kitchen") - expect(error.install_path).to eq(install_path) - } - end - - end -end diff --git a/spec/unit/knife/supermarket_list_spec.rb b/spec/unit/knife/supermarket_list_spec.rb deleted file mode 100644 index a1acccaaaa..0000000000 --- a/spec/unit/knife/supermarket_list_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -# -# Author:: Vivek Singh (<vivek.singh@msystechnologies.com>) -# 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 "chef/knife/supermarket_list" -require "spec_helper" - -describe Chef::Knife::SupermarketList do - let(:knife) { described_class.new } - let(:noauth_rest) { double("no auth rest") } - let(:stdout) { StringIO.new } - let(:cookbooks_data) { - [ - { "cookbook_name" => "1password", "cookbook_maintainer" => "jtimberman", "cookbook_description" => "Installs 1password", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/1password" }, - { "cookbook_name" => "301", "cookbook_maintainer" => "markhuge", "cookbook_description" => "Installs/Configures 301", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/301" }, - { "cookbook_name" => "3cx", "cookbook_maintainer" => "obay", "cookbook_description" => "Installs/Configures 3cx", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/3cx" }, - { "cookbook_name" => "7dtd", "cookbook_maintainer" => "gregf", "cookbook_description" => "Installs/Configures the 7 Days To Die server", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/7dtd" }, - { "cookbook_name" => "7-zip", "cookbook_maintainer" => "sneal", "cookbook_description" => "Installs/Configures the 7-zip file archiver", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/7-zip" }, - ] - } - - let(:response_text) { - { - "start" => 0, - "total" => 5, - "items" => cookbooks_data, - } - } - - describe "run" do - before do - allow(knife.ui).to receive(:stdout).and_return(stdout) - allow(knife).to receive(:noauth_rest).and_return(noauth_rest) - expect(noauth_rest).to receive(:get).and_return(response_text) - knife.configure_chef - end - - it "should display all supermarket cookbooks" do - knife.run - cookbooks_data.each do |item| - expect(stdout.string).to match(/#{item["cookbook_name"]}\s/) - end - end - - describe "with -w or --with-uri" do - it "should display the cookbook uris" do - knife.config[:with_uri] = true - knife.run - cookbooks_data.each do |item| - expect(stdout.string).to match(/#{item["cookbook_name"]}\s/) - expect(stdout.string).to match(/#{item["cookbook"]}\s/) - end - end - end - end -end diff --git a/spec/unit/knife/supermarket_search_spec.rb b/spec/unit/knife/supermarket_search_spec.rb deleted file mode 100644 index cba2f615aa..0000000000 --- a/spec/unit/knife/supermarket_search_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -# -# Author:: Vivek Singh (<vivek.singh@msystechnologies.com>) -# 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 "chef/knife/supermarket_search" -require "spec_helper" - -describe Chef::Knife::SupermarketSearch do - let(:knife) { described_class.new } - let(:noauth_rest) { double("no auth rest") } - let(:stdout) { StringIO.new } - let(:cookbooks_data) { - [ - { "cookbook_name" => "mysql", "cookbook_maintainer" => "sous-chefs", "cookbook_description" => "Provides mysql_service, mysql_config, and mysql_client resources", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mysql" }, - { "cookbook_name" => "mw_mysql", "cookbook_maintainer" => "car", "cookbook_description" => "Installs/Configures mw_mysql", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mw_mysql" }, - { "cookbook_name" => "L7-mysql", "cookbook_maintainer" => "szelcsanyi", "cookbook_description" => "Installs/Configures MySQL server", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/l7-mysql" }, - { "cookbook_name" => "mysql-sys", "cookbook_maintainer" => "ovaistariq", "cookbook_description" => "Installs the mysql-sys tool. Description of the tool is available here https://github.com/MarkLeith/mysql-sys", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mysql-sys" }, - { "cookbook_name" => "cg_mysql", "cookbook_maintainer" => "phai", "cookbook_description" => "Installs/Configures mysql with master and slave", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/cg_mysql" }, - ] - } - - let(:response_text) { - { - "start" => 0, - "total" => 5, - "items" => cookbooks_data, - } - } - - let(:empty_response_text) { - { - "start" => 0, - "total" => 0, - "items" => [], - } - } - - describe "run" do - before do - allow(knife.ui).to receive(:stdout).and_return(stdout) - allow(knife).to receive(:noauth_rest).and_return(noauth_rest) - knife.configure_chef - end - - context "when name_args is present" do - before do - expect(noauth_rest).to receive(:get).and_return(response_text) - end - - it "should display cookbooks with given name value" do - knife.name_args = ["mysql"] - knife.run - cookbooks_data.each do |item| - expect(stdout.string).to match(/#{item["cookbook_name"]}\s/) - end - end - end - - context "when name_args is empty string" do - before do - expect(noauth_rest).to receive(:get).and_return(empty_response_text) - end - - it "display nothing with name arg empty string" do - knife.name_args = [""] - knife.run - expect(stdout.string).to eq("\n") - end - end - end -end diff --git a/spec/unit/knife/supermarket_share_spec.rb b/spec/unit/knife/supermarket_share_spec.rb deleted file mode 100644 index f6c44f4cd8..0000000000 --- a/spec/unit/knife/supermarket_share_spec.rb +++ /dev/null @@ -1,209 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@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 "spec_helper" -require "chef/knife/supermarket_share" -require "chef/cookbook_uploader" -require "chef/cookbook_site_streaming_uploader" - -describe Chef::Knife::SupermarketShare do - - before(:each) do - @knife = Chef::Knife::SupermarketShare.new - # Merge default settings in. - @knife.merge_configs - @knife.name_args = %w{cookbook_name AwesomeSausage} - - @cookbook = Chef::CookbookVersion.new("cookbook_name") - - @cookbook_loader = double("Chef::CookbookLoader") - allow(@cookbook_loader).to receive(:cookbook_exists?).and_return(true) - allow(@cookbook_loader).to receive(:[]).and_return(@cookbook) - allow(Chef::CookbookLoader).to receive(:new).and_return(@cookbook_loader) - - @noauth_rest = double(Chef::ServerAPI) - allow(@knife).to receive(:noauth_rest).and_return(@noauth_rest) - - @cookbook_uploader = Chef::CookbookUploader.new("herpderp", rest: "norest") - allow(Chef::CookbookUploader).to receive(:new).and_return(@cookbook_uploader) - allow(@cookbook_uploader).to receive(:validate_cookbooks).and_return(true) - allow(Chef::CookbookSiteStreamingUploader).to receive(:create_build_dir).and_return(Dir.mktmpdir) - - allow(@knife).to receive(:shell_out!).and_return(true) - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - - before(:each) do - allow(@knife).to receive(:do_upload).and_return(true) - @category_response = { - "name" => "cookbook_name", - "category" => "Testing Category", - } - @bad_category_response = { - "error_code" => "NOT_FOUND", - "error_messages" => [ - "Resource does not exist.", - ], - } - end - - it "should set true to config[:dry_run] as default" do - expect(@knife.config[:dry_run]).to be_falsey - end - - it "should should print usage and exit when given no arguments" do - @knife.name_args = [] - expect(@knife).to receive(:show_usage) - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should not fail when given only 1 argument and can determine category" do - @knife.name_args = ["cookbook_name"] - expect(@noauth_rest).to receive(:get).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name").and_return(@category_response) - expect(@knife).to receive(:do_upload) - @knife.run - end - - it "should use a default category when given only 1 argument and cannot determine category" do - @knife.name_args = ["cookbook_name"] - expect(@noauth_rest).to receive(:get).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name") { raise Net::HTTPClientException.new("404 Not Found", OpenStruct.new(code: "404")) } - expect(@knife).to receive(:do_upload) - expect { @knife.run }.to_not raise_error - end - - it "should print error and exit when given only 1 argument and Chef::ServerAPI throws an exception" do - @knife.name_args = ["cookbook_name"] - expect(@noauth_rest).to receive(:get).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name") { raise Errno::ECONNREFUSED, "Connection refused" } - expect(@knife.ui).to receive(:fatal) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should check if the cookbook exists" do - expect(@cookbook_loader).to receive(:cookbook_exists?) - @knife.run - end - - it "should exit and log to error if the cookbook doesn't exist" do - allow(@cookbook_loader).to receive(:cookbook_exists?).and_return(false) - expect(@knife.ui).to receive(:error) - expect { @knife.run }.to raise_error(SystemExit) - end - - if File.exist?("/usr/bin/gnutar") || File.exist?("/bin/gnutar") - it "should use gnutar to make a tarball of the cookbook" do - expect(@knife).to receive(:shell_out!) do |args| - expect(args.to_s).to match(/gnutar -czf/) - end - @knife.run - end - else - it "should make a tarball of the cookbook" do - expect(@knife).to receive(:shell_out!) do |args| - expect(args.to_s).to match(/tar -czf/) - end - @knife.run - end - end - - it "should exit and log to error when the tarball creation fails" do - allow(@knife).to receive(:shell_out!).and_raise(Chef::Exceptions::Exec) - expect(@knife.ui).to receive(:error) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should upload the cookbook and clean up the tarball" do - expect(@knife).to receive(:do_upload) - expect(FileUtils).to receive(:rm_rf) - @knife.run - end - - context "when the --dry-run flag is specified" do - before do - allow(Chef::CookbookSiteStreamingUploader).to receive(:create_build_dir).and_return("/var/tmp/dummy") - @knife.config = { dry_run: true } - allow(@knife).to receive_message_chain(:shell_out!, :stdout).and_return("file") - end - - it "should list files in the tarball" do - allow(@knife).to receive(:tar_cmd).and_return("footar") - expect(@knife).to receive(:shell_out!).with("footar -czf #{@cookbook.name}.tgz #{@cookbook.name}", { cwd: "/var/tmp/dummy" }) - expect(@knife).to receive(:shell_out!).with("footar -tzf #{@cookbook.name}.tgz", { cwd: "/var/tmp/dummy" }) - @knife.run - end - - it "does not upload the cookbook" do - allow(@knife).to receive(:shell_out!).and_return(true) - expect(@knife).not_to receive(:do_upload) - @knife.run - end - end - end - - describe "do_upload" do - - before(:each) do - @upload_response = double("Net::HTTPResponse") - allow(Chef::CookbookSiteStreamingUploader).to receive(:post).and_return(@upload_response) - - @stdout = StringIO.new - @stderr = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - allow(File).to receive(:open).and_return(true) - end - - it 'should post the cookbook to "https://supermarket.chef.io"' do - response_text = Chef::JSONCompat.to_json({ uri: "https://supermarket.chef.io/cookbooks/cookbook_name" }) - allow(@upload_response).to receive(:body).and_return(response_text) - allow(@upload_response).to receive(:code).and_return(201) - expect(Chef::CookbookSiteStreamingUploader).to receive(:post).with(/supermarket\.chef\.io/, anything, anything, anything) - @knife.run - end - - it "should alert the user when a version already exists" do - response_text = Chef::JSONCompat.to_json({ error_messages: ["Version already exists"] }) - allow(@upload_response).to receive(:body).and_return(response_text) - allow(@upload_response).to receive(:code).and_return(409) - expect { @knife.run }.to raise_error(SystemExit) - expect(@stderr.string).to match(/ERROR(.+)cookbook already exists/) - end - - it "should pass any errors on to the user" do - response_text = Chef::JSONCompat.to_json({ error_messages: ["You're holding it wrong"] }) - allow(@upload_response).to receive(:body).and_return(response_text) - allow(@upload_response).to receive(:code).and_return(403) - expect { @knife.run }.to raise_error(SystemExit) - expect(@stderr.string).to match("ERROR(.*)You're holding it wrong") - end - - it "should print the body if no errors are exposed on failure" do - response_text = Chef::JSONCompat.to_json({ system_error: "Your call was dropped", reason: "There's a map for that" }) - allow(@upload_response).to receive(:body).and_return(response_text) - allow(@upload_response).to receive(:code).and_return(500) - expect(@knife.ui).to receive(:error).with(/#{Regexp.escape(response_text)}/) # .ordered - expect(@knife.ui).to receive(:error).with(/Unknown error/) # .ordered - expect { @knife.run }.to raise_error(SystemExit) - end - - end - -end diff --git a/spec/unit/knife/supermarket_unshare_spec.rb b/spec/unit/knife/supermarket_unshare_spec.rb deleted file mode 100644 index 8ae4d03cb5..0000000000 --- a/spec/unit/knife/supermarket_unshare_spec.rb +++ /dev/null @@ -1,78 +0,0 @@ -# -# Author:: Stephen Delano (<stephen@chef.io>) -# Author:: Tim Hinderliter (<tim@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 "spec_helper" -require "chef/knife/supermarket_unshare" - -describe Chef::Knife::SupermarketUnshare do - - before(:each) do - @knife = Chef::Knife::SupermarketUnshare.new - @knife.name_args = ["cookbook_name"] - allow(@knife).to receive(:confirm).and_return(true) - - @rest = double("Chef::ServerAPI") - allow(@rest).to receive(:delete).and_return(true) - allow(@knife).to receive(:rest).and_return(@rest) - @stdout = StringIO.new - allow(@knife.ui).to receive(:stdout).and_return(@stdout) - end - - describe "run" do - - describe "with no cookbook argument" do - it "should print the usage and exit" do - @knife.name_args = [] - expect(@knife.ui).to receive(:fatal) - expect(@knife).to receive(:show_usage) - expect { @knife.run }.to raise_error(SystemExit) - end - end - - it "should confirm you want to unshare the cookbook" do - expect(@knife).to receive(:confirm) - @knife.run - end - - it "should send a delete request to the cookbook site" do - expect(@rest).to receive(:delete) - @knife.run - end - - it "should log an error and exit when forbidden" do - exception = double('403 "Forbidden"', code: "403") - allow(@rest).to receive(:delete).and_raise(Net::HTTPClientException.new('403 "Forbidden"', exception)) - expect(@knife.ui).to receive(:error) - expect { @knife.run }.to raise_error(SystemExit) - end - - it "should re-raise any non-forbidden errors on delete" do - exception = double('500 "Application Error"', code: "500") - allow(@rest).to receive(:delete).and_raise(Net::HTTPClientException.new('500 "Application Error"', exception)) - expect { @knife.run }.to raise_error(Net::HTTPClientException) - end - - it "should log a success message" do - expect(@knife.ui).to receive(:info) - @knife.run - end - - end - -end diff --git a/spec/unit/knife/tag_create_spec.rb b/spec/unit/knife/tag_create_spec.rb deleted file mode 100644 index a1a4923871..0000000000 --- a/spec/unit/knife/tag_create_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require "spec_helper" - -describe Chef::Knife::TagCreate do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::TagCreate.new - @knife.name_args = [ Chef::Config[:node_name], "happytag" ] - - @node = Chef::Node.new - allow(@node).to receive :save - allow(Chef::Node).to receive(:load).and_return @node - @stderr = StringIO.new - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - end - - describe "run" do - it "can create tags on a node" do - @knife.run - expect(@node.tags).to eq(["happytag"]) - expect(@stderr.string).to match(/created tags happytag.+node webmonkey.example.com/i) - end - end -end diff --git a/spec/unit/knife/tag_delete_spec.rb b/spec/unit/knife/tag_delete_spec.rb deleted file mode 100644 index 4201196de0..0000000000 --- a/spec/unit/knife/tag_delete_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "spec_helper" - -describe Chef::Knife::TagDelete do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::TagDelete.new - @knife.name_args = [ Chef::Config[:node_name], "sadtag" ] - - @node = Chef::Node.new - allow(@node).to receive :save - @node.tags << "sadtag" << "happytag" - allow(Chef::Node).to receive(:load).and_return @node - @stderr = StringIO.new - allow(@knife.ui).to receive(:stderr).and_return(@stderr) - end - - describe "run" do - it "can delete tags on a node" do - expect(@node.tags).to eq(%w{sadtag happytag}) - @knife.run - expect(@node.tags).to eq(["happytag"]) - expect(@stderr.string).to match(/deleted.+sadtag/i) - end - end -end diff --git a/spec/unit/knife/tag_list_spec.rb b/spec/unit/knife/tag_list_spec.rb deleted file mode 100644 index dceec9a5ea..0000000000 --- a/spec/unit/knife/tag_list_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require "spec_helper" - -describe Chef::Knife::TagList do - before(:each) do - Chef::Config[:node_name] = "webmonkey.example.com" - @knife = Chef::Knife::TagList.new - @knife.name_args = [ Chef::Config[:node_name], "sadtag" ] - - @node = Chef::Node.new - allow(@node).to receive :save - @node.tags << "sadtag" << "happytag" - allow(Chef::Node).to receive(:load).and_return @node - end - - describe "run" do - it "can list tags on a node" do - expected = %w{sadtag happytag} - expect(@node.tags).to eq(expected) - expect(@knife).to receive(:output).with(expected) - @knife.run - end - end -end diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb deleted file mode 100644 index be3d2fd99c..0000000000 --- a/spec/unit/knife/user_create_spec.rb +++ /dev/null @@ -1,184 +0,0 @@ -# -# Author:: Steven Danna (<steve@chef.io>) -# Author:: Tyler Cloke (<tyler@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 "spec_helper" - -Chef::Knife::UserCreate.load_deps - -describe Chef::Knife::UserCreate do - let(:knife) { Chef::Knife::UserCreate.new } - - let(:stderr) do - StringIO.new - end - - let(:stdout) do - StringIO.new - end - - before(:each) do - allow(knife.ui).to receive(:stdout).and_return(stdout) - allow(knife.ui).to receive(:stderr).and_return(stderr) - allow(knife.ui).to receive(:warn) - end - - context "when USERNAME isn't specified" do - # from spec/support/shared/unit/knife_shared.rb - it_should_behave_like "mandatory field missing" do - let(:name_args) { [] } - let(:fieldname) { "username" } - end - end - - context "when FIRST_NAME isn't specified" do - # from spec/support/shared/unit/knife_shared.rb - it_should_behave_like "mandatory field missing" do - let(:name_args) { %w{some_user some_display_name} } - let(:fieldname) { "first name" } - end - end - - context "when LAST_NAME isn't specified" do - # from spec/support/shared/unit/knife_shared.rb - it_should_behave_like "mandatory field missing" do - let(:name_args) { %w{some_user some_display_name some_first_name} } - let(:fieldname) { "last name" } - end - end - - context "when EMAIL isn't specified" do - # from spec/support/shared/unit/knife_shared.rb - it_should_behave_like "mandatory field missing" do - let(:name_args) { %w{some_user some_display_name some_first_name some_last_name} } - let(:fieldname) { "email" } - end - end - - context "when PASSWORD isn't specified" do - # from spec/support/shared/unit/knife_shared.rb - it_should_behave_like "mandatory field missing" do - let(:name_args) { %w{some_user some_display_name some_first_name some_last_name some_email} } - let(:fieldname) { "password" } - end - end - - context "when all mandatory fields are validly specified" do - before do - knife.name_args = %w{some_user some_display_name some_first_name some_last_name some_email some_password} - allow(knife).to receive(:edit_hash).and_return(knife.user.to_hash) - allow(knife).to receive(:create_user_from_hash).and_return(knife.user) - end - - before(:each) do - # reset the user field every run - knife.user_field = nil - end - - it "sets all the mandatory fields" do - knife.run - expect(knife.user.username).to eq("some_user") - expect(knife.user.display_name).to eq("some_display_name") - expect(knife.user.first_name).to eq("some_first_name") - expect(knife.user.last_name).to eq("some_last_name") - expect(knife.user.email).to eq("some_email") - expect(knife.user.password).to eq("some_password") - end - - context "when user_key and prevent_keygen are passed" do - before do - knife.config[:user_key] = "some_key" - knife.config[:prevent_keygen] = true - end - it "prints the usage" do - expect(knife).to receive(:show_usage) - expect { knife.run }.to raise_error(SystemExit) - end - - it "prints a relevant error message" do - expect { knife.run }.to raise_error(SystemExit) - expect(stderr.string).to match(/You cannot pass --user-key and --prevent-keygen/) - end - end - - context "when --prevent-keygen is passed" do - before do - knife.config[:prevent_keygen] = true - end - - it "does not set user.create_key" do - knife.run - expect(knife.user.create_key).to be_falsey - end - end - - context "when --prevent-keygen is not passed" do - it "sets user.create_key to true" do - knife.run - expect(knife.user.create_key).to be_truthy - end - end - - context "when --user-key is passed" do - before do - knife.config[:user_key] = "some_key" - allow(File).to receive(:read).and_return("some_key") - allow(File).to receive(:expand_path) - end - - it "sets user.public_key" do - knife.run - expect(knife.user.public_key).to eq("some_key") - end - end - - context "when --user-key is not passed" do - it "does not set user.public_key" do - knife.run - expect(knife.user.public_key).to be_nil - end - end - - context "when a private_key is returned" do - before do - allow(knife).to receive(:create_user_from_hash).and_return(Chef::UserV1.from_hash(knife.user.to_hash.merge({ "private_key" => "some_private_key" }))) - end - - context "when --file is passed" do - before do - knife.config[:file] = "/some/path" - end - - it "creates a new file of the path passed" do - filehandle = double("filehandle") - expect(filehandle).to receive(:print).with("some_private_key") - expect(File).to receive(:open).with("/some/path", "w").and_yield(filehandle) - knife.run - end - end - - context "when --file is not passed" do - it "prints the private key to stdout" do - expect(knife.ui).to receive(:msg).with("some_private_key") - knife.run - end - end - end - - end # when all mandatory fields are validly specified -end diff --git a/spec/unit/knife/user_delete_spec.rb b/spec/unit/knife/user_delete_spec.rb deleted file mode 100644 index 959d792b9e..0000000000 --- a/spec/unit/knife/user_delete_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -# -# Author:: Steven Danna (<steve@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 "spec_helper" - -describe Chef::Knife::UserDelete do - let(:knife) { Chef::Knife::UserDelete.new } - let(:user) { double("user_object") } - let(:stdout) { StringIO.new } - - before(:each) do - Chef::Knife::UserDelete.load_deps - knife.name_args = [ "my_user" ] - allow(Chef::UserV1).to receive(:load).and_return(user) - allow(user).to receive(:username).and_return("my_user") - allow(knife.ui).to receive(:stderr).and_return(stdout) - allow(knife.ui).to receive(:stdout).and_return(stdout) - end - - it "deletes the user" do - expect(knife).to receive(:delete_object).with(Chef::UserV1, "my_user") - knife.run - end - - it "prints usage and exits when a user name is not provided" do - knife.name_args = [] - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end -end diff --git a/spec/unit/knife/user_edit_spec.rb b/spec/unit/knife/user_edit_spec.rb deleted file mode 100644 index 54a44890e0..0000000000 --- a/spec/unit/knife/user_edit_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -# -# Author:: Steven Danna (<steve@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 "spec_helper" - -describe Chef::Knife::UserEdit do - let(:knife) { Chef::Knife::UserEdit.new } - - before(:each) do - @stderr = StringIO.new - @stdout = StringIO.new - - Chef::Knife::UserEdit.load_deps - allow(knife.ui).to receive(:stderr).and_return(@stderr) - allow(knife.ui).to receive(:stdout).and_return(@stdout) - knife.name_args = [ "my_user" ] - knife.config[:disable_editing] = true - end - - it "loads and edits the user" do - data = { "username" => "my_user" } - allow(Chef::UserV1).to receive(:load).with("my_user").and_return(data) - expect(knife).to receive(:edit_hash).with(data).and_return(data) - knife.run - end - - it "prints usage and exits when a user name is not provided" do - knife.name_args = [] - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end -end diff --git a/spec/unit/knife/user_list_spec.rb b/spec/unit/knife/user_list_spec.rb deleted file mode 100644 index 21c07f3fb1..0000000000 --- a/spec/unit/knife/user_list_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -# -# Author:: Steven Danna -# 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 "spec_helper" - -describe Chef::Knife::UserList do - let(:knife) { Chef::Knife::UserList.new } - let(:stdout) { StringIO.new } - - before(:each) do - Chef::Knife::UserList.load_deps - allow(knife.ui).to receive(:stderr).and_return(stdout) - allow(knife.ui).to receive(:stdout).and_return(stdout) - end - - it "lists the users" do - expect(Chef::UserV1).to receive(:list) - expect(knife).to receive(:format_list_for_display) - knife.run - end -end diff --git a/spec/unit/knife/user_reregister_spec.rb b/spec/unit/knife/user_reregister_spec.rb deleted file mode 100644 index 481415e432..0000000000 --- a/spec/unit/knife/user_reregister_spec.rb +++ /dev/null @@ -1,56 +0,0 @@ -# -# Author:: Steven Danna (<steve@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 "spec_helper" - -describe Chef::Knife::UserReregister do - let(:knife) { Chef::Knife::UserReregister.new } - let(:user_mock) { double("user_mock", private_key: "private_key") } - let(:stdout) { StringIO.new } - - before do - Chef::Knife::UserReregister.load_deps - knife.name_args = [ "a_user" ] - allow(Chef::UserV1).to receive(:load).and_return(user_mock) - allow(knife.ui).to receive(:stdout).and_return(stdout) - allow(knife.ui).to receive(:stderr).and_return(stdout) - allow(user_mock).to receive(:username).and_return("a_user") - end - - it "prints usage and exits when a user name is not provided" do - knife.name_args = [] - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end - - it "reregisters the user and prints the key" do - expect(user_mock).to receive(:reregister).and_return(user_mock) - knife.run - expect(stdout.string).to match( /private_key/ ) - end - - it "writes the private key to a file when --file is specified" do - expect(user_mock).to receive(:reregister).and_return(user_mock) - knife.config[:file] = "/tmp/a_file" - filehandle = StringIO.new - expect(File).to receive(:open).with("/tmp/a_file", "w").and_yield(filehandle) - knife.run - expect(filehandle.string).to eq("private_key") - end -end diff --git a/spec/unit/knife/user_show_spec.rb b/spec/unit/knife/user_show_spec.rb deleted file mode 100644 index 198b9352f3..0000000000 --- a/spec/unit/knife/user_show_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -# -# Author:: Steven Danna (<steve@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 "spec_helper" - -describe Chef::Knife::UserShow do - let(:knife) { Chef::Knife::UserShow.new } - let(:user_mock) { double("user_mock") } - let(:stdout) { StringIO.new } - - before do - Chef::Knife::UserShow.load_deps - knife.name_args = [ "my_user" ] - allow(user_mock).to receive(:username).and_return("my_user") - allow(knife.ui).to receive(:stderr).and_return(stdout) - allow(knife.ui).to receive(:stdout).and_return(stdout) - end - - it "loads and displays the user" do - expect(Chef::UserV1).to receive(:load).with("my_user").and_return(user_mock) - expect(knife).to receive(:format_for_display).with(user_mock) - knife.run - end - - it "prints usage and exits when a user name is not provided" do - knife.name_args = [] - expect(knife).to receive(:show_usage) - expect(knife.ui).to receive(:fatal) - expect { knife.run }.to raise_error(SystemExit) - end -end |