-
Notifications
You must be signed in to change notification settings - Fork 76
Kitchen::Base and Windows support #92
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
Changes from all commits
9a2be32
e604d5a
6ef2139
0adf327
a17c8a0
b916312
a892377
4a310a6
b89981a
cefb86e
dabe654
fd718bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,10 @@ | ||
| # Encoding: UTF-8 | ||
| # | ||
| # Author:: Jonathan Hartman (<j@p4nt5.com>) | ||
| # Author:: JJ Asghar (<jj@chef.io>) | ||
| # | ||
| # Copyright (C) 2013-2015, Jonathan Hartman | ||
| # Copyright (C) 2015, Chef Inc | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
|
|
@@ -16,23 +18,20 @@ | |
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| require 'benchmark' | ||
| require 'fog' | ||
| require 'kitchen' | ||
| require 'etc' | ||
| require 'ipaddr' | ||
| require 'socket' | ||
| require 'fog' | ||
| require 'ohai' | ||
| require_relative 'openstack/volume' | ||
|
|
||
| module Kitchen | ||
| module Driver | ||
| # Openstack driver for Kitchen. | ||
| # | ||
| # @author Jonathan Hartman <j@p4nt5.com> | ||
| class Openstack < Kitchen::Driver::SSHBase | ||
| # This takes from the Base Class and creates the OpenStack driver. | ||
| class Openstack < Kitchen::Driver::Base # rubocop:disable Metrics/ClassLength, Metrics/LineLength | ||
| @@ip_pool_lock = Mutex.new | ||
|
|
||
| kitchen_driver_api_version 2 | ||
| plugin_version Kitchen::Driver::OPENSTACK_VERSION | ||
|
|
||
| default_config :server_name, nil | ||
| default_config :server_name_prefix, nil | ||
| default_config :key_name, nil | ||
|
|
@@ -62,6 +61,7 @@ class Openstack < Kitchen::Driver::SSHBase | |
| default_config :network_ref, nil | ||
| default_config :no_ssh_tcp_check, false | ||
| default_config :no_ssh_tcp_check_sleep, 120 | ||
| default_config :winrm_wait, 0 | ||
| default_config :block_device_mapping, nil | ||
|
|
||
| required_config :private_key_path | ||
|
|
@@ -82,22 +82,18 @@ def create(state) | |
| config[:server_name] = default_name | ||
| end | ||
| end | ||
| config[:disable_ssl_validation] && disable_ssl_validation | ||
| disable_ssl_validation if config[:disable_ssl_validation] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where would this option ever get set? I don't see a configuration option in your driver or the base driver for :disable_ssl_validation
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it's mentioned in the README, about being turned on ONLY if you know what you're doing. I don't think it's supposed to be used or acknowledged without specific reasons. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To @smurawski's point, while TK doesn't complain if you pass in configuration options that are not specified, it's good practice to define a default so the code self-documents the fact that options are available. I'd recommend putting this at the top of your class: default_config :disable_ssl_validation, falseThat way it's 100% clear what the intention is, and you never have to worry about an edge case where this being nil bites you :) |
||
| server = create_server | ||
| state[:server_id] = server.id | ||
| info "OpenStack instance <#{state[:server_id]}> created." | ||
| server.wait_for do | ||
| print '.' | ||
| ready? | ||
| end | ||
| info "\n(server ready)" | ||
| info "OpenStack instance with ID of <#{state[:server_id]}> is ready." # rubocop:disable Metrics/LineLength | ||
| sleep 30 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be configurable? Why is it needed? |
||
| if config[:floating_ip] | ||
| attach_ip(server, config[:floating_ip]) | ||
| elsif config[:floating_ip_pool] | ||
| attach_ip_from_pool(server, config[:floating_ip_pool]) | ||
| end | ||
| state[:hostname] = get_ip(server) | ||
| setup_ssh(server, state) | ||
| wait_for_server(state) | ||
| setup_ssh(server, state) if bourne_shell? | ||
| add_ohai_hint(state) | ||
| rescue Fog::Errors::Error, Excon::Errors::Error => ex | ||
| raise ActionFailed, ex.message | ||
|
|
@@ -106,7 +102,7 @@ def create(state) | |
| def destroy(state) | ||
| return if state[:server_id].nil? | ||
|
|
||
| config[:disable_ssl_validation] && disable_ssl_validation | ||
| disable_ssl_validation if config[:disable_ssl_validation] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above.. will this ever get hit?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it's mentioned in the README, about being turned on ONLY if you know what you're doing. I don't think it's supposed to be used or acknowledged without specific reasons. |
||
| server = compute.servers.get(state[:server_id]) | ||
| server.destroy unless server.nil? | ||
| info "OpenStack instance <#{state[:server_id]}> destroyed." | ||
|
|
@@ -192,7 +188,7 @@ def optional_config(c) | |
| when :security_groups | ||
| config[c] if config[c].is_a?(Array) | ||
| when :user_data | ||
| File.open(config[c]) { |f| f.read } if File.exist?(config[c]) | ||
| File.open(config[c], &:read) if File.exist?(config[c]) | ||
| else | ||
| config[c] | ||
| end | ||
|
|
@@ -279,7 +275,6 @@ def attach_ip_from_pool(server, pool) | |
| def attach_ip(server, ip) | ||
| info "Attaching floating IP <#{ip}>" | ||
| server.associate_address ip | ||
| (server.addresses['public'] ||= []) << { 'version' => 4, 'addr' => ip } | ||
| end | ||
|
|
||
| def get_public_private_ips(server) | ||
|
|
@@ -324,12 +319,25 @@ def parse_ips(pub, priv) | |
| end | ||
|
|
||
| def add_ohai_hint(state) | ||
| info 'Adding OpenStack hint for ohai' | ||
| ssh = Fog::SSH.new(*build_ssh_args(state)) | ||
| ssh.run([ | ||
| %(sudo mkdir -p #{Ohai::Config[:hints_path][0]}), | ||
| %(sudo touch #{Ohai::Config[:hints_path][0]}/openstack.json) | ||
| ]) | ||
| if bourne_shell? | ||
| info 'Adding OpenStack hint for ohai' | ||
| mkdir_cmd = "sudo mkdir -p #{hints_path}" | ||
| touch_cmd = "sudo touch #{hints_path}/openstack.json" | ||
| instance.transport.connection(state).execute( | ||
| "#{mkdir_cmd} && #{touch_cmd}" | ||
| ) | ||
| elsif windows_os? | ||
| info 'Adding OpenStack hint for ohai' | ||
| mkdir_cmd = "mkdir #{hints_path}" | ||
| touch_cmd = "'' > #{hints_path}\\openstack.json" | ||
| instance.transport.connection(state).execute( | ||
| "#{mkdir_cmd} && #{touch_cmd}" | ||
| ) | ||
| end | ||
| end | ||
|
|
||
| def hints_path | ||
| Ohai::Config[:hints_path][0] | ||
| end | ||
|
|
||
| def setup_ssh(server, state) | ||
|
|
@@ -366,14 +374,37 @@ def tcp_check(state) | |
| config[:username], | ||
| port: config[:port]) | ||
| end | ||
| info '(ssh ready)' | ||
| info "Server #{state[:hostname]} has ssh ready..." | ||
| end | ||
|
|
||
| def disable_ssl_validation | ||
| require 'excon' | ||
| Excon.defaults[:ssl_verify_peer] = false | ||
| end | ||
|
|
||
| def wait_for_server(state) | ||
| state[:hostname] = get_ip(state) | ||
| if config[:winrm_wait] | ||
| info "Sleeping for #{config[:winrm_wait]} seconds to let WinRM start up..." # rubocop:disable Metrics/LineLength | ||
| countdown(config[:winrm_wait]) | ||
| end | ||
| info 'Waiting for server to be ready...' | ||
| instance.transport.connection(state).wait_until_ready | ||
| rescue | ||
| error "Server #{state[:hostname]} (#{state[:server_id]}) not reachable. Destroying server..." # rubocop:disable Metrics/LineLength | ||
| destroy(state) | ||
| raise | ||
| end | ||
|
|
||
| def countdown(seconds) | ||
| date1 = Time.now + seconds | ||
| while Time.now < date1 | ||
| t = Time.at(date1.to_i - Time.now.to_i) | ||
| puts t.strftime('%M:%S') | ||
| sleep 1 | ||
| end | ||
| end | ||
|
|
||
| def find_matching(collection, name) | ||
| name = name.to_s | ||
| if name.start_with?('/') && name.end_with?('/') | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to add this due to 1.4 tk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If username and password are available in the state file (from the driver), you don't need to add them to transport, unless you want to connect with a different account.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'd like to keep this in the readme, but that's good to know. I know with my image i had to put a different administrator password in.