ansible / ansible-container

DEPRECATED -- Ansible Container was a tool to build Docker images and orchestrate containers using only Ansible playbooks.
GNU Lesser General Public License v3.0
2.19k stars 392 forks source link

Can't commit a layer when playbook finishes correctly #706

Open alexppg opened 7 years ago

alexppg commented 7 years ago
ISSUE TYPE
container.yml
version: "2"
settings:
  conductor:
    base: ubuntu:16.04
  project_name: php7-ubuntu

defaults:

services:
  base:
    from        : ubuntu:16.04
    command     :
      - /bin/bash
    environment:
      nginx_vhosts:
        - listen: "80"
          server_name: "example.com www.example.com"
          return: "301 https://example.com$request_uri"
          filename: "example.com.80.conf"
    roles:
      - geerlingguy.nginx
OS / ENVIRONMENT
Linux, notebook, 4.9.0-3-amd64, #1 SMP Debian 4.9.30-2+deb9u3 (2017-08-06), x86_64
2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118] /usr/bin/python
{
  "ContainersPaused": 0, 
  "Labels": null, 
  "CgroupDriver": "cgroupfs", 
  "ContainersRunning": 0, 
  "ContainerdCommit": {
    "Expected": "cfb82a876ecc11b5ca0977d1733adbe58599088a", 
    "ID": "cfb82a876ecc11b5ca0977d1733adbe58599088a"
  }, 
  "InitBinary": "docker-init", 
  "NGoroutines": 26, 
  "Swarm": {
    "ControlAvailable": false, 
    "NodeID": "", 
    "Error": "", 
    "RemoteManagers": null, 
    "LocalNodeState": "inactive", 
    "NodeAddr": ""
  }, 
  "LoggingDriver": "json-file", 
  "OSType": "linux", 
  "HttpProxy": "", 
  "Runtimes": {
    "runc": {
      "path": "docker-runc"
    }
  }, 
  "DriverStatus": [
    [
      "Backing Filesystem", 
      "extfs"
    ], 
    [
      "Supports d_type", 
      "true"
    ], 
    [
      "Native Overlay Diff", 
      "true"
    ]
  ], 
  "OperatingSystem": "Debian GNU/Linux 9 (stretch)", 
  "Containers": 2, 
  "HttpsProxy": "", 
  "BridgeNfIp6tables": true, 
  "MemTotal": 16760045568, 
  "SecurityOptions": [
    "name=seccomp,profile=default"
  ], 
  "Driver": "overlay2", 
  "IndexServerAddress": "https://index.docker.io/v1/", 
  "ClusterStore": "", 
  "InitCommit": {
    "Expected": "949e6fa", 
    "ID": "949e6fa"
  }, 
  "Isolation": "", 
  "SystemStatus": null, 
  "OomKillDisable": true, 
  "ClusterAdvertise": "", 
  "SystemTime": "2017-08-17T09:58:10.286970134+02:00", 
  "Name": "notebook", 
  "CPUSet": true, 
  "RegistryConfig": {
    "AllowNondistributableArtifactsCIDRs": [], 
    "Mirrors": [], 
    "IndexConfigs": {
      "docker.io": {
        "Official": true, 
        "Name": "docker.io", 
        "Secure": true, 
        "Mirrors": []
      }
    }, 
    "AllowNondistributableArtifactsHostnames": [], 
    "InsecureRegistryCIDRs": [
      "127.0.0.0/8"
    ]
  }, 
  "DefaultRuntime": "runc", 
  "ContainersStopped": 2, 
  "NCPU": 8, 
  "NFd": 17, 
  "Architecture": "x86_64", 
  "KernelMemory": true, 
  "CpuCfsQuota": true, 
  "Debug": false, 
  "ID": "YEYW:FXKT:2HOB:S242:BQCA:E3OB:ADSH:CU6E:JUVN:S66Y:MONE:FNUB", 
  "IPv4Forwarding": true, 
  "KernelVersion": "4.9.0-3-amd64", 
  "BridgeNfIptables": true, 
  "NoProxy": "", 
  "LiveRestoreEnabled": false, 
  "ServerVersion": "17.06.0-ce", 
  "CpuCfsPeriod": true, 
  "ExperimentalBuild": false, 
  "MemoryLimit": true, 
  "SwapLimit": false, 
  "Plugins": {
    "Volume": [
      "local"
    ], 
    "Network": [
      "bridge", 
      "host", 
      "macvlan", 
      "null", 
      "overlay"
    ], 
    "Authorization": null, 
    "Log": [
      "awslogs", 
      "fluentd", 
      "gcplogs", 
      "gelf", 
      "journald", 
      "json-file", 
      "logentries", 
      "splunk", 
      "syslog"
    ]
  }, 
  "Images": 13, 
  "DockerRootDir": "/var/lib/docker", 
  "NEventsListener": 0, 
  "CPUShares": true, 
  "RuncCommit": {
    "Expected": "2d41c047c83e09a6d61d464906feb2a2f3c52aa4", 
    "ID": "2d41c047c83e09a6d61d464906feb2a2f3c52aa4"
  }
}
{
  "KernelVersion": "4.9.0-3-amd64", 
  "Arch": "amd64", 
  "BuildTime": "2017-06-23T21:16:12.825866885+00:00", 
  "ApiVersion": "1.30", 
  "Version": "17.06.0-ce", 
  "MinAPIVersion": "1.12", 
  "GitCommit": "02c1d87", 
  "Os": "linux", 
  "GoVersion": "go1.8.3"
}
SUMMARY

The playbook is executed correctly but it fails when commiting the layer.

STEPS TO REPRODUCE
ansible-container --debug build

It will return:

[...]
UNNING HANDLER [geerlingguy.nginx : reload nginx] *****************************
Running service
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/system/service.py
<c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08> ESTABLISH DOCKER CONNECTION FOR USER: root
<c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08> EXEC ['/usr/local/bin/docker', 'exec', '-i', u'c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08', u'/bin/sh', '-c', u"/bin/sh -c 'echo ~ && sleep 0'"]
<c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08> EXEC ['/usr/local/bin/docker', 'exec', '-i', u'c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08', u'/bin/sh', '-c', u'/bin/sh -c \'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496 `" && echo ansible-tmp-1502956541.04-224192092929496="` echo /root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496 `" ) && sleep 0\'']
<c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08> PUT /tmp/tmptL9lGa TO /root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496/service.py
<c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08> EXEC ['/usr/local/bin/docker', 'exec', '-i', u'c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08', u'/bin/sh', '-c', u"/bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496/ /root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496/service.py && sleep 0'"]
<c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08> EXEC ['/usr/local/bin/docker', 'exec', '-i', u'c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08', u'/bin/sh', '-c', u'/bin/sh -c \'/_usr/bin/python /root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496/service.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1502956541.04-224192092929496/" > /dev/null 2>&1 && sleep 0\'']
changed: [base] => {
    "changed": true,
    "failed": false,
    "invocation": {
        "module_args": {
            "arguments": "",
            "enabled": null,
            "name": "nginx",
            "pattern": null,
            "runlevel": "default",
            "sleep": null,
            "state": "reloaded"
        }
    },
    "name": "nginx",
    "state": "started"
}
META: ran handlers
META: ran handlers

PLAY RECAP *********************************************************************
base                       : ok=10   changed=3    unreachable=0    failed=0

2017-08-17T07:55:41.443534 Playbook run finished.         [container.core] caller_file=/_ansible/container/core.py caller_func=conductorcmd_build caller_line=784 exit_code=0
2017-08-17T07:55:41.445465 Applied role to service        [container.core] caller_file=/_ansible/container/core.py caller_func=conductorcmd_build caller_line=787 role=geerlingguy.nginx service=u'base'
2017-08-17T07:55:41.783091 Call: Engine.commit_role_as_layer [container.docker.engine] args=(u'c1755fb9b45b1a3163a83ddbe3f2f4330d34ecd12222e45292919026486b6e08', u'base', 'dac8a0013f8cdb6fb1828552089a581282ed5780cb0b22e120c980cd36f56ef1', ordereddict([(u'environment', ordereddict([('nginx_vhosts', [ordereddict([('filename', 'example.com.80.conf'), ('return', '301 https://example.com$request_uri'), ('server_name', 'example.com www.example.com'), ('listen', '80')])])])), (u'command', ['/bin/bash']), (u'from', u'ubuntu:16.04'), (u'roles', ['geerlingguy.nginx']), ('defaults', ordereddict([('nginx_default_release', ''), ('nginx_yum_repo_enabled', True), ('nginx_ppa_use', False), ('nginx_ppa_version', 'stable'), ('nginx_package_name', 'nginx'), ('nginx_conf_template', 'nginx.conf.j2'), ('nginx_vhost_template', 'vhost.j2'), ('nginx_worker_processes', '{{ ansible_processor_vcpus | default(ansible_processor_count) }}'), ('nginx_worker_connections', '1024'), ('nginx_multi_accept', 'off'), ('nginx_error_log', '/var/log/nginx/error.log warn'), ('nginx_access_log', '/var/log/nginx/access.log main buffer=16k flush=2m'), ('nginx_sendfile', 'on'), ('nginx_tcp_nopush', 'on'), ('nginx_tcp_nodelay', 'on'), ('nginx_keepalive_timeout', '65'), ('nginx_keepalive_requests', '100'), ('nginx_server_tokens', 'on'), ('nginx_client_max_body_size', '64m'), ('nginx_server_names_hash_bucket_size', '64'), ('nginx_proxy_cache_path', ''), ('nginx_extra_conf_options', ''), ('nginx_extra_http_options', ''), ('nginx_remove_default_vhost', False), ('nginx_vhosts', []), ('nginx_upstreams', []), ('nginx_log_format', u'\'$remote_addr - $remote_user [$time_local] "$request" \'\n\'$status $body_bytes_sent "$http_referer" \'\n\'"$http_user_agent" "$http_x_forwarded_for"\'\n')]))])) caller_file=/_ansible/container/docker/engine.py caller_func=Engine.commit_role_as_layer caller_line=14 kwargs={'with_name': True}
Traceback (most recent call last):
  File "/usr/local/bin/conductor", line 11, in <module>
    load_entry_point('ansible-container', 'console_scripts', 'conductor')()
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/cli.py", line 392, in conductor_commandline
    **params)
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/core.py", line 800, in conductorcmd_build
    with_name=is_last_role)
  File "/_ansible/container/docker/engine.py", line 87, in __wrapped__
    return fn(self, *args, **kwargs)
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/docker/engine.py", line 623, in commit_role_as_layer
    image_config = utils.metadata_to_image_config(metadata)
  File "/_ansible/container/utils/__init__.py", line 152, in metadata_to_image_config
    config[key] = (translator(metadata[metadata_key]) if translator
  File "/_ansible/container/utils/__init__.py", line 113, in format_environment
    return ['='.join(tpl) for tpl in iteritems(to_return)]
TypeError: sequence item 1: expected string, CommentedSeq found
2017-08-17T09:55:42.081724 Conductor terminated. Preserving as requested. [container.docker.engine] caller_file=/home/aperezpujol/Instalados/ansible-container/container/docker/engine.py caller_func=await_conductor_command caller_line=413 command_rc=1 conductor_id=u'4bba5421b89cf35a8d2404ff9b2d780b195a455ba555681b04e9bb129505dd66' save_container=True
2017-08-17T09:55:42.082176 Conductor exited with status 1 [container.cli] caller_file=/home/aperezpujol/Instalados/ansible-container/container/cli.py caller_func=__call__ caller_line=303
EXPECTED RESULTS

It should create a new image, since the playbook finishes correctly.

ACTUAL RESULTS

It doesn't.

chouseknecht commented 7 years ago

@alexppg

It's failing due to:

File "/_ansible/container/utils/__init__.py", line 113, in format_environment
    return ['='.join(tpl) for tpl in iteritems(to_return)]

The environment syntax in your container.yml is incorrect. Looks you stuck the role parameters under environment. If you change your container.yml to the following, it should work:

version: "2"
settings:
  conductor:
    base: ubuntu:16.04
  project_name: php7-ubuntu

defaults:

services:
  base:
    from        : ubuntu:16.04
    command     :
      - /bin/bash
    roles:
      - geerlingguy.nginx
        nginx_vhosts:
          - listen: "80"
            server_name: "example.com www.example.com"
            return: "301 https://example.com$request_uri"
            filename: "example.com.80.conf"
alexppg commented 7 years ago

Oh, what a stupid error, my bad. But isn't it weird that it begins to build the image when there's a syntax error?

Also, the way you suggest doesn't work. I can't find any information on how to pass variables to the roles, is there any other way?

chouseknecht commented 7 years ago

O. Sorry. It needs the object form of the role. So it should be the following:

roles:
  - role: geerlingguy.nginx
     nginx_vhosts:
     - listen: "80"
        server_name: "example.com www.example.com"
        return: "301 https://example.com$request_uri"
        filename: "example.com.80.conf"

Note that the name of the role is preceded by role:

alexppg commented 7 years ago

Thank you very much, it works now. I think it would be useful to add an example of how to pass variables to the roles in the documentation.