github.com/ratanraj/packer@v1.3.2/website/source/docs/provisioners/ansible.html.md (about)

     1  ---
     2  description: |
     3      The ansible Packer provisioner allows Ansible playbooks to be run to
     4      provision the machine.
     5  layout: docs
     6  page_title: 'Ansible - Provisioners'
     7  sidebar_current: 'docs-provisioners-ansible-remote'
     8  ---
     9  
    10  # Ansible Provisioner
    11  
    12  Type: `ansible`
    13  
    14  The `ansible` Packer provisioner runs Ansible playbooks. It dynamically creates
    15  an Ansible inventory file configured to use SSH, runs an SSH server, executes
    16  `ansible-playbook`, and marshals Ansible plays through the SSH server to the
    17  machine being provisioned by Packer.
    18  
    19  -> **Note:**: Any `remote_user` defined in tasks will be ignored. Packer will
    20  always connect with the user given in the json config for this provisioner.
    21  
    22  ## Basic Example
    23  
    24  This is a fully functional template that will provision an image on
    25  DigitalOcean. Replace the mock `api_token` value with your own.
    26  
    27  ``` json
    28  {
    29    "provisioners": [
    30      {
    31        "type": "ansible",
    32        "playbook_file": "./playbook.yml"
    33      }
    34    ],
    35  
    36    "builders": [
    37      {
    38        "type": "digitalocean",
    39        "api_token": "6a561151587389c7cf8faa2d83e94150a4202da0e2bad34dd2bf236018ffaeeb",
    40        "image": "ubuntu-14-04-x64",
    41        "region": "sfo1"
    42      }
    43    ]
    44  }
    45  ```
    46  
    47  ## Configuration Reference
    48  
    49  Required Parameters:
    50  
    51  -   `playbook_file` - The playbook to be run by Ansible.
    52  
    53  Optional Parameters:
    54  
    55  -   `ansible_env_vars` (array of strings) - Environment variables to set before
    56      running Ansible.
    57      Usage example:
    58  
    59      ``` json
    60      {
    61        "ansible_env_vars": [ "ANSIBLE_HOST_KEY_CHECKING=False", "ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s'", "ANSIBLE_NOCOLOR=True" ]
    62      }
    63      ```
    64      If you are running a Windows build on AWS, Azure or Google Compute and would
    65      like to access the auto-generated password that Packer uses to connect to a
    66      Windows instance via WinRM, you can use the template variable
    67      {{.WinRMPassword}} in this option.
    68      For example:
    69  
    70      ```json
    71      "ansible_env_vars": [ "WINRM_PASSWORD={{.WinRMPassword}}" ],
    72      ```
    73  
    74  -   `command` (string) - The command to invoke ansible.
    75      Defaults to `ansible-playbook`.
    76  
    77  -   `empty_groups` (array of strings) - The groups which should be present in
    78      inventory file but remain empty.
    79  
    80  -   `extra_arguments` (array of strings) - Extra arguments to pass to Ansible.
    81      These arguments *will not* be passed through a shell and arguments should
    82      not be quoted. Usage example:
    83  
    84      ```json
    85      {
    86        "extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ]
    87      }
    88      ```
    89  
    90      If you are running a Windows build on AWS, Azure or Google Compute and would
    91      like to access the auto-generated password that Packer uses to connect to a
    92      Windows instance via WinRM, you can use the template variable
    93      {{.WinRMPassword}} in this option.
    94      For example:
    95  
    96      ```json
    97        "extra_arguments": [
    98          "--extra-vars", "winrm_password={{ .WinRMPassword }}"
    99        ]
   100      ```
   101  
   102  -   `groups` (array of strings) - The groups into which the Ansible host
   103      should be placed. When unspecified, the host is not associated with any
   104      groups.
   105  
   106  -   `inventory_file` (string) - The inventory file to use during provisioning.
   107      When unspecified, Packer will create a temporary inventory file and will
   108      use the `host_alias`.
   109  
   110  -   `host_alias` (string) - The alias by which the Ansible host should be known.
   111      Defaults to `default`. This setting is ignored when using a custom inventory
   112      file.
   113  
   114  -   `inventory_directory` (string) - The directory in which to place the
   115      temporary generated Ansible inventory file. By default, this is the
   116      system-specific temporary file location. The fully-qualified name of this
   117      temporary file will be passed to the `-i` argument of the `ansible` command
   118      when this provisioner runs ansible. Specify this if you have an existing
   119      inventory directory with `host_vars` `group_vars` that you would like to use
   120      in the playbook that this provisioner will run.
   121  
   122  -   `local_port` (string) - The port on which to attempt to listen for SSH
   123      connections. This value is a starting point. The provisioner will attempt
   124      listen for SSH connections on the first available of ten ports, starting at
   125      `local_port`. A system-chosen port is used when `local_port` is missing or
   126      empty.
   127  
   128  -   `sftp_command` (string) - The command to run on the machine being provisioned
   129      by Packer to handle the SFTP protocol that Ansible will use to transfer
   130      files. The command should read and write on stdin and stdout, respectively.
   131      Defaults to `/usr/lib/sftp-server -e`.
   132  
   133  -   `skip_version_check` (boolean) - Check if ansible is installed prior to running.
   134      Set this to `true`, for example, if you're going to install ansible during
   135      the packer run.
   136  
   137  -   `ssh_host_key_file` (string) - The SSH key that will be used to run the SSH
   138      server on the host machine to forward commands to the target machine. Ansible
   139      connects to this server and will validate the identity of the server using
   140      the system known\_hosts. The default behavior is to generate and use a
   141      onetime key. Host key checking is disabled via the
   142      `ANSIBLE_HOST_KEY_CHECKING` environment variable if the key is generated.
   143  
   144  -   `ssh_authorized_key_file` (string) - The SSH public key of the Ansible
   145      `ssh_user`. The default behavior is to generate and use a onetime key. If
   146      this key is generated, the corresponding private key is passed to
   147      `ansible-playbook` with the `--private-key` option.
   148  
   149  -   `user` (string) - The `ansible_user` to use. Defaults to the user running
   150      packer.
   151  
   152  ## Default Extra Variables
   153  
   154  In addition to being able to specify extra arguments using the
   155  `extra_arguments` configuration, the provisioner automatically defines certain
   156  commonly useful Ansible variables:
   157  
   158  -   `packer_build_name` is set to the name of the build that Packer is running.
   159      This is most useful when Packer is making multiple builds and you want to
   160      distinguish them slightly when using a common playbook.
   161  
   162  -   `packer_builder_type` is the type of the builder that was used to create the
   163      machine that the script is running on. This is useful if you want to run
   164      only certain parts of the playbook on systems built with certain builders.
   165  
   166  -   `packer_http_addr` If using a builder that provides an http server for file
   167      transfer (such as hyperv, parallels, qemu, virtualbox, and vmware), this
   168      will be set to the address. You can use this address in your provisioner to
   169      download large files over http. This may be useful if you're experiencing
   170      slower speeds using the default file provisioner. A file provisioner using
   171      the `winrm` communicator may experience these types of difficulties.
   172  
   173  ## Debugging
   174  
   175  To debug underlying issues with Ansible, add `"-vvvv"` to `"extra_arguments"` to enable verbose logging.
   176  
   177  ```json
   178  {
   179    "extra_arguments": [ "-vvvv" ]
   180  }
   181  ```
   182  
   183  ## Limitations
   184  
   185  ### Redhat / CentOS
   186  
   187  Redhat / CentOS builds have been known to fail with the following error due to `sftp_command`, which should be set to `/usr/libexec/openssh/sftp-server -e`:
   188  
   189  ``` text
   190  ==> virtualbox-ovf: starting sftp subsystem
   191      virtualbox-ovf: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh", "unreachable": true}
   192  ```
   193  
   194  ### chroot communicator
   195  
   196  Building within a chroot (e.g. `amazon-chroot`) requires changing the Ansible connection to chroot.
   197  
   198  ```json
   199  {
   200    "builders": [
   201      {
   202        "type": "amazon-chroot",
   203        "mount_path": "/mnt/packer-amazon-chroot",
   204        "region": "us-east-1",
   205        "source_ami": "ami-123456"
   206      }
   207    ],
   208    "provisioners": [
   209      {
   210        "type": "ansible",
   211        "extra_arguments": [
   212          "--connection=chroot",
   213          "--inventory-file=/mnt/packer-amazon-chroot,"
   214        ],
   215        "playbook_file": "main.yml"
   216      }
   217    ]
   218  }
   219  ```
   220  
   221  ### winrm communicator
   222  
   223  Windows builds require a custom Ansible connection plugin and a particular configuration. Assuming a directory named `connection_plugins` is next to the playbook and contains a file named `packer.py` which implements
   224  the connection plugin.  On versions of Ansible before 2.4.x, the following works as the connection plugin
   225  
   226  ``` python
   227  from __future__ import (absolute_import, division, print_function)
   228  __metaclass__ = type
   229  
   230  from ansible.plugins.connection.ssh import Connection as SSHConnection
   231  
   232  class Connection(SSHConnection):
   233      ''' ssh based connections for powershell via packer'''
   234  
   235      transport = 'packer'
   236      has_pipelining = True
   237      become_methods = []
   238      allow_executable = False
   239      module_implementation_preferences = ('.ps1', '')
   240  
   241      def __init__(self, *args, **kwargs):
   242          super(Connection, self).__init__(*args, **kwargs)
   243  ```
   244  
   245  Newer versions of Ansible require all plugins to have a documentation string. You can see if there is a
   246  plugin available for the version of Ansible you are using [here](https://github.com/hashicorp/packer/tree/master/examples/ansible/connection-plugin).
   247  
   248  To create the plugin yourself, you will need to copy all of the `options` from the `DOCUMENTATION` string
   249  from the [ssh.py Ansible connection plugin](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py)
   250  of the Ansible version you are using and add it to a packer.py file similar to as follows
   251  
   252  ``` python
   253  from __future__ import (absolute_import, division, print_function)
   254  __metaclass__ = type
   255  
   256  from ansible.plugins.connection.ssh import Connection as SSHConnection
   257  
   258  DOCUMENTATION = '''
   259      connection: packer
   260      short_description: ssh based connections for powershell via packer
   261      description:
   262          - This connection plugin allows ansible to communicate to the target packer
   263          machines via ssh based connections for powershell.
   264      author: Packer
   265      version_added: na
   266      options:
   267        **** Copy ALL the options from
   268        https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py
   269        for the version of Ansible you are using ****
   270  '''
   271  
   272  class Connection(SSHConnection):
   273      ''' ssh based connections for powershell via packer'''
   274  
   275      transport = 'packer'
   276      has_pipelining = True
   277      become_methods = []
   278      allow_executable = False
   279      module_implementation_preferences = ('.ps1', '')
   280  
   281      def __init__(self, *args, **kwargs):
   282          super(Connection, self).__init__(*args, **kwargs)
   283  ```
   284  
   285  This template should build a Windows Server 2012 image on Google Cloud Platform:
   286  
   287  ``` json
   288  {
   289    "variables": {},
   290    "provisioners": [
   291      {
   292        "type":  "ansible",
   293        "playbook_file": "./win-playbook.yml",
   294        "extra_arguments": [
   295          "--connection", "packer",
   296          "--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None"
   297        ]
   298      }
   299    ],
   300    "builders": [
   301      {
   302        "type": "googlecompute",
   303        "account_file": "{{user `account_file`}}",
   304        "project_id": "{{user `project_id`}}",
   305        "source_image": "windows-server-2012-r2-dc-v20160916",
   306        "communicator": "winrm",
   307        "zone": "us-central1-a",
   308        "disk_size": 50,
   309        "winrm_username": "packer",
   310        "winrm_use_ssl": true,
   311        "winrm_insecure": true,
   312        "metadata": {
   313          "sysprep-specialize-script-cmd": "winrm set winrm/config/service/auth @{Basic=\"true\"}"
   314        }
   315      }
   316    ]
   317  }
   318  ```
   319  
   320  ### Post i/o timeout errors
   321  If you see `unknown error: Post http://<ip>:<port>/wsman:dial tcp <ip>:<port>: i/o timeout` errors while provisioning a Windows machine, try setting Ansible to copy files over [ssh instead of sftp](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#envvar-ANSIBLE_SCP_IF_SSH).
   322  
   323  ### Too many SSH keys
   324  
   325  SSH servers only allow you to attempt to authenticate a certain number of times. All of your loaded keys will be tried before the dynamically generated key. If you have too many SSH keys loaded in your `ssh-agent`, the Ansible provisioner may fail authentication with a message similar to this:
   326  
   327  ```console
   328      googlecompute: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '[127.0.0.1]:62684' (RSA) to the list of known hosts.\r\nReceived disconnect from 127.0.0.1 port 62684:2: too many authentication failures\r\nAuthentication failed.\r\n", "unreachable": true}
   329  ```
   330  
   331  To unload all keys from your `ssh-agent`, run:
   332  
   333  ```console
   334  $ ssh-add -D
   335  ```
   336  
   337  ### Become: yes
   338  
   339  We recommend against running Packer as root; if you do then you won't be able to successfully run your ansible playbook as root; `become: yes` will fail.