Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support all Fog OpenStack options #179

Merged
merged 4 commits into from
Oct 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ In order to communicate with an OpenStack API you will need to tell Knife your O
knife[:openstack_tenant] = "Your OpenStack tenant name"
knife[:openstack_region] = "Your OpenStack Region"

All of Fog's `openstack` options (`openstack_domain_name`, `openstack_project_name`, ...) are supported. This includes support for the OpenStack Identity v3 API:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjasghar, is this the kind of example you were looking for?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this works!

knife[:openstack_auth_url] = "http://cloud.mycompany.com:5000/v3/auth/tokens"
knife[:openstack_username] = "Your OpenStack Dashboard username"
knife[:openstack_password] = "Your OpenStack Dashboard password"
knife[:openstack_project_name] = "Your OpenStack project"
knife[:openstack_domain_name] = "Your OpenStack domain"

If your knife.rb file will be checked into a SCM system (ie readable by others) you may want to read the values from environment variables. For example, using the conventions of [OpenStack's RC file](http://docs.openstack.org/user-guide/content/cli_openrc.html) (note the `openstack_auth_url`):

knife[:openstack_auth_url] = "#{ENV['OS_AUTH_URL']}/tokens"
Expand Down
35 changes: 23 additions & 12 deletions lib/chef/knife/cloud/openstack_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,7 @@ def initialize(options = {})
Chef::Log.debug("openstack_insecure #{Chef::Config[:knife][:openstack_insecure]}")
Chef::Log.debug("openstack_region #{Chef::Config[:knife][:openstack_region]}")

super(options.merge(auth_params: {
provider: 'OpenStack',
openstack_username: Chef::Config[:knife][:openstack_username],
openstack_api_key: Chef::Config[:knife][:openstack_password],
openstack_auth_url: Chef::Config[:knife][:openstack_auth_url],
openstack_endpoint_type: Chef::Config[:knife][:openstack_endpoint_type],
openstack_tenant: Chef::Config[:knife][:openstack_tenant],
openstack_region: Chef::Config[:knife][:openstack_region],
connection_options: {
ssl_verify_peer: !Chef::Config[:knife][:openstack_insecure]
}
}))
super(options.merge(auth_params: get_auth_params))
end

# add alternate user defined api_endpoint value.
Expand All @@ -54,6 +43,28 @@ def get_server(search_term)
rescue Excon::Errors::BadRequest => e
handle_excon_exception(CloudExceptions::KnifeCloudError, e)
end

def get_auth_params
load_fog_gem
params = {
provider: 'OpenStack',
connection_options: {
ssl_verify_peer: !Chef::Config[:knife][:openstack_insecure]
}
}

(
Fog::Compute::OpenStack.requirements +
Fog::Compute::OpenStack.recognized -
[:openstack_api_key]
).each do |k|
next unless k.to_s.start_with?('openstack')
params[k] = Chef::Config[:knife][k]
end
params[:openstack_api_key] = Chef::Config[:knife][:openstack_password] || Chef::Config[:knife][:openstack_api_key]

params
end
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/functional/server_create_func_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@

context 'for Linux' do
before do
@config = { openstack_floating_ip: '-1', bootstrap_ip_address: '75.101.253.10', ssh_password: 'password' }
@config = { openstack_floating_ip: '-1', bootstrap_ip_address: '75.101.253.10', ssh_password: 'password', hints: { "openstack" => {} }}
@knife_openstack_create.config[:distro] = 'chef-full'
@bootstrapper = Chef::Knife::Cloud::Bootstrapper.new(@config)
@ssh_bootstrap_protocol = Chef::Knife::Cloud::SshBootstrapProtocol.new(@config)
Expand All @@ -95,7 +95,7 @@

context 'for Windows' do
before do
@config = { openstack_floating_ip: '-1', image_os_type: 'windows', bootstrap_ip_address: '75.101.253.10', bootstrap_protocol: 'winrm', ssh_password: 'password' }
@config = { openstack_floating_ip: '-1', image_os_type: 'windows', bootstrap_ip_address: '75.101.253.10', bootstrap_protocol: 'winrm', ssh_password: 'password', hints: { "openstack" => {} } }
@knife_openstack_create.config[:image_os_type] = 'windows'
@knife_openstack_create.config[:bootstrap_protocol] = 'winrm'
@knife_openstack_create.config[:distro] = 'windows-chef-client-msi'
Expand Down
37 changes: 19 additions & 18 deletions spec/functional/server_list_func_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@
end

it 'lists formatted list of resources' do
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Public IP', 'Private IP', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone',
'ubuntu01', 'resource-1', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-2', '172.31.6.132', nil, 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone', 'windows2008', 'resource-3-err', nil, nil, 'id2', 'image2', 'keypair', 'ERROR', 'test zone'], :uneven_columns_across, 9)
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Addresses', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone',
'ubuntu01', 'resource-1', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-2', 'public:IPv4: 172.31.6.132', 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-3-err', '', 'id2', 'image2', 'keypair', 'ERROR', 'test zone'], :uneven_columns_across, 8)
instance.run
end

Expand All @@ -54,22 +55,22 @@
end

it 'lists formatted list of resources on chef data option set' do
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Public IP', 'Private IP', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone', 'Chef Node Name', 'Environment', 'FQDN', 'Runlist', 'Tags', 'Platform',
'server-4', 'server-4', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', 'server-4', '_default', 'testfqdnnode.us', '[]', '[]', 'ubuntu',
'ubuntu01', 'resource-1', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '',
'windows2008', 'resource-2', '172.31.6.132', nil, 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '',
'windows2008', 'resource-3-err', nil, nil, 'id2', 'image2', 'keypair', 'ERROR', 'test zone', '', '', '', '', '', ''], :uneven_columns_across, 15)
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Addresses', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone', 'Chef Node Name', 'Environment', 'FQDN', 'Runlist', 'Tags', 'Platform',
'server-4', 'server-4', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', 'server-4', '_default', 'testfqdnnode.us', '[]', '[]', 'ubuntu',
'ubuntu01', 'resource-1', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '',
'windows2008', 'resource-2', 'public:IPv4: 172.31.6.132', 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '',
'windows2008', 'resource-3-err', '', 'id2', 'image2', 'keypair', 'ERROR', 'test zone', '', '', '', '', '', ''], :uneven_columns_across, 14)
instance.run
end

it 'lists formatted list of resources on chef-data and chef-node-attribute option set' do
instance.config[:chef_node_attribute] = 'platform_family'
expect(@node).to receive(:attribute?).with('platform_family').and_return(true)
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Public IP', 'Private IP', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone', 'Chef Node Name', 'Environment', 'FQDN', 'Runlist', 'Tags', 'Platform', 'platform_family',
'server-4', 'server-4', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', 'server-4', '_default', 'testfqdnnode.us', '[]', '[]', 'ubuntu', 'debian',
'ubuntu01', 'resource-1', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '', '',
'windows2008', 'resource-2', '172.31.6.132', nil, 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '', '',
'windows2008', 'resource-3-err', nil, nil, 'id2', 'image2', 'keypair', 'ERROR', 'test zone', '', '', '', '', '', '', ''], :uneven_columns_across, 16)
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Addresses', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone', 'Chef Node Name', 'Environment', 'FQDN', 'Runlist', 'Tags', 'Platform', 'platform_family',
'server-4', 'server-4', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', 'server-4', '_default', 'testfqdnnode.us', '[]', '[]', 'ubuntu', 'debian',
'ubuntu01', 'resource-1', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '', '',
'windows2008', 'resource-2', 'public:IPv4: 172.31.6.132', 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone', '', '', '', '', '', '', '',
'windows2008', 'resource-3-err', '', 'id2', 'image2', 'keypair', 'ERROR', 'test zone', '', '', '', '', '', '', ''], :uneven_columns_across, 15)
instance.run
end

Expand All @@ -84,11 +85,11 @@
it 'not display chef-data on chef-node-attribute set but chef-data option missing' do
instance.config[:chef_data] = false
instance.config[:chef_node_attribute] = 'platform_family'
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Public IP', 'Private IP', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone',
'server-4', 'server-4', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone',
'ubuntu01', 'resource-1', '172.31.6.132', '172.31.6.133', '1', 'image1', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-2', '172.31.6.132', nil, 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-3-err', nil, nil, 'id2', 'image2', 'keypair', 'ERROR', 'test zone'], :uneven_columns_across, 9)
expect(instance.ui).to receive(:list).with(['Name', 'Instance ID', 'Addresses', 'Flavor', 'Image', 'Keypair', 'State', 'Availability Zone',
'server-4', 'server-4', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone',
'ubuntu01', 'resource-1', 'public:IPv4: 172.31.6.132', '1', 'image1', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-2', 'public:IPv4: 172.31.6.132', 'id2', 'image2', 'keypair', 'ACTIVE', 'test zone',
'windows2008', 'resource-3-err', '', 'id2', 'image2', 'keypair', 'ERROR', 'test zone'], :uneven_columns_across, 8)
instance.run
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/openstack_server_create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@

it 'ensures default value for metadata' do
options = @instance.options
expect(options[:metadata][:default]).to be.nil?
expect(options[:metadata][:default]).to be_nil
end
end

Expand Down
46 changes: 42 additions & 4 deletions spec/unit/openstack_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@
end

it 'sets the api_endpoint in auth params' do
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be.nil?
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be_nil
@instance.add_api_endpoint
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be == @api_endpoint
end

it 'does not set the endpoint when --api-endpoint option is missing' do
Chef::Config[:knife][:api_endpoint] = nil
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be.nil?
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be_nil
@instance.add_api_endpoint
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to_not be == @api_endpoint
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be.nil?
expect(@instance.instance_variable_get(:@auth_params)[:openstack_auth_url]).to be_nil
end

it "doesn't set an OpenStack endpoint type by default" do
expect(Chef::Config[:knife][:openstack_endpoint_type]).to be.nil?
expect(Chef::Config[:knife][:openstack_endpoint_type]).to be_nil
end
end

Expand Down Expand Up @@ -86,4 +86,42 @@
end
end
end

describe '#get_auth_params' do
let(:auth_params) do
Chef::Knife::Cloud::OpenstackService.new.instance_variable_get(:@auth_params)
end

it 'sets ssl_verify_peer to false when openstack_insecure is true' do
Chef::Config[:knife][:openstack_insecure] = true
expect(auth_params[:connection_options][:ssl_verify_peer]).to be false
end

it 'only copies openstack options from Fog' do
params = auth_params.keys - [:provider, :connection_options]
expect(params.all? { |p| p.to_s.start_with?('openstack') }).to be true
end

context 'when openstack_password is set' do
before(:each) do
@expected = 'password'
Chef::Config[:knife][:openstack_password] = @expected
end

it 'sets openstack_api_key from openstack_password' do
expect(auth_params[:openstack_api_key]).to be == @expected
end

it 'prefers openstack_password over openstack_api_key' do
Chef::Config[:knife][:openstack_api_key] = 'unexpected'
expect(auth_params[:openstack_api_key]).to be == @expected
end
end

it 'uses openstack_api_key if openstack_password is not set' do
@expected = 'password'
Chef::Config[:knife][:openstack_api_key] = @expected
expect(auth_params[:openstack_api_key]).to be == @expected
end
end
end