chef-provisioning-docker icon indicating copy to clipboard operation
chef-provisioning-docker copied to clipboard

ERROR: machine_batch[default] (@recipe_files::/root/workdir/kafka-cluster.rb line 64) had an error: Errno::ENOENT: No such file or directory @ rb_sysopen - proc/10110/root/etc/chef/client.pem

Open yazgoo opened this issue 9 years ago • 6 comments

Hi, I'm having this error when trying to run chef-provisioning-docker from within docker (which is actually quite useful to get a reproducible self-contained chef environment and allows to run multiple chef-provisioning on different drivers in parallel ). I don't know the cause of this behaviour, all that I know is that write_file method in /lib/chef/provisioning/docker_driver/docker_transport.rb determins the pem path from container_path() method, which in turn, does:

    def container_path(path)
      File.join('proc', container.info['State']['Pid'].to_s, 'root', path)
    end

My quick and dirty bypass is to force the containing directory creation:

    def write_file(path, content)
      require "file_utils"
      mkdir_p File.dirname(container_path(path))
      File.open(container_path(path), 'w') { |file| file.write(content) }
    end

I'm guessing that the fact that I'm in a container changes the way the driver behaves, what do you think ? If you think this bypass is acceptable, I can submit a PR.

yazgoo avatar Sep 28 '15 09:09 yazgoo

This won't work. First, chef-provisioning is not designed to run under docker. Second, problem in your scenario is that CPD tries to copy files directly into newly created container fs bypassing standard docker approach for this (Dockerfile+ADD, or download files from remote location). So creating directory just makes no sense. From my perspective, write_file must be reimplemented by downloading files from host system via http. This also supposed to work in your case. You also can try older version of CPD prior to 07753c4520d3364124dbdca434cd102e471b8bb4, which has different implementation of write_file. I was also thinking about mounting /proc directory to your CPD container. Unfortunately it will be direct mapping -v /proc:/proc, which doesn't seem a good idea. You can try to parametrize File.join('proc', and mount it some where else.

marc- avatar Sep 28 '15 09:09 marc-

Thanks marc-,

Does chef provide a library to do the http transfer - if so what is it, or would it be necessary to write it from scratch ?

yazgoo avatar Sep 28 '15 10:09 yazgoo

No, it doesn't. You can probably start from looking at lib/chef/provisioning/docker_driver/chef_zero_http_proxy.rb .

marc- avatar Sep 28 '15 10:09 marc-

Here is a first "stupid" (not using HTTP) implementation using netcat on the destination:


    def write_file(path, content)
        server = Socket.new(:INET, :STREAM, 0)
        ip = Socket.ip_address_list.detect{|intf| intf.ipv4_private?}
        ip = ip.ip_address if ip
        server.bind(Addrinfo.tcp(ip, 0))
        port = server.local_address.ip_port
        server.close
        server = TCPServer.new(port)
        Thread.new do
            client = server.accept
            client.print content
            client.flush
            client.close
        end
        execute "mkdir -p #{File.dirname path}"
        res = 1
        while res != 0
            res = execute("sh -c 'nc -v -q1 #{ip} #{port} > #{path} 2>/tmp/nc_error'").exitstatus
        end
        Chef::Log.debug("write_file server.close")
        server.close
    end
    def upload_file(local_path, path)
        write_file(path, File.read(local_path))
    end

yazgoo avatar Sep 28 '15 15:09 yazgoo

LGTM. You need to replace nc with ruby code and make a PR. And BTW, it shouldn't be necessary http, plain sockets are fine too. Though, it would be nice to have some secure transport between node where you run chef and node with container (in case docker service is run remotely). We use write file to deliver certificates.

marc- avatar Sep 28 '15 16:09 marc-

I opened PR #67

yazgoo avatar Sep 30 '15 11:09 yazgoo