LoginSignup
7
5

More than 5 years have passed since last update.

ServerspecがWindows相手に動かない

Last updated at Posted at 2016-10-28

今年(2016年)になってからrubygemsのWinRMでインターフェース変更が激しく周りが追いついていない。

例えば現状(2016/10/28)、ServerspecでWindows相手にテスト実行する環境を整えてrake実行しても以下のようなエラーが出て止まってしまうわけですが、それを回避するためのメモ。

[root@alpha-139 ~]# rake
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.5.4/lib:/usr/local/share/gems/gems/rspec-support-3.5.0/lib /usr/local/share/gems/gems/rspec-core-3.5.4/exe/rspec --pattern spec/testw/\*_spec.rb
/root/spec/spec_helper.rb:10:in `<top (required)>': uninitialized constant WinRM::WinRMWebService (NameError)

1.spec/spec_helper.rb を修正する

spec/spec_helper.rb は serverspec-init を実行すると生成されるもので、現状(serverspec (2.37.2))では以下の様なものですが、まずはここから動かんです。

(修正前)spec/spec_helper.rb
require 'serverspec'
require 'winrm'

set :backend, :winrm

user = <username>
pass = <password>
endpoint = "http://#{ENV['TARGET_HOST']}:5985/wsman"

winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => user, :pass => pass, :basic_auth_only => true)
winrm.set_timeout 300 # 5 minutes max timeout for any operation
Specinfra.configuration.winrm = winrm

WinRM::WinRMWebServiceを、WinRM::Connectionを使用するように修正します。

(修正後)spec/spec_helper.rb
require 'serverspec'
require 'winrm'

set :backend, :winrm

opts = {
  user: "Administrator",
  password: "password",
  endpoint: "http://#{ENV['TARGET_HOST']}:5985/wsman",
  operation_timeout: 300,
}

winrm = WinRM::Connection.new(opts)
Specinfra.configuration.winrm = winrm

(参考)github - WinRb/WinRM
https://github.com/WinRb/WinRM

2.backend/winrm.rb を修正する

あー、元のコードをすべて掲載するのは面倒くさいことであるので省略しますが、specinfra(現時点のバージョン 2.63.3)の一部のファイルも新しいgem/winrmの実装に追いついていないので(powershellというメソッドが廃止されて、shell(:powershell) になっているのに対応していない)、そちらも修正する必要があります。
ちなみに修正しないと以下様なエラーが出ます

  1) Port "80" should be listening
     On host `testw'
     Failure/Error: it { should be_listening }
     NoMethodError:
       undefined method `powershell' for #<WinRM::Connection:0x00000003244ea8>

     # /usr/local/share/gems/gems/specinfra-2.63.3/lib/specinfra/backend/winrm.rb:14:in `run_command'
     # /usr/local/share/gems/gems/specinfra-2.63.3/lib/specinfra/runner.rb:27:in `run'
     # /usr/local/share/gems/gems/specinfra-2.63.3/lib/specinfra/runner.rb:19:in `method_missing'

とりあえず、bashプロンプトで以下を実行すると修正されます(rubyコードそのものではないです)。
念のためオリジナルの winrm.rb を winrm.rb.org という名前でとっています。

pushd /usr/local/share/gems/gems/specinfra-*/lib/specinfra/backend
if [ ! -e winrm.rb.org ] ; then cp winrm.rb winrm.rb.org ; fi
cat > winrm.rb << 'EOF'
module Specinfra
  module Backend
    class Winrm < Base
      include PowerShell::ScriptHelper

      def os_info
        { :family => 'windows', :release => nil, :arch => nil }
      end

      def run_command(cmd, opts={})
        script = create_script(cmd)
        winrm = get_config(:winrm)

        shell = winrm.shell(:powershell)
        result = shell.run(script)
        stdout = result.stdout
        stderr = result.stderr
        exit_status = result.exitcode
        shell.close

        if @example
          @example.metadata[:command] = script
          @example.metadata[:stdout]  = stdout + stderr
        end

        CommandResult.new :stdout => stdout, :stderr => stderr, :exit_status => exit_status
      end
    end
  end
end
EOF
popd

ちなみにspecinfraのgithubは以下ですが、フィードバックするのが手間なので親切な方がいれば是非・・
https://github.com/mizzy/specinfra

とはいえ、2016年はじめぐらいにgem/WinRMが認証プロトコルとして:negotiateに対応し始めたのですが、このおかげでWindows側にHTTPS/basic認証を有効にするとかの手間が要らなくなっており、これがそれなりにすばらしい。
この辺はAnsibleのためにpython/winrmでも早く実装してくれればと、

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5