summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authortylercloke <tylercloke@gmail.com>2015-07-01 15:58:05 -0700
committertylercloke <tylercloke@gmail.com>2015-07-06 14:36:02 -0700
commite35250325f6836b464841441d33336c988b8ccc6 (patch)
tree290fea59f69f72ce5d412a313d918cbbce1dd766 /spec
parent320afd88bb6751b67573af982a0cf5d51a035af7 (diff)
downloadchef-e35250325f6836b464841441d33336c988b8ccc6.tar.gz
Move Chef::OscUser back to Chef::User namespace and new user code to Chef::UserV1.
Also, have Chef::User (formally Chef::OscUser) use API V0 to make requests.
Diffstat (limited to 'spec')
-rw-r--r--spec/support/shared/unit/api_versioning.rb4
-rw-r--r--spec/unit/knife/osc_user_create_spec.rb10
-rw-r--r--spec/unit/knife/osc_user_delete_spec.rb2
-rw-r--r--spec/unit/knife/osc_user_edit_spec.rb2
-rw-r--r--spec/unit/knife/osc_user_list_spec.rb2
-rw-r--r--spec/unit/knife/osc_user_reregister_spec.rb2
-rw-r--r--spec/unit/knife/osc_user_show_spec.rb2
-rw-r--r--spec/unit/knife/user_create_spec.rb2
-rw-r--r--spec/unit/knife/user_delete_spec.rb4
-rw-r--r--spec/unit/knife/user_edit_spec.rb4
-rw-r--r--spec/unit/knife/user_list_spec.rb2
-rw-r--r--spec/unit/knife/user_reregister_spec.rb2
-rw-r--r--spec/unit/knife/user_show_spec.rb4
-rw-r--r--spec/unit/osc_user_spec.rb276
-rw-r--r--spec/unit/user_spec.rb508
-rw-r--r--spec/unit/user_v1_spec.rb584
16 files changed, 705 insertions, 705 deletions
diff --git a/spec/support/shared/unit/api_versioning.rb b/spec/support/shared/unit/api_versioning.rb
index a4f353de60..05a4117f8e 100644
--- a/spec/support/shared/unit/api_versioning.rb
+++ b/spec/support/shared/unit/api_versioning.rb
@@ -26,7 +26,7 @@ shared_examples_for "version handling" do
allow(rest_v1).to receive(http_verb).and_raise(exception_406)
end
- context "when the server does not support the min or max server API version that Chef::User supports" do
+ context "when the server does not support the min or max server API version that Chef::UserV1 supports" do
before do
allow(object).to receive(:server_client_api_version_intersection).and_return([])
end
@@ -34,7 +34,7 @@ shared_examples_for "version handling" do
it "raises the original exception" do
expect{ object.send(method) }.to raise_error(exception_406)
end
- end # when the server does not support the min or max server API version that Chef::User supports
+ end # when the server does not support the min or max server API version that Chef::UserV1 supports
end # version handling
shared_examples_for "user and client reregister" do
diff --git a/spec/unit/knife/osc_user_create_spec.rb b/spec/unit/knife/osc_user_create_spec.rb
index 1b17d0d22f..e4ed78fe2b 100644
--- a/spec/unit/knife/osc_user_create_spec.rb
+++ b/spec/unit/knife/osc_user_create_spec.rb
@@ -36,19 +36,19 @@ describe Chef::Knife::OscUserCreate do
@knife.name_args = [ 'a_user' ]
@knife.config[:user_password] = "foobar"
- @user = Chef::OscUser.new
+ @user = Chef::User.new
@user.name "a_user"
- @user_with_private_key = Chef::OscUser.new
+ @user_with_private_key = Chef::User.new
@user_with_private_key.name "a_user"
@user_with_private_key.private_key 'private_key'
allow(@user).to receive(:create).and_return(@user_with_private_key)
- allow(Chef::OscUser).to receive(:new).and_return(@user)
- allow(Chef::OscUser).to receive(:from_hash).and_return(@user)
+ allow(Chef::User).to receive(:new).and_return(@user)
+ allow(Chef::User).to receive(:from_hash).and_return(@user)
allow(@knife).to receive(:edit_data).and_return(@user.to_hash)
end
it "creates a new user" do
- expect(Chef::OscUser).to receive(:new).and_return(@user)
+ expect(Chef::User).to receive(:new).and_return(@user)
expect(@user).to receive(:create)
@knife.run
expect(@stderr.string).to match /created user.+a_user/i
diff --git a/spec/unit/knife/osc_user_delete_spec.rb b/spec/unit/knife/osc_user_delete_spec.rb
index 0e16393ffe..4a3ec4228f 100644
--- a/spec/unit/knife/osc_user_delete_spec.rb
+++ b/spec/unit/knife/osc_user_delete_spec.rb
@@ -31,7 +31,7 @@ describe Chef::Knife::OscUserDelete do
end
it 'deletes the user' do
- expect(@knife).to receive(:delete_object).with(Chef::OscUser, 'my_user')
+ expect(@knife).to receive(:delete_object).with(Chef::User, 'my_user')
@knife.run
end
diff --git a/spec/unit/knife/osc_user_edit_spec.rb b/spec/unit/knife/osc_user_edit_spec.rb
index 71a9192389..279f2e30ef 100644
--- a/spec/unit/knife/osc_user_edit_spec.rb
+++ b/spec/unit/knife/osc_user_edit_spec.rb
@@ -38,7 +38,7 @@ describe Chef::Knife::OscUserEdit do
it 'loads and edits the user' do
data = { :name => "my_user" }
- allow(Chef::OscUser).to receive(:load).with("my_user").and_return(data)
+ allow(Chef::User).to receive(:load).with("my_user").and_return(data)
expect(@knife).to receive(:edit_data).with(data).and_return(data)
@knife.run
end
diff --git a/spec/unit/knife/osc_user_list_spec.rb b/spec/unit/knife/osc_user_list_spec.rb
index 59a15be058..f496a414b8 100644
--- a/spec/unit/knife/osc_user_list_spec.rb
+++ b/spec/unit/knife/osc_user_list_spec.rb
@@ -30,7 +30,7 @@ describe Chef::Knife::OscUserList do
end
it 'lists the users' do
- expect(Chef::OscUser).to receive(:list)
+ expect(Chef::User).to receive(:list)
expect(@knife).to receive(:format_list_for_display)
@knife.run
end
diff --git a/spec/unit/knife/osc_user_reregister_spec.rb b/spec/unit/knife/osc_user_reregister_spec.rb
index 406bbf1f3e..989eb180f1 100644
--- a/spec/unit/knife/osc_user_reregister_spec.rb
+++ b/spec/unit/knife/osc_user_reregister_spec.rb
@@ -29,7 +29,7 @@ describe Chef::Knife::OscUserReregister do
@knife = Chef::Knife::OscUserReregister.new
@knife.name_args = [ 'a_user' ]
@user_mock = double('user_mock', :private_key => "private_key")
- allow(Chef::OscUser).to receive(:load).and_return(@user_mock)
+ allow(Chef::User).to receive(:load).and_return(@user_mock)
@stdout = StringIO.new
allow(@knife.ui).to receive(:stdout).and_return(@stdout)
end
diff --git a/spec/unit/knife/osc_user_show_spec.rb b/spec/unit/knife/osc_user_show_spec.rb
index 67b9b45809..18d2086099 100644
--- a/spec/unit/knife/osc_user_show_spec.rb
+++ b/spec/unit/knife/osc_user_show_spec.rb
@@ -32,7 +32,7 @@ describe Chef::Knife::OscUserShow do
end
it 'loads and displays the user' do
- expect(Chef::OscUser).to receive(:load).with('my_user').and_return(@user_mock)
+ expect(Chef::User).to receive(:load).with('my_user').and_return(@user_mock)
expect(@knife).to receive(:format_for_display).with(@user_mock)
@knife.run
end
diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb
index 49d62cc2d7..fa5c8324b4 100644
--- a/spec/unit/knife/user_create_spec.rb
+++ b/spec/unit/knife/user_create_spec.rb
@@ -186,7 +186,7 @@ describe Chef::Knife::UserCreate do
context "when a private_key is returned" do
before do
- allow(knife).to receive(:create_user_from_hash).and_return(Chef::User.from_hash(knife.user.to_hash.merge({"private_key" => "some_private_key"})))
+ 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
diff --git a/spec/unit/knife/user_delete_spec.rb b/spec/unit/knife/user_delete_spec.rb
index e49c781358..a24160624a 100644
--- a/spec/unit/knife/user_delete_spec.rb
+++ b/spec/unit/knife/user_delete_spec.rb
@@ -26,7 +26,7 @@ describe Chef::Knife::UserDelete do
before(:each) do
Chef::Knife::UserDelete.load_deps
knife.name_args = [ 'my_user' ]
- allow(Chef::User).to receive(:load).and_return(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)
@@ -51,7 +51,7 @@ describe Chef::Knife::UserDelete do
end
it 'deletes the user' do
- #expect(knife).to receive(:delete_object).with(Chef::User, 'my_user')
+ #expect(knife).to receive(:delete_object).with(Chef::UserV1, 'my_user')
expect(knife).to receive(:delete_object).with('my_user')
knife.run
end
diff --git a/spec/unit/knife/user_edit_spec.rb b/spec/unit/knife/user_edit_spec.rb
index 15a7726b20..a21d982d29 100644
--- a/spec/unit/knife/user_edit_spec.rb
+++ b/spec/unit/knife/user_edit_spec.rb
@@ -36,7 +36,7 @@ describe Chef::Knife::UserEdit do
context "when the username field is not supported by the server" do
before do
allow(knife).to receive(:run_osc_11_user_edit).and_raise(SystemExit)
- allow(Chef::User).to receive(:load).and_return({"username" => nil})
+ allow(Chef::UserV1).to receive(:load).and_return({"username" => nil})
end
it "displays the osc warning" do
@@ -52,7 +52,7 @@ describe Chef::Knife::UserEdit do
it 'loads and edits the user' do
data = { "username" => "my_user" }
- allow(Chef::User).to receive(:load).with("my_user").and_return(data)
+ allow(Chef::UserV1).to receive(:load).with("my_user").and_return(data)
expect(knife).to receive(:edit_data).with(data).and_return(data)
knife.run
end
diff --git a/spec/unit/knife/user_list_spec.rb b/spec/unit/knife/user_list_spec.rb
index 9990cc802d..fa2bac426e 100644
--- a/spec/unit/knife/user_list_spec.rb
+++ b/spec/unit/knife/user_list_spec.rb
@@ -29,7 +29,7 @@ describe Chef::Knife::UserList do
end
it 'lists the users' do
- expect(Chef::User).to receive(:list)
+ expect(Chef::UserV1).to receive(:list)
expect(knife).to receive(:format_list_for_display)
knife.run
end
diff --git a/spec/unit/knife/user_reregister_spec.rb b/spec/unit/knife/user_reregister_spec.rb
index 412a6ec374..89aa6726cd 100644
--- a/spec/unit/knife/user_reregister_spec.rb
+++ b/spec/unit/knife/user_reregister_spec.rb
@@ -26,7 +26,7 @@ describe Chef::Knife::UserReregister do
before do
Chef::Knife::UserReregister.load_deps
knife.name_args = [ 'a_user' ]
- allow(Chef::User).to receive(:load).and_return(user_mock)
+ 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')
diff --git a/spec/unit/knife/user_show_spec.rb b/spec/unit/knife/user_show_spec.rb
index 43392a3a5c..7c39e428c0 100644
--- a/spec/unit/knife/user_show_spec.rb
+++ b/spec/unit/knife/user_show_spec.rb
@@ -35,7 +35,7 @@ describe Chef::Knife::UserShow do
context "when the username field is not supported by the server" do
before do
allow(knife).to receive(:run_osc_11_user_show).and_raise(SystemExit)
- allow(Chef::User).to receive(:load).with('my_user').and_return(user_mock)
+ allow(Chef::UserV1).to receive(:load).with('my_user').and_return(user_mock)
allow(user_mock).to receive(:username).and_return(nil)
end
@@ -51,7 +51,7 @@ describe Chef::Knife::UserShow do
end
it 'loads and displays the user' do
- expect(Chef::User).to receive(:load).with('my_user').and_return(user_mock)
+ 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
diff --git a/spec/unit/osc_user_spec.rb b/spec/unit/osc_user_spec.rb
deleted file mode 100644
index 16731b47bd..0000000000
--- a/spec/unit/osc_user_spec.rb
+++ /dev/null
@@ -1,276 +0,0 @@
-#
-# Author:: Steven Danna (steve@opscode.com)
-# Copyright:: Copyright (c) 2012 Opscode, 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.
-#
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_spec.rb.
-
-require 'spec_helper'
-
-require 'chef/osc_user'
-require 'tempfile'
-
-describe Chef::OscUser do
- before(:each) do
- @user = Chef::OscUser.new
- end
-
- describe "initialize" do
- it "should be a Chef::OscUser" do
- expect(@user).to be_a_kind_of(Chef::OscUser)
- end
- end
-
- describe "name" do
- it "should let you set the name to a string" do
- expect(@user.name("ops_master")).to eq("ops_master")
- end
-
- it "should return the current name" do
- @user.name "ops_master"
- expect(@user.name).to eq("ops_master")
- end
-
- # It is not feasible to check all invalid characters. Here are a few
- # that we probably care about.
- it "should not accept invalid characters" do
- # capital letters
- expect { @user.name "Bar" }.to raise_error(ArgumentError)
- # slashes
- expect { @user.name "foo/bar" }.to raise_error(ArgumentError)
- # ?
- expect { @user.name "foo?" }.to raise_error(ArgumentError)
- # &
- expect { @user.name "foo&" }.to raise_error(ArgumentError)
- end
-
-
- it "should not accept spaces" do
- expect { @user.name "ops master" }.to raise_error(ArgumentError)
- end
-
- it "should throw an ArgumentError if you feed it anything but a string" do
- expect { @user.name Hash.new }.to raise_error(ArgumentError)
- end
- end
-
- describe "admin" do
- it "should let you set the admin bit" do
- expect(@user.admin(true)).to eq(true)
- end
-
- it "should return the current admin value" do
- @user.admin true
- expect(@user.admin).to eq(true)
- end
-
- it "should default to false" do
- expect(@user.admin).to eq(false)
- end
-
- it "should throw an ArgumentError if you feed it anything but true or false" do
- expect { @user.name Hash.new }.to raise_error(ArgumentError)
- end
- end
-
- describe "public_key" do
- it "should let you set the public key" do
- expect(@user.public_key("super public")).to eq("super public")
- end
-
- it "should return the current public key" do
- @user.public_key("super public")
- expect(@user.public_key).to eq("super public")
- end
-
- it "should throw an ArgumentError if you feed it something lame" do
- expect { @user.public_key Hash.new }.to raise_error(ArgumentError)
- end
- end
-
- describe "private_key" do
- it "should let you set the private key" do
- expect(@user.private_key("super private")).to eq("super private")
- end
-
- it "should return the private key" do
- @user.private_key("super private")
- expect(@user.private_key).to eq("super private")
- end
-
- it "should throw an ArgumentError if you feed it something lame" do
- expect { @user.private_key Hash.new }.to raise_error(ArgumentError)
- end
- end
-
- describe "when serializing to JSON" do
- before(:each) do
- @user.name("black")
- @user.public_key("crowes")
- @json = @user.to_json
- end
-
- it "serializes as a JSON object" do
- expect(@json).to match(/^\{.+\}$/)
- end
-
- it "includes the name value" do
- expect(@json).to include(%q{"name":"black"})
- end
-
- it "includes the public key value" do
- expect(@json).to include(%{"public_key":"crowes"})
- end
-
- it "includes the 'admin' flag" do
- expect(@json).to include(%q{"admin":false})
- end
-
- it "includes the private key when present" do
- @user.private_key("monkeypants")
- expect(@user.to_json).to include(%q{"private_key":"monkeypants"})
- end
-
- it "does not include the private key if not present" do
- expect(@json).not_to include("private_key")
- end
-
- it "includes the password if present" do
- @user.password "password"
- expect(@user.to_json).to include(%q{"password":"password"})
- end
-
- it "does not include the password if not present" do
- expect(@json).not_to include("password")
- end
-
- include_examples "to_json equivalent to Chef::JSONCompat.to_json" do
- let(:jsonable) { @user }
- end
- end
-
- describe "when deserializing from JSON" do
- before(:each) do
- user = { "name" => "mr_spinks",
- "public_key" => "turtles",
- "private_key" => "pandas",
- "password" => "password",
- "admin" => true }
- @user = Chef::OscUser.from_json(Chef::JSONCompat.to_json(user))
- end
-
- it "should deserialize to a Chef::OscUser object" do
- expect(@user).to be_a_kind_of(Chef::OscUser)
- end
-
- it "preserves the name" do
- expect(@user.name).to eq("mr_spinks")
- end
-
- it "preserves the public key" do
- expect(@user.public_key).to eq("turtles")
- end
-
- it "preserves the admin status" do
- expect(@user.admin).to be_truthy
- end
-
- it "includes the private key if present" do
- expect(@user.private_key).to eq("pandas")
- end
-
- it "includes the password if present" do
- expect(@user.password).to eq("password")
- end
-
- end
-
- describe "API Interactions" do
- before (:each) do
- @user = Chef::OscUser.new
- @user.name "foobar"
- @http_client = double("Chef::REST mock")
- allow(Chef::REST).to receive(:new).and_return(@http_client)
- end
-
- describe "list" do
- before(:each) do
- Chef::Config[:chef_server_url] = "http://www.example.com"
- @osc_response = { "admin" => "http://www.example.com/users/admin"}
- @ohc_response = [ { "user" => { "username" => "admin" }} ]
- allow(Chef::OscUser).to receive(:load).with("admin").and_return(@user)
- @osc_inflated_response = { "admin" => @user }
- end
-
- it "lists all clients on an OSC server" do
- allow(@http_client).to receive(:get_rest).with("users").and_return(@osc_response)
- expect(Chef::OscUser.list).to eq(@osc_response)
- end
-
- it "inflate all clients on an OSC server" do
- allow(@http_client).to receive(:get_rest).with("users").and_return(@osc_response)
- expect(Chef::OscUser.list(true)).to eq(@osc_inflated_response)
- end
-
- it "lists all clients on an OHC/OPC server" do
- allow(@http_client).to receive(:get_rest).with("users").and_return(@ohc_response)
- # We expect that Chef::OscUser.list will give a consistent response
- # so OHC API responses should be transformed to OSC-style output.
- expect(Chef::OscUser.list).to eq(@osc_response)
- end
-
- it "inflate all clients on an OHC/OPC server" do
- allow(@http_client).to receive(:get_rest).with("users").and_return(@ohc_response)
- expect(Chef::OscUser.list(true)).to eq(@osc_inflated_response)
- end
- end
-
- describe "create" do
- it "creates a new user via the API" do
- @user.password "password"
- expect(@http_client).to receive(:post_rest).with("users", {:name => "foobar", :admin => false, :password => "password"}).and_return({})
- @user.create
- end
- end
-
- describe "read" do
- it "loads a named user from the API" do
- expect(@http_client).to receive(:get_rest).with("users/foobar").and_return({"name" => "foobar", "admin" => true, "public_key" => "pubkey"})
- user = Chef::OscUser.load("foobar")
- expect(user.name).to eq("foobar")
- expect(user.admin).to eq(true)
- expect(user.public_key).to eq("pubkey")
- end
- end
-
- describe "update" do
- it "updates an existing user on via the API" do
- expect(@http_client).to receive(:put_rest).with("users/foobar", {:name => "foobar", :admin => false}).and_return({})
- @user.update
- end
- end
-
- describe "destroy" do
- it "deletes the specified user via the API" do
- expect(@http_client).to receive(:delete_rest).with("users/foobar")
- @user.destroy
- end
- end
- end
-end
diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb
index 5222c951b3..777a4e6ef0 100644
--- a/spec/unit/user_spec.rb
+++ b/spec/unit/user_spec.rb
@@ -16,6 +16,11 @@
# limitations under the License.
#
+# DEPRECATION NOTE
+# This code only remains to support users still operating with
+# Open Source Chef Server 11 and should be removed once support
+# for OSC 11 ends. New development should occur in user_spec.rb.
+
require 'spec_helper'
require 'chef/user'
@@ -26,141 +31,98 @@ describe Chef::User do
@user = Chef::User.new
end
- shared_examples_for "string fields with no contraints" do
- it "should let you set the public key" do
- expect(@user.send(method, "some_string")).to eq("some_string")
- end
-
- it "should return the current public key" do
- @user.send(method, "some_string")
- expect(@user.send(method)).to eq("some_string")
- end
-
- it "should throw an ArgumentError if you feed it something lame" do
- expect { @user.send(method, Hash.new) }.to raise_error(ArgumentError)
- end
- end
-
- shared_examples_for "boolean fields with no constraints" do
- it "should let you set the field" do
- expect(@user.send(method, true)).to eq(true)
- end
-
- it "should return the current field value" do
- @user.send(method, true)
- expect(@user.send(method)).to eq(true)
- end
-
- it "should return the false value when false" do
- @user.send(method, false)
- expect(@user.send(method)).to eq(false)
- end
-
- it "should throw an ArgumentError if you feed it anything but true or false" do
- expect { @user.send(method, Hash.new) }.to raise_error(ArgumentError)
- end
- end
-
describe "initialize" do
it "should be a Chef::User" do
expect(@user).to be_a_kind_of(Chef::User)
end
end
- describe "username" do
- it "should let you set the username to a string" do
- expect(@user.username("ops_master")).to eq("ops_master")
+ describe "name" do
+ it "should let you set the name to a string" do
+ expect(@user.name("ops_master")).to eq("ops_master")
end
- it "should return the current username" do
- @user.username "ops_master"
- expect(@user.username).to eq("ops_master")
+ it "should return the current name" do
+ @user.name "ops_master"
+ expect(@user.name).to eq("ops_master")
end
# It is not feasible to check all invalid characters. Here are a few
# that we probably care about.
it "should not accept invalid characters" do
# capital letters
- expect { @user.username "Bar" }.to raise_error(ArgumentError)
+ expect { @user.name "Bar" }.to raise_error(ArgumentError)
# slashes
- expect { @user.username "foo/bar" }.to raise_error(ArgumentError)
+ expect { @user.name "foo/bar" }.to raise_error(ArgumentError)
# ?
- expect { @user.username "foo?" }.to raise_error(ArgumentError)
+ expect { @user.name "foo?" }.to raise_error(ArgumentError)
# &
- expect { @user.username "foo&" }.to raise_error(ArgumentError)
+ expect { @user.name "foo&" }.to raise_error(ArgumentError)
end
it "should not accept spaces" do
- expect { @user.username "ops master" }.to raise_error(ArgumentError)
+ expect { @user.name "ops master" }.to raise_error(ArgumentError)
end
it "should throw an ArgumentError if you feed it anything but a string" do
- expect { @user.username Hash.new }.to raise_error(ArgumentError)
+ expect { @user.name Hash.new }.to raise_error(ArgumentError)
end
end
- describe "boolean fields" do
- describe "create_key" do
- it_should_behave_like "boolean fields with no constraints" do
- let(:method) { :create_key }
- end
+ describe "admin" do
+ it "should let you set the admin bit" do
+ expect(@user.admin(true)).to eq(true)
end
- end
- describe "string fields" do
- describe "public_key" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :public_key }
- end
+ it "should return the current admin value" do
+ @user.admin true
+ expect(@user.admin).to eq(true)
end
- describe "private_key" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :private_key }
- end
+ it "should default to false" do
+ expect(@user.admin).to eq(false)
end
- describe "display_name" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :display_name }
- end
+ it "should throw an ArgumentError if you feed it anything but true or false" do
+ expect { @user.name Hash.new }.to raise_error(ArgumentError)
end
+ end
- describe "first_name" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :first_name }
- end
+ describe "public_key" do
+ it "should let you set the public key" do
+ expect(@user.public_key("super public")).to eq("super public")
end
- describe "middle_name" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :middle_name }
- end
+ it "should return the current public key" do
+ @user.public_key("super public")
+ expect(@user.public_key).to eq("super public")
end
- describe "last_name" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :last_name }
- end
+ it "should throw an ArgumentError if you feed it something lame" do
+ expect { @user.public_key Hash.new }.to raise_error(ArgumentError)
end
+ end
- describe "email" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :email }
- end
+ describe "private_key" do
+ it "should let you set the private key" do
+ expect(@user.private_key("super private")).to eq("super private")
end
- describe "password" do
- it_should_behave_like "string fields with no contraints" do
- let(:method) { :password }
- end
+ it "should return the private key" do
+ @user.private_key("super private")
+ expect(@user.private_key).to eq("super private")
+ end
+
+ it "should throw an ArgumentError if you feed it something lame" do
+ expect { @user.private_key Hash.new }.to raise_error(ArgumentError)
end
end
describe "when serializing to JSON" do
before(:each) do
- @user.username("black")
+ @user.name("black")
+ @user.public_key("crowes")
@json = @user.to_json
end
@@ -168,62 +130,16 @@ describe Chef::User do
expect(@json).to match(/^\{.+\}$/)
end
- it "includes the username value" do
- expect(@json).to include(%q{"username":"black"})
- end
-
- it "includes the display name when present" do
- @user.display_name("get_displayed")
- expect(@user.to_json).to include(%{"display_name":"get_displayed"})
- end
-
- it "does not include the display name if not present" do
- expect(@json).not_to include("display_name")
- end
-
- it "includes the first name when present" do
- @user.first_name("char")
- expect(@user.to_json).to include(%{"first_name":"char"})
- end
-
- it "does not include the first name if not present" do
- expect(@json).not_to include("first_name")
- end
-
- it "includes the middle name when present" do
- @user.middle_name("man")
- expect(@user.to_json).to include(%{"middle_name":"man"})
- end
-
- it "does not include the middle name if not present" do
- expect(@json).not_to include("middle_name")
- end
-
- it "includes the last name when present" do
- @user.last_name("der")
- expect(@user.to_json).to include(%{"last_name":"der"})
- end
-
- it "does not include the last name if not present" do
- expect(@json).not_to include("last_name")
- end
-
- it "includes the email when present" do
- @user.email("charmander@pokemon.poke")
- expect(@user.to_json).to include(%{"email":"charmander@pokemon.poke"})
- end
-
- it "does not include the email if not present" do
- expect(@json).not_to include("email")
+ it "includes the name value" do
+ expect(@json).to include(%q{"name":"black"})
end
- it "includes the public key when present" do
- @user.public_key("crowes")
- expect(@user.to_json).to include(%{"public_key":"crowes"})
+ it "includes the public key value" do
+ expect(@json).to include(%{"public_key":"crowes"})
end
- it "does not include the public key if not present" do
- expect(@json).not_to include("public_key")
+ it "includes the 'admin' flag" do
+ expect(@json).to include(%q{"admin":false})
end
it "includes the private key when present" do
@@ -251,18 +167,11 @@ describe Chef::User do
describe "when deserializing from JSON" do
before(:each) do
- user = {
- "username" => "mr_spinks",
- "display_name" => "displayed",
- "first_name" => "char",
- "middle_name" => "man",
- "last_name" => "der",
- "email" => "charmander@pokemon.poke",
- "password" => "password",
+ user = { "name" => "mr_spinks",
"public_key" => "turtles",
"private_key" => "pandas",
- "create_key" => false
- }
+ "password" => "password",
+ "admin" => true }
@user = Chef::User.from_json(Chef::JSONCompat.to_json(user))
end
@@ -270,277 +179,34 @@ describe Chef::User do
expect(@user).to be_a_kind_of(Chef::User)
end
- it "preserves the username" do
- expect(@user.username).to eq("mr_spinks")
- end
-
- it "preserves the display name if present" do
- expect(@user.display_name).to eq("displayed")
+ it "preserves the name" do
+ expect(@user.name).to eq("mr_spinks")
end
- it "preserves the first name if present" do
- expect(@user.first_name).to eq("char")
- end
-
- it "preserves the middle name if present" do
- expect(@user.middle_name).to eq("man")
+ it "preserves the public key" do
+ expect(@user.public_key).to eq("turtles")
end
- it "preserves the last name if present" do
- expect(@user.last_name).to eq("der")
+ it "preserves the admin status" do
+ expect(@user.admin).to be_truthy
end
- it "preserves the email if present" do
- expect(@user.email).to eq("charmander@pokemon.poke")
+ it "includes the private key if present" do
+ expect(@user.private_key).to eq("pandas")
end
it "includes the password if present" do
expect(@user.password).to eq("password")
end
- it "preserves the public key if present" do
- expect(@user.public_key).to eq("turtles")
- end
-
- it "includes the private key if present" do
- expect(@user.private_key).to eq("pandas")
- end
-
- it "includes the create key status if not nil" do
- expect(@user.create_key).to be_falsey
- end
end
- describe "Versioned API Interactions" do
- let(:response_406) { OpenStruct.new(:code => '406') }
- let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) }
-
- before (:each) do
- @user = Chef::User.new
- allow(@user).to receive(:chef_root_rest_v0).and_return(double('chef rest root v0 object'))
- allow(@user).to receive(:chef_root_rest_v1).and_return(double('chef rest root v1 object'))
- end
-
- describe "update" do
- before do
- # populate all fields that are valid between V0 and V1
- @user.username "some_username"
- @user.display_name "some_display_name"
- @user.first_name "some_first_name"
- @user.middle_name "some_middle_name"
- @user.last_name "some_last_name"
- @user.email "some_email"
- @user.password "some_password"
- end
-
- let(:payload) {
- {
- :username => "some_username",
- :display_name => "some_display_name",
- :first_name => "some_first_name",
- :middle_name => "some_middle_name",
- :last_name => "some_last_name",
- :email => "some_email",
- :password => "some_password"
- }
- }
-
- context "when server API V1 is valid on the Chef Server receiving the request" do
- context "when the user submits valid data" do
- it "properly updates the user" do
- expect(@user.chef_root_rest_v1).to receive(:put).with("users/some_username", payload).and_return({})
- @user.update
- end
- end
- end
-
- context "when server API V1 is not valid on the Chef Server receiving the request" do
- let(:payload) {
- {
- :username => "some_username",
- :display_name => "some_display_name",
- :first_name => "some_first_name",
- :middle_name => "some_middle_name",
- :last_name => "some_last_name",
- :email => "some_email",
- :password => "some_password",
- :public_key => "some_public_key"
- }
- }
-
- before do
- @user.public_key "some_public_key"
- allow(@user.chef_root_rest_v1).to receive(:put)
- end
-
- context "when the server returns a 400" do
- let(:response_400) { OpenStruct.new(:code => '400') }
- let(:exception_400) { Net::HTTPServerException.new("400 Bad Request", response_400) }
-
- context "when the 400 was due to public / private key fields no longer being supported" do
- let(:response_body_400) { '{"error":["Since Server API v1, all keys must be updated via the keys endpoint. "]}' }
-
- before do
- allow(response_400).to receive(:body).and_return(response_body_400)
- allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_400)
- end
-
- it "proceeds with the V0 PUT since it can handle public / private key fields" do
- expect(@user.chef_root_rest_v0).to receive(:put).with("users/some_username", payload).and_return({})
- @user.update
- end
-
- it "does not call server_client_api_version_intersection, since we know to proceed with V0 in this case" do
- expect(@user).to_not receive(:server_client_api_version_intersection)
- allow(@user.chef_root_rest_v0).to receive(:put).and_return({})
- @user.update
- end
- end # when the 400 was due to public / private key fields
-
- context "when the 400 was NOT due to public / private key fields no longer being supported" do
- let(:response_body_400) { '{"error":["Some other error. "]}' }
-
- before do
- allow(response_400).to receive(:body).and_return(response_body_400)
- allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_400)
- end
-
- it "will not proceed with the V0 PUT since the original bad request was not key related" do
- expect(@user.chef_root_rest_v0).to_not receive(:put).with("users/some_username", payload)
- expect { @user.update }.to raise_error(exception_400)
- end
-
- it "raises the original error" do
- expect { @user.update }.to raise_error(exception_400)
- end
-
- end
- end # when the server returns a 400
-
- context "when the server returns a 406" do
- # from spec/support/shared/unit/api_versioning.rb
- it_should_behave_like "version handling" do
- let(:object) { @user }
- let(:method) { :update }
- let(:http_verb) { :put }
- let(:rest_v1) { @user.chef_root_rest_v1 }
- end
-
- context "when the server supports API V0" do
- before do
- allow(@user).to receive(:server_client_api_version_intersection).and_return([0])
- allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_406)
- end
-
- it "properly updates the user" do
- expect(@user.chef_root_rest_v0).to receive(:put).with("users/some_username", payload).and_return({})
- @user.update
- end
- end # when the server supports API V0
- end # when the server returns a 406
-
- end # when server API V1 is not valid on the Chef Server receiving the request
- end # update
-
- describe "create" do
- let(:payload) {
- {
- :username => "some_username",
- :display_name => "some_display_name",
- :first_name => "some_first_name",
- :last_name => "some_last_name",
- :email => "some_email",
- :password => "some_password"
- }
- }
- before do
- @user.username "some_username"
- @user.display_name "some_display_name"
- @user.first_name "some_first_name"
- @user.last_name "some_last_name"
- @user.email "some_email"
- @user.password "some_password"
- end
-
- # from spec/support/shared/unit/user_and_client_shared.rb
- it_should_behave_like "user or client create" do
- let(:object) { @user }
- let(:error) { Chef::Exceptions::InvalidUserAttribute }
- let(:rest_v0) { @user.chef_root_rest_v0 }
- let(:rest_v1) { @user.chef_root_rest_v1 }
- let(:url) { "users" }
- end
-
- context "when handling API V1" do
- it "creates a new user via the API with a middle_name when it exists" do
- @user.middle_name "some_middle_name"
- expect(@user.chef_root_rest_v1).to receive(:post).with("users", payload.merge({:middle_name => "some_middle_name"})).and_return({})
- @user.create
- end
- end # when server API V1 is valid on the Chef Server receiving the request
-
- context "when API V1 is not supported by the server" do
- # from spec/support/shared/unit/api_versioning.rb
- it_should_behave_like "version handling" do
- let(:object) { @user }
- let(:method) { :create }
- let(:http_verb) { :post }
- let(:rest_v1) { @user.chef_root_rest_v1 }
- end
- end
-
- context "when handling API V0" do
- before do
- allow(@user).to receive(:server_client_api_version_intersection).and_return([0])
- allow(@user.chef_root_rest_v1).to receive(:post).and_raise(exception_406)
- end
-
- it "creates a new user via the API with a middle_name when it exists" do
- @user.middle_name "some_middle_name"
- expect(@user.chef_root_rest_v0).to receive(:post).with("users", payload.merge({:middle_name => "some_middle_name"})).and_return({})
- @user.create
- end
- end # when server API V1 is not valid on the Chef Server receiving the request
-
- end # create
-
- # DEPRECATION
- # This can be removed after API V0 support is gone
- describe "reregister" do
- let(:payload) {
- {
- "username" => "some_username",
- }
- }
-
- before do
- @user.username "some_username"
- end
-
- context "when server API V0 is valid on the Chef Server receiving the request" do
- it "creates a new object via the API" do
- expect(@user.chef_root_rest_v0).to receive(:put).with("users/#{@user.username}", payload.merge({"private_key" => true})).and_return({})
- @user.reregister
- end
- end # when server API V0 is valid on the Chef Server receiving the request
-
- context "when server API V0 is not supported by the Chef Server" do
- # from spec/support/shared/unit/api_versioning.rb
- it_should_behave_like "user and client reregister" do
- let(:object) { @user }
- let(:rest_v0) { @user.chef_root_rest_v0 }
- end
- end # when server API V0 is not supported by the Chef Server
- end # reregister
-
- end # Versioned API Interactions
-
describe "API Interactions" do
before (:each) do
@user = Chef::User.new
- @user.username "foobar"
- @http_client = double("Chef::REST mock")
- allow(Chef::REST).to receive(:new).and_return(@http_client)
+ @user.name "foobar"
+ @http_client = double("Chef::ServerAPI mock")
+ allow(Chef::ServerAPI).to receive(:new).and_return(@http_client)
end
describe "list" do
@@ -552,31 +218,57 @@ describe Chef::User do
@osc_inflated_response = { "admin" => @user }
end
+ it "lists all clients on an OSC server" do
+ allow(@http_client).to receive(:get_rest).with("users").and_return(@osc_response)
+ expect(Chef::User.list).to eq(@osc_response)
+ end
+
+ it "inflate all clients on an OSC server" do
+ allow(@http_client).to receive(:get_rest).with("users").and_return(@osc_response)
+ expect(Chef::User.list(true)).to eq(@osc_inflated_response)
+ end
+
it "lists all clients on an OHC/OPC server" do
- allow(@http_client).to receive(:get).with("users").and_return(@ohc_response)
+ allow(@http_client).to receive(:get_rest).with("users").and_return(@ohc_response)
# We expect that Chef::User.list will give a consistent response
# so OHC API responses should be transformed to OSC-style output.
expect(Chef::User.list).to eq(@osc_response)
end
it "inflate all clients on an OHC/OPC server" do
- allow(@http_client).to receive(:get).with("users").and_return(@ohc_response)
+ allow(@http_client).to receive(:get_rest).with("users").and_return(@ohc_response)
expect(Chef::User.list(true)).to eq(@osc_inflated_response)
end
end
+ describe "create" do
+ it "creates a new user via the API" do
+ @user.password "password"
+ expect(@http_client).to receive(:post_rest).with("users", {:name => "foobar", :admin => false, :password => "password"}).and_return({})
+ @user.create
+ end
+ end
+
describe "read" do
it "loads a named user from the API" do
- expect(@http_client).to receive(:get).with("users/foobar").and_return({"username" => "foobar", "admin" => true, "public_key" => "pubkey"})
+ expect(@http_client).to receive(:get_rest).with("users/foobar").and_return({"name" => "foobar", "admin" => true, "public_key" => "pubkey"})
user = Chef::User.load("foobar")
- expect(user.username).to eq("foobar")
+ expect(user.name).to eq("foobar")
+ expect(user.admin).to eq(true)
expect(user.public_key).to eq("pubkey")
end
end
+ describe "update" do
+ it "updates an existing user on via the API" do
+ expect(@http_client).to receive(:put_rest).with("users/foobar", {:name => "foobar", :admin => false}).and_return({})
+ @user.update
+ end
+ end
+
describe "destroy" do
it "deletes the specified user via the API" do
- expect(@http_client).to receive(:delete).with("users/foobar")
+ expect(@http_client).to receive(:delete_rest).with("users/foobar")
@user.destroy
end
end
diff --git a/spec/unit/user_v1_spec.rb b/spec/unit/user_v1_spec.rb
new file mode 100644
index 0000000000..8fd370a010
--- /dev/null
+++ b/spec/unit/user_v1_spec.rb
@@ -0,0 +1,584 @@
+#
+# Author:: Steven Danna (steve@opscode.com)
+# Copyright:: Copyright (c) 2012 Opscode, 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/user_v1'
+require 'tempfile'
+
+describe Chef::UserV1 do
+ before(:each) do
+ @user = Chef::UserV1.new
+ end
+
+ shared_examples_for "string fields with no contraints" do
+ it "should let you set the public key" do
+ expect(@user.send(method, "some_string")).to eq("some_string")
+ end
+
+ it "should return the current public key" do
+ @user.send(method, "some_string")
+ expect(@user.send(method)).to eq("some_string")
+ end
+
+ it "should throw an ArgumentError if you feed it something lame" do
+ expect { @user.send(method, Hash.new) }.to raise_error(ArgumentError)
+ end
+ end
+
+ shared_examples_for "boolean fields with no constraints" do
+ it "should let you set the field" do
+ expect(@user.send(method, true)).to eq(true)
+ end
+
+ it "should return the current field value" do
+ @user.send(method, true)
+ expect(@user.send(method)).to eq(true)
+ end
+
+ it "should return the false value when false" do
+ @user.send(method, false)
+ expect(@user.send(method)).to eq(false)
+ end
+
+ it "should throw an ArgumentError if you feed it anything but true or false" do
+ expect { @user.send(method, Hash.new) }.to raise_error(ArgumentError)
+ end
+ end
+
+ describe "initialize" do
+ it "should be a Chef::UserV1" do
+ expect(@user).to be_a_kind_of(Chef::UserV1)
+ end
+ end
+
+ describe "username" do
+ it "should let you set the username to a string" do
+ expect(@user.username("ops_master")).to eq("ops_master")
+ end
+
+ it "should return the current username" do
+ @user.username "ops_master"
+ expect(@user.username).to eq("ops_master")
+ end
+
+ # It is not feasible to check all invalid characters. Here are a few
+ # that we probably care about.
+ it "should not accept invalid characters" do
+ # capital letters
+ expect { @user.username "Bar" }.to raise_error(ArgumentError)
+ # slashes
+ expect { @user.username "foo/bar" }.to raise_error(ArgumentError)
+ # ?
+ expect { @user.username "foo?" }.to raise_error(ArgumentError)
+ # &
+ expect { @user.username "foo&" }.to raise_error(ArgumentError)
+ end
+
+
+ it "should not accept spaces" do
+ expect { @user.username "ops master" }.to raise_error(ArgumentError)
+ end
+
+ it "should throw an ArgumentError if you feed it anything but a string" do
+ expect { @user.username Hash.new }.to raise_error(ArgumentError)
+ end
+ end
+
+ describe "boolean fields" do
+ describe "create_key" do
+ it_should_behave_like "boolean fields with no constraints" do
+ let(:method) { :create_key }
+ end
+ end
+ end
+
+ describe "string fields" do
+ describe "public_key" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :public_key }
+ end
+ end
+
+ describe "private_key" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :private_key }
+ end
+ end
+
+ describe "display_name" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :display_name }
+ end
+ end
+
+ describe "first_name" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :first_name }
+ end
+ end
+
+ describe "middle_name" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :middle_name }
+ end
+ end
+
+ describe "last_name" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :last_name }
+ end
+ end
+
+ describe "email" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :email }
+ end
+ end
+
+ describe "password" do
+ it_should_behave_like "string fields with no contraints" do
+ let(:method) { :password }
+ end
+ end
+ end
+
+ describe "when serializing to JSON" do
+ before(:each) do
+ @user.username("black")
+ @json = @user.to_json
+ end
+
+ it "serializes as a JSON object" do
+ expect(@json).to match(/^\{.+\}$/)
+ end
+
+ it "includes the username value" do
+ expect(@json).to include(%q{"username":"black"})
+ end
+
+ it "includes the display name when present" do
+ @user.display_name("get_displayed")
+ expect(@user.to_json).to include(%{"display_name":"get_displayed"})
+ end
+
+ it "does not include the display name if not present" do
+ expect(@json).not_to include("display_name")
+ end
+
+ it "includes the first name when present" do
+ @user.first_name("char")
+ expect(@user.to_json).to include(%{"first_name":"char"})
+ end
+
+ it "does not include the first name if not present" do
+ expect(@json).not_to include("first_name")
+ end
+
+ it "includes the middle name when present" do
+ @user.middle_name("man")
+ expect(@user.to_json).to include(%{"middle_name":"man"})
+ end
+
+ it "does not include the middle name if not present" do
+ expect(@json).not_to include("middle_name")
+ end
+
+ it "includes the last name when present" do
+ @user.last_name("der")
+ expect(@user.to_json).to include(%{"last_name":"der"})
+ end
+
+ it "does not include the last name if not present" do
+ expect(@json).not_to include("last_name")
+ end
+
+ it "includes the email when present" do
+ @user.email("charmander@pokemon.poke")
+ expect(@user.to_json).to include(%{"email":"charmander@pokemon.poke"})
+ end
+
+ it "does not include the email if not present" do
+ expect(@json).not_to include("email")
+ end
+
+ it "includes the public key when present" do
+ @user.public_key("crowes")
+ expect(@user.to_json).to include(%{"public_key":"crowes"})
+ end
+
+ it "does not include the public key if not present" do
+ expect(@json).not_to include("public_key")
+ end
+
+ it "includes the private key when present" do
+ @user.private_key("monkeypants")
+ expect(@user.to_json).to include(%q{"private_key":"monkeypants"})
+ end
+
+ it "does not include the private key if not present" do
+ expect(@json).not_to include("private_key")
+ end
+
+ it "includes the password if present" do
+ @user.password "password"
+ expect(@user.to_json).to include(%q{"password":"password"})
+ end
+
+ it "does not include the password if not present" do
+ expect(@json).not_to include("password")
+ end
+
+ include_examples "to_json equivalent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @user }
+ end
+ end
+
+ describe "when deserializing from JSON" do
+ before(:each) do
+ user = {
+ "username" => "mr_spinks",
+ "display_name" => "displayed",
+ "first_name" => "char",
+ "middle_name" => "man",
+ "last_name" => "der",
+ "email" => "charmander@pokemon.poke",
+ "password" => "password",
+ "public_key" => "turtles",
+ "private_key" => "pandas",
+ "create_key" => false
+ }
+ @user = Chef::UserV1.from_json(Chef::JSONCompat.to_json(user))
+ end
+
+ it "should deserialize to a Chef::UserV1 object" do
+ expect(@user).to be_a_kind_of(Chef::UserV1)
+ end
+
+ it "preserves the username" do
+ expect(@user.username).to eq("mr_spinks")
+ end
+
+ it "preserves the display name if present" do
+ expect(@user.display_name).to eq("displayed")
+ end
+
+ it "preserves the first name if present" do
+ expect(@user.first_name).to eq("char")
+ end
+
+ it "preserves the middle name if present" do
+ expect(@user.middle_name).to eq("man")
+ end
+
+ it "preserves the last name if present" do
+ expect(@user.last_name).to eq("der")
+ end
+
+ it "preserves the email if present" do
+ expect(@user.email).to eq("charmander@pokemon.poke")
+ end
+
+ it "includes the password if present" do
+ expect(@user.password).to eq("password")
+ end
+
+ it "preserves the public key if present" do
+ expect(@user.public_key).to eq("turtles")
+ end
+
+ it "includes the private key if present" do
+ expect(@user.private_key).to eq("pandas")
+ end
+
+ it "includes the create key status if not nil" do
+ expect(@user.create_key).to be_falsey
+ end
+ end
+
+ describe "Versioned API Interactions" do
+ let(:response_406) { OpenStruct.new(:code => '406') }
+ let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) }
+
+ before (:each) do
+ @user = Chef::UserV1.new
+ allow(@user).to receive(:chef_root_rest_v0).and_return(double('chef rest root v0 object'))
+ allow(@user).to receive(:chef_root_rest_v1).and_return(double('chef rest root v1 object'))
+ end
+
+ describe "update" do
+ before do
+ # populate all fields that are valid between V0 and V1
+ @user.username "some_username"
+ @user.display_name "some_display_name"
+ @user.first_name "some_first_name"
+ @user.middle_name "some_middle_name"
+ @user.last_name "some_last_name"
+ @user.email "some_email"
+ @user.password "some_password"
+ end
+
+ let(:payload) {
+ {
+ :username => "some_username",
+ :display_name => "some_display_name",
+ :first_name => "some_first_name",
+ :middle_name => "some_middle_name",
+ :last_name => "some_last_name",
+ :email => "some_email",
+ :password => "some_password"
+ }
+ }
+
+ context "when server API V1 is valid on the Chef Server receiving the request" do
+ context "when the user submits valid data" do
+ it "properly updates the user" do
+ expect(@user.chef_root_rest_v1).to receive(:put).with("users/some_username", payload).and_return({})
+ @user.update
+ end
+ end
+ end
+
+ context "when server API V1 is not valid on the Chef Server receiving the request" do
+ let(:payload) {
+ {
+ :username => "some_username",
+ :display_name => "some_display_name",
+ :first_name => "some_first_name",
+ :middle_name => "some_middle_name",
+ :last_name => "some_last_name",
+ :email => "some_email",
+ :password => "some_password",
+ :public_key => "some_public_key"
+ }
+ }
+
+ before do
+ @user.public_key "some_public_key"
+ allow(@user.chef_root_rest_v1).to receive(:put)
+ end
+
+ context "when the server returns a 400" do
+ let(:response_400) { OpenStruct.new(:code => '400') }
+ let(:exception_400) { Net::HTTPServerException.new("400 Bad Request", response_400) }
+
+ context "when the 400 was due to public / private key fields no longer being supported" do
+ let(:response_body_400) { '{"error":["Since Server API v1, all keys must be updated via the keys endpoint. "]}' }
+
+ before do
+ allow(response_400).to receive(:body).and_return(response_body_400)
+ allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_400)
+ end
+
+ it "proceeds with the V0 PUT since it can handle public / private key fields" do
+ expect(@user.chef_root_rest_v0).to receive(:put).with("users/some_username", payload).and_return({})
+ @user.update
+ end
+
+ it "does not call server_client_api_version_intersection, since we know to proceed with V0 in this case" do
+ expect(@user).to_not receive(:server_client_api_version_intersection)
+ allow(@user.chef_root_rest_v0).to receive(:put).and_return({})
+ @user.update
+ end
+ end # when the 400 was due to public / private key fields
+
+ context "when the 400 was NOT due to public / private key fields no longer being supported" do
+ let(:response_body_400) { '{"error":["Some other error. "]}' }
+
+ before do
+ allow(response_400).to receive(:body).and_return(response_body_400)
+ allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_400)
+ end
+
+ it "will not proceed with the V0 PUT since the original bad request was not key related" do
+ expect(@user.chef_root_rest_v0).to_not receive(:put).with("users/some_username", payload)
+ expect { @user.update }.to raise_error(exception_400)
+ end
+
+ it "raises the original error" do
+ expect { @user.update }.to raise_error(exception_400)
+ end
+
+ end
+ end # when the server returns a 400
+
+ context "when the server returns a 406" do
+ # from spec/support/shared/unit/api_versioning.rb
+ it_should_behave_like "version handling" do
+ let(:object) { @user }
+ let(:method) { :update }
+ let(:http_verb) { :put }
+ let(:rest_v1) { @user.chef_root_rest_v1 }
+ end
+
+ context "when the server supports API V0" do
+ before do
+ allow(@user).to receive(:server_client_api_version_intersection).and_return([0])
+ allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_406)
+ end
+
+ it "properly updates the user" do
+ expect(@user.chef_root_rest_v0).to receive(:put).with("users/some_username", payload).and_return({})
+ @user.update
+ end
+ end # when the server supports API V0
+ end # when the server returns a 406
+
+ end # when server API V1 is not valid on the Chef Server receiving the request
+ end # update
+
+ describe "create" do
+ let(:payload) {
+ {
+ :username => "some_username",
+ :display_name => "some_display_name",
+ :first_name => "some_first_name",
+ :last_name => "some_last_name",
+ :email => "some_email",
+ :password => "some_password"
+ }
+ }
+ before do
+ @user.username "some_username"
+ @user.display_name "some_display_name"
+ @user.first_name "some_first_name"
+ @user.last_name "some_last_name"
+ @user.email "some_email"
+ @user.password "some_password"
+ end
+
+ # from spec/support/shared/unit/user_and_client_shared.rb
+ it_should_behave_like "user or client create" do
+ let(:object) { @user }
+ let(:error) { Chef::Exceptions::InvalidUserAttribute }
+ let(:rest_v0) { @user.chef_root_rest_v0 }
+ let(:rest_v1) { @user.chef_root_rest_v1 }
+ let(:url) { "users" }
+ end
+
+ context "when handling API V1" do
+ it "creates a new user via the API with a middle_name when it exists" do
+ @user.middle_name "some_middle_name"
+ expect(@user.chef_root_rest_v1).to receive(:post).with("users", payload.merge({:middle_name => "some_middle_name"})).and_return({})
+ @user.create
+ end
+ end # when server API V1 is valid on the Chef Server receiving the request
+
+ context "when API V1 is not supported by the server" do
+ # from spec/support/shared/unit/api_versioning.rb
+ it_should_behave_like "version handling" do
+ let(:object) { @user }
+ let(:method) { :create }
+ let(:http_verb) { :post }
+ let(:rest_v1) { @user.chef_root_rest_v1 }
+ end
+ end
+
+ context "when handling API V0" do
+ before do
+ allow(@user).to receive(:server_client_api_version_intersection).and_return([0])
+ allow(@user.chef_root_rest_v1).to receive(:post).and_raise(exception_406)
+ end
+
+ it "creates a new user via the API with a middle_name when it exists" do
+ @user.middle_name "some_middle_name"
+ expect(@user.chef_root_rest_v0).to receive(:post).with("users", payload.merge({:middle_name => "some_middle_name"})).and_return({})
+ @user.create
+ end
+ end # when server API V1 is not valid on the Chef Server receiving the request
+
+ end # create
+
+ # DEPRECATION
+ # This can be removed after API V0 support is gone
+ describe "reregister" do
+ let(:payload) {
+ {
+ "username" => "some_username",
+ }
+ }
+
+ before do
+ @user.username "some_username"
+ end
+
+ context "when server API V0 is valid on the Chef Server receiving the request" do
+ it "creates a new object via the API" do
+ expect(@user.chef_root_rest_v0).to receive(:put).with("users/#{@user.username}", payload.merge({"private_key" => true})).and_return({})
+ @user.reregister
+ end
+ end # when server API V0 is valid on the Chef Server receiving the request
+
+ context "when server API V0 is not supported by the Chef Server" do
+ # from spec/support/shared/unit/api_versioning.rb
+ it_should_behave_like "user and client reregister" do
+ let(:object) { @user }
+ let(:rest_v0) { @user.chef_root_rest_v0 }
+ end
+ end # when server API V0 is not supported by the Chef Server
+ end # reregister
+
+ end # Versioned API Interactions
+
+ describe "API Interactions" do
+ before (:each) do
+ @user = Chef::UserV1.new
+ @user.username "foobar"
+ @http_client = double("Chef::REST mock")
+ allow(Chef::REST).to receive(:new).and_return(@http_client)
+ end
+
+ describe "list" do
+ before(:each) do
+ Chef::Config[:chef_server_url] = "http://www.example.com"
+ @osc_response = { "admin" => "http://www.example.com/users/admin"}
+ @ohc_response = [ { "user" => { "username" => "admin" }} ]
+ allow(Chef::UserV1).to receive(:load).with("admin").and_return(@user)
+ @osc_inflated_response = { "admin" => @user }
+ end
+
+ it "lists all clients on an OHC/OPC server" do
+ allow(@http_client).to receive(:get).with("users").and_return(@ohc_response)
+ # We expect that Chef::UserV1.list will give a consistent response
+ # so OHC API responses should be transformed to OSC-style output.
+ expect(Chef::UserV1.list).to eq(@osc_response)
+ end
+
+ it "inflate all clients on an OHC/OPC server" do
+ allow(@http_client).to receive(:get).with("users").and_return(@ohc_response)
+ expect(Chef::UserV1.list(true)).to eq(@osc_inflated_response)
+ end
+ end
+
+ describe "read" do
+ it "loads a named user from the API" do
+ expect(@http_client).to receive(:get).with("users/foobar").and_return({"username" => "foobar", "admin" => true, "public_key" => "pubkey"})
+ user = Chef::UserV1.load("foobar")
+ expect(user.username).to eq("foobar")
+ expect(user.public_key).to eq("pubkey")
+ end
+ end
+
+ describe "destroy" do
+ it "deletes the specified user via the API" do
+ expect(@http_client).to receive(:delete).with("users/foobar")
+ @user.destroy
+ end
+ end
+ end
+end