summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chef/resource/rhsm_errata.rb45
-rw-r--r--lib/chef/resource/rhsm_errata_level.rb53
-rw-r--r--lib/chef/resource/rhsm_register.rb170
-rw-r--r--lib/chef/resource/rhsm_repo.rb63
-rw-r--r--lib/chef/resource/rhsm_subscription.rb96
-rw-r--r--lib/chef/resources.rb5
-rw-r--r--spec/unit/resource/rhsm_errata_level_spec.rb46
-rw-r--r--spec/unit/resource/rhsm_errata_spec.rb35
-rw-r--r--spec/unit/resource/rhsm_register_spec.rb199
-rw-r--r--spec/unit/resource/rhsm_repo_spec.rb59
-rw-r--r--spec/unit/resource/rhsm_subscription_spec.rb93
11 files changed, 864 insertions, 0 deletions
diff --git a/lib/chef/resource/rhsm_errata.rb b/lib/chef/resource/rhsm_errata.rb
new file mode 100644
index 0000000000..56779909f5
--- /dev/null
+++ b/lib/chef/resource/rhsm_errata.rb
@@ -0,0 +1,45 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmErrata < Chef::Resource
+ resource_name :rhsm_errata
+
+ description "A resource for installing packages associated with a given Red"\
+ " Hat Subscription Manager Errata ID. This is helpful if packages"\
+ " to mitigate a single vulnerability must be installed on your hosts."
+ introduced "14.0"
+
+ property :errata_id,
+ String,
+ description: "An optional property for specifying the errata ID if not using the resource's name.",
+ name_property: true
+
+ action :install do
+ description "Installs a package for a specific errata ID"
+
+ execute "Install errata packages for #{new_resource.errata_id}" do
+ command "yum update --advisory #{new_resource.errata_id} -y"
+ action :run
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_errata_level.rb b/lib/chef/resource/rhsm_errata_level.rb
new file mode 100644
index 0000000000..3aa289ac2e
--- /dev/null
+++ b/lib/chef/resource/rhsm_errata_level.rb
@@ -0,0 +1,53 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmErrataLevel < Chef::Resource
+ resource_name :rhsm_errata_level
+
+ description "A resource for installing all packages of a specified errata level"\
+ " from the Red Hat Subscript Manager. For example, you can ensure"\
+ " that all packages associated with errata marked at a 'Critical'"\
+ " security level are installed."
+ introduced "14.0"
+
+ property :errata_level,
+ String,
+ coerce: proc { |x| x.downcase },
+ equal_to: %w{critical moderate important low},
+ description: "The errata level of packages to install.",
+ name_property: true
+
+ action :install do
+ descripton "Install all packages of the specified errata level"
+
+ yum_package "yum-plugin-security" do
+ action :install
+ only_if { node["platform_version"].to_i == 6 }
+ end
+
+ execute "Install any #{new_resource.errata_level} errata" do
+ command "yum update --sec-severity=#{new_resource.errata_level.capitalize} -y"
+ action :run
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_register.rb b/lib/chef/resource/rhsm_register.rb
new file mode 100644
index 0000000000..47fe67d1cf
--- /dev/null
+++ b/lib/chef/resource/rhsm_register.rb
@@ -0,0 +1,170 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+require "shellwords"
+
+class Chef
+ class Resource
+ class RhsmRegister < Chef::Resource
+ resource_name :rhsm_register
+
+ description "A resource for registering a node with the Red Hat Subscription Manager"\
+ " or a local Red Hat Satellite server."
+ introduced "14.0"
+
+ property :activation_key,
+ [String, Array],
+ coerce: proc { |x| Array(x) },
+ description: "A String or array of the activation keys to use when registering. You must also specify the organization property if using activation_key."
+
+ property :satellite_host,
+ String,
+ description: "The FQDN of the Satellite host to register with. If not specified, the host will be registered with Red Hat's public RHSM service."
+
+ property :organization,
+ String,
+ description: "The organization to use when registering, required when using an activation key"
+
+ property :environment,
+ String,
+ description: "The environment to use when registering, required when using username and password"
+
+ property :username,
+ String,
+ description: "The username to use when registering. Not applicable if using an activation key. If specified, password and environment are also required."
+
+ property :password,
+ String,
+ description: "The password to use when registering. Not applicable if using an activation key. If specified, username and environment are also required."
+
+ property :auto_attach,
+ [TrueClass, FalseClass],
+ description: "If true, RHSM will attempt to automatically attach the host to applicable subscriptions. It is generally better to use an activation key with the subscriptions pre-defined.",
+ default: false
+
+ property :install_katello_agent,
+ [TrueClass, FalseClass],
+ description: "If true, the 'katello-agent' RPM will be installed.",
+ default: true
+
+ property :force,
+ [TrueClass, FalseClass],
+ description: "If true, the system will be registered even if it is already registered. Normally, any register operations will fail if the machine is has already registered.",
+ default: false
+
+ action :register do
+ description "Register the node with RHSM"
+
+ package "subscription-manager"
+
+ unless new_resource.satellite_host.nil? || registered_with_rhsm?
+ remote_file "#{Chef::Config[:file_cache_path]}/katello-package.rpm" do
+ source "http://#{new_resource.satellite_host}/pub/katello-ca-consumer-latest.noarch.rpm"
+ action :create
+ notifies :install, "yum_package[katello-ca-consumer-latest]", :immediately
+ not_if { katello_cert_rpm_installed? }
+ end
+
+ yum_package "katello-ca-consumer-latest" do
+ options "--nogpgcheck"
+ source "#{Chef::Config[:file_cache_path]}/katello-package.rpm"
+ action :nothing
+ end
+
+ file "#{Chef::Config[:file_cache_path]}/katello-package.rpm" do
+ action :delete
+ end
+ end
+
+ execute "Register to RHSM" do
+ sensitive new_resource.sensitive
+ command register_command
+ action :run
+ not_if { registered_with_rhsm? }
+ end
+
+ yum_package "katello-agent" do
+ action :install
+ only_if { new_resource.install_katello_agent && !new_resource.satellite_host.nil? }
+ end
+ end
+
+ action :unregister do
+ description "Unregister the node from RHSM"
+
+ execute "Unregister from RHSM" do
+ command "subscription-manager unregister"
+ action :run
+ only_if { registered_with_rhsm? }
+ notifies :run, "execute[Clean RHSM Config]", :immediately
+ end
+
+ execute "Clean RHSM Config" do
+ command "subscription-manager clean"
+ action :nothing
+ end
+ end
+
+ action_class do
+ def registered_with_rhsm?
+ cmd = Mixlib::ShellOut.new("subscription-manager status", env: { LANG: "en_US" })
+ cmd.run_command
+ !cmd.stdout.match(/Overall Status: Unknown/)
+ end
+
+ def katello_cert_rpm_installed?
+ cmd = Mixlib::ShellOut.new("rpm -qa | grep katello-ca-consumer")
+ cmd.run_command
+ !cmd.stdout.match(/katello-ca-consumer/).nil?
+ end
+
+ def register_command
+ command = %w{subscription-manager register}
+
+ unless new_resource.activation_key.empty?
+ raise "Unable to register - you must specify organization when using activation keys" if new_resource.organization.nil?
+
+ command << new_resource.activation_key.map { |key| "--activationkey=#{Shellwords.shellescape(key)}" }
+ command << "--org=#{Shellwords.shellescape(new_resource.organization)}"
+ command << "--force" if new_resource.force
+
+ return command.join(" ")
+ end
+
+ if new_resource.username && new_resource.password
+ raise "Unable to register - you must specify environment when using username/password" if new_resource.environment.nil? && using_satellite_host?
+
+ command << "--username=#{Shellwords.shellescape(new_resource.username)}"
+ command << "--password=#{Shellwords.shellescape(new_resource.password)}"
+ command << "--environment=#{Shellwords.shellescape(new_resource.environment)}" if using_satellite_host?
+ command << "--auto-attach" if new_resource.auto_attach
+ command << "--force" if new_resource.force
+
+ return command.join(" ")
+ end
+
+ raise "Unable to create register command - you must specify activation_key or username/password"
+ end
+
+ def using_satellite_host?
+ !new_resource.satellite_host.nil?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_repo.rb b/lib/chef/resource/rhsm_repo.rb
new file mode 100644
index 0000000000..aef4dd43d6
--- /dev/null
+++ b/lib/chef/resource/rhsm_repo.rb
@@ -0,0 +1,63 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmRepo < Chef::Resource
+ resource_name :rhsm_repo
+
+ description "A resource for enabling and disabling Red Hat Subscription Manager"\
+ " repositories that are made available via attached subscriptions."
+ introduced "14.0"
+
+ property :repo_name,
+ String,
+ description: "An optional property for specifying the repository name if not using the resource's name.",
+ name_property: true
+
+ action :enable do
+ description "Enable a RHSM repository"
+
+ execute "Enable repository #{repo_name}" do
+ command "subscription-manager repos --enable=#{repo_name}"
+ action :run
+ not_if { repo_enabled?(repo_name) }
+ end
+ end
+
+ action :disable do
+ description "Disable a RHSM repository"
+
+ execute "Enable repository #{repo_name}" do
+ command "subscription-manager repos --disable=#{repo_name}"
+ action :run
+ only_if { repo_enabled?(repo_name) }
+ end
+ end
+
+ action_class do
+ def repo_enabled?(repo)
+ cmd = Mixlib::ShellOut.new("subscription-manager repos --list-enabled", env: { LANG: "en_US" })
+ cmd.run_command
+ !cmd.stdout.match(/Repo ID:\s+#{repo}$/).nil?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_subscription.rb b/lib/chef/resource/rhsm_subscription.rb
new file mode 100644
index 0000000000..41dd398cd5
--- /dev/null
+++ b/lib/chef/resource/rhsm_subscription.rb
@@ -0,0 +1,96 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmSubscription < Chef::Resource
+ resource_name :rhsm_subscription
+
+ description "A resource for adding additional Redhat Subscription Manager subscriptions"\
+ " to your host. This can be used when a host's activation_key"\
+ " does not attach all necessary subscriptions to your host."
+ introduced "14.0"
+
+ property :pool_id,
+ String,
+ description: "An optional property for specifying the Pool ID if not using the resource's name.",
+ name_property: true
+
+ action :attach do
+ description "Attach the node to a subscription pool"
+
+ execute "Attach subscription pool #{new_resource.pool_id}" do
+ command "subscription-manager attach --pool=#{new_resource.pool_id}"
+ action :run
+ not_if { subscription_attached?(new_resource.pool_id) }
+ end
+ end
+
+ action :remove do
+ description "Remove the node from a subscription pool"
+
+ execute "Remove subscription pool #{new_resource.pool_id}" do
+ command "subscription-manager remove --serial=#{pool_serial(new_resource.pool_id)}"
+ action :run
+ only_if { subscription_attached?(new_resource.pool_id) }
+ end
+ end
+
+ action_class do
+ def subscription_attached?(subscription)
+ cmd = Mixlib::ShellOut.new("subscription-manager list --consumed | grep #{subscription}", env: { LANG: "en_US" })
+ cmd.run_command
+ !cmd.stdout.match(/Pool ID:\s+#{subscription}$/).nil?
+ end
+
+ def serials_by_pool
+ serials = {}
+ pool = nil
+ serial = nil
+
+ cmd = Mixlib::ShellOut.new("subscription-manager list --consumed", env: { LANG: "en_US" })
+ cmd.run_command
+ cmd.stdout.lines.each do |line|
+ line.strip!
+ key, value = line.split(/:\s+/, 2)
+ next unless ["Pool ID", "Serial"].include?(key)
+
+ if key == "Pool ID"
+ pool = value
+ elsif key == "Serial"
+ serial = value
+ end
+
+ next unless pool && serial
+
+ serials[pool] = serial
+ pool = nil
+ serial = nil
+ end
+
+ serials
+ end
+
+ def pool_serial(pool_id)
+ serials_by_pool[pool_id]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index b580a01c29..cc89de749f 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -67,6 +67,11 @@ require "chef/resource/reboot"
require "chef/resource/registry_key"
require "chef/resource/remote_directory"
require "chef/resource/remote_file"
+require "chef/resource/rhsm_errata_level"
+require "chef/resource/rhsm_errata"
+require "chef/resource/rhsm_register"
+require "chef/resource/rhsm_repo"
+require "chef/resource/rhsm_subscription"
require "chef/resource/rpm_package"
require "chef/resource/solaris_package"
require "chef/resource/route"
diff --git a/spec/unit/resource/rhsm_errata_level_spec.rb b/spec/unit/resource/rhsm_errata_level_spec.rb
new file mode 100644
index 0000000000..3284107e75
--- /dev/null
+++ b/spec/unit/resource/rhsm_errata_level_spec.rb
@@ -0,0 +1,46 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmErrataLevel do
+
+ let(:resource) { Chef::Resource::RhsmErrataLevel.new("moderate") }
+
+ it "has a resource name of :rhsm_errata_level" do
+ expect(resource.resource_name).to eql(:rhsm_errata_level)
+ end
+
+ it "has a default action of install" do
+ expect(resource.action).to eql([:install])
+ end
+
+ it "the errata_level property is the name property" do
+ expect(resource.errata_level).to eql("moderate")
+ end
+
+ it "coerces the errata_level to be lowercase" do
+ resource.errata_level "Important"
+ expect(resource.errata_level).to eql("important")
+ end
+
+ it "raises an exception if invalid errata_level is passed" do
+ expect do
+ resource.errata_level "FOO"
+ end.to raise_error(Chef::Exceptions::ValidationFailed)
+ end
+end
diff --git a/spec/unit/resource/rhsm_errata_spec.rb b/spec/unit/resource/rhsm_errata_spec.rb
new file mode 100644
index 0000000000..8da7269ca8
--- /dev/null
+++ b/spec/unit/resource/rhsm_errata_spec.rb
@@ -0,0 +1,35 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmErrata do
+
+ let(:resource) { Chef::Resource::RhsmErrata.new("foo") }
+
+ it "has a resource name of :rhsm_errata" do
+ expect(resource.resource_name).to eql(:rhsm_errata)
+ end
+
+ it "has a default action of install" do
+ expect(resource.action).to eql([:install])
+ end
+
+ it "the errata_id property is the name property" do
+ expect(resource.errata_id).to eql("foo")
+ end
+end
diff --git a/spec/unit/resource/rhsm_register_spec.rb b/spec/unit/resource/rhsm_register_spec.rb
new file mode 100644
index 0000000000..2e360b5708
--- /dev/null
+++ b/spec/unit/resource/rhsm_register_spec.rb
@@ -0,0 +1,199 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmRegister do
+
+ let(:resource) { Chef::Resource::RhsmRegister.new("foo") }
+ let(:provider) { resource.provider_for_action(:register) }
+
+ it "has a resource name of :rhsm_register" do
+ expect(resource.resource_name).to eql(:rhsm_register)
+ end
+
+ it "has a default action of register" do
+ expect(resource.action).to eql([:register])
+ end
+
+ it "coerces activation_key to an array" do
+ resource.activation_key "foo"
+ expect(resource.activation_key).to eql(["foo"])
+ end
+
+ describe "#katello_cert_rpm_installed?" do
+ let(:cmd) { double("cmd") }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ end
+
+ context "when the output contains katello-ca-consumer" do
+ it "returns true" do
+ allow(cmd).to receive(:stdout).and_return("katello-ca-consumer-somehostname-1.0-1")
+ expect(provider.katello_cert_rpm_installed?).to eq(true)
+ end
+ end
+
+ context "when the output does not contain katello-ca-consumer" do
+ it "returns false" do
+ allow(cmd).to receive(:stdout).and_return("katello-agent-but-not-the-ca")
+ expect(provider.katello_cert_rpm_installed?).to eq(false)
+ end
+ end
+ end
+
+ describe "#register_command" do
+ before do
+ allow(provider).to receive(:activation_key).and_return([])
+ allow(provider).to receive(:auto_attach)
+ end
+
+ context "when activation keys exist" do
+ before do
+ allow(resource).to receive(:activation_key).and_return(%w{key1 key2})
+ end
+
+ context "when no org exists" do
+ it "raises an exception" do
+ allow(resource).to receive(:organization).and_return(nil)
+ expect { provider.register_command }.to raise_error(RuntimeError)
+ end
+ end
+
+ context "when an org exists" do
+ it "returns a command containing the keys and org" do
+ allow(resource).to receive(:organization).and_return("myorg")
+
+ expect(provider.register_command).to match("--activationkey=key1 --activationkey=key2 --org=myorg")
+ end
+ end
+
+ context "when auto_attach is true" do
+ it "does not return a command with --auto-attach since it is not supported with activation keys" do
+ allow(resource).to receive(:organization).and_return("myorg")
+ allow(resource).to receive(:auto_attach).and_return(true)
+
+ expect(provider.register_command).not_to match("--auto-attach")
+ end
+ end
+ end
+
+ context "when username and password exist" do
+ before do
+ allow(resource).to receive(:username).and_return("myuser")
+ allow(resource).to receive(:password).and_return("mypass")
+ allow(resource).to receive(:environment)
+ allow(resource).to receive(:using_satellite_host?)
+ allow(resource).to receive(:activation_key).and_return([])
+ end
+
+ context "when auto_attach is true" do
+ it "returns a command containing --auto-attach" do
+ allow(resource).to receive(:auto_attach).and_return(true)
+
+ expect(provider.register_command).to match("--auto-attach")
+ end
+ end
+
+ context "when auto_attach is false" do
+ it "returns a command that does not contain --auto-attach" do
+ allow(resource).to receive(:auto_attach).and_return(false)
+
+ expect(provider.register_command).not_to match("--auto-attach")
+ end
+ end
+
+ context "when auto_attach is nil" do
+ it "returns a command that does not contain --auto-attach" do
+ allow(resource).to receive(:auto_attach).and_return(nil)
+
+ expect(provider.register_command).not_to match("--auto-attach")
+ end
+ end
+
+ context "when environment does not exist" do
+ context "when registering to a satellite server" do
+ it "raises an exception" do
+ allow(provider).to receive(:using_satellite_host?).and_return(true)
+ allow(resource).to receive(:environment).and_return(nil)
+ expect { provider.register_command }.to raise_error(RuntimeError)
+ end
+ end
+
+ context "when registering to RHSM proper" do
+ before do
+ allow(provider).to receive(:using_satellite_host?).and_return(false)
+ allow(resource).to receive(:environment).and_return(nil)
+ end
+
+ it "does not raise an exception" do
+ expect { provider.register_command }.not_to raise_error
+ end
+
+ it "returns a command containing the username and password and no environment" do
+ allow(resource).to receive(:environment).and_return("myenv")
+ expect(provider.register_command).to match("--username=myuser --password=mypass")
+ expect(provider.register_command).not_to match("--environment")
+ end
+ end
+ end
+
+ context "when an environment exists" do
+ it "returns a command containing the username, password, and environment" do
+ allow(provider).to receive(:using_satellite_host?).and_return(true)
+ allow(resource).to receive(:environment).and_return("myenv")
+ expect(provider.register_command).to match("--username=myuser --password=mypass --environment=myenv")
+ end
+ end
+ end
+
+ context "when no activation keys, username, or password exist" do
+ it "raises an exception" do
+ allow(resource).to receive(:activation_key).and_return([])
+ allow(resource).to receive(:username).and_return(nil)
+ allow(resource).to receive(:password).and_return(nil)
+
+ expect { provider.register_command }.to raise_error(RuntimeError)
+ end
+ end
+ end
+
+ describe "#registered_with_rhsm?" do
+ let(:cmd) { double("cmd") }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ end
+
+ context "when the status is Unknown" do
+ it "returns false" do
+ allow(cmd).to receive(:stdout).and_return("Overall Status: Unknown")
+ expect(provider.registered_with_rhsm?).to eq(false)
+ end
+ end
+
+ context "when the status is anything else" do
+ it "returns true" do
+ allow(cmd).to receive(:stdout).and_return("Overall Status: Insufficient")
+ expect(provider.registered_with_rhsm?).to eq(true)
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/rhsm_repo_spec.rb b/spec/unit/resource/rhsm_repo_spec.rb
new file mode 100644
index 0000000000..97606a03c8
--- /dev/null
+++ b/spec/unit/resource/rhsm_repo_spec.rb
@@ -0,0 +1,59 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmRepo do
+
+ let(:resource) { Chef::Resource::RhsmRepo.new("foo") }
+ let(:provider) { resource.provider_for_action(:enable) }
+
+ it "has a resource name of :rhsm_repo" do
+ expect(resource.resource_name).to eql(:rhsm_repo)
+ end
+
+ it "has a default action of enable" do
+ expect(resource.action).to eql([:enable])
+ end
+
+ it "the repo_name property is the name property" do
+ expect(resource.repo_name).to eql("foo")
+ end
+
+ describe "#repo_enabled?" do
+ let(:cmd) { double("cmd") }
+ let(:output) { "Repo ID: repo123" }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ allow(cmd).to receive(:stdout).and_return(output)
+ end
+
+ context "when the repo provided matches the output" do
+ it "returns true" do
+ expect(provider.repo_enabled?("repo123")).to eq(true)
+ end
+ end
+
+ context "when the repo provided does not match the output" do
+ it "returns false" do
+ expect(provider.repo_enabled?("differentrepo")).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/rhsm_subscription_spec.rb b/spec/unit/resource/rhsm_subscription_spec.rb
new file mode 100644
index 0000000000..0160624f39
--- /dev/null
+++ b/spec/unit/resource/rhsm_subscription_spec.rb
@@ -0,0 +1,93 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmSubscription do
+ let(:resource) { Chef::Resource::RhsmSubscription.new("foo") }
+ let(:provider) { resource.provider_for_action(:attach) }
+
+ it "has a resource name of :rhsm_subscription" do
+ expect(resource.resource_name).to eql(:rhsm_subscription)
+ end
+
+ it "has a default action of attach" do
+ expect(resource.action).to eql([:attach])
+ end
+
+ it "the pool_id property is the name property" do
+ expect(resource.pool_id).to eql("foo")
+ end
+
+ describe "#subscription_attached?" do
+ let(:cmd) { double("cmd") }
+ let(:output) { "Pool ID: pool123" }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ allow(cmd).to receive(:stdout).and_return(output)
+ end
+
+ context "when the pool provided matches the output" do
+ it "returns true" do
+ expect(provider.subscription_attached?("pool123")).to eq(true)
+ end
+ end
+
+ context "when the pool provided does not match the output" do
+ it "returns false" do
+ expect(provider.subscription_attached?("differentpool")).to eq(false)
+ end
+ end
+ end
+
+ describe "#serials_by_pool" do
+ let(:cmd) { double("cmd") }
+ let(:output) do
+ <<~EOL
+ Key1: value1
+ Pool ID: pool1
+ Serial: serial1
+ Key2: value2
+
+ Key1: value1
+ Pool ID: pool2
+ Serial: serial2
+ Key2: value2
+EOL
+ end
+
+ it "parses the output correctly" do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ allow(cmd).to receive(:stdout).and_return(output)
+
+ expect(provider.serials_by_pool["pool1"]).to eq("serial1")
+ expect(provider.serials_by_pool["pool2"]).to eq("serial2")
+ end
+ end
+
+ describe "#pool_serial" do
+ let(:serials) { { "pool1" => "serial1", "pool2" => "serial2" } }
+
+ it "returns the serial for a given pool" do
+ allow(provider).to receive(:serials_by_pool).and_return(serials)
+ expect(provider.pool_serial("pool1")).to eq("serial1")
+ end
+ end
+end