summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsnehaldwivedi <sdwivedi@msystechnologies.com>2020-07-31 04:37:07 -0700
committersnehaldwivedi <sdwivedi@msystechnologies.com>2021-02-16 02:45:12 -0800
commitf9f3fe38013846ffc8a7bb080363c27e02837307 (patch)
tree0562ea254790ac9e8c50f5375e69602c3d9580ec
parent1f655be8219c9e20dffd68adc2ff97c29e2c29b3 (diff)
downloadchef-f9f3fe38013846ffc8a7bb080363c27e02837307.tar.gz
Updated reviewed changes
Signed-off-by: snehaldwivedi <sdwivedi@msystechnologies.com>
-rw-r--r--lib/chef/group.rb75
-rw-r--r--lib/chef/knife/opc_org_create.rb67
-rw-r--r--lib/chef/knife/opc_org_list.rb45
-rw-r--r--lib/chef/knife/opc_org_user_add.rb61
-rw-r--r--lib/chef/knife/opc_org_user_remove.rb103
-rw-r--r--lib/chef/knife/opc_user_create.rb101
-rw-r--r--lib/chef/knife/opc_user_delete.rb144
-rw-r--r--lib/chef/knife/opc_user_edit.rb69
-rw-r--r--lib/chef/knife/opc_user_list.rb37
-rw-r--r--lib/chef/knife/opc_user_password.rb72
-rw-r--r--lib/chef/knife/org_create.rb68
-rw-r--r--lib/chef/knife/org_delete.rb (renamed from lib/chef/knife/opc_org_delete.rb)20
-rw-r--r--lib/chef/knife/org_edit.rb (renamed from lib/chef/knife/opc_user_show.rb)40
-rw-r--r--lib/chef/knife/org_list.rb (renamed from lib/chef/knife/opc_org_edit.rb)40
-rw-r--r--lib/chef/knife/org_show.rb (renamed from lib/chef/knife/opc_org_show.rb)18
-rw-r--r--lib/chef/knife/org_user_add.rb62
-rw-r--r--lib/chef/knife/org_user_remove.rb103
-rw-r--r--lib/chef/knife/user_create.rb62
-rw-r--r--lib/chef/knife/user_delete.rb119
-rw-r--r--lib/chef/knife/user_dissociate.rb2
-rw-r--r--lib/chef/knife/user_edit.rb58
-rw-r--r--lib/chef/knife/user_list.rb12
-rw-r--r--lib/chef/knife/user_password.rb73
-rw-r--r--lib/chef/knife/user_show.rb21
-rw-r--r--lib/chef/mixin/root_rest.rb2
-rw-r--r--lib/chef/org.rb5
-rw-r--r--lib/chef/org/group_operations.rb.old (renamed from lib/chef/org/group_operations.rb)0
-rw-r--r--spec/spec_helper.rb4
-rw-r--r--spec/unit/knife/opc_org_list_spec.rb39
-rw-r--r--spec/unit/knife/opc_org_user_add_spec.rb24
-rw-r--r--spec/unit/knife/opc_user_create_spec.rb121
-rw-r--r--spec/unit/knife/opc_user_delete_spec.rb157
-rw-r--r--spec/unit/knife/opc_user_show_spec.rb68
-rw-r--r--spec/unit/knife/org_create_spec.rb (renamed from spec/unit/knife/opc_org_create_spec.rb)25
-rw-r--r--spec/unit/knife/org_delete_spec.rb (renamed from spec/unit/knife/opc_org_delete_spec.rb)6
-rw-r--r--spec/unit/knife/org_list_spec.rb (renamed from spec/unit/knife/opc_user_list_spec.rb)29
-rw-r--r--spec/unit/knife/org_show_spec.rb (renamed from spec/unit/knife/opc_org_show_spec.rb)6
-rw-r--r--spec/unit/knife/org_user_add_spec.rb39
-rw-r--r--spec/unit/knife/user_create_spec.rb91
-rw-r--r--spec/unit/knife/user_delete_spec.rb162
-rw-r--r--spec/unit/knife/user_edit_spec.rb2
-rw-r--r--spec/unit/knife/user_list_spec.rb51
-rw-r--r--spec/unit/knife/user_password_spec.rb (renamed from spec/unit/knife/opc_user_password_spec.rb)6
-rw-r--r--spec/unit/knife/user_show_spec.rb75
-rw-r--r--spec/unit/org_group_spec.rb1
45 files changed, 1085 insertions, 1300 deletions
diff --git a/lib/chef/group.rb b/lib/chef/group.rb
new file mode 100644
index 0000000000..d1b4f1ac01
--- /dev/null
+++ b/lib/chef/group.rb
@@ -0,0 +1,75 @@
+#
+# Copyright:: Copyright 2011-2016 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_relative "org"
+
+class Chef
+ class Group
+
+ def group(groupname)
+ @group ||= {}
+ @group[groupname] ||= chef_rest.get_rest "organizations/#{name}/groups/#{groupname}"
+ end
+
+ def user_member_of_group?(username, groupname)
+ group = group(groupname)
+ group["actors"].include? username
+ end
+
+ def add_user_to_group(groupname, username)
+ group = group(groupname)
+ body_hash = {
+ groupname: "#{groupname}",
+ actors: {
+ "users" => group["actors"].concat([username]),
+ "groups" => group["groups"],
+ },
+ }
+ chef_rest.put_rest "organizations/#{name}/groups/#{groupname}", body_hash
+ end
+
+ def remove_user_from_group(groupname, username)
+ group = group(groupname)
+ group["actors"].delete(username)
+ body_hash = {
+ groupname: "#{groupname}",
+ actors: {
+ "users" => group["actors"],
+ "groups" => group["groups"],
+ },
+ }
+ chef_rest.put_rest "organizations/#{name}/groups/#{groupname}", body_hash
+ end
+
+ def actor_delete_would_leave_admins_empty?
+ admins = group("admins")
+ if admins["groups"].empty?
+ # exclude 'pivotal' but don't mutate the group since we're caching it
+ if admins["actors"].include? "pivotal"
+ admins["actors"].length <= 2
+ else
+ admins["actors"].length <= 1
+ end
+ else
+ # We don't check recursively. If the admins group contains a group,
+ # and the user is the only member of that group,
+ # we'll still turn up a 'safe to delete'.
+ false
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/opc_org_create.rb b/lib/chef/knife/opc_org_create.rb
deleted file mode 100644
index 4e016f2630..0000000000
--- a/lib/chef/knife/opc_org_create.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2011-2016 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.
-#
-
-module Opc
- class OpcOrgCreate < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org create ORG_SHORT_NAME ORG_FULL_NAME (options)"
-
- option :filename,
- long: "--filename FILENAME",
- short: "-f FILENAME",
- description: "Write validator private key to FILENAME rather than STDOUT"
-
- option :association_user,
- long: "--association_user USERNAME",
- short: "-a USERNAME",
- description: "Invite USERNAME to the new organization after creation"
-
- attr_accessor :org_name, :org_full_name
-
- deps do
- require_relative "../org"
- require_relative "../org/group_operations"
- end
-
- def run
- @org_name, @org_full_name = @name_args
-
- if !org_name || !org_full_name
- ui.fatal "You must specify an ORG_NAME and an ORG_FULL_NAME"
- show_usage
- exit 1
- end
-
- org = Chef::Org.from_hash({ "name" => org_name,
- "full_name" => org_full_name }).create
- if config[:filename]
- File.open(config[:filename], "w") do |f|
- f.print(org.private_key)
- end
- else
- ui.msg org.private_key
- end
-
- if config[:association_user]
- org.associate_user(config[:association_user])
- org.add_user_to_group("admins", config[:association_user])
- org.add_user_to_group("billing-admins", config[:association_user])
- end
- end
- end
-end
diff --git a/lib/chef/knife/opc_org_list.rb b/lib/chef/knife/opc_org_list.rb
deleted file mode 100644
index 2220b3e737..0000000000
--- a/lib/chef/knife/opc_org_list.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2011-2016 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_relative "../mixin/root_rest"
-
-module Opc
- class OpcOrgList < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org list"
-
- option :with_uri,
- long: "--with-uri",
- short: "-w",
- description: "Show corresponding URIs"
-
- option :all_orgs,
- long: "--all-orgs",
- short: "-a",
- description: "Show auto-generated hidden orgs in output"
-
- include Chef::Mixin::RootRestv0
-
- def run
- results = root_rest.get("organizations")
- unless config[:all_orgs]
- results = results.select { |k, v| !(k.length == 20 && k =~ /^[a-z]+$/) }
- end
- ui.output(ui.format_list_for_display(results))
- end
- end
-end
diff --git a/lib/chef/knife/opc_org_user_add.rb b/lib/chef/knife/opc_org_user_add.rb
deleted file mode 100644
index 2209fdd4f9..0000000000
--- a/lib/chef/knife/opc_org_user_add.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# Author:: Marc Paradise (<marc@chef.io>)
-# Copyright:: Copyright 2014-2016 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.
-#
-
-module Opc
- class OpcOrgUserAdd < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org user add ORG_NAME USER_NAME"
- attr_accessor :org_name, :username
-
- option :admin,
- long: "--admin",
- short: "-a",
- description: "Add user to admin group"
-
- deps do
- require_relative "../org"
- require_relative "../org/group_operations"
- end
-
- def run
- @org_name, @username = @name_args
-
- if !org_name || !username
- ui.fatal "You must specify an ORG_NAME and USER_NAME"
- show_usage
- exit 1
- end
-
- org = Chef::Org.new(@org_name)
- begin
- org.associate_user(@username)
- rescue Net::HTTPServerException => e
- if e.response.code == "409"
- ui.msg "User #{username} already associated with organization #{org_name}"
- else
- raise e
- end
- end
- if config[:admin]
- org.add_user_to_group("admins", @username)
- org.add_user_to_group("billing-admins", @username)
- ui.msg "User #{username} is added to admins and billing-admins group"
- end
- end
- end
-end
diff --git a/lib/chef/knife/opc_org_user_remove.rb b/lib/chef/knife/opc_org_user_remove.rb
deleted file mode 100644
index fd3c518e9c..0000000000
--- a/lib/chef/knife/opc_org_user_remove.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-#
-# Author:: Marc Paradise (<marc@getchef.com>)
-# Copyright:: Copyright 2014-2016 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.
-#
-
-module Opc
- class OpcOrgUserRemove < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org user remove ORG_NAME USER_NAME"
- attr_accessor :org_name, :username
-
- option :force_remove_from_admins,
- long: "--force",
- short: "-f",
- description: "Force removal of user from the organization's admins and billing-admins group."
-
- deps do
- require_relative "../org"
- require_relative "../org/group_operations"
- require "chef/json_compat"
- end
-
- def run
- @org_name, @username = @name_args
-
- if !org_name || !username
- ui.fatal "You must specify an ORG_NAME and USER_NAME"
- show_usage
- exit 1
- end
-
- org = Chef::Org.new(@org_name)
-
- if config[:force_remove_from_admins]
- if org.actor_delete_would_leave_admins_empty?
- failure_error_message(org_name, username)
- ui.msg <<~EOF
- You ran with --force which force removes the user from the admins and billing-admins groups.
- However, removing #{username} from the admins group would leave it empty, which breaks the org.
- Please add another user to org #{org_name} admins group and try again.
- EOF
- exit 1
- end
- remove_user_from_admin_group(org, org_name, username, "admins")
- remove_user_from_admin_group(org, org_name, username, "billing-admins")
- end
-
- begin
- org.dissociate_user(@username)
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- ui.msg "User #{username} is not associated with organization #{org_name}"
- exit 1
- elsif e.response.code == "403"
- body = Chef::JSONCompat.from_json(e.response.body)
- if body.key?("error") && body["error"] == "Please remove #{username} from this organization's admins group before removing him or her from the organization."
- failure_error_message(org_name, username)
- ui.msg <<~EOF
- User #{username} is in the organization's admin group. Removing users from an organization without removing them from the admins group is not allowed.
- Re-run this command with --force to remove this user from the admins prior to removing it from the organization.
- EOF
- exit 1
- else
- raise e
- end
- else
- raise e
- end
- end
- end
-
- def failure_error_message(org_name, username)
- ui.error "Error removing user #{username} from organization #{org_name}."
- end
-
- def remove_user_from_admin_group(org, org_name, username, admin_group_string)
- org.remove_user_from_group(admin_group_string, username)
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- ui.warn <<~EOF
- User #{username} is not in the #{admin_group_string} group for organization #{org_name}.
- You probably don't need to pass --force.
- EOF
- else
- raise e
- end
- end
-
- end
-end
diff --git a/lib/chef/knife/opc_user_create.rb b/lib/chef/knife/opc_user_create.rb
deleted file mode 100644
index 48fd4eba8f..0000000000
--- a/lib/chef/knife/opc_user_create.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2011-2016 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_relative "../mixin/root_rest"
-
-module Opc
- class OpcUserCreate < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc user create USERNAME FIRST_NAME [MIDDLE_NAME] LAST_NAME EMAIL PASSWORD"
-
- option :filename,
- long: "--filename FILENAME",
- short: "-f FILENAME",
- description: "Write private key to FILENAME rather than STDOUT"
-
- option :orgname,
- long: "--orgname ORGNAME",
- short: "-o ORGNAME",
- description: "Associate new user to an organization matching ORGNAME"
-
- option :passwordprompt,
- long: "--prompt-for-password",
- short: "-p",
- description: "Prompt for user password"
-
- include Chef::Mixin::RootRestv0
-
- def run
- case @name_args.count
- when 6
- username, first_name, middle_name, last_name, email, password = @name_args
- when 5
- username, first_name, last_name, email, password = @name_args
- when 4
- username, first_name, last_name, email = @name_args
- else
- ui.fatal "Wrong number of arguments"
- show_usage
- exit 1
- end
- password = prompt_for_password if config[:passwordprompt]
- unless password
- ui.fatal "You must either provide a password or use the --prompt-for-password (-p) option"
- exit 1
- end
- middle_name ||= ""
-
- user_hash = {
- username: username,
- first_name: first_name,
- middle_name: middle_name,
- last_name: last_name,
- display_name: "#{first_name} #{last_name}",
- email: email,
- password: password,
- }
-
- # Check the file before creating the user so the api is more transactional.
- if config[:filename]
- file = config[:filename]
- unless File.exist?(file) ? File.writable?(file) : File.writable?(File.dirname(file))
- ui.fatal "File #{config[:filename]} is not writable. Check permissions."
- exit 1
- end
- end
-
- result = root_rest.post("users/", user_hash)
- if config[:filename]
- File.open(config[:filename], "w") do |f|
- f.print(result["private_key"])
- end
- else
- ui.msg result["private_key"]
- end
- if config[:orgname]
- request_body = { user: username }
- response = root_rest.post("organizations/#{config[:orgname]}/association_requests", request_body)
- association_id = response["uri"].split("/").last
- root_rest.put("users/#{username}/association_requests/#{association_id}", { response: "accept" })
- end
- end
-
- def prompt_for_password
- ui.ask("Please enter the user's password: ") { |q| q.echo = false }
- end
- end
-end
diff --git a/lib/chef/knife/opc_user_delete.rb b/lib/chef/knife/opc_user_delete.rb
deleted file mode 100644
index b749b8a5d4..0000000000
--- a/lib/chef/knife/opc_user_delete.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2011-2016 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_relative "../mixin/root_rest"
-
-module Opc
- class OpcUserDelete < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc user delete USERNAME [-d] [-R]"
-
- option :no_disassociate_user,
- long: "--no-disassociate-user",
- short: "-d",
- description: "Don't disassociate the user first"
-
- option :remove_from_admin_groups,
- long: "--remove-from-admin-groups",
- short: "-R",
- description: "If the user is a member of any org admin groups, attempt to remove from those groups. Ignored if --no-disassociate-user is set."
-
- attr_reader :username
- include Chef::Mixin::RootRestv0
-
- deps do
- require_relative "../org"
- require_relative "../org/group_operations"
- end
-
- def run
- @username = @name_args[0]
- admin_memberships = []
- unremovable_memberships = []
-
- ui.confirm "Do you want to delete the user #{username}"
-
- unless config[:no_disassociate_user]
- ui.stderr.puts("Checking organization memberships...")
- orgs = org_memberships(username)
- if orgs.length > 0
- ui.stderr.puts("Checking admin group memberships for #{orgs.length} org(s).")
- admin_memberships, unremovable_memberships = admin_group_memberships(orgs, username)
- end
-
- unless admin_memberships.empty?
- unless config[:remove_from_admin_groups]
- error_exit_admin_group_member!(username, admin_memberships)
- end
-
- unless unremovable_memberships.empty?
- error_exit_cant_remove_admin_membership!(username, unremovable_memberships)
- end
- remove_from_admin_groups(admin_memberships, username)
- end
- disassociate_user(orgs, username)
- end
-
- delete_user(username)
- end
-
- def disassociate_user(orgs, username)
- orgs.each { |org| org.dissociate_user(username) }
- end
-
- def org_memberships(username)
- org_data = root_rest.get("users/#{username}/organizations")
- org_data.map { |org| Chef::Org.new(org["organization"]["name"]) }
- end
-
- def remove_from_admin_groups(admin_of, username)
- admin_of.each do |org|
- ui.stderr.puts "Removing #{username} from admins group of '#{org.name}'"
- org.remove_user_from_group("admins", username)
- end
- end
-
- def admin_group_memberships(orgs, username)
- admin_of = []
- unremovable = []
- orgs.each do |org|
- if org.user_member_of_group?(username, "admins")
- admin_of << org
- if org.actor_delete_would_leave_admins_empty?
- unremovable << org
- end
- end
- end
- [admin_of, unremovable]
- end
-
- def delete_user(username)
- ui.stderr.puts "Deleting user #{username}."
- root_rest.delete("users/#{username}")
- end
-
- # Error message that says how to removed from org
- # admin groups before deleting
- # Further
- def error_exit_admin_group_member!(username, admin_of)
- message = "#{username} is in the 'admins' group of the following organization(s):\n\n"
- admin_of.each { |org| message << "- #{org.name}\n" }
- message << <<~EOM
-
- Run this command again with the --remove-from-admin-groups option to
- remove the user from these admin group(s) automatically.
-
- EOM
- ui.fatal message
- exit 1
- end
-
- def error_exit_cant_remove_admin_membership!(username, only_admin_of)
- message = <<~EOM
-
- #{username} is the only member of the 'admins' group of the
- following organization(s):
-
- EOM
- only_admin_of.each { |org| message << "- #{org.name}\n" }
- message << <<~EOM
-
- Removing the only administrator of an organization can break it.
- Assign additional users or groups to the admin group(s) before
- deleting this user.
-
- EOM
- ui.fatal message
- exit 1
- end
- end
-end
diff --git a/lib/chef/knife/opc_user_edit.rb b/lib/chef/knife/opc_user_edit.rb
deleted file mode 100644
index 26118bce9f..0000000000
--- a/lib/chef/knife/opc_user_edit.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2011-2016 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_relative "../mixin/root_rest"
-
-module Opc
- class OpcUserEdit < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc user edit USERNAME"
-
- option :input,
- long: "--input FILENAME",
- short: "-i FILENAME",
- description: "Name of file to use for PUT or POST"
-
- option :filename,
- long: "--filename FILENAME",
- short: "-f FILENAME",
- description: "Write private key to FILENAME rather than STDOUT"
-
- include Chef::Mixin::RootRestv0
-
- def run
- user_name = @name_args[0]
-
- if user_name.nil?
- show_usage
- ui.fatal("You must specify a user name")
- exit 1
- end
-
- original_user = root_rest.get("users/#{user_name}")
- if config[:input]
- edited_user = JSON.parse(IO.read(config[:input]))
- else
- edited_user = edit_data(original_user)
- end
- if original_user != edited_user
- result = root_rest.put("users/#{user_name}", edited_user)
- ui.msg("Saved #{user_name}.")
- unless result["private_key"].nil?
- if config[:filename]
- File.open(config[:filename], "w") do |f|
- f.print(result["private_key"])
- end
- else
- ui.msg result["private_key"]
- end
- end
- else
- ui.msg("User unchanged, not saving.")
- end
- end
- end
-end
diff --git a/lib/chef/knife/opc_user_list.rb b/lib/chef/knife/opc_user_list.rb
deleted file mode 100644
index 33402175ec..0000000000
--- a/lib/chef/knife/opc_user_list.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2011-2016 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_relative "../mixin/root_rest"
-
-module Opc
- class OpcUserList < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc user list"
-
- option :with_uri,
- long: "--with-uri",
- short: "-w",
- description: "Show corresponding URIs"
-
- include Chef::Mixin::RootRestv0
-
- def run
- results = root_rest.get("users")
- ui.output(ui.format_list_for_display(results))
- end
- end
-end
diff --git a/lib/chef/knife/opc_user_password.rb b/lib/chef/knife/opc_user_password.rb
deleted file mode 100644
index b9b087324e..0000000000
--- a/lib/chef/knife/opc_user_password.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-#
-# Author:: Tyler Cloke (<tyler@getchef.com>)
-# Copyright:: Copyright 2014-2016 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_relative "../mixin/root_rest"
-
-module Opc
- class OpcUserPassword < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc user password USERNAME [PASSWORD | --enable-external-auth]"
-
- option :enable_external_auth,
- long: "--enable-external-auth",
- short: "-e",
- description: "Enable external authentication for this user (such as LDAP)"
-
- include Chef::Mixin::RootRestv0
-
- def run
- # check that correct number of args was passed, should be either
- # USERNAME PASSWORD or USERNAME --enable-external-auth
- #
- # note that you can't pass USERNAME PASSWORD --enable-external-auth
- unless (@name_args.length == 2 && !config[:enable_external_auth]) || (@name_args.length == 1 && config[:enable_external_auth])
- show_usage
- ui.fatal("You must pass two arguments")
- ui.fatal("Note that --enable-external-auth cannot be passed with a password")
- exit 1
- end
-
- user_name = @name_args[0]
-
- # note that this will be nil if config[:enable_external_auth] is true
- password = @name_args[1]
-
- # since the API does not pass back whether recovery_authentication_enabled is
- # true or false, there is no way of knowing if the user is using ldap or not,
- # so we will update the user every time, instead of checking if we are actually
- # changing anything before we PUT.
- user = root_rest.get("users/#{user_name}")
-
- user["password"] = password unless password.nil?
-
- # if --enable-external-auth was passed, enable it, else disable it.
- # there is never a situation where we would want to enable ldap
- # AND change the password. changing the password means that the user
- # wants to disable ldap and put user in recover (if they are using ldap).
- user["recovery_authentication_enabled"] = !config[:enable_external_auth]
-
- begin
- root_rest.put("users/#{user_name}", user)
- rescue => e
- raise e
- end
-
- ui.msg("Authentication info updated for #{user_name}.")
- end
- end
-end
diff --git a/lib/chef/knife/org_create.rb b/lib/chef/knife/org_create.rb
new file mode 100644
index 0000000000..0eba7ccda6
--- /dev/null
+++ b/lib/chef/knife/org_create.rb
@@ -0,0 +1,68 @@
+#
+# Author:: Steven Danna (<steve@chef.io>)
+# Copyright:: Copyright 2011-2016 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.
+#
+
+class Chef
+ class Knife
+ class OrgCreate < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org create ORG_SHORT_NAME ORG_FULL_NAME (options)"
+
+ option :filename,
+ long: "--filename FILENAME",
+ short: "-f FILENAME",
+ description: "Write validator private key to FILENAME rather than STDOUT"
+
+ option :association_user,
+ long: "--association_user USERNAME",
+ short: "-a USERNAME",
+ description: "Invite USERNAME to the new organization after creation"
+
+ attr_accessor :org_name, :org_full_name
+
+ deps do
+ require_relative "../org"
+ end
+
+ def run
+ @org_name, @org_full_name = @name_args
+
+ if !org_name || !org_full_name
+ ui.fatal "You must specify an ORG_NAME and an ORG_FULL_NAME"
+ show_usage
+ exit 1
+ end
+
+ org = Chef::Org.from_hash({ "name" => org_name,
+ "full_name" => org_full_name }).create
+ if config[:filename]
+ File.open(config[:filename], "w") do |f|
+ f.print(org.private_key)
+ end
+ else
+ ui.msg org.private_key
+ end
+
+ if config[:association_user]
+ org.associate_user(config[:association_user])
+ org.add_user_to_group("admins", config[:association_user])
+ org.add_user_to_group("billing-admins", config[:association_user])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/opc_org_delete.rb b/lib/chef/knife/org_delete.rb
index ff30c4b6dc..d6748f7b21 100644
--- a/lib/chef/knife/opc_org_delete.rb
+++ b/lib/chef/knife/org_delete.rb
@@ -17,17 +17,19 @@
#
require_relative "../mixin/root_rest"
-module Opc
- class OpcOrgDelete < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org delete ORG_NAME"
+class Chef
+ class Knife
+ class OrgDelete < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org delete ORG_NAME"
- include Chef::Mixin::RootRestv0
+ include Chef::Mixin::RootRestv0
- def run
- org_name = @name_args[0]
- ui.confirm "Do you want to delete the organization #{org_name}"
- ui.output root_rest.delete("organizations/#{org_name}")
+ def run
+ org_name = @name_args[0]
+ ui.confirm "Do you want to delete the organization #{org_name}"
+ ui.output root_rest.delete("organizations/#{org_name}")
+ end
end
end
end
diff --git a/lib/chef/knife/opc_user_show.rb b/lib/chef/knife/org_edit.rb
index 26b3b04474..54bbaaede6 100644
--- a/lib/chef/knife/opc_user_show.rb
+++ b/lib/chef/knife/org_edit.rb
@@ -17,25 +17,35 @@
#
require_relative "../mixin/root_rest"
-module Opc
- class OpcUserShow < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc user show USERNAME"
+class Chef
+ class Knife
+ class OrgEdit < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org edit ORG"
- option :with_orgs,
- long: "--with-orgs",
- short: "-l"
+ def run
+ org_name = @name_args[0]
- include Chef::Mixin::RootRestv0
+ if org_name.nil?
+ show_usage
+ ui.fatal("You must specify an organization name")
+ exit 1
+ end
- def run
- user_name = @name_args[0]
- results = root_rest.get("users/#{user_name}")
- if config[:with_orgs]
- orgs = root_rest.get("users/#{user_name}/organizations")
- results["organizations"] = orgs.map { |o| o["organization"]["name"] }
+ include Chef::Mixin::RootRestv0
+
+ original_org = root_rest.get("organizations/#{org_name}")
+ edited_org = edit_data(original_org)
+
+ if original_org == edited_org
+ ui.msg("Organization unchanged, not saving.")
+ exit
+ end
+
+ ui.msg edited_org
+ root_rest.put("organizations/#{org_name}", edited_org)
+ ui.msg("Saved #{org_name}.")
end
- ui.output results
end
end
end
diff --git a/lib/chef/knife/opc_org_edit.rb b/lib/chef/knife/org_list.rb
index 202369707d..1138743abe 100644
--- a/lib/chef/knife/opc_org_edit.rb
+++ b/lib/chef/knife/org_list.rb
@@ -17,33 +17,31 @@
#
require_relative "../mixin/root_rest"
-module Opc
- class OpcOrgEdit < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org edit ORG"
+class Chef
+ class Knife
+ class OrgList < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org list"
- def run
- org_name = @name_args[0]
+ option :with_uri,
+ long: "--with-uri",
+ short: "-w",
+ description: "Show corresponding URIs"
- if org_name.nil?
- show_usage
- ui.fatal("You must specify an organization name")
- exit 1
- end
+ option :all_orgs,
+ long: "--all-orgs",
+ short: "-a",
+ description: "Show auto-generated hidden orgs in output"
include Chef::Mixin::RootRestv0
- original_org = root_rest.get("organizations/#{org_name}")
- edited_org = edit_data(original_org)
-
- if original_org == edited_org
- ui.msg("Organization unchanged, not saving.")
- exit
+ def run
+ results = root_rest.get("organizations")
+ unless config[:all_orgs]
+ results = results.select { |k, v| !(k.length == 20 && k =~ /^[a-z]+$/) }
+ end
+ ui.output(ui.format_list_for_display(results))
end
-
- ui.msg edited_org
- root_rest.put("organizations/#{org_name}", edited_org)
- ui.msg("Saved #{org_name}.")
end
end
end
diff --git a/lib/chef/knife/opc_org_show.rb b/lib/chef/knife/org_show.rb
index ee9c0c6bb3..035658ad47 100644
--- a/lib/chef/knife/opc_org_show.rb
+++ b/lib/chef/knife/org_show.rb
@@ -17,16 +17,18 @@
#
require_relative "../mixin/root_rest"
-module Opc
- class OpcOrgShow < Chef::Knife
- category "CHEF ORGANIZATION MANAGEMENT"
- banner "knife opc org show ORGNAME"
+class Chef
+ class Knife
+ class OrgShow < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org show ORGNAME"
- include Chef::Mixin::RootRestv0
+ include Chef::Mixin::RootRestv0
- def run
- org_name = @name_args[0]
- ui.output root_rest.get("organizations/#{org_name}")
+ def run
+ org_name = @name_args[0]
+ ui.output root_rest.get("organizations/#{org_name}")
+ end
end
end
end
diff --git a/lib/chef/knife/org_user_add.rb b/lib/chef/knife/org_user_add.rb
new file mode 100644
index 0000000000..550bb77f4d
--- /dev/null
+++ b/lib/chef/knife/org_user_add.rb
@@ -0,0 +1,62 @@
+#
+# Author:: Marc Paradise (<marc@chef.io>)
+# Copyright:: Copyright 2014-2016 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.
+#
+
+class Chef
+ class Knife
+ class OrgUserAdd < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org user add ORG_NAME USER_NAME"
+ attr_accessor :org_name, :username
+
+ option :admin,
+ long: "--admin",
+ short: "-a",
+ description: "Add user to admin group"
+
+ deps do
+ require_relative "../org"
+ end
+
+ def run
+ @org_name, @username = @name_args
+
+ if !org_name || !username
+ ui.fatal "You must specify an ORG_NAME and USER_NAME"
+ show_usage
+ exit 1
+ end
+
+ org = Chef::Org.new(@org_name)
+ begin
+ org.associate_user(@username)
+ rescue Net::HTTPServerException => e
+ if e.response.code == "409"
+ ui.msg "User #{username} already associated with organization #{org_name}"
+ else
+ raise e
+ end
+ end
+ if config[:admin]
+ org.add_user_to_group("admins", @username)
+ org.add_user_to_group("billing-admins", @username)
+ ui.msg "User #{username} is added to admins and billing-admins group"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/org_user_remove.rb b/lib/chef/knife/org_user_remove.rb
new file mode 100644
index 0000000000..f9fa49611c
--- /dev/null
+++ b/lib/chef/knife/org_user_remove.rb
@@ -0,0 +1,103 @@
+#
+# Author:: Marc Paradise (<marc@getchef.com>)
+# Copyright:: Copyright 2014-2016 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.
+#
+
+class Chef
+ class Knife
+ class OrgUserRemove < Knife
+ category "CHEF ORGANIZATION MANAGEMENT"
+ banner "knife org user remove ORG_NAME USER_NAME"
+ attr_accessor :org_name, :username
+
+ option :force_remove_from_admins,
+ long: "--force",
+ short: "-f",
+ description: "Force removal of user from the organization's admins and billing-admins group."
+
+ deps do
+ require_relative "../org"
+ require "chef/json_compat"
+ end
+
+ def run
+ @org_name, @username = @name_args
+
+ if !org_name || !username
+ ui.fatal "You must specify an ORG_NAME and USER_NAME"
+ show_usage
+ exit 1
+ end
+
+ org = Chef::Org.new(@org_name)
+
+ if config[:force_remove_from_admins]
+ if org.actor_delete_would_leave_admins_empty?
+ failure_error_message(org_name, username)
+ ui.msg <<~EOF
+ You ran with --force which force removes the user from the admins and billing-admins groups.
+ However, removing #{username} from the admins group would leave it empty, which breaks the org.
+ Please add another user to org #{org_name} admins group and try again.
+ EOF
+ exit 1
+ end
+ remove_user_from_admin_group(org, org_name, username, "admins")
+ remove_user_from_admin_group(org, org_name, username, "billing-admins")
+ end
+
+ begin
+ org.dissociate_user(@username)
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ ui.msg "User #{username} is not associated with organization #{org_name}"
+ exit 1
+ elsif e.response.code == "403"
+ body = Chef::JSONCompat.from_json(e.response.body)
+ if body.key?("error") && body["error"] == "Please remove #{username} from this organization's admins group before removing him or her from the organization."
+ failure_error_message(org_name, username)
+ ui.msg <<~EOF
+ User #{username} is in the organization's admin group. Removing users from an organization without removing them from the admins group is not allowed.
+ Re-run this command with --force to remove this user from the admins prior to removing it from the organization.
+ EOF
+ exit 1
+ else
+ raise e
+ end
+ else
+ raise e
+ end
+ end
+ end
+
+ def failure_error_message(org_name, username)
+ ui.error "Error removing user #{username} from organization #{org_name}."
+ end
+
+ def remove_user_from_admin_group(org, org_name, username, admin_group_string)
+ org.remove_user_from_group(admin_group_string, username)
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ ui.warn <<~EOF
+ User #{username} is not in the #{admin_group_string} group for organization #{org_name}.
+ You probably don't need to pass --force.
+ EOF
+ else
+ raise e
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/user_create.rb b/lib/chef/knife/user_create.rb
index 6d68f3ebbb..0517e43e49 100644
--- a/lib/chef/knife/user_create.rb
+++ b/lib/chef/knife/user_create.rb
@@ -1,7 +1,7 @@
#
# Author:: Steven Danna (<steve@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,12 +17,15 @@
# limitations under the License.
#
+require_relative "../mixin/root_rest"
require_relative "../knife"
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
class Chef
class Knife
- class UserCreate < Knife
+ class UserCreate < Chef::Knife
+
+ include Chef::Mixin::RootRestv0
attr_accessor :user_field
@@ -45,6 +48,16 @@ class Chef
description: "API V1 (#{ChefUtils::Dist::Server::PRODUCT} 12.1+) only. Prevent server from generating a default key pair for you. Cannot be passed with --user-key.",
boolean: true
+ option :orgname,
+ long: "--orgname ORGNAME",
+ short: "-o ORGNAME",
+ description: "Associate new user to an organization matching ORGNAME"
+
+ option :passwordprompt,
+ long: "--prompt-for-password",
+ short: "-p",
+ description: "Prompt for user password"
+
banner "knife user create USERNAME DISPLAY_NAME FIRST_NAME LAST_NAME EMAIL PASSWORD (options)"
def user
@@ -71,8 +84,11 @@ class Chef
test_mandatory_field(@name_args[4], "email")
user.email @name_args[4]
- test_mandatory_field(@name_args[5], "password")
- user.password @name_args[5]
+ password = config[:passwordprompt] ? prompt_for_password : @name_args[5]
+ unless password
+ ui.fatal "You must either provide a password or use the --prompt-for-password (-p) option"
+ exit 1
+ end
if config[:user_key] && config[:prevent_keygen]
show_usage
@@ -88,20 +104,48 @@ class Chef
user.public_key File.read(File.expand_path(config[:user_key]))
end
- output = edit_hash(user)
- final_user = create_user_from_hash(output)
+ user_hash = {
+ username: user.username,
+ first_name: user.first_name,
+ last_name: user.last_name,
+ display_name: "#{user.first_name} #{user.last_name}",
+ email: user.email,
+ password: password,
+ }
+
+ # Check the file before creating the user so the api is more transactional.
+ if config[:file]
+ file = config[:file]
+ unless File.exist?(file) ? File.writable?(file) : File.writable?(File.dirname(file))
+ ui.fatal "File #{config[:file]} is not writable. Check permissions."
+ exit 1
+ end
+ end
+
+ final_user = root_rest.post("users/", user_hash)
+
+ if config[:orgname]
+ request_body = { user: user.username }
+ response = root_rest.post("organizations/#{config[:orgname]}/association_requests", request_body)
+ association_id = response["uri"].split("/").last
+ root_rest.put("users/#{user.username}/association_requests/#{association_id}", { response: "accept" })
+ end
ui.info("Created #{user}")
- if final_user.private_key
+ if final_user["private_key"]
if config[:file]
File.open(config[:file], "w") do |f|
- f.print(final_user.private_key)
+ f.print(final_user["private_key"])
end
else
- ui.msg final_user.private_key
+ ui.msg final_user["private_key"]
end
end
end
+
+ def prompt_for_password
+ ui.ask("Please enter the user's password: ") { |q| q.echo = false }
+ end
end
end
end
diff --git a/lib/chef/knife/user_delete.rb b/lib/chef/knife/user_delete.rb
index 87c1f734bb..7ddc0871ae 100644
--- a/lib/chef/knife/user_delete.rb
+++ b/lib/chef/knife/user_delete.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,27 +17,136 @@
#
require_relative "../knife"
+require_relative "../mixin/root_rest"
class Chef
class Knife
class UserDelete < Knife
deps do
- require_relative "../user_v1"
+ require_relative "../org"
end
banner "knife user delete USER (options)"
+ option :no_disassociate_user,
+ long: "--no-disassociate-user",
+ short: "-d",
+ description: "Don't disassociate the user first"
+
+ option :remove_from_admin_groups,
+ long: "--remove-from-admin-groups",
+ short: "-R",
+ description: "If the user is a member of any org admin groups, attempt to remove from those groups. Ignored if --no-disassociate-user is set."
+
+ attr_reader :username
+ include Chef::Mixin::RootRestv0
+
def run
- @user_name = @name_args[0]
+ @username = @name_args[0]
+ admin_memberships = []
+ unremovable_memberships = []
- if @user_name.nil?
+ if @username.nil?
show_usage
ui.fatal("You must specify a user name")
exit 1
end
- delete_object(Chef::UserV1, @user_name)
+ ui.confirm "Do you want to delete the user #{username}"
+
+ unless config[:no_disassociate_user]
+ ui.stderr.puts("Checking organization memberships...")
+ orgs = org_memberships(username)
+ if orgs.length > 0
+ ui.stderr.puts("Checking admin group memberships for #{orgs.length} org(s).")
+ admin_memberships, unremovable_memberships = admin_group_memberships(orgs, username)
+ end
+
+ unless admin_memberships.empty?
+ unless config[:remove_from_admin_groups]
+ error_exit_admin_group_member!(username, admin_memberships)
+ end
+
+ unless unremovable_memberships.empty?
+ error_exit_cant_remove_admin_membership!(username, unremovable_memberships)
+ end
+ remove_from_admin_groups(admin_memberships, username)
+ end
+ disassociate_user(orgs, username)
+ end
+
+ delete_user(username)
+ end
+
+ def disassociate_user(orgs, username)
+ orgs.each { |org| org.dissociate_user(username) }
+ end
+
+ def org_memberships(username)
+ org_data = root_rest.get("users/#{username}/organizations")
+ org_data.map { |org| Chef::Org.new(org["organization"]["name"]) }
+ end
+
+ def remove_from_admin_groups(admin_of, username)
+ admin_of.each do |org|
+ ui.stderr.puts "Removing #{username} from admins group of '#{org.name}'"
+ org.remove_user_from_group("admins", username)
+ end
+ end
+
+ def admin_group_memberships(orgs, username)
+ admin_of = []
+ unremovable = []
+ orgs.each do |org|
+ if org.user_member_of_group?(username, "admins")
+ admin_of << org
+ if org.actor_delete_would_leave_admins_empty?
+ unremovable << org
+ end
+ end
+ end
+ [admin_of, unremovable]
+ end
+
+ def delete_user(username)
+ ui.stderr.puts "Deleting user #{username}."
+ root_rest.delete("users/#{username}")
+ end
+
+ # Error message that says how to removed from org
+ # admin groups before deleting
+ # Further
+ def error_exit_admin_group_member!(username, admin_of)
+ message = "#{username} is in the 'admins' group of the following organization(s):\n\n"
+ admin_of.each { |org| message << "- #{org.name}\n" }
+ message << <<~EOM
+
+ Run this command again with the --remove-from-admin-groups option to
+ remove the user from these admin group(s) automatically.
+
+ EOM
+ ui.fatal message
+ exit 1
+ end
+
+ def error_exit_cant_remove_admin_membership!(username, only_admin_of)
+ message = <<~EOM
+
+ #{username} is the only member of the 'admins' group of the
+ following organization(s):
+
+ EOM
+ only_admin_of.each { |org| message << "- #{org.name}\n" }
+ message << <<~EOM
+
+ Removing the only administrator of an organization can break it.
+ Assign additional users or groups to the admin group(s) before
+ deleting this user.
+
+ EOM
+ ui.fatal message
+ exit 1
end
end
end
diff --git a/lib/chef/knife/user_dissociate.rb b/lib/chef/knife/user_dissociate.rb
index 6af1559608..a69394dabd 100644
--- a/lib/chef/knife/user_dissociate.rb
+++ b/lib/chef/knife/user_dissociate.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/lib/chef/knife/user_edit.rb b/lib/chef/knife/user_edit.rb
index ad9dfac079..3ff23bbad5 100644
--- a/lib/chef/knife/user_edit.rb
+++ b/lib/chef/knife/user_edit.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +28,18 @@ class Chef
banner "knife user edit USER (options)"
+ option :input,
+ long: "--input FILENAME",
+ short: "-i FILENAME",
+ description: "Name of file to use for PUT or POST"
+
+ option :filename,
+ long: "--filename FILENAME",
+ short: "-f FILENAME",
+ description: "Write private key to FILENAME rather than STDOUT"
+
+ include Chef::Mixin::RootRestv0
+
def run
@user_name = @name_args[0]
@@ -40,13 +52,51 @@ class Chef
original_user = Chef::UserV1.load(@user_name).to_hash
edited_user = edit_hash(original_user)
if original_user != edited_user
- user = Chef::UserV1.from_hash(edited_user)
- user.update
- ui.msg("Saved #{user}.")
+ # user = Chef::UserV1.from_hash(edited_user)
+ result = root_rest.put("users/#{@user_name}", edited_user)
+ ui.msg("Saved #{@user_name}.")
+ unless result["private_key"].nil?
+ if config[:filename]
+ File.open(config[:filename], "w") do |f|
+ f.print(result["private_key"])
+ end
+ else
+ ui.msg result["private_key"]
+ end
+ end
else
ui.msg("User unchanged, not saving.")
end
end
end
+
+ private
+
+ # Check the options for ex: input or filename
+ # Read Or Open file to update user information
+ # return updated user
+ def get_updated_user(original_user)
+ if config[:input]
+ edited_user = JSON.parse(IO.read(config[:input]))
+ elsif config[:filename]
+ file = config[:filename]
+ unless File.exist?(file) ? File.writable?(file) : File.writable?(File.dirname(file))
+ ui.fatal "File #{file} is not writable. Check permissions."
+ exit 1
+ else
+ output = Chef::JSONCompat.to_json_pretty(original_user)
+ File.open(file, "w") do |f|
+ f.sync = true
+ f.puts output
+ f.close
+ raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup/ for details." unless system("#{config[:editor]} #{f.path}")
+
+ edited_user = JSON.parse(IO.read(f.path))
+ end
+ end
+ else
+ edited_user = JSON.parse(edit_data(original_user, false))
+ end
+ end
end
end
diff --git a/lib/chef/knife/user_list.rb b/lib/chef/knife/user_list.rb
index f6aa7bcfc4..2a7e6a0e79 100644
--- a/lib/chef/knife/user_list.rb
+++ b/lib/chef/knife/user_list.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,16 +16,13 @@
# limitations under the License.
#
+require_relative "../mixin/root_rest"
require_relative "../knife"
class Chef
class Knife
class UserList < Knife
- deps do
- require_relative "../user_v1"
- end
-
banner "knife user list (options)"
option :with_uri,
@@ -33,8 +30,11 @@ class Chef
long: "--with-uri",
description: "Show corresponding URIs."
+ include Chef::Mixin::RootRestv0
+
def run
- output(format_list_for_display(Chef::UserV1.list))
+ results = root_rest.get("users")
+ output(format_list_for_display(results))
end
end
diff --git a/lib/chef/knife/user_password.rb b/lib/chef/knife/user_password.rb
new file mode 100644
index 0000000000..7a237b9643
--- /dev/null
+++ b/lib/chef/knife/user_password.rb
@@ -0,0 +1,73 @@
+#
+# Author:: Tyler Cloke (<tyler@getchef.com>)
+# Copyright:: Copyright 2014-2016 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_relative "../mixin/root_rest"
+
+class Chef
+ class Knife
+ class UserPassword < Knife
+ banner "knife user password USERNAME [PASSWORD | --enable-external-auth]"
+
+ option :enable_external_auth,
+ long: "--enable-external-auth",
+ short: "-e",
+ description: "Enable external authentication for this user (such as LDAP)"
+
+ include Chef::Mixin::RootRestv0
+
+ def run
+ # check that correct number of args was passed, should be either
+ # USERNAME PASSWORD or USERNAME --enable-external-auth
+ #
+ # note that you can't pass USERNAME PASSWORD --enable-external-auth
+ unless (@name_args.length == 2 && !config[:enable_external_auth]) || (@name_args.length == 1 && config[:enable_external_auth])
+ show_usage
+ ui.fatal("You must pass two arguments")
+ ui.fatal("Note that --enable-external-auth cannot be passed with a password")
+ exit 1
+ end
+
+ user_name = @name_args[0]
+
+ # note that this will be nil if config[:enable_external_auth] is true
+ password = @name_args[1]
+
+ # since the API does not pass back whether recovery_authentication_enabled is
+ # true or false, there is no way of knowing if the user is using ldap or not,
+ # so we will update the user every time, instead of checking if we are actually
+ # changing anything before we PUT.
+ user = root_rest.get("users/#{user_name}")
+
+ user["password"] = password unless password.nil?
+
+ # if --enable-external-auth was passed, enable it, else disable it.
+ # there is never a situation where we would want to enable ldap
+ # AND change the password. changing the password means that the user
+ # wants to disable ldap and put user in recover (if they are using ldap).
+ user["recovery_authentication_enabled"] = !config[:enable_external_auth]
+
+ begin
+ root_rest.put("users/#{user_name}", user)
+ rescue => e
+ raise e
+ end
+
+ ui.msg("Authentication info updated for #{user_name}.")
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/user_show.rb b/lib/chef/knife/user_show.rb
index e59f969e9a..4383070e98 100644
--- a/lib/chef/knife/user_show.rb
+++ b/lib/chef/knife/user_show.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,6 +17,7 @@
#
require_relative "../knife"
+require_relative "../mixin/root_rest"
class Chef
class Knife
@@ -24,12 +25,14 @@ class Chef
include Knife::Core::MultiAttributeReturnOption
- deps do
- require_relative "../user_v1"
- end
-
banner "knife user show USER (options)"
+ option :with_orgs,
+ long: "--with-orgs",
+ short: "-l"
+
+ include Chef::Mixin::RootRestv0
+
def run
@user_name = @name_args[0]
@@ -39,8 +42,12 @@ class Chef
exit 1
end
- user = Chef::UserV1.load(@user_name)
- output(format_for_display(user))
+ results = root_rest.get("users/#{@user_name}")
+ if config[:with_orgs]
+ orgs = root_rest.get("users/#{@user_name}/organizations")
+ results["organizations"] = orgs.map { |o| o["organization"]["name"] }
+ end
+ output(format_for_display(results))
end
end
diff --git a/lib/chef/mixin/root_rest.rb b/lib/chef/mixin/root_rest.rb
index 967213a16c..02462fb3cb 100644
--- a/lib/chef/mixin/root_rest.rb
+++ b/lib/chef/mixin/root_rest.rb
@@ -24,7 +24,7 @@ class Chef
# Rather than upgrade all of this code to move to v1, the goal is to remove the
# need for this plugin. See
# https://github.com/chef/chef/issues/3517
- @root_rest ||= Chef::ServerAPI.new(Chef::Config[:chef_server_root], { api_version: "0" })
+ @root_rest ||= Chef::ServerAPI.new(Chef::Config[:chef_server_root])
end
end
end
diff --git a/lib/chef/org.rb b/lib/chef/org.rb
index e2b7c49051..4ba27d1ea0 100644
--- a/lib/chef/org.rb
+++ b/lib/chef/org.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (steve@chef.io)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,9 +19,10 @@
require_relative "json_compat"
require_relative "mixin/params_validate"
require_relative "server_api"
+require_relative "group"
class Chef
- class Org
+ class Org < Group
include Chef::Mixin::ParamsValidate
diff --git a/lib/chef/org/group_operations.rb b/lib/chef/org/group_operations.rb.old
index fd75e50f41..fd75e50f41 100644
--- a/lib/chef/org/group_operations.rb
+++ b/lib/chef/org/group_operations.rb.old
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c1507e3203..5d49d54cd3 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -331,9 +331,5 @@ module WEBrick
end
end
-class Chef::Knife
- include Opc
-end
-
# Enough stuff needs json serialization that I'm just adding it here for equality asserts
require "chef/json_compat"
diff --git a/spec/unit/knife/opc_org_list_spec.rb b/spec/unit/knife/opc_org_list_spec.rb
deleted file mode 100644
index 00401f1c3c..0000000000
--- a/spec/unit/knife/opc_org_list_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require "spec_helper"
-require "chef/knife/opc_org_list"
-
-describe Opc::OpcOrgList do
-
- let(:orgs) do
- {
- "org1" => "first",
- "org2" => "second",
- "hiddenhiddenhiddenhi" => "hidden",
- }
- end
-
- before :each do
- @rest = double("Chef::ServerAPI")
- allow(Chef::ServerAPI).to receive(:new).and_return(@rest)
- allow(@rest).to receive(:get).with("organizations").and_return(orgs)
- @knife = Chef::Knife::OpcOrgList.new
- end
-
- describe "with no arguments" do
- it "lists all non hidden orgs" do
- expect(@knife.ui).to receive(:output).with(%w{org1 org2})
- @knife.run
- end
-
- end
-
- describe "with all_orgs argument" do
- before do
- @knife.config[:all_orgs] = true
- end
-
- it "lists all orgs including hidden orgs" do
- expect(@knife.ui).to receive(:output).with(%w{hiddenhiddenhiddenhi org1 org2})
- @knife.run
- end
- end
-end
diff --git a/spec/unit/knife/opc_org_user_add_spec.rb b/spec/unit/knife/opc_org_user_add_spec.rb
deleted file mode 100644
index 37ac4274e3..0000000000
--- a/spec/unit/knife/opc_org_user_add_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require "spec_helper"
-require "chef/org"
-require "chef/org/group_operations"
-require "chef/knife/opc_org_user_add"
-
-describe Opc::OpcOrgUserAdd do
- context "with --admin" do
- subject(:knife) { Chef::Knife::OpcOrgUserAdd.new }
- let(:org) { double("Chef::Org") }
-
- it "adds the user to admins and billing-admins groups" do
- allow(Chef::Org).to receive(:new).and_return(org)
-
- knife.config[:admin] = true
- knife.name_args = %w{testorg testuser}
-
- expect(org).to receive(:associate_user).with("testuser")
- expect(org).to receive(:add_user_to_group).with("admins", "testuser")
- expect(org).to receive(:add_user_to_group).with("billing-admins", "testuser")
-
- knife.run
- end
- end
-end
diff --git a/spec/unit/knife/opc_user_create_spec.rb b/spec/unit/knife/opc_user_create_spec.rb
deleted file mode 100644
index e614015c3c..0000000000
--- a/spec/unit/knife/opc_user_create_spec.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
-# Copyright:: Copyright (c) Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-
-describe Opc::OpcUserCreate do
-
- before :each do
- @knife = Chef::Knife::OpcUserCreate.new
- @user_name = "foobar"
- @first_name = "foo"
- @last_name = "bar"
- @email = "abc@test.com"
- @password = "t123"
- @knife.config[:yes] = true
- end
-
- let(:rest) do
- Chef::Config[:chef_server_root] = "http://www.example.com"
- root_rest = double("rest")
- allow(Chef::ServerAPI).to receive(:new).and_return(root_rest)
- end
-
- describe "with no user_name and user_fullname" do
-
- before :each do
- @knife.config[:orgname] = "ramsay"
- end
-
- it "fails with an informative message" do
- expect(@knife.ui).to receive(:fatal).with("Wrong number of arguments")
- expect(@knife).to receive(:show_usage)
- expect { @knife.run }.to raise_error(SystemExit)
- end
- end
-
- describe "with user_name, first_name, last_name, email and password" do
- before :each do
- @user = double("Chef::User")
- allow(Chef::User).to receive(:new).and_return(@user)
- @key = "You don't come into cooking to get rich - Ramsay"
- allow(@user).to receive(:[]).with("private_key").and_return(@key)
- @knife.name_args << @user_name << @first_name << @last_name << @email << @password
- end
-
- it "creates an user" do
- allow(@knife).to receive(:root_rest).and_return(rest)
- expect(rest).to receive(:post).and_return(@user)
- expect(@knife.ui).to receive(:msg).with(@key)
- @knife.run
- end
-
- context "with --orgname" do
- before :each do
- @knife.config[:orgname] = "ramsay"
- @uri = "http://www.example.com/1"
- allow(@user).to receive(:[]).with("uri").and_return(@uri)
- end
-
- let(:request_body) {
- { user: @user_name }
- }
-
- it "creates an user, associates a user, and adds it to the admins group" do
- allow(@knife).to receive(:root_rest).and_return(rest)
- expect(rest).to receive(:post).and_return(@user)
- expect(rest).to receive(:post).with("organizations/ramsay/association_requests", request_body).and_return(@user)
- expect(rest).to receive(:put).with("users/foobar/association_requests/1", { response: "accept" })
- @knife.run
- end
- end
- end
-
- describe "with prompt password" do
- before :each do
- @user = double("Chef::User")
- allow(Chef::User).to receive(:new).and_return(@user)
- @key = "You don't come into cooking to get rich - Ramsay"
- allow(@user).to receive(:[]).with("private_key").and_return(@key)
- @knife.config[:passwordprompt] = true
- @knife.name_args << @user_name << @first_name << @last_name << @email
- end
-
- it "creates an user" do
- allow(@knife).to receive(:root_rest).and_return(rest)
- expect(rest).to receive(:post).and_return(@user)
- expect(@knife.ui).to receive(:msg).with(@key)
- @knife.run
- end
- end
-
- describe "should raise prompt password error" do
- before :each do
- @user = double("Chef::User")
- allow(Chef::User).to receive(:new).and_return(@user)
- @key = "You don't come into cooking to get rich - Ramsay"
- allow(@user).to receive(:[]).with("private_key").and_return(@key)
- @knife.name_args << @user_name << @first_name << @last_name << @email
- end
-
- it "fails with an informative message" do
- expect(@knife.ui).to receive(:fatal).with("You must either provide a password or use the --prompt-for-password (-p) option")
- expect { @knife.run }.to raise_error(SystemExit)
- end
- end
-end
diff --git a/spec/unit/knife/opc_user_delete_spec.rb b/spec/unit/knife/opc_user_delete_spec.rb
deleted file mode 100644
index 7eddbc7a99..0000000000
--- a/spec/unit/knife/opc_user_delete_spec.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-require "spec_helper"
-require "chef/org"
-require "chef/org/group_operations"
-require "chef/knife/opc_user_delete"
-
-describe Opc::OpcUserDelete do
- subject(:knife) { Chef::Knife::OpcUserDelete.new }
-
- let(:non_admin_member_org) { Chef::Org.new("non-admin-member") }
- let(:solo_admin_member_org) { Chef::Org.new("solo-admin-member") }
- let(:shared_admin_member_org) { Chef::Org.new("shared-admin-member") }
-
- let(:removable_orgs) { [non_admin_member_org, shared_admin_member_org] }
- let(:non_removable_orgs) { [solo_admin_member_org] }
-
- let(:admin_memberships) { [ removable_orgs, non_removable_orgs ] }
- let(:username) { "test_user" }
-
- let(:rest) { double("Chef::ServerAPI") }
- let(:orgs) { [non_admin_member_org, solo_admin_member_org, shared_admin_member_org] }
- let(:knife) { Chef::Knife::OpcUserDelete.new }
-
- let(:orgs_data) do
- [{ "organization" => { "name" => "non-admin-member" } },
- { "organization" => { "name" => "solo-admin-member" } },
- { "organization" => { "name" => "shared-admin-member" } },
- ]
- end
-
- before(:each) do
- allow(Chef::ServerAPI).to receive(:new).and_return(rest)
- knife.name_args << username
- knife.config[:yes] = true
- end
-
- context "when invoked" do
- before do
- allow(knife).to receive(:admin_group_memberships).and_return(admin_memberships)
- end
-
- context "with --no-disassociate-user" do
- before(:each) do
- knife.config[:no_disassociate_user] = true
- end
-
- it "should bypass all checks and go directly to user deletion" do
- expect(knife).to receive(:delete_user).with(username)
- knife.run
- end
- end
-
- context "without --no-disassociate-user" do
- before do
- allow(knife).to receive(:org_memberships).and_return(orgs)
- end
-
- context "and with --remove-from-admin-groups" do
- let(:non_removable_orgs) { [ solo_admin_member_org ] }
- before(:each) do
- knife.config[:remove_from_admin_groups] = true
- end
-
- context "when an associated user the only organization admin" do
- let(:non_removable_orgs) { [ solo_admin_member_org ] }
-
- it "refuses to proceed with because the user is the only admin" do
- expect(knife).to receive(:error_exit_cant_remove_admin_membership!).and_call_original
- expect { knife.run }.to raise_error SystemExit
- end
- end
-
- context "when an associated user is one of many organization admins" do
- let(:non_removable_orgs) { [] }
-
- it "should remove the user from the group, the org, and then and delete the user" do
- expect(knife).to receive(:disassociate_user)
- expect(knife).to receive(:remove_from_admin_groups)
- expect(knife).to receive(:delete_user)
- expect(knife).to receive(:error_exit_cant_remove_admin_membership!).exactly(0).times
- expect(knife).to receive(:error_exit_admin_group_member!).exactly(0).times
- knife.run
- end
-
- end
- end
-
- context "and without --remove-from-admin-groups" do
- before(:each) do
- knife.config[:remove_from_admin_groups] = false
- end
-
- context "when an associated user is in admins group" do
- let(:removable_orgs) { [ shared_admin_member_org ] }
- let(:non_removable_orgs) { [ ] }
- it "refuses to proceed with because the user is an admin" do
- # Default setup
- expect(knife).to receive(:error_exit_admin_group_member!).and_call_original
- expect { knife.run }.to raise_error SystemExit
- end
- end
- end
-
- end
- context "without --remove-from-admin-groups" do
-
- end
-
- end
-
- context "#admin_group_memberships" do
- before do
- expect(non_admin_member_org).to receive(:user_member_of_group?).and_return false
-
- expect(solo_admin_member_org).to receive(:user_member_of_group?).and_return true
- expect(solo_admin_member_org).to receive(:actor_delete_would_leave_admins_empty?).and_return true
-
- expect(shared_admin_member_org).to receive(:user_member_of_group?).and_return true
- expect(shared_admin_member_org).to receive(:actor_delete_would_leave_admins_empty?).and_return false
-
- end
-
- it "returns an array of organizations in which the user is an admin, and an array of orgs which block removal" do
- expect(knife.admin_group_memberships(orgs, username)).to eq [ [solo_admin_member_org, shared_admin_member_org], [solo_admin_member_org]]
- end
- end
-
- context "#delete_user" do
- it "attempts to delete the user from the system via DELETE to the /users endpoint" do
- expect(rest).to receive(:delete).with("users/#{username}")
- knife.delete_user(username)
- end
- end
-
- context "#disassociate_user" do
- it "attempts to remove dissociate the user from each org" do
- removable_orgs.each { |org| expect(org).to receive(:dissociate_user).with(username) }
- knife.disassociate_user(removable_orgs, username)
- end
- end
-
- context "#remove_from_admin_groups" do
- it "attempts to remove the given user from the organizations' groups" do
- removable_orgs.each { |org| expect(org).to receive(:remove_user_from_group).with("admins", username) }
- knife.remove_from_admin_groups(removable_orgs, username)
- end
- end
-
- context "#org_memberships" do
- it "should make a REST request to return the list of organizations that the user is a member of" do
- expect(rest).to receive(:get).with("users/test_user/organizations").and_return orgs_data
- result = knife.org_memberships(username)
- result.each_with_index do |v, x|
- expect(v.to_hash).to eq(orgs[x].to_hash)
- end
- end
- end
-end
diff --git a/spec/unit/knife/opc_user_show_spec.rb b/spec/unit/knife/opc_user_show_spec.rb
deleted file mode 100644
index 224d801cb2..0000000000
--- a/spec/unit/knife/opc_user_show_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
-# Copyright:: Copyright (c) Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-require "chef/org"
-
-describe Chef::Knife::OpcUserShow do
-
- before :each do
- @knife = Chef::Knife::OpcUserShow.new
- @user_name = "foobar"
- @knife.name_args << @user_name
- @org = double("Chef::Org")
- allow(Chef::Org).to receive(:new).and_return(@org)
- @key = "You don't come into cooking to get rich - Ramsay"
- end
-
- let(:rest) do
- Chef::Config[:chef_server_root] = "http://www.example.com"
- root_rest = double("rest")
- allow(Chef::ServerAPI).to receive(:new).and_return(root_rest)
- end
-
- let(:orgs) do
- [@org]
- end
-
- it "should load the user" do
- allow(@knife).to receive(:root_rest).and_return(rest)
- expect(rest).to receive(:get).with("users/#{@user_name}")
- @knife.run
- end
-
- it "should pretty print the output user" do
- allow(@knife).to receive(:root_rest).and_return(rest)
- expect(rest).to receive(:get).with("users/#{@user_name}")
- expect(@knife.ui).to receive(:output)
- @knife.run
- end
-
- it "should load the user with organisation" do
- @org_name = "abc_org"
- @knife.name_args << @user_name << @org_name
- result = { "organizations" => [] }
- @knife.config[:with_orgs] = true
-
- allow(@knife).to receive(:root_rest).and_return(rest)
- allow(@org).to receive(:[]).with("organization").and_return({ "name" => "test" })
- expect(rest).to receive(:get).with("users/#{@user_name}").and_return(result)
- expect(rest).to receive(:get).with("users/#{@user_name}/organizations").and_return(orgs)
- @knife.run
- end
-end
diff --git a/spec/unit/knife/opc_org_create_spec.rb b/spec/unit/knife/org_create_spec.rb
index 5d61b5ed2b..3c33817b55 100644
--- a/spec/unit/knife/opc_org_create_spec.rb
+++ b/spec/unit/knife/org_create_spec.rb
@@ -1,12 +1,27 @@
+#
+# Copyright:: Copyright 2014-2016 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
require "spec_helper"
require "chef/org"
-require "chef/org/group_operations"
-require "chef/knife/opc_org_create"
-describe Opc::OpcOrgCreate do
+describe Chef::Knife::OrgCreate do
before :each do
- Chef::Knife::OpcOrgCreate.load_deps
- @knife = Chef::Knife::OpcOrgCreate.new
+ Chef::Knife::OrgCreate.load_deps
+ @knife = Chef::Knife::OrgCreate.new
@org = double("Chef::Org")
allow(Chef::Org).to receive(:new).and_return(@org)
@key = "You don't come into cooking to get rich - Ramsay"
diff --git a/spec/unit/knife/opc_org_delete_spec.rb b/spec/unit/knife/org_delete_spec.rb
index bac082790b..a39965c761 100644
--- a/spec/unit/knife/opc_org_delete_spec.rb
+++ b/spec/unit/knife/org_delete_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2014-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,10 +18,10 @@
require "spec_helper"
-describe Chef::Knife::OpcOrgDelete do
+describe Chef::Knife::OrgDelete do
before :each do
- @knife = Chef::Knife::OpcOrgDelete.new
+ @knife = Chef::Knife::OrgDelete.new
@org_name = "foobar"
@knife.name_args << @org_name
end
diff --git a/spec/unit/knife/opc_user_list_spec.rb b/spec/unit/knife/org_list_spec.rb
index f6f2d1a89a..de4affe83c 100644
--- a/spec/unit/knife/opc_user_list_spec.rb
+++ b/spec/unit/knife/org_list_spec.rb
@@ -1,6 +1,5 @@
#
-# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2014-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,39 +16,39 @@
#
require "spec_helper"
-require "chef/knife/opc_user_list"
-describe Opc::OpcUserList do
+describe Chef::Knife::OrgList do
- let(:users) do
+ let(:orgs) do
{
- "user1" => "first",
- "user2" => "second",
+ "org1" => "first",
+ "org2" => "second",
+ "hiddenhiddenhiddenhi" => "hidden",
}
end
before :each do
@rest = double("Chef::ServerAPI")
allow(Chef::ServerAPI).to receive(:new).and_return(@rest)
- allow(@rest).to receive(:get).with("users").and_return(users)
- @knife = Chef::Knife::OpcUserList.new
+ allow(@rest).to receive(:get).with("organizations").and_return(orgs)
+ @knife = Chef::Knife::OrgList.new
end
describe "with no arguments" do
- it "lists all non users" do
- expect(@knife.ui).to receive(:output).with(%w{user1 user2})
+ it "lists all non hidden orgs" do
+ expect(@knife.ui).to receive(:output).with(%w{org1 org2})
@knife.run
end
end
- describe "with all_users argument" do
+ describe "with all_orgs argument" do
before do
- @knife.config[:all_users] = true
+ @knife.config[:all_orgs] = true
end
- it "lists all users including hidden users" do
- expect(@knife.ui).to receive(:output).with(%w{user1 user2})
+ it "lists all orgs including hidden orgs" do
+ expect(@knife.ui).to receive(:output).with(%w{hiddenhiddenhiddenhi org1 org2})
@knife.run
end
end
diff --git a/spec/unit/knife/opc_org_show_spec.rb b/spec/unit/knife/org_show_spec.rb
index 7561119b21..7c7e044b64 100644
--- a/spec/unit/knife/opc_org_show_spec.rb
+++ b/spec/unit/knife/org_show_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,10 +19,10 @@
require "spec_helper"
require "chef/org"
-describe Chef::Knife::OpcOrgShow do
+describe Chef::Knife::OrgShow do
before :each do
- @knife = Chef::Knife::OpcOrgShow.new
+ @knife = Chef::Knife::OrgShow.new
@org_name = "foobar"
@knife.name_args << @org_name
end
diff --git a/spec/unit/knife/org_user_add_spec.rb b/spec/unit/knife/org_user_add_spec.rb
new file mode 100644
index 0000000000..b92ceaed21
--- /dev/null
+++ b/spec/unit/knife/org_user_add_spec.rb
@@ -0,0 +1,39 @@
+#
+# Copyright:: Copyright 2014-2016 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "chef/org"
+
+describe Chef::Knife::OrgUserAdd do
+ context "with --admin" do
+ subject(:knife) { Chef::Knife::OrgUserAdd.new }
+ let(:org) { double("Chef::Org") }
+
+ it "adds the user to admins and billing-admins groups" do
+ allow(Chef::Org).to receive(:new).and_return(org)
+
+ knife.config[:admin] = true
+ knife.name_args = %w{testorg testuser}
+
+ expect(org).to receive(:associate_user).with("testuser")
+ expect(org).to receive(:add_user_to_group).with("admins", "testuser")
+ expect(org).to receive(:add_user_to_group).with("billing-admins", "testuser")
+
+ knife.run
+ end
+ end
+end
diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb
index be3d2fd99c..16479402a1 100644
--- a/spec/unit/knife/user_create_spec.rb
+++ b/spec/unit/knife/user_create_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Steven Danna (<steve@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,6 +38,12 @@ describe Chef::Knife::UserCreate do
allow(knife.ui).to receive(:warn)
end
+ let(:rest) do
+ Chef::Config[:chef_server_root] = "http://www.example.com"
+ root_rest = double("rest")
+ allow(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_root]).and_return(root_rest)
+ end
+
context "when USERNAME isn't specified" do
# from spec/support/shared/unit/knife_shared.rb
it_should_behave_like "mandatory field missing" do
@@ -70,19 +76,32 @@ describe Chef::Knife::UserCreate do
end
end
- context "when PASSWORD isn't specified" do
- # from spec/support/shared/unit/knife_shared.rb
- it_should_behave_like "mandatory field missing" do
- let(:name_args) { %w{some_user some_display_name some_first_name some_last_name some_email} }
- let(:fieldname) { "password" }
+ describe "with prompt password" do
+ let(:name_args) { %w{some_user some_display_name some_first_name some_last_name test@email.com} }
+
+ before :each do
+ @user = double("Chef::User")
+ allow(Chef::User).to receive(:new).and_return(@user)
+ @key = "You don't come into cooking to get rich - Ramsay"
+ allow(@user).to receive(:[]).with("private_key").and_return(@key)
+ knife.config[:passwordprompt] = true
+ knife.name_args = name_args
+ end
+
+ it "creates an user" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
+ knife.run
end
end
context "when all mandatory fields are validly specified" do
before do
+ @user = double("Chef::User")
+ allow(Chef::User).to receive(:new).and_return(@user)
+ @key = "You don't come into cooking to get rich - Ramsay"
+ allow(@user).to receive(:[]).with("private_key").and_return(@key)
knife.name_args = %w{some_user some_display_name some_first_name some_last_name some_email some_password}
- allow(knife).to receive(:edit_hash).and_return(knife.user.to_hash)
- allow(knife).to receive(:create_user_from_hash).and_return(knife.user)
end
before(:each) do
@@ -91,13 +110,14 @@ describe Chef::Knife::UserCreate do
end
it "sets all the mandatory fields" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
knife.run
expect(knife.user.username).to eq("some_user")
expect(knife.user.display_name).to eq("some_display_name")
expect(knife.user.first_name).to eq("some_first_name")
expect(knife.user.last_name).to eq("some_last_name")
expect(knife.user.email).to eq("some_email")
- expect(knife.user.password).to eq("some_password")
end
context "when user_key and prevent_keygen are passed" do
@@ -122,6 +142,8 @@ describe Chef::Knife::UserCreate do
end
it "does not set user.create_key" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
knife.run
expect(knife.user.create_key).to be_falsey
end
@@ -129,6 +151,8 @@ describe Chef::Knife::UserCreate do
context "when --prevent-keygen is not passed" do
it "sets user.create_key to true" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
knife.run
expect(knife.user.create_key).to be_truthy
end
@@ -142,6 +166,8 @@ describe Chef::Knife::UserCreate do
end
it "sets user.public_key" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
knife.run
expect(knife.user.public_key).to eq("some_key")
end
@@ -149,32 +175,47 @@ describe Chef::Knife::UserCreate do
context "when --user-key is not passed" do
it "does not set user.public_key" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
knife.run
expect(knife.user.public_key).to be_nil
end
end
- context "when a private_key is returned" do
- before do
- allow(knife).to receive(:create_user_from_hash).and_return(Chef::UserV1.from_hash(knife.user.to_hash.merge({ "private_key" => "some_private_key" })))
+ describe "with user_name, first_name, last_name, email and password" do
+ let(:name_args) { %w{some_user some_display_name some_first_name some_last_name test@email.com some_password} }
+
+ before :each do
+ @user = double("Chef::User")
+ allow(Chef::User).to receive(:new).and_return(@user)
+ @key = "You don't come into cooking to get rich - Ramsay"
+ allow(@user).to receive(:[]).with("private_key").and_return(@key)
+ knife.name_args = name_args
end
- context "when --file is passed" do
- before do
- knife.config[:file] = "/some/path"
- end
+ it "creates an user" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
+ expect(knife.ui).to receive(:msg).with(@key)
+ knife.run
+ end
- it "creates a new file of the path passed" do
- filehandle = double("filehandle")
- expect(filehandle).to receive(:print).with("some_private_key")
- expect(File).to receive(:open).with("/some/path", "w").and_yield(filehandle)
- knife.run
+ context "with --orgname" do
+ before :each do
+ knife.config[:orgname] = "ramsay"
+ @uri = "http://www.example.com/1"
+ allow(@user).to receive(:[]).with("uri").and_return(@uri)
end
- end
- context "when --file is not passed" do
- it "prints the private key to stdout" do
- expect(knife.ui).to receive(:msg).with("some_private_key")
+ let(:request_body) {
+ { user: "some_user" }
+ }
+
+ it "creates an user, associates a user, and adds it to the admins group" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:post).and_return(@user)
+ expect(rest).to receive(:post).with("organizations/ramsay/association_requests", request_body).and_return(@user)
+ expect(rest).to receive(:put).with("users/some_user/association_requests/1", { response: "accept" })
knife.run
end
end
diff --git a/spec/unit/knife/user_delete_spec.rb b/spec/unit/knife/user_delete_spec.rb
index 959d792b9e..31dd43cfa2 100644
--- a/spec/unit/knife/user_delete_spec.rb
+++ b/spec/unit/knife/user_delete_spec.rb
@@ -1,6 +1,5 @@
#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# # Copyright:: Copyright 2014-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,30 +16,157 @@
#
require "spec_helper"
+require "chef/org"
describe Chef::Knife::UserDelete do
+ subject(:knife) { Chef::Knife::UserDelete.new }
+
+ let(:non_admin_member_org) { Chef::Org.new("non-admin-member") }
+ let(:solo_admin_member_org) { Chef::Org.new("solo-admin-member") }
+ let(:shared_admin_member_org) { Chef::Org.new("shared-admin-member") }
+
+ let(:removable_orgs) { [non_admin_member_org, shared_admin_member_org] }
+ let(:non_removable_orgs) { [solo_admin_member_org] }
+
+ let(:admin_memberships) { [ removable_orgs, non_removable_orgs ] }
+ let(:username) { "test_user" }
+
+ let(:rest) { double("Chef::ServerAPI") }
+ let(:orgs) { [non_admin_member_org, solo_admin_member_org, shared_admin_member_org] }
let(:knife) { Chef::Knife::UserDelete.new }
- let(:user) { double("user_object") }
- let(:stdout) { StringIO.new }
+
+ let(:orgs_data) do
+ [{ "organization" => { "name" => "non-admin-member" } },
+ { "organization" => { "name" => "solo-admin-member" } },
+ { "organization" => { "name" => "shared-admin-member" } },
+ ]
+ end
before(:each) do
- Chef::Knife::UserDelete.load_deps
- knife.name_args = [ "my_user" ]
- allow(Chef::UserV1).to receive(:load).and_return(user)
- allow(user).to receive(:username).and_return("my_user")
- allow(knife.ui).to receive(:stderr).and_return(stdout)
- allow(knife.ui).to receive(:stdout).and_return(stdout)
+ allow(Chef::ServerAPI).to receive(:new).and_return(rest)
+ knife.name_args << username
+ knife.config[:yes] = true
+ end
+
+ context "when invoked" do
+ before do
+ allow(knife).to receive(:admin_group_memberships).and_return(admin_memberships)
+ end
+
+ context "with --no-disassociate-user" do
+ before(:each) do
+ knife.config[:no_disassociate_user] = true
+ end
+
+ it "should bypass all checks and go directly to user deletion" do
+ expect(knife).to receive(:delete_user).with(username)
+ knife.run
+ end
+ end
+
+ context "without --no-disassociate-user" do
+ before do
+ allow(knife).to receive(:org_memberships).and_return(orgs)
+ end
+
+ context "and with --remove-from-admin-groups" do
+ let(:non_removable_orgs) { [ solo_admin_member_org ] }
+ before(:each) do
+ knife.config[:remove_from_admin_groups] = true
+ end
+
+ context "when an associated user the only organization admin" do
+ let(:non_removable_orgs) { [ solo_admin_member_org ] }
+
+ it "refuses to proceed with because the user is the only admin" do
+ expect(knife).to receive(:error_exit_cant_remove_admin_membership!).and_call_original
+ expect { knife.run }.to raise_error SystemExit
+ end
+ end
+
+ context "when an associated user is one of many organization admins" do
+ let(:non_removable_orgs) { [] }
+
+ it "should remove the user from the group, the org, and then and delete the user" do
+ expect(knife).to receive(:disassociate_user)
+ expect(knife).to receive(:remove_from_admin_groups)
+ expect(knife).to receive(:delete_user)
+ expect(knife).to receive(:error_exit_cant_remove_admin_membership!).exactly(0).times
+ expect(knife).to receive(:error_exit_admin_group_member!).exactly(0).times
+ knife.run
+ end
+
+ end
+ end
+
+ context "and without --remove-from-admin-groups" do
+ before(:each) do
+ knife.config[:remove_from_admin_groups] = false
+ end
+
+ context "when an associated user is in admins group" do
+ let(:removable_orgs) { [ shared_admin_member_org ] }
+ let(:non_removable_orgs) { [ ] }
+ it "refuses to proceed with because the user is an admin" do
+ # Default setup
+ expect(knife).to receive(:error_exit_admin_group_member!).and_call_original
+ expect { knife.run }.to raise_error SystemExit
+ end
+ end
+ end
+
+ end
+ context "without --remove-from-admin-groups" do
+
+ end
+
+ end
+
+ context "#admin_group_memberships" do
+ before do
+ expect(non_admin_member_org).to receive(:user_member_of_group?).and_return false
+
+ expect(solo_admin_member_org).to receive(:user_member_of_group?).and_return true
+ expect(solo_admin_member_org).to receive(:actor_delete_would_leave_admins_empty?).and_return true
+
+ expect(shared_admin_member_org).to receive(:user_member_of_group?).and_return true
+ expect(shared_admin_member_org).to receive(:actor_delete_would_leave_admins_empty?).and_return false
+
+ end
+
+ it "returns an array of organizations in which the user is an admin, and an array of orgs which block removal" do
+ expect(knife.admin_group_memberships(orgs, username)).to eq [ [solo_admin_member_org, shared_admin_member_org], [solo_admin_member_org]]
+ end
+ end
+
+ context "#delete_user" do
+ it "attempts to delete the user from the system via DELETE to the /users endpoint" do
+ expect(rest).to receive(:delete).with("users/#{username}")
+ knife.delete_user(username)
+ end
+ end
+
+ context "#disassociate_user" do
+ it "attempts to remove dissociate the user from each org" do
+ removable_orgs.each { |org| expect(org).to receive(:dissociate_user).with(username) }
+ knife.disassociate_user(removable_orgs, username)
+ end
end
- it "deletes the user" do
- expect(knife).to receive(:delete_object).with(Chef::UserV1, "my_user")
- knife.run
+ context "#remove_from_admin_groups" do
+ it "attempts to remove the given user from the organizations' groups" do
+ removable_orgs.each { |org| expect(org).to receive(:remove_user_from_group).with("admins", username) }
+ knife.remove_from_admin_groups(removable_orgs, username)
+ end
end
- it "prints usage and exits when a user name is not provided" do
- knife.name_args = []
- expect(knife).to receive(:show_usage)
- expect(knife.ui).to receive(:fatal)
- expect { knife.run }.to raise_error(SystemExit)
+ context "#org_memberships" do
+ it "should make a REST request to return the list of organizations that the user is a member of" do
+ expect(rest).to receive(:get).with("users/test_user/organizations").and_return orgs_data
+ result = knife.org_memberships(username)
+ result.each_with_index do |v, x|
+ expect(v.to_hash).to eq(orgs[x].to_hash)
+ end
+ end
end
end
diff --git a/spec/unit/knife/user_edit_spec.rb b/spec/unit/knife/user_edit_spec.rb
index 54a44890e0..c160f8c402 100644
--- a/spec/unit/knife/user_edit_spec.rb
+++ b/spec/unit/knife/user_edit_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/spec/unit/knife/user_list_spec.rb b/spec/unit/knife/user_list_spec.rb
index 21c07f3fb1..a5895cf82d 100644
--- a/spec/unit/knife/user_list_spec.rb
+++ b/spec/unit/knife/user_list_spec.rb
@@ -1,6 +1,6 @@
#
-# Author:: Steven Danna
-# Copyright:: Copyright (c) Chef Software Inc.
+# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
+# Copyright:: Copyright 2014-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,18 +19,53 @@
require "spec_helper"
describe Chef::Knife::UserList do
+
let(:knife) { Chef::Knife::UserList.new }
- let(:stdout) { StringIO.new }
+ let(:users) do
+ {
+ "user1" => "http//test/users/user1",
+ "user2" => "http//test/users/user2",
+ }
+ end
+
+ before :each do
+ @rest = double("Chef::ServerAPI")
+ allow(Chef::ServerAPI).to receive(:new).and_return(@rest)
+ allow(@rest).to receive(:get).with("users").and_return(users)
+ end
+
+ describe "with no arguments" do
+ it "lists all non users" do
+ expect(knife.ui).to receive(:output).with(%w{user1 user2})
+ knife.run
+ end
- before(:each) do
- Chef::Knife::UserList.load_deps
- allow(knife.ui).to receive(:stderr).and_return(stdout)
- allow(knife.ui).to receive(:stdout).and_return(stdout)
+ end
+
+ describe "with all_users argument" do
+ before do
+ knife.config[:all_users] = true
+ end
+
+ it "lists all users including hidden users" do
+ expect(knife.ui).to receive(:output).with(%w{user1 user2})
+ knife.run
+ end
end
it "lists the users" do
- expect(Chef::UserV1).to receive(:list)
expect(knife).to receive(:format_list_for_display)
knife.run
end
+
+ describe "with options with_uri argument" do
+ before do
+ knife.config[:with_uri] = true
+ end
+
+ it "lists all users including hidden users" do
+ expect(knife.ui).to receive(:output).with(users)
+ knife.run
+ end
+ end
end
diff --git a/spec/unit/knife/opc_user_password_spec.rb b/spec/unit/knife/user_password_spec.rb
index 0ca7394f93..c34f2074a5 100644
--- a/spec/unit/knife/opc_user_password_spec.rb
+++ b/spec/unit/knife/user_password_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Snehal Dwivedi (<sdwivedi@msystechnologies.com>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2014-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,10 +19,10 @@
require "spec_helper"
require "chef/org"
-describe Chef::Knife::OpcUserPassword do
+describe Chef::Knife::UserPassword do
before :each do
- @knife = Chef::Knife::OpcUserPassword.new
+ @knife = Chef::Knife::UserPassword.new
@user_name = "foobar"
@password = "abc123"
@user = double("Chef::User")
diff --git a/spec/unit/knife/user_show_spec.rb b/spec/unit/knife/user_show_spec.rb
index 198b9352f3..ec473f5e7c 100644
--- a/spec/unit/knife/user_show_spec.rb
+++ b/spec/unit/knife/user_show_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
+# Copyright:: Copyright 2011-2016 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,30 +17,69 @@
#
require "spec_helper"
+require "chef/org"
describe Chef::Knife::UserShow do
let(:knife) { Chef::Knife::UserShow.new }
let(:user_mock) { double("user_mock") }
- let(:stdout) { StringIO.new }
-
- before do
- Chef::Knife::UserShow.load_deps
- knife.name_args = [ "my_user" ]
- allow(user_mock).to receive(:username).and_return("my_user")
- allow(knife.ui).to receive(:stderr).and_return(stdout)
- allow(knife.ui).to receive(:stdout).and_return(stdout)
+
+ let(:rest) do
+ Chef::Config[:chef_server_root] = "http://www.example.com"
+ root_rest = double("rest")
+ allow(Chef::ServerAPI).to receive(:new).and_return(root_rest)
end
- it "loads and displays the user" do
- expect(Chef::UserV1).to receive(:load).with("my_user").and_return(user_mock)
- expect(knife).to receive(:format_for_display).with(user_mock)
- knife.run
+ describe "withot organisation argument" do
+ before do
+ knife.name_args = [ "my_user" ]
+ allow(user_mock).to receive(:username).and_return("my_user")
+ end
+
+ it "should load the user" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:get).with("users/my_user")
+ knife.run
+ end
+
+ it "loads and displays the user" do
+ allow(knife).to receive(:root_rest).and_return(rest)
+ expect(rest).to receive(:get).with("users/my_user")
+ expect(knife).to receive(:format_for_display)
+ knife.run
+ end
+
+ it "prints usage and exits when a user name is not provided" do
+ knife.name_args = []
+ expect(knife).to receive(:show_usage)
+ expect(knife.ui).to receive(:fatal)
+ expect { knife.run }.to raise_error(SystemExit)
+ end
end
- it "prints usage and exits when a user name is not provided" do
- knife.name_args = []
- expect(knife).to receive(:show_usage)
- expect(knife.ui).to receive(:fatal)
- expect { knife.run }.to raise_error(SystemExit)
+ describe "with organisation argument" do
+ before :each do
+ @user_name = "foobar"
+ @org_name = "abc_org"
+ knife.name_args << @user_name << @org_name
+ @org = double("Chef::Org")
+ allow(Chef::Org).to receive(:new).and_return(@org)
+ @key = "You don't come into cooking to get rich - Ramsay"
+ end
+
+ let(:orgs) do
+ [@org]
+ end
+
+ it "should load the user with organisation" do
+
+ result = { "organizations" => [] }
+ knife.config[:with_orgs] = true
+
+ allow(knife).to receive(:root_rest).and_return(rest)
+ allow(@org).to receive(:[]).with("organization").and_return({ "name" => "test" })
+ expect(rest).to receive(:get).with("users/#{@user_name}").and_return(result)
+ expect(rest).to receive(:get).with("users/#{@user_name}/organizations").and_return(orgs)
+ knife.run
+ end
end
end
diff --git a/spec/unit/org_group_spec.rb b/spec/unit/org_group_spec.rb
index 0d72228f22..47a2587a9b 100644
--- a/spec/unit/org_group_spec.rb
+++ b/spec/unit/org_group_spec.rb
@@ -14,7 +14,6 @@
require "spec_helper"
require "chef/org"
-require "chef/org/group_operations"
describe Chef::Org do
let(:org) { Chef::Org.new("myorg") }