spec/integration/delete_spec.rb in knife-18.1.0 vs spec/integration/delete_spec.rb in knife-18.2.5

- old
+ new

@@ -1,1018 +1,1018 @@ -# -# 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 "knife_spec_helper" -require "support/shared/integration/integration_helper" -require "chef/knife/delete" -require "chef/knife/list" -require "chef/knife/raw" - -describe "knife delete", :workstation do - include IntegrationSupport - include KnifeSupport - - let :everything do - <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - let :server_everything do - <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - end - let :server_nothing do - <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /cookbooks - /data_bags - /environments - /environments/_default.json - /nodes - /roles - /users - /users/admin.json - EOM - end - - let :nothing do - <<~EOM - /clients - /cookbooks - /data_bags - /environments - /nodes - /roles - /users - EOM - end - - when_the_chef_server "has one of each thing" do - before do - client "x", "{}" - cookbook "x", "1.0.0" - data_bag "x", { "y" => "{}" } - environment "x", "{}" - node "x", "{}" - role "x", "{}" - user "x", "{}" - end - - when_the_repository "also has one of each thing" do - before do - file "clients/x.json", {} - file "cookbooks/x/metadata.rb", "" - file "data_bags/x/y.json", {} - file "environments/_default.json", {} - file "environments/x.json", {} - file "nodes/x.json", {} - file "roles/x.json", {} - file "users/x.json", {} - end - - it "knife delete --both /cookbooks/x fails" do - knife("delete --both /cookbooks/x").should_fail <<~EOM - ERROR: /cookbooks/x (remote) must be deleted recursively! Pass -r to knife delete. - ERROR: /cookbooks/x (local) must be deleted recursively! Pass -r to knife delete. - EOM - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both -r /cookbooks/x deletes x" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete -r --local /cookbooks/x deletes x locally but not remotely" do - knife("delete -r --local /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete -r /cookbooks/x deletes x remotely but not locally" do - knife("delete -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed everything - end - - # TODO delete empty data bag (particularly different on local side) - context "with an empty data bag on both" do - before do - data_bag "empty", {} - directory "data_bags/empty" - end - - it "knife delete --both /data_bags/empty fails but deletes local version" do - knife("delete --both /data_bags/empty").should_fail <<~EOM - ERROR: /data_bags/empty (remote) must be deleted recursively! Pass -r to knife delete. - ERROR: /data_bags/empty (local) must be deleted recursively! Pass -r to knife delete. - EOM - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/empty - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/empty - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - end - - it "knife delete --both /data_bags/x fails" do - knife("delete --both /data_bags/x").should_fail <<~EOM - ERROR: /data_bags/x (remote) must be deleted recursively! Pass -r to knife delete. - ERROR: /data_bags/x (local) must be deleted recursively! Pass -r to knife delete. - EOM - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both -r /data_bags/x deletes x" do - knife("delete --both -r /data_bags/x").should_succeed "Deleted /data_bags/x\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both /environments/x.json deletes x" do - knife("delete --both /environments/x.json").should_succeed "Deleted /environments/x.json\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both /roles/x.json deletes x" do - knife("delete --both /roles/x.json").should_succeed "Deleted /roles/x.json\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /users - /users/x.json - EOM - end - - it "knife delete --both /environments/_default.json fails but still deletes the local copy" do - knife("delete --both /environments/_default.json").should_fail stderr: "ERROR: /environments/_default.json (remote) cannot be deleted (default environment cannot be modified).\n", stdout: "Deleted /environments/_default.json\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both /environments/nonexistent.json fails" do - knife("delete --both /environments/nonexistent.json").should_fail "ERROR: /environments/nonexistent.json: No such file or directory\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both / fails" do - knife("delete --both /").should_fail <<~EOM - ERROR: / (remote) cannot be deleted. - ERROR: / (local) cannot be deleted. - EOM - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both -r /* fails" do - knife("delete --both -r /*").should_fail <<~EOM - ERROR: / (remote) cannot be deleted. - ERROR: / (local) cannot be deleted. - ERROR: /clients (remote) cannot be deleted. - ERROR: /clients (local) cannot be deleted. - ERROR: /cookbooks (remote) cannot be deleted. - ERROR: /cookbooks (local) cannot be deleted. - ERROR: /data_bags (remote) cannot be deleted. - ERROR: /data_bags (local) cannot be deleted. - ERROR: /environments (remote) cannot be deleted. - ERROR: /environments (local) cannot be deleted. - ERROR: /nodes (remote) cannot be deleted. - ERROR: /nodes (local) cannot be deleted. - ERROR: /roles (remote) cannot be deleted. - ERROR: /roles (local) cannot be deleted. - ERROR: /users (remote) cannot be deleted. - ERROR: /users (local) cannot be deleted. - EOM - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed everything - end - end - - when_the_repository "has only top-level directories" do - before do - directory "clients" - directory "cookbooks" - directory "data_bags" - directory "environments" - directory "nodes" - directory "roles" - directory "users" - end - - it "knife delete --both /cookbooks/x fails" do - knife("delete --both /cookbooks/x").should_fail "ERROR: /cookbooks/x (remote) must be deleted recursively! Pass -r to knife delete.\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both -r /cookbooks/x deletes x" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both /data_bags/x fails" do - knife("delete --both /data_bags/x").should_fail "ERROR: /data_bags/x (remote) must be deleted recursively! Pass -r to knife delete.\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both -r /data_bags/x deletes x" do - knife("delete --both -r /data_bags/x").should_succeed "Deleted /data_bags/x\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both /environments/x.json deletes x" do - knife("delete --both /environments/x.json").should_succeed "Deleted /environments/x.json\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both /roles/x.json deletes x" do - knife("delete --both /roles/x.json").should_succeed "Deleted /roles/x.json\n" - knife("list -Rf /").should_succeed <<~EOM - /clients - /clients/chef-validator.json - /clients/chef-webui.json - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /users - /users/admin.json - /users/x.json - EOM - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both /environments/_default.json fails" do - knife("delete --both /environments/_default.json").should_fail "", stderr: "ERROR: /environments/_default.json (remote) cannot be deleted (default environment cannot be modified).\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both / fails" do - knife("delete --both /").should_fail "ERROR: / (remote) cannot be deleted.\nERROR: / (local) cannot be deleted.\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both -r /* fails" do - knife("delete --both -r /*").should_fail <<~EOM - ERROR: / (remote) cannot be deleted. - ERROR: / (local) cannot be deleted. - ERROR: /clients (remote) cannot be deleted. - ERROR: /clients (local) cannot be deleted. - ERROR: /cookbooks (remote) cannot be deleted. - ERROR: /cookbooks (local) cannot be deleted. - ERROR: /data_bags (remote) cannot be deleted. - ERROR: /data_bags (local) cannot be deleted. - ERROR: /environments (remote) cannot be deleted. - ERROR: /environments (local) cannot be deleted. - ERROR: /nodes (remote) cannot be deleted. - ERROR: /nodes (local) cannot be deleted. - ERROR: /roles (remote) cannot be deleted. - ERROR: /roles (local) cannot be deleted. - ERROR: /users (remote) cannot be deleted. - ERROR: /users (local) cannot be deleted. - EOM - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed nothing - end - - it "knife delete --both /environments/nonexistent.json fails" do - knife("delete --both /environments/nonexistent.json").should_fail "ERROR: /environments/nonexistent.json: No such file or directory\n" - knife("list -Rf /").should_succeed server_everything - knife("list -Rf --local /").should_succeed nothing - end - - context "and cwd is at the top level" do - before { cwd "." } - it "knife delete fails" do - knife("delete").should_fail "FATAL: You must specify at least one argument. If you want to delete everything in this directory, run \"knife delete --recurse .\"\n", stdout: /USAGE/ - knife("list -Rf /").should_succeed <<~EOM - clients - clients/chef-validator.json - clients/chef-webui.json - clients/x.json - cookbooks - cookbooks/x - cookbooks/x/metadata.rb - data_bags - data_bags/x - data_bags/x/y.json - environments - environments/_default.json - environments/x.json - nodes - nodes/x.json - roles - roles/x.json - users - users/admin.json - users/x.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - clients - cookbooks - data_bags - environments - nodes - roles - users - EOM - end - end - end - end - - when_the_chef_server "is empty" do - when_the_repository "has one of each thing" do - before do - file "clients/x.json", {} - file "cookbooks/x/metadata.rb", "" - file "data_bags/x/y.json", {} - file "environments/_default.json", {} - file "environments/x.json", {} - file "nodes/x.json", {} - file "roles/x.json", {} - file "users/x.json", {} - end - - it "knife delete --both /cookbooks/x fails" do - knife("delete --both /cookbooks/x").should_fail "ERROR: /cookbooks/x (local) must be deleted recursively! Pass -r to knife delete.\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both -r /cookbooks/x deletes x" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both /data_bags/x fails" do - knife("delete --both /data_bags/x").should_fail "ERROR: /data_bags/x (local) must be deleted recursively! Pass -r to knife delete.\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both -r /data_bags/x deletes x" do - knife("delete --both -r /data_bags/x").should_succeed "Deleted /data_bags/x\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both /environments/x.json deletes x" do - knife("delete --both /environments/x.json").should_succeed "Deleted /environments/x.json\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both /roles/x.json deletes x" do - knife("delete --both /roles/x.json").should_succeed "Deleted /roles/x.json\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/_default.json - /environments/x.json - /nodes - /nodes/x.json - /roles - /users - /users/x.json - EOM - end - - it "knife delete --both /environments/_default.json fails but still deletes the local copy" do - knife("delete --both /environments/_default.json").should_fail stderr: "ERROR: /environments/_default.json (remote) cannot be deleted (default environment cannot be modified).\n", stdout: "Deleted /environments/_default.json\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed <<~EOM - /clients - /clients/x.json - /cookbooks - /cookbooks/x - /cookbooks/x/metadata.rb - /data_bags - /data_bags/x - /data_bags/x/y.json - /environments - /environments/x.json - /nodes - /nodes/x.json - /roles - /roles/x.json - /users - /users/x.json - EOM - end - - it "knife delete --both / fails" do - knife("delete --both /").should_fail "ERROR: / (remote) cannot be deleted.\nERROR: / (local) cannot be deleted.\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both -r /* fails" do - knife("delete --both -r /*").should_fail <<~EOM - ERROR: / (remote) cannot be deleted. - ERROR: / (local) cannot be deleted. - ERROR: /clients (remote) cannot be deleted. - ERROR: /clients (local) cannot be deleted. - ERROR: /cookbooks (remote) cannot be deleted. - ERROR: /cookbooks (local) cannot be deleted. - ERROR: /data_bags (remote) cannot be deleted. - ERROR: /data_bags (local) cannot be deleted. - ERROR: /environments (remote) cannot be deleted. - ERROR: /environments (local) cannot be deleted. - ERROR: /nodes (remote) cannot be deleted. - ERROR: /nodes (local) cannot be deleted. - ERROR: /roles (remote) cannot be deleted. - ERROR: /roles (local) cannot be deleted. - ERROR: /users (remote) cannot be deleted. - ERROR: /users (local) cannot be deleted. - EOM - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed everything - end - - it "knife delete --both /environments/nonexistent.json fails" do - knife("delete --both /environments/nonexistent.json").should_fail "ERROR: /environments/nonexistent.json: No such file or directory\n" - knife("list -Rf /").should_succeed server_nothing - knife("list -Rf --local /").should_succeed everything - end - - context "and cwd is at the top level" do - before { cwd "." } - it "knife delete fails" do - knife("delete").should_fail "FATAL: You must specify at least one argument. If you want to delete everything in this directory, run \"knife delete --recurse .\"\n", stdout: /USAGE/ - knife("list -Rf /").should_succeed <<~EOM - clients - clients/chef-validator.json - clients/chef-webui.json - cookbooks - data_bags - environments - environments/_default.json - nodes - roles - users - users/admin.json - EOM - knife("list -Rf --local /").should_succeed <<~EOM - clients - clients/x.json - cookbooks - cookbooks/x - cookbooks/x/metadata.rb - data_bags - data_bags/x - data_bags/x/y.json - environments - environments/_default.json - environments/x.json - nodes - nodes/x.json - roles - roles/x.json - users - users/x.json - EOM - end - end - end - end - - when_the_repository "has a cookbook" do - before do - file "cookbooks/x/metadata.rb", 'version "1.0.0"' - file "cookbooks/x/onlyin1.0.0.rb", "old_text" - end - - when_the_chef_server "has a later version for the cookbook" do - before do - cookbook "x", "1.0.0", { "onlyin1.0.0.rb" => "" } - cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "hi" } - end - - # TODO this seems wrong - it "knife delete --both -r /cookbooks/x deletes the latest version on the server and the local version" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("raw /cookbooks/x").should_succeed(/1.0.0/) - knife("list --local /cookbooks").should_succeed "" - end - end - - when_the_chef_server "has an earlier version for the cookbook" do - before do - cookbook "x", "1.0.0", { "onlyin1.0.0.rb" => "" } - cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "hi" } - end - - it "knife delete --both /cookbooks/x deletes the latest version on the server and the local version" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("raw /cookbooks/x").should_succeed(/0.9.9/) - knife("list --local /cookbooks").should_succeed "" - end - end - - when_the_chef_server "has a later version for the cookbook, and no current version" do - before { cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "hi" } } - - it "knife delete --both /cookbooks/x deletes the server and client version of the cookbook" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("raw /cookbooks/x").should_fail(/404/) - knife("list --local /cookbooks").should_succeed "" - end - end - - when_the_chef_server "has an earlier version for the cookbook, and no current version" do - before { cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "hi" } } - - it "knife delete --both /cookbooks/x deletes the server and client version of the cookbook" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("raw /cookbooks/x").should_fail(/404/) - knife("list --local /cookbooks").should_succeed "" - end - end - end - - when_the_repository "is empty" do - when_the_chef_server "has two versions of a cookbook" do - before do - cookbook "x", "2.0.11" - cookbook "x", "11.0.0" - end - - it "knife delete deletes the latest version" do - knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" - knife("raw /cookbooks/x").should_succeed( /2.0.11/ ) - end - end - end - - when_the_chef_server "is in Enterprise mode", osc_compat: false, single_org: false do - before do - organization "foo" do - container "x", {} - group "x", {} - policy "x", "1.2.3", {} - policy_group "x", { "policies" => { "x" => { "revision_id" => "1.2.3" } } } - end - end - - before :each do - Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, "/organizations/foo") - end - - it "knife delete /acls/containers/environments.json fails with a reasonable error" do - knife("delete /acls/containers/environments.json").should_fail "ERROR: /acls/containers/environments.json (remote) ACLs cannot be deleted.\n" - end - - it "knife delete /containers/x.json succeeds" do - knife("delete /containers/x.json").should_succeed "Deleted /containers/x.json\n" - knife("raw /containers/x.json").should_fail(/404/) - end - - it "knife delete /groups/x.json succeeds" do - knife("delete /groups/x.json").should_succeed "Deleted /groups/x.json\n" - knife("raw /groups/x.json").should_fail(/404/) - end - - it "knife delete /policies/x-1.2.3.json succeeds" do - knife("raw /policies/x/revisions/1.2.3").should_succeed "{\n \"policy_group_list\": [\n \"x\"\n ],\n \"name\": \"x\",\n \"revision_id\": \"1.2.3\",\n \"run_list\": [\n\n ],\n \"cookbook_locks\": {\n\n }\n}\n" - knife("delete /policies/x-1.2.3.json").should_succeed "Deleted /policies/x-1.2.3.json\n" - knife("raw /policies/x/revisions/1.2.3").should_fail(/404/) - end - - it "knife delete /policy_groups/x.json succeeds" do - knife("raw /policy_groups/x").should_succeed "{\n \"uri\": \"http://127.0.0.1:8900/organizations/foo/policy_groups/x\",\n \"policies\": {\n \"x\": {\n \"revision_id\": \"1.2.3\"\n }\n }\n}\n" - knife("delete /policy_groups/x.json").should_succeed "Deleted /policy_groups/x.json\n" - knife("raw /policy_groups/x").should_fail(/404/) - end - - it "knife delete /org.json fails with a reasonable error" do - knife("delete /org.json").should_fail "ERROR: /org.json (remote) cannot be deleted.\n" - end - - it "knife delete /invitations.json fails with a reasonable error" do - knife("delete /invitations.json").should_fail "ERROR: /invitations.json (remote) cannot be deleted.\n" - end - - it "knife delete /members.json fails with a reasonable error" do - knife("delete /members.json").should_fail "ERROR: /members.json (remote) cannot be deleted.\n" - end - end -end +# +# 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 "knife_spec_helper" +require "support/shared/integration/integration_helper" +require "chef/knife/delete" +require "chef/knife/list" +require "chef/knife/raw" + +describe "knife delete", :workstation do + include IntegrationSupport + include KnifeSupport + + let :everything do + <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + let :server_everything do + <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + end + let :server_nothing do + <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /cookbooks + /data_bags + /environments + /environments/_default.json + /nodes + /roles + /users + /users/admin.json + EOM + end + + let :nothing do + <<~EOM + /clients + /cookbooks + /data_bags + /environments + /nodes + /roles + /users + EOM + end + + when_the_chef_server "has one of each thing" do + before do + client "x", "{}" + cookbook "x", "1.0.0" + data_bag "x", { "y" => "{}" } + environment "x", "{}" + node "x", "{}" + role "x", "{}" + user "x", "{}" + end + + when_the_repository "also has one of each thing" do + before do + file "clients/x.json", {} + file "cookbooks/x/metadata.rb", "" + file "data_bags/x/y.json", {} + file "environments/_default.json", {} + file "environments/x.json", {} + file "nodes/x.json", {} + file "roles/x.json", {} + file "users/x.json", {} + end + + it "knife delete --both /cookbooks/x fails" do + knife("delete --both /cookbooks/x").should_fail <<~EOM + ERROR: /cookbooks/x (remote) must be deleted recursively! Pass -r to knife delete. + ERROR: /cookbooks/x (local) must be deleted recursively! Pass -r to knife delete. + EOM + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both -r /cookbooks/x deletes x" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete -r --local /cookbooks/x deletes x locally but not remotely" do + knife("delete -r --local /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete -r /cookbooks/x deletes x remotely but not locally" do + knife("delete -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed everything + end + + # TODO delete empty data bag (particularly different on local side) + context "with an empty data bag on both" do + before do + data_bag "empty", {} + directory "data_bags/empty" + end + + it "knife delete --both /data_bags/empty fails but deletes local version" do + knife("delete --both /data_bags/empty").should_fail <<~EOM + ERROR: /data_bags/empty (remote) must be deleted recursively! Pass -r to knife delete. + ERROR: /data_bags/empty (local) must be deleted recursively! Pass -r to knife delete. + EOM + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/empty + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/empty + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + end + + it "knife delete --both /data_bags/x fails" do + knife("delete --both /data_bags/x").should_fail <<~EOM + ERROR: /data_bags/x (remote) must be deleted recursively! Pass -r to knife delete. + ERROR: /data_bags/x (local) must be deleted recursively! Pass -r to knife delete. + EOM + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both -r /data_bags/x deletes x" do + knife("delete --both -r /data_bags/x").should_succeed "Deleted /data_bags/x\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both /environments/x.json deletes x" do + knife("delete --both /environments/x.json").should_succeed "Deleted /environments/x.json\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both /roles/x.json deletes x" do + knife("delete --both /roles/x.json").should_succeed "Deleted /roles/x.json\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /users + /users/x.json + EOM + end + + it "knife delete --both /environments/_default.json fails but still deletes the local copy" do + knife("delete --both /environments/_default.json").should_fail stderr: "ERROR: /environments/_default.json (remote) cannot be deleted (default environment cannot be modified).\n", stdout: "Deleted /environments/_default.json\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both /environments/nonexistent.json fails" do + knife("delete --both /environments/nonexistent.json").should_fail "ERROR: /environments/nonexistent.json: No such file or directory\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both / fails" do + knife("delete --both /").should_fail <<~EOM + ERROR: / (remote) cannot be deleted. + ERROR: / (local) cannot be deleted. + EOM + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both -r /* fails" do + knife("delete --both -r /*").should_fail <<~EOM + ERROR: / (remote) cannot be deleted. + ERROR: / (local) cannot be deleted. + ERROR: /clients (remote) cannot be deleted. + ERROR: /clients (local) cannot be deleted. + ERROR: /cookbooks (remote) cannot be deleted. + ERROR: /cookbooks (local) cannot be deleted. + ERROR: /data_bags (remote) cannot be deleted. + ERROR: /data_bags (local) cannot be deleted. + ERROR: /environments (remote) cannot be deleted. + ERROR: /environments (local) cannot be deleted. + ERROR: /nodes (remote) cannot be deleted. + ERROR: /nodes (local) cannot be deleted. + ERROR: /roles (remote) cannot be deleted. + ERROR: /roles (local) cannot be deleted. + ERROR: /users (remote) cannot be deleted. + ERROR: /users (local) cannot be deleted. + EOM + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed everything + end + end + + when_the_repository "has only top-level directories" do + before do + directory "clients" + directory "cookbooks" + directory "data_bags" + directory "environments" + directory "nodes" + directory "roles" + directory "users" + end + + it "knife delete --both /cookbooks/x fails" do + knife("delete --both /cookbooks/x").should_fail "ERROR: /cookbooks/x (remote) must be deleted recursively! Pass -r to knife delete.\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both -r /cookbooks/x deletes x" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both /data_bags/x fails" do + knife("delete --both /data_bags/x").should_fail "ERROR: /data_bags/x (remote) must be deleted recursively! Pass -r to knife delete.\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both -r /data_bags/x deletes x" do + knife("delete --both -r /data_bags/x").should_succeed "Deleted /data_bags/x\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both /environments/x.json deletes x" do + knife("delete --both /environments/x.json").should_succeed "Deleted /environments/x.json\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both /roles/x.json deletes x" do + knife("delete --both /roles/x.json").should_succeed "Deleted /roles/x.json\n" + knife("list -Rf /").should_succeed <<~EOM + /clients + /clients/chef-validator.json + /clients/chef-webui.json + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /users + /users/admin.json + /users/x.json + EOM + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both /environments/_default.json fails" do + knife("delete --both /environments/_default.json").should_fail "", stderr: "ERROR: /environments/_default.json (remote) cannot be deleted (default environment cannot be modified).\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both / fails" do + knife("delete --both /").should_fail "ERROR: / (remote) cannot be deleted.\nERROR: / (local) cannot be deleted.\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both -r /* fails" do + knife("delete --both -r /*").should_fail <<~EOM + ERROR: / (remote) cannot be deleted. + ERROR: / (local) cannot be deleted. + ERROR: /clients (remote) cannot be deleted. + ERROR: /clients (local) cannot be deleted. + ERROR: /cookbooks (remote) cannot be deleted. + ERROR: /cookbooks (local) cannot be deleted. + ERROR: /data_bags (remote) cannot be deleted. + ERROR: /data_bags (local) cannot be deleted. + ERROR: /environments (remote) cannot be deleted. + ERROR: /environments (local) cannot be deleted. + ERROR: /nodes (remote) cannot be deleted. + ERROR: /nodes (local) cannot be deleted. + ERROR: /roles (remote) cannot be deleted. + ERROR: /roles (local) cannot be deleted. + ERROR: /users (remote) cannot be deleted. + ERROR: /users (local) cannot be deleted. + EOM + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed nothing + end + + it "knife delete --both /environments/nonexistent.json fails" do + knife("delete --both /environments/nonexistent.json").should_fail "ERROR: /environments/nonexistent.json: No such file or directory\n" + knife("list -Rf /").should_succeed server_everything + knife("list -Rf --local /").should_succeed nothing + end + + context "and cwd is at the top level" do + before { cwd "." } + it "knife delete fails" do + knife("delete").should_fail "FATAL: You must specify at least one argument. If you want to delete everything in this directory, run \"knife delete --recurse .\"\n", stdout: /USAGE/ + knife("list -Rf /").should_succeed <<~EOM + clients + clients/chef-validator.json + clients/chef-webui.json + clients/x.json + cookbooks + cookbooks/x + cookbooks/x/metadata.rb + data_bags + data_bags/x + data_bags/x/y.json + environments + environments/_default.json + environments/x.json + nodes + nodes/x.json + roles + roles/x.json + users + users/admin.json + users/x.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + clients + cookbooks + data_bags + environments + nodes + roles + users + EOM + end + end + end + end + + when_the_chef_server "is empty" do + when_the_repository "has one of each thing" do + before do + file "clients/x.json", {} + file "cookbooks/x/metadata.rb", "" + file "data_bags/x/y.json", {} + file "environments/_default.json", {} + file "environments/x.json", {} + file "nodes/x.json", {} + file "roles/x.json", {} + file "users/x.json", {} + end + + it "knife delete --both /cookbooks/x fails" do + knife("delete --both /cookbooks/x").should_fail "ERROR: /cookbooks/x (local) must be deleted recursively! Pass -r to knife delete.\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both -r /cookbooks/x deletes x" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both /data_bags/x fails" do + knife("delete --both /data_bags/x").should_fail "ERROR: /data_bags/x (local) must be deleted recursively! Pass -r to knife delete.\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both -r /data_bags/x deletes x" do + knife("delete --both -r /data_bags/x").should_succeed "Deleted /data_bags/x\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both /environments/x.json deletes x" do + knife("delete --both /environments/x.json").should_succeed "Deleted /environments/x.json\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both /roles/x.json deletes x" do + knife("delete --both /roles/x.json").should_succeed "Deleted /roles/x.json\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/_default.json + /environments/x.json + /nodes + /nodes/x.json + /roles + /users + /users/x.json + EOM + end + + it "knife delete --both /environments/_default.json fails but still deletes the local copy" do + knife("delete --both /environments/_default.json").should_fail stderr: "ERROR: /environments/_default.json (remote) cannot be deleted (default environment cannot be modified).\n", stdout: "Deleted /environments/_default.json\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed <<~EOM + /clients + /clients/x.json + /cookbooks + /cookbooks/x + /cookbooks/x/metadata.rb + /data_bags + /data_bags/x + /data_bags/x/y.json + /environments + /environments/x.json + /nodes + /nodes/x.json + /roles + /roles/x.json + /users + /users/x.json + EOM + end + + it "knife delete --both / fails" do + knife("delete --both /").should_fail "ERROR: / (remote) cannot be deleted.\nERROR: / (local) cannot be deleted.\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both -r /* fails" do + knife("delete --both -r /*").should_fail <<~EOM + ERROR: / (remote) cannot be deleted. + ERROR: / (local) cannot be deleted. + ERROR: /clients (remote) cannot be deleted. + ERROR: /clients (local) cannot be deleted. + ERROR: /cookbooks (remote) cannot be deleted. + ERROR: /cookbooks (local) cannot be deleted. + ERROR: /data_bags (remote) cannot be deleted. + ERROR: /data_bags (local) cannot be deleted. + ERROR: /environments (remote) cannot be deleted. + ERROR: /environments (local) cannot be deleted. + ERROR: /nodes (remote) cannot be deleted. + ERROR: /nodes (local) cannot be deleted. + ERROR: /roles (remote) cannot be deleted. + ERROR: /roles (local) cannot be deleted. + ERROR: /users (remote) cannot be deleted. + ERROR: /users (local) cannot be deleted. + EOM + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed everything + end + + it "knife delete --both /environments/nonexistent.json fails" do + knife("delete --both /environments/nonexistent.json").should_fail "ERROR: /environments/nonexistent.json: No such file or directory\n" + knife("list -Rf /").should_succeed server_nothing + knife("list -Rf --local /").should_succeed everything + end + + context "and cwd is at the top level" do + before { cwd "." } + it "knife delete fails" do + knife("delete").should_fail "FATAL: You must specify at least one argument. If you want to delete everything in this directory, run \"knife delete --recurse .\"\n", stdout: /USAGE/ + knife("list -Rf /").should_succeed <<~EOM + clients + clients/chef-validator.json + clients/chef-webui.json + cookbooks + data_bags + environments + environments/_default.json + nodes + roles + users + users/admin.json + EOM + knife("list -Rf --local /").should_succeed <<~EOM + clients + clients/x.json + cookbooks + cookbooks/x + cookbooks/x/metadata.rb + data_bags + data_bags/x + data_bags/x/y.json + environments + environments/_default.json + environments/x.json + nodes + nodes/x.json + roles + roles/x.json + users + users/x.json + EOM + end + end + end + end + + when_the_repository "has a cookbook" do + before do + file "cookbooks/x/metadata.rb", 'version "1.0.0"' + file "cookbooks/x/onlyin1.0.0.rb", "old_text" + end + + when_the_chef_server "has a later version for the cookbook" do + before do + cookbook "x", "1.0.0", { "onlyin1.0.0.rb" => "" } + cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "hi" } + end + + # TODO this seems wrong + it "knife delete --both -r /cookbooks/x deletes the latest version on the server and the local version" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("raw /cookbooks/x").should_succeed(/1.0.0/) + knife("list --local /cookbooks").should_succeed "" + end + end + + when_the_chef_server "has an earlier version for the cookbook" do + before do + cookbook "x", "1.0.0", { "onlyin1.0.0.rb" => "" } + cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "hi" } + end + + it "knife delete --both /cookbooks/x deletes the latest version on the server and the local version" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("raw /cookbooks/x").should_succeed(/0.9.9/) + knife("list --local /cookbooks").should_succeed "" + end + end + + when_the_chef_server "has a later version for the cookbook, and no current version" do + before { cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "hi" } } + + it "knife delete --both /cookbooks/x deletes the server and client version of the cookbook" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("raw /cookbooks/x").should_fail(/404/) + knife("list --local /cookbooks").should_succeed "" + end + end + + when_the_chef_server "has an earlier version for the cookbook, and no current version" do + before { cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "hi" } } + + it "knife delete --both /cookbooks/x deletes the server and client version of the cookbook" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("raw /cookbooks/x").should_fail(/404/) + knife("list --local /cookbooks").should_succeed "" + end + end + end + + when_the_repository "is empty" do + when_the_chef_server "has two versions of a cookbook" do + before do + cookbook "x", "2.0.11" + cookbook "x", "11.0.0" + end + + it "knife delete deletes the latest version" do + knife("delete --both -r /cookbooks/x").should_succeed "Deleted /cookbooks/x\n" + knife("raw /cookbooks/x").should_succeed( /2.0.11/ ) + end + end + end + + when_the_chef_server "is in Enterprise mode", osc_compat: false, single_org: false do + before do + organization "foo" do + container "x", {} + group "x", {} + policy "x", "1.2.3", {} + policy_group "x", { "policies" => { "x" => { "revision_id" => "1.2.3" } } } + end + end + + before :each do + Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, "/organizations/foo") + end + + it "knife delete /acls/containers/environments.json fails with a reasonable error" do + knife("delete /acls/containers/environments.json").should_fail "ERROR: /acls/containers/environments.json (remote) ACLs cannot be deleted.\n" + end + + it "knife delete /containers/x.json succeeds" do + knife("delete /containers/x.json").should_succeed "Deleted /containers/x.json\n" + knife("raw /containers/x.json").should_fail(/404/) + end + + it "knife delete /groups/x.json succeeds" do + knife("delete /groups/x.json").should_succeed "Deleted /groups/x.json\n" + knife("raw /groups/x.json").should_fail(/404/) + end + + it "knife delete /policies/x-1.2.3.json succeeds" do + knife("raw /policies/x/revisions/1.2.3").should_succeed "{\n \"policy_group_list\": [\n \"x\"\n ],\n \"name\": \"x\",\n \"revision_id\": \"1.2.3\",\n \"run_list\": [\n\n ],\n \"cookbook_locks\": {\n\n }\n}\n" + knife("delete /policies/x-1.2.3.json").should_succeed "Deleted /policies/x-1.2.3.json\n" + knife("raw /policies/x/revisions/1.2.3").should_fail(/404/) + end + + it "knife delete /policy_groups/x.json succeeds" do + knife("raw /policy_groups/x").should_succeed "{\n \"uri\": \"http://127.0.0.1:8900/organizations/foo/policy_groups/x\",\n \"policies\": {\n \"x\": {\n \"revision_id\": \"1.2.3\"\n }\n }\n}\n" + knife("delete /policy_groups/x.json").should_succeed "Deleted /policy_groups/x.json\n" + knife("raw /policy_groups/x").should_fail(/404/) + end + + it "knife delete /org.json fails with a reasonable error" do + knife("delete /org.json").should_fail "ERROR: /org.json (remote) cannot be deleted.\n" + end + + it "knife delete /invitations.json fails with a reasonable error" do + knife("delete /invitations.json").should_fail "ERROR: /invitations.json (remote) cannot be deleted.\n" + end + + it "knife delete /members.json fails with a reasonable error" do + knife("delete /members.json").should_fail "ERROR: /members.json (remote) cannot be deleted.\n" + end + end +end