Cleanup minor rubocop offenses

Cleaned up all the minor rubocop issues, the ones left relate to
complex logic and what I think is a bug in rubocop for nested
vs compact modules/class definitions.

Change-Id: Ic0c0677de44642e0994c0b95a3c270cbd4749b40
This commit is contained in:
Mark Vanderwiel 2015-05-28 12:11:23 -05:00
parent cc89c5ec09
commit fc217f6ce4
31 changed files with 134 additions and 216 deletions

View File

@ -1,90 +1,28 @@
# This configuration was generated by `rubocop --auto-gen-config`
# on 2015-02-27 11:18:27 -0600 using RuboCop version 0.29.1.
# on 2015-05-28 12:53:22 -0500 using RuboCop version 0.29.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 3
# Cop supports --auto-correct.
Lint/UnusedBlockArgument:
Enabled: false
# Offense count: 9
Metrics/AbcSize:
Max: 56
# Offense count: 1
Metrics/PerceivedComplexity:
Max: 15
Max: 14
# Offense count: 11
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/ClassAndModuleChildren:
Enabled: false
# Offense count: 10
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/EmptyLinesAroundBlockBody:
Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/FirstParameterIndentation:
Enabled: false
# Offense count: 3
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/FormatString:
Enabled: false
# Offense count: 1
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Enabled: false
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/IndentHash:
Enabled: false
# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/MultilineOperationIndentation:
Enabled: false
# Offense count: 2
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
Style/Next:
Enabled: false
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
Enabled: false
# Offense count: 13
# Cop supports --auto-correct.
Style/SingleSpaceBeforeFirstArg:
Enabled: false
# Offense count: 6
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyleInsidePipes, SupportedStyles.
Style/SpaceAroundBlockParameters:
Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Style/StringLiterals:
Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.

View File

@ -81,23 +81,23 @@ default['openstack']['endpoints']['db']['bind_interface'] = nil
default['openstack']['db']['server_role'] = 'os-ops-database'
# Database charset during create database
default['openstack']['db']['charset'] = {
mysql: 'utf8',
mariadb: 'utf8',
postgresql: nil,
pgsql: nil,
sqlite: nil,
db2: 'utf8',
nosql: nil
mysql: 'utf8',
mariadb: 'utf8',
postgresql: nil,
pgsql: nil,
sqlite: nil,
db2: 'utf8',
nosql: nil
}
# Database connection options. Should include starting '?'
default['openstack']['db']['options'] = {
mysql: "?charset=#{node['openstack']['db']['charset']['mysql']}",
mariadb: "?charset=#{node['openstack']['db']['charset']['mariadb']}",
postgresql: '',
sqlite: '',
db2: "?charset=#{node['openstack']['db']['charset']['db2']}",
nosql: ''
mysql: "?charset=#{node['openstack']['db']['charset']['mysql']}",
mariadb: "?charset=#{node['openstack']['db']['charset']['mariadb']}",
postgresql: '',
sqlite: '',
db2: "?charset=#{node['openstack']['db']['charset']['db2']}",
nosql: ''
}
# platform and DBMS-specific python client packages
@ -172,7 +172,6 @@ node['openstack']['common']['services'].each do |service, project|
default['openstack']['db'][service]['nosql']['used'] = false
default['openstack']['db'][service]['nosql']['port'] = '27017'
end
end
# DB key to the get_password library routine

View File

@ -69,7 +69,7 @@ default['openstack']['vault_gem_version'] = '~> 2.3'
# Default attributes when not using data bags (use_databags = false)
node['openstack']['common']['services'].each_key do |service|
%w{user service db token}.each do |type|
%w(user service db token).each do |type|
default['openstack']['secret'][service][type] = "#{service}-#{type}"
end
end

View File

@ -34,8 +34,8 @@ default['openstack']['endpoints']['mq']['bind_interface'] = nil
###################################################################
# Services to assign mq attributes for
###################################################################
services = %w{bare-metal block-storage compute database image
identity telemetry network orchestration}
services = %w(bare-metal block-storage compute database image
identity telemetry network orchestration)
###################################################################
# Generic default attributes

View File

@ -23,7 +23,8 @@ require 'chef/mixin/shell_out'
include Chef::Mixin::ShellOut
require 'uri'
module ::Openstack # rubocop:disable Documentation
# CLI methods
module ::Openstack
# return an environment suitable for calling openstack commands.
#
# @param [String] user name
@ -34,10 +35,10 @@ module ::Openstack # rubocop:disable Documentation
auth_uri = ::URI.decode identity_admin_endpoint.to_s
pass = get_password 'user', name
{
'OS_USERNAME' => name,
'OS_PASSWORD' => pass,
'OS_TENANT_NAME' => tenant,
'OS_AUTH_URL' => auth_uri
'OS_USERNAME' => name,
'OS_PASSWORD' => pass,
'OS_TENANT_NAME' => tenant,
'OS_AUTH_URL' => auth_uri
}
end

View File

@ -19,7 +19,8 @@
# limitations under the License.
#
module ::Openstack # rubocop:disable Documentation
# Database methods
module ::Openstack
# Library routine that uses the database cookbook to create the
# service's database and grant read/write access to the
# given user and password.

View File

@ -21,7 +21,8 @@
require 'uri'
module ::Openstack # rubocop:disable Documentation
# Endpoint methods
module ::Openstack
# Shortcut to get the full URI for an endpoint, and return it as a URI object
# First we get the attribute hash for the endpoint, using endpoint_for().
# Then we call uri_from_hash(). If the hash has a 'uri' key,
@ -34,7 +35,7 @@ module ::Openstack # rubocop:disable Documentation
# Useful for iterating over the OpenStack endpoints
def endpoints(&block)
node['openstack']['endpoints'].each do | name, info |
node['openstack']['endpoints'].each do |name, info|
block.call(name, info)
end
rescue
@ -53,42 +54,41 @@ module ::Openstack # rubocop:disable Documentation
# Shortcut to get the SQLAlchemy DB URI for a named service
def db_uri(service, user, pass) # rubocop:disable MethodLength, CyclomaticComplexity
info = db(service)
if info
host = info['host']
port = info['port'].to_s
type = info['service_type']
name = info['db_name']
options = info['options'][type]
return unless info
host = info['host']
port = info['port'].to_s
type = info['service_type']
name = info['db_name']
options = info['options'][type]
# Normalize to the SQLAlchemy standard db type identifier
case type
when 'db2'
# NoSQL is used for telemetry in the DB2 case
if service == 'telemetry' && node['openstack']['db']['telemetry']['nosql']['used']
options = info['options']['nosql']
port = info['nosql']['port']
type = 'db2'
else
type = 'ibm_db_sa'
end
when 'pgsql'
type = 'postgresql'
when 'mariadb'
type = 'mysql'
# Normalize to the SQLAlchemy standard db type identifier
case type
when 'db2'
# NoSQL is used for telemetry in the DB2 case
if service == 'telemetry' && node['openstack']['db']['telemetry']['nosql']['used']
options = info['options']['nosql']
port = info['nosql']['port']
type = 'db2'
else
type = 'ibm_db_sa'
end
when 'pgsql'
type = 'postgresql'
when 'mariadb'
type = 'mysql'
end
# Build uri
case type
when 'mysql', 'postgresql', 'db2', 'ibm_db_sa'
"#{type}://#{user}:#{pass}@#{host}:#{port}/#{name}#{options}"
when 'sqlite'
# SQLite uses filepaths not db name
# README(galstrom): 3 slashes is a relative path, 4 slashes is an absolute path
# example: info['path'] = 'path/to/foo.db' -- will return sqlite:///foo.db
# example: info['path'] = '/path/to/foo.db' -- will return sqlite:////foo.db
path = info['path']
"#{type}:///#{path}#{options}"
end
# Build uri
case type
when 'mysql', 'postgresql', 'db2', 'ibm_db_sa'
"#{type}://#{user}:#{pass}@#{host}:#{port}/#{name}#{options}"
when 'sqlite'
# SQLite uses filepaths not db name
# README(galstrom): 3 slashes is a relative path, 4 slashes is an absolute path
# example: info['path'] = 'path/to/foo.db' -- will return sqlite:///foo.db
# example: info['path'] = '/path/to/foo.db' -- will return sqlite:////foo.db
path = info['path']
"#{type}:///#{path}#{options}"
end
end

View File

@ -19,7 +19,8 @@
# limitations under the License.
#
module ::Openstack # rubocop:disable Documentation
# Network methods
module ::Openstack
# return the IPv4 (default) address of the given interface.
#
# @param [String] interface The interface to query.

View File

@ -18,7 +18,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
module ::Openstack # rubocop:disable Documentation
# Parse methods
module ::Openstack
# The current state of (at least some) OpenStack CLI tools do not provide a
# mechanism for outputting data in formats other than PrettyTable output.
# Therefore this function is intended to parse PrettyTable output into a

View File

@ -20,7 +20,8 @@
# limitations under the License.
#
module ::Openstack # rubocop:disable Documentation
# Password methods
module ::Openstack
# Library routine that returns an encrypted data bag value
# for a supplied string. The key used in decrypting the
# encrypted value should be located at
@ -65,7 +66,7 @@ module ::Openstack # rubocop:disable Documentation
# attribute-specified openstack secrets databag.
def get_secret(key)
::Chef::Log.warn(
"The get_secret method is DEPRECATED. "\
'The get_secret method is DEPRECATED. '\
"Use get_password(key, 'token') instead")
if node['openstack']['use_databags']
@ -83,7 +84,7 @@ module ::Openstack # rubocop:disable Documentation
# component name, but can also be a token name
# e.g. openstack_identity_bootstrap_token
def get_password(type, key)
unless %w{db user service token}.include?(type)
unless %w(db user service token).include?(type)
::Chef::Log.error("Unsupported type for get_password: #{type}")
return
end

View File

@ -18,7 +18,8 @@
# limitations under the License.
#
module ::Openstack # rubocop:disable Documentation
# Search methods
module ::Openstack
# Search the nodes environment for the given role or recipe.
#
# @param [String] The role or recipe to be found.

View File

@ -21,7 +21,8 @@
require 'uri'
module ::Openstack # rubocop:disable Documentation
# URI methods
module ::Openstack
# Returns a uri::URI from a hash. If the hash has a 'uri' key, the value
# of that is returned. If not, then the routine attempts to construct
# the URI from other parts of the hash. The values of the 'port' and 'path'

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Wrapper methods
module ::Openstack
# Wrapper method to allow to easier spec testing
def recipe_included?(recipe)

View File

@ -1,18 +1,18 @@
name 'openstack-common'
maintainer 'openstack-chef'
name 'openstack-common'
maintainer 'openstack-chef'
maintainer_email 'opscode-chef-openstack@googlegroups.com'
license 'Apache 2.0'
description 'Common OpenStack attributes, libraries and recipes.'
license 'Apache 2.0'
description 'Common OpenStack attributes, libraries and recipes.'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '11.3.0'
version '11.3.0'
recipe 'openstack-common', 'Installs/Configures common recipes'
recipe 'openstack-common::set_endpoints_by_interface', 'Set endpoints by interface'
recipe 'openstack-common::logging', 'Installs/Configures common logging'
recipe 'openstack-common::sysctl', 'Configures sysctl settings'
recipe 'openstack-common::openrc', 'Creates openrc file'
recipe 'openstack-common', 'Installs/Configures common recipes'
recipe 'openstack-common::set_endpoints_by_interface', 'Set endpoints by interface'
recipe 'openstack-common::logging', 'Installs/Configures common logging'
recipe 'openstack-common::sysctl', 'Configures sysctl settings'
recipe 'openstack-common::openrc', 'Creates openrc file'
%w{ ubuntu suse redhat centos }.each do |os|
%w(ubuntu suse redhat centos).each do |os|
supports os
end

View File

@ -18,10 +18,6 @@
# limitations under the License.
#
class ::Chef::Recipe # rubocop:disable Documentation
include ::Openstack
end
platform_options = node['openstack']['common']['platform']
platform_options['common_client_packages'].each do |pkg|
package pkg do

View File

@ -33,7 +33,7 @@ when 'debian'
if node['openstack']['apt']['live_updates_enabled']
apt_components = node['openstack']['apt']['components']
# Simple variable substitution for LSB codename and OpenStack release
apt_components.each do | comp |
apt_components.each do |comp|
comp.gsub! '%release%', node['openstack']['release']
comp.gsub! '%codename%', node['lsb']['codename']
end

View File

@ -27,7 +27,7 @@ end
template '/etc/openstack/logging.conf' do
source 'logging.conf.erb'
owner 'root'
group 'root'
mode 00644
owner 'root'
group 'root'
mode 00644
end

View File

@ -18,7 +18,8 @@
# limitations under the License.
#
class ::Chef::Recipe # rubocop:disable Documentation
# Chef
class ::Chef::Recipe
include ::Openstack
end

View File

@ -18,7 +18,8 @@
# limitations under the License.
#
class ::Chef::Recipe # rubocop:disable Documentation
# Chef
class ::Chef::Recipe
include ::Openstack
end

View File

@ -16,8 +16,8 @@ describe 'openstack-common::default' do
describe 'openstack_command_env' do
it 'returns cli enviroment' do
allow(subject).to receive(:get_password)
.with('user', 'name')
.and_return('pass')
.with('user', 'name')
.and_return('pass')
expect(
subject.openstack_command_env('name', 'tenant')

View File

@ -2,9 +2,7 @@
require_relative 'spec_helper'
describe 'openstack-common::client' do
describe 'redhat' do
let(:runner) { ChefSpec::SoloRunner.new(REDHAT_OPTS) }
let(:node) { runner.node }
let(:chef_run) do

View File

@ -2,9 +2,7 @@
require_relative 'spec_helper'
describe 'openstack-common::client' do
describe 'ubuntu' do
let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) }
let(:node) { runner.node }
let(:chef_run) do

View File

@ -12,7 +12,6 @@ describe 'openstack-common::default' do
include_context 'library-stubs'
describe '#db_create_with_user' do
it 'returns nil when no such service was found' do
expect(
subject.db_create_with_user('nonexisting', 'user', 'pass')

View File

@ -15,7 +15,7 @@ describe 'openstack-common::default' do
allow(Mixlib::ShellOut).to receive_message_chain(
new: 'rpm -qa gpg-pubkey', run_command: nil, stdout: nil,
new: 'zypper repos --export -').and_return(
'http://download.opensuse.org/repositories/Cloud:/OpenStack:/Kilo/SLE_11_SP3/')
'http://download.opensuse.org/repositories/Cloud:/OpenStack:/Kilo/SLE_11_SP3/')
expect(chef_run).to run_bash('add repository key')
expect(chef_run).not_to run_execute('add repository').with(command: /zypper addrepo/)
@ -37,8 +37,8 @@ describe 'openstack-common::default' do
allow(Mixlib::ShellOut).to receive_message_chain(
new: 'rpm -qa gpg-pubkey', run_command: nil, stdout: nil,
new: 'zypper repos --export -').and_return(
'd85f9316',
'http://download.opensuse.org/repositories/Cloud:/OpenStack:/Kilo/SLE_11_SP3/')
'd85f9316',
'http://download.opensuse.org/repositories/Cloud:/OpenStack:/Kilo/SLE_11_SP3/')
expect(chef_run).not_to run_bash('add repository key')
expect(chef_run).not_to run_execute('add repository').with(command: /zypper addrepo/)
end

View File

@ -4,7 +4,7 @@ require_relative 'spec_helper'
describe 'openstack-common::default' do
describe 'ubuntu' do
let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) }
let(:mq_services) { %w{bare-metal block-storage compute database image telemetry network orchestration} }
let(:mq_services) { %w(bare-metal block-storage compute database image telemetry network orchestration) }
let(:node) { runner.node }
let(:chef_run) do
runner.converge(described_recipe)
@ -46,7 +46,7 @@ describe 'openstack-common::default' do
it 'installs the gem chef-vault if databag_type is vault' do
node.set['openstack']['databag_type'] = 'vault'
expect(chef_run).to install_chef_gem('chef-vault')
.with(version: '~> 2.3')
.with(version: '~> 2.3')
end
it 'enables rabbit ha for all services' do
@ -57,32 +57,32 @@ describe 'openstack-common::default' do
end
it 'has correct host for endpoints' do
%w{identity-api identity-internal identity-admin compute-api compute-ec2-api compute-ec2-admin
%w(identity-api identity-internal identity-admin compute-api compute-ec2-api compute-ec2-admin
compute-xvpvnc compute-novnc compute-vnc compute-metadata-api network-api network-linuxbridge
network-openvswitch image-api block-storage-api object-storage-api telemetry-api orchestration-api
orchestration-api-cfn orchestration-api-cloudwatch database-api bare-metal-api}.each do |endpoint|
orchestration-api-cfn orchestration-api-cloudwatch database-api bare-metal-api).each do |endpoint|
expect(chef_run.node['openstack']['endpoints'][endpoint]['host']).to eq('127.0.0.1')
end
end
it 'allows bind_interface override for all bind endpoints' do
node.set['openstack']['endpoints']['bind_interface'] = 'eth1'
%w{identity-bind identity-admin-bind compute-api-bind compute-ec2-api-bind compute-ec2-admin-bind
%w(identity-bind identity-admin-bind compute-api-bind compute-ec2-api-bind compute-ec2-admin-bind
compute-xvpvnc-bind compute-novnc-bind compute-vnc-bind compute-vnc-proxy-bind compute-metadata-api-bind
network-api-bind image-api-bind image-registry-bind block-storage-api-bind object-storage-api-bind
telemetry-api-bind orchestration-api-bind orchestration-api-cfn-bind orchestration-api-cloudwatch-bind
database-api-bind bare-metal-api-bind dashboard-http-bind dashboard-https-bind}.each do |endpoint|
database-api-bind bare-metal-api-bind dashboard-http-bind dashboard-https-bind).each do |endpoint|
expect(chef_run.node['openstack']['endpoints'][endpoint]['bind_interface']).to eq('eth1')
end
end
it 'allows scheme for all bind endpoints' do
node.set['openstack']['endpoints']['scheme'] = 'https'
%w{identity-api identity-internal identity-admin compute-api compute-ec2-api compute-ec2-admin
%w(identity-api identity-internal identity-admin compute-api compute-ec2-api compute-ec2-admin
compute-xvpvnc compute-novnc compute-metadata-api
network-api image-api image-registry block-storage-api object-storage-api
telemetry-api orchestration-api orchestration-api-cfn orchestration-api-cloudwatch
database-api bare-metal-api}.each do |endpoint|
database-api bare-metal-api).each do |endpoint|
expect(chef_run.node['openstack']['endpoints'][endpoint]['scheme']).to eq('https')
end
end

View File

@ -287,7 +287,7 @@ describe 'openstack-common::set_endpoints_by_interface' do
it 'does nothing when empty endpoints' do
allow(subject).to receive(:node).and_return('openstack' => { 'endpoints' => {} })
count = 0
subject.endpoints do | ep |
subject.endpoints do
count += 1
end
expect(count).to eq(0)
@ -296,7 +296,7 @@ describe 'openstack-common::set_endpoints_by_interface' do
it 'executes block count when have endpoints' do
allow(subject).to receive(:node).and_return(chef_run.node)
count = 0
subject.endpoints do |ep|
subject.endpoints do
count += 1
end
expect(count).to be >= 1

View File

@ -11,16 +11,11 @@ describe 'openstack-common::logging' do
let(:dir) { chef_run.directory('/etc/openstack') }
it 'should create /etc/openstack' do
expect(chef_run).to create_directory('/etc/openstack')
end
it 'has proper owner' do
expect(dir.owner).to eq('root')
expect(dir.group).to eq('root')
end
it 'has proper modes' do
expect(sprintf('%o', dir.mode)).to eq '755'
expect(chef_run).to create_directory('/etc/openstack').with(
owner: 'root',
group: 'root',
mode: 00755
)
end
end
@ -28,16 +23,11 @@ describe 'openstack-common::logging' do
let(:file) { chef_run.template('/etc/openstack/logging.conf') }
it 'should create /etc/openstack/logging.conf' do
expect(chef_run).to create_template(file.name)
end
it 'has proper owner' do
expect(file.owner).to eq('root')
expect(file.group).to eq('root')
end
it 'has proper modes' do
expect(sprintf('%o', file.mode)).to eq '644'
expect(chef_run).to create_template(file.name).with(
owner: 'root',
group: 'root',
mode: 00644
)
end
context 'loggers' do

View File

@ -46,7 +46,6 @@ describe 'openstack-common::default' do
subject.address_for('all')
).to eq('0.0.0.0')
end
end
describe '#address_for ipv6' do

View File

@ -28,7 +28,7 @@ describe 'openstack-common::default' do
end
it 'returns the data from a chef vault item' do
allow(ChefVault::Item).to receive(:load).with('vault_passwords', 'nova')
.and_return('nova' => 'novapassword')
.and_return('nova' => 'novapassword')
expect(subject.secret('passwords', 'nova')).to eq('novapassword')
end
end
@ -126,7 +126,7 @@ describe 'openstack-common::default' do
before { node.set['openstack']['use_databags'] = false }
describe '#get_password' do
%w{service db user token}.each do |type|
%w(service db user token).each do |type|
it "returns the set attribute for #{type}" do
expect(subject.get_password(type, 'compute')).to eq("compute-#{type}")
end

View File

@ -32,15 +32,15 @@ end
shared_context 'common-stubs' do
before do
allow_any_instance_of(Chef::Recipe).to receive(:search_for)
.with('os-identity').and_return(
[{
'openstack' => {
'identity' => {
'admin_tenant_name' => 'admin',
'admin_user' => 'admin'
.with('os-identity').and_return(
[{
'openstack' => {
'identity' => {
'admin_tenant_name' => 'admin',
'admin_user' => 'admin'
}
}
}
}]
}]
)
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
.with('user', 'admin')

View File

@ -8,27 +8,20 @@ describe 'openstack-common::sysctl' do
let(:chef_run) { runner.converge(described_recipe) }
describe 'sysctl.d directory' do
it 'should create /etc/systctl.d' do
expect(chef_run).to create_directory('/etc/sysctl.d')
end
end
describe '60-openstack.conf' do
let(:file) { chef_run.template('/etc/sysctl.d/60-openstack.conf') }
it 'should create the template /etc/systctl.d/60-openstack.conf' do
expect(chef_run).to create_template('/etc/sysctl.d/60-openstack.conf')
end
it 'has proper owner' do
expect(file.owner).to eq('root')
expect(file.group).to eq('root')
end
it 'has proper modes' do
expect(sprintf('%o', file.mode)).to eq '644'
expect(chef_run).to create_template('/etc/sysctl.d/60-openstack.conf').with(
owner: 'root',
group: 'root',
mode: 0644
)
end
it 'sets the sysctl attributes' do
@ -39,17 +32,14 @@ describe 'openstack-common::sysctl' do
expect(chef_run).to render_file(file.name).with_content(/^#{k} = #{v}$/)
end
end
end
describe 'execute sysctl' do
it 'should execute sysctl for 60-openstack' do
resource = chef_run.execute('sysctl -p /etc/sysctl.d/60-openstack.conf')
expect(resource).to do_nothing
expect(resource).to subscribe_to('template[/etc/sysctl.d/60-openstack.conf]').on(:run).immediately
end
end
end
end