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

Converge fails when http_proxy and/or https_proxy is/are specified to the vagrant driver #7

Closed
mikerwilson opened this issue Sep 23, 2014 · 14 comments

Comments

@mikerwilson
Copy link

When http_proxy and/or https_proxy is/are specified in the driver stanza of the .kitchen.yml, I get the following error:

<snip>
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: SSH exited (1) for command: [env http_proxy=http://myproxy.domain.com:8080 https_proxy=http://myproxy.domain.com:8080           if [ ! $(which ansible) ]; then
            if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
               sudo -E rpm -ivh https://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
</snip>

The proxies are valid (I've scrubbed the names for the purposes of this bug report), and work regularly with other kitchen providers (like chef for example).

Full run output:

-----> Starting Kitchen (v1.2.1)
-----> Creating <webtier-nocm-ubuntu-1204>...
       Bringing machine 'default' up with 'virtualbox' provider...
       ==> default: Importing base box 'nocm_ubuntu-12.04'...
       ==> default: Matching MAC address for NAT networking...
       ==> default: Setting the name of the VM: webtier-nocm-ubuntu-1204_default_1411500225542_35968
       ==> default: Clearing any previously set forwarded ports...
       ==> default: Clearing any previously set network interfaces...
       ==> default: Preparing network interfaces based on configuration...
           default: Adapter 1: nat
       ==> default: Forwarding ports...
           default: 22 => 2222 (adapter 1)
       ==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...           default: SSH address: 127.0.0.1:2222
           default: SSH username: vagrant
           default: SSH auth method: private key
           default: Warning: Connection timeout. Retrying...
       ==> default: Machine booted and ready!
       ==> default: Checking for guest additions in VM...
           default: The guest additions on this VM do not match the installed version of
           default: VirtualBox! In most cases this is fine, but in rare cases it can
           default: prevent things such as shared folders from working properly. If you see
           default: shared folder errors, please make sure the guest additions within the
           default: virtual machine match the version of VirtualBox you have installed on
           default: your host and reload your VM.
           default:
           default: Guest Additions Version: 4.2.10
           default: VirtualBox Version: 4.3
       ==> default: Setting hostname...
       ==> default: Machine not provisioning because `--no-provision` is specified.
       Vagrant instance <webtier-nocm-ubuntu-1204> created.
       Finished creating <webtier-nocm-ubuntu-1204> (0m30.50s).
-----> Converging <webtier-nocm-ubuntu-1204>...
       Preparing files for transfer
       Preparing playbook
       Preparing modules
       nothing to do for modules
       Preparing roles
       Preparing ansible.cfg file
       Preparing group_vars
       nothing to do for group_vars
       Preparing host_vars
       nothing to do for host_vars
       Preparing hosts file
       Finished Preparing files for transfer
       Installing ansible, will try to determine platform os
       bash: -c: line 0: syntax error near unexpected token `then'
       bash: -c: line 0: `env http_proxy=http://myproxy.domain.com:8080 https_proxy=http://myproxy.domain.com:8080           if [ ! $(which ansible) ]; then'
>>>>>> Converge failed on instance <webtier-nocm-ubuntu-1204>.
>>>>>> Please see .kitchen/logs/webtier-nocm-ubuntu-1204.log for more details
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: SSH exited (1) for command: [env http_proxy=http://myproxy.domain.com:8080 https_proxy=http://myproxy.domain.com:8080           if [ ! $(which ansible) ]; then
            if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
               sudo -E rpm -ivh https://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
               sudo -E yum makecache
               sudo -E yum -y install ansible
            else
           #   sudo -E wget ppa:rquillo/ansible
           #   sudo -E dpkg -i ansible
           #   sudo -E apt-get update
           #   sudo -E apt-get -y install ansible
               sudo -E add-apt-repository ppa:rquillo/ansible
           sudo -E apt-get update
               sudo -E apt-get -y install ansible
            fi
          fi
                            # Check whether a command exists - returns 0 if it does, 1 if it does not
        exists() {
          if command -v $1 >/dev/null 2>&1
          then
            return 0
          else
            return 1
          fi
        }

        # do_wget URL FILENAME
        do_wget() {
          echo "trying wget..."
          wget -O "$2" "$1" 2>/tmp/stderr
          # check for bad return status
          test $? -ne 0 && return 1
          # check for 404 or empty file
          grep "ERROR 404" /tmp/stderr 2>&1 >/dev/null
          if test $? -eq 0 || test ! -s "$2"; then
            return 1
          fi
          return 0
        }

        # do_curl URL FILENAME
        do_curl() {
          echo "trying curl..."
          curl -L "$1" > "$2"
          # check for bad return status
          [ $? -ne 0 ] && return 1
          # check for bad output or empty file
          grep "The specified key does not exist." "$2" 2>&1 >/dev/null
          if test $? -eq 0 || test ! -s "$2"; then
            return 1
          fi
          return 0
        }

        # do_fetch URL FILENAME
        do_fetch() {
          echo "trying fetch..."
          fetch -o "$2" "$1" 2>/tmp/stderr
          # check for bad return status
          test $? -ne 0 && return 1
          return 0
        }

        # do_perl URL FILENAME
        do_perl() {
          echo "trying perl..."
          perl -e "use LWP::Simple; getprint($ARGV[0]);" "$1" > "$2"
          # check for bad return status
          test $? -ne 0 && return 1
          # check for bad output or empty file
          # grep "The specified key does not exist." "$2" 2>&1 >/dev/null
          # if test $? -eq 0 || test ! -s "$2"; then
          #   unable_to_retrieve_package
          # fi
          return 0
        }

        # do_python URL FILENAME
        do_python() {
          echo "trying python..."
          python -c "import sys,urllib2 ; sys.stdout.write(urllib2.urlopen(sys.argv[1]).read())" "$1" > "$2"
          # check for bad return status
          test $? -ne 0 && return 1
          # check for bad output or empty file
          #grep "The specified key does not exist." "$2" 2>&1 >/dev/null
          #if test $? -eq 0 || test ! -s "$2"; then
          #  unable_to_retrieve_package
          #fi
          return 0
        }

        # do_download URL FILENAME
        do_download() {
          PATH=/opt/local/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
          export PATH

          echo "downloading $1"
          echo "  to file $2"

          # we try all of these until we get success.
          # perl, in particular may be present but LWP::Simple may not be installed

          if exists wget; then
            do_wget $1 $2 && return 0
          fi

          if exists curl; then
            do_curl $1 $2 && return 0
          fi

          if exists fetch; then
            do_fetch $1 $2 && return 0
          fi

          if exists perl; then
            do_perl $1 $2 && return 0
          fi

          if exists python; then
            do_python $1 $2 && return 0
          fi

          echo ">>>>>> wget, curl, fetch, perl or python not found on this instance."
          return 16
        }

          # install chef omnibus so that busser works as this is needed to run tests :(
          # TODO: work out how to install enough ruby
          # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
          # whole chef client
          if [ ! -d "/opt/chef" ]
          then
            echo "-----> Installing Chef Omnibus to install busser to run tests"
            do_download https://www.getchef.com/chef/install.sh /tmp/install.sh
            sudo -E sh /tmp/install.sh
          fi

]
>>>>>> ----------------------

.kitchen.yml contents:

---
driver:
  name: vagrant
  http_proxy: http://myproxy.domain.com:8080 
  https_proxy: http://myproxy.domain.com:8080 

provisioner:
  name: ansible_playbook
  require_ansible_repo: true
  ansible_verbose: true
  roles_path: roles
  group_vars_path: group_vars
  host_vars_path: host_vars
  hosts: all

platforms:
- name: nocm_ubuntu-12.04
  driver_plugin: vagrant
  driver_config:
    box: nocm_ubuntu-12.04
    box_url: http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box

suites:
  - name: webtier
    provisioner:
      hosts: webtier
@neillturner
Copy link
Owner

Don't know i'm afraid. I have used test-kitchen extensively with chef and puppet and a little with ansible but not used http proxies.
I suppose need to first run with say chef using maybe my sample chef repo
https://github.com/neillturner/chef-repo
the .kitchen.yaml file is in folder site-cookbooks/mycompany_webserver.
then test with a proxy and check that it works with chef.
Then test with ansible and see if it works or not with the same proxies.
If not this need to fix. my code does not do anything for proxies i guess i'm hoping that test-kitchen handles it.
Currently do a puppet contract using the kitchen-puppet plugin. Maybe next week i might get some time to look at this. I have a couple of other pulls request for kitchen-ansible as well.

@jalessio
Copy link

jalessio commented Jan 6, 2015

I tracked down this issue. The environment variables for http_proxy and https_proxy are getting prepended to the return value of kitchen-ansible's install_command method. In some cases the return of the install_command method begins with this:

if [ ! $(which ansible) ]; then

which gets turned into something like this by test-kitchen:

env http_proxy=http://example.com/ https_proxy=http://example.com/  if [ ! $(which ansible) ]; then

which results in a bash syntax error. The super hacky fix is to simply put a bash command ahead of the if that tolerates the addition of a string like env http_proxy=http://example.com/ https_proxy=http://example.com/. For testing I just added a simple echo command above the if statement which fixed the failure.

Now, with that in mind, I don't think the http_proxy settings will actually be used during the installation of ansible since the return string consists of many lines and it appears that test-kitchen's env_cmd method assumes it will be a single line string. You could do all sorts of workarounds for this, but for starters do you see any path for paring down what is returned by kitchen-ansible's install_command method? If it's somehow possible to get the return value down to a single string (perhaps by doing more of the logic for OS detection in Ruby?) then it will behave as test-kitchen expects it to.

And thanks for creating kitchen-ansible -- it's really nice to have an quick way to use Test Kitchen as I begin experimenting with Ansible coming from a Chef background.

@neillturner
Copy link
Owner

I know this issue. had same issue in kitchen-puppet. The driver preprend the http_proxy and https_proxy values to an env command and then call the install script. This is tough to get working when the install scripts get big.
In kitchen puppet I support have http_proxy and https_proxy in the provisioner as it easier that way. I put it in kitchen-ansible as some as i get time.

@trinitronx
Copy link
Contributor

if things get too tricky to solve another way, we could always try prepending with /bin/sh -c ", but that would make quote escaping an issue. The other option is use bash HEREDOC with a unique identifier like: <<EOTESTKITCHENINSTALLCOMMAND. Not sure since I've never messed with proxies very much, and am not sure how the rpm command behaves with these env vars set... Since it's setting them with env rather than the export shell builtin, I don't think they'd actually affect a subshell, in which case my suggestion is invalid.

@neillturner
Copy link
Owner

Yes. in kitchen-puppet i found it easier to add the http_proxy and https_proxy parameters to the provisioner part of kitchen.yaml and then put them in the commands individually in the install parts of the code. I think this approach will work for ansible just have not had time to do it. -)

@jalessio
Copy link

@neillturner It looks like this is the diff where you added http_proxy support to kitchen-puppet. Fair to say this is a good template for what needs to happen in kitchen-ansible?

neillturner/kitchen-puppet@0.0.17...0.0.18

@neillturner
Copy link
Owner

yes it is. I added http_proxy support to kitchen-puppet as i needed it on a contract i was doing using puppet and aws. I will see if i get time this week and next contract will involve ansible so i may well get time to do it.
Most of the enhancements beyond my initial development on kitchen-ansible have come from other people via pull requests which is great. -)
i do contracting using chef, puppet or ansible with AWS, openstack, vcloud etc and one of the great things about test-kitchen and its plugin architecture is i can use the same tooling on all these contracts.

@neillturner
Copy link
Owner

this is now support in kitchen-ansible 0.0.25

@jalessio
Copy link

jalessio commented Sep 2, 2015

👍 confirmed working with kitchen-ansible 0.0.25 from rubygems.org. Thanks!

@jsok
Copy link

jsok commented Mar 18, 2016

There seems to have been a regression, I'm seeing the same issue as originally reported.

My setup is:

  • kitchen-ansible
  • kitchen-docker

extract:

       Installing ansible, will try to determine platform os
       bash: -c: line 0: syntax error near unexpected token `then'
       bash: -c: line 0: `env http_proxy=http://10.0.2.2:3128 https_proxy=http://10.0.2.2:3128             if [ ! $(which ansible) ]; then'
>>>>>> Converge failed on instance <default-centos-67>.
>>>>>> Please see .kitchen/logs/default-centos-67.log for more details
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: SSH exited (1) for command: [env http_proxy=http://10.0.2.2:3128 https_proxy=http://10.0.2.2:3128             if [ ! $(which ansible) ]; then
              if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
                if ! [ grep -q 'Amazon Linux' /etc/system-release ]; then
                          if [ ! $(which ansible) ]; then

@neillturner
Copy link
Owner

I don't support putting http_proxy and/or https_proxy in the driver stanza of the .kitchen.yml
you should specify then n the provisioner stanza.
are you specifying in driver or provisioner stanzas?

@jsok
Copy link

jsok commented Mar 18, 2016

In the driver, @neillturner, as I need to set an HTTP proxy during the Docker build.
If I added it in the provisioner only, the docker driver would fail before it even got to the ansible provisioner.

I'm happy to create a PR, do you have any advice on how to approach this issue?

@neillturner
Copy link
Owner

try specifying the platform as it won't do the if statements
ie in the kitchen.yml

ansible_platform: centos

ie one of debian', 'ubuntu' 'redhat', 'centos', 'fedora' 'amazon' 'suse', 'opensuse', 'sles'

@neillturner
Copy link
Owner

added an extra initial blank line to the beginning of the install scripts and this allows the driver env variable to work at least for the install command.
so closing. fixed in version 0.40.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants