github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/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  
    65  -   `command` (string) - The command to invoke ansible.
    66      Defaults to `ansible-playbook`.
    67  
    68  -   `empty_groups` (array of strings) - The groups which should be present in
    69      inventory file but remain empty.
    70  
    71  -   `extra_arguments` (array of strings) - Extra arguments to pass to Ansible.
    72      These arguments *will not* be passed through a shell and arguments should
    73      not be quoted. Usage example:
    74  
    75      ``` json
    76      {
    77        "extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ]
    78      }
    79      ```
    80  
    81  -   `groups` (array of strings) - The groups into which the Ansible host
    82      should be placed. When unspecified, the host is not associated with any
    83      groups.
    84  
    85  -   `inventory_file` (string) - The inventory file to use during provisioning.
    86      When unspecified, Packer will create a temporary inventory file and will
    87      use the `host_alias`.
    88  
    89  -   `host_alias` (string) - The alias by which the Ansible host should be known.
    90      Defaults to `default`. This setting is ignored when using a custom inventory
    91      file.
    92  
    93  -   `inventory_directory` (string) - The directory in which to place the
    94      temporary generated Ansible inventory file. By default, this is the
    95      system-specific temporary file location. The fully-qualified name of this
    96      temporary file will be passed to the `-i` argument of the `ansible` command
    97      when this provisioner runs ansible. Specify this if you have an existing
    98      inventory directory with `host_vars` `group_vars` that you would like to use
    99      in the playbook that this provisioner will run.
   100  
   101  -   `local_port` (string) - The port on which to attempt to listen for SSH
   102      connections. This value is a starting point. The provisioner will attempt
   103      listen for SSH connections on the first available of ten ports, starting at
   104      `local_port`. A system-chosen port is used when `local_port` is missing or
   105      empty.
   106  
   107  -   `sftp_command` (string) - The command to run on the machine being provisioned
   108      by Packer to handle the SFTP protocol that Ansible will use to transfer
   109      files. The command should read and write on stdin and stdout, respectively.
   110      Defaults to `/usr/lib/sftp-server -e`.
   111  
   112  -   `skip_version_check` (boolean) - Check if ansible is installed prior to running.
   113      Set this to `true`, for example, if you're going to install ansible during
   114      the packer run.
   115  
   116  -   `ssh_host_key_file` (string) - The SSH key that will be used to run the SSH
   117      server on the host machine to forward commands to the target machine. Ansible
   118      connects to this server and will validate the identity of the server using
   119      the system known\_hosts. The default behavior is to generate and use a
   120      onetime key. Host key checking is disabled via the
   121      `ANSIBLE_HOST_KEY_CHECKING` environment variable if the key is generated.
   122  
   123  -   `ssh_authorized_key_file` (string) - The SSH public key of the Ansible
   124      `ssh_user`. The default behavior is to generate and use a onetime key. If
   125      this key is generated, the corresponding private key is passed to
   126      `ansible-playbook` with the `--private-key` option.
   127  
   128  -   `user` (string) - The `ansible_user` to use. Defaults to the user running
   129      packer.
   130  
   131  ## Default Extra Variables
   132  
   133  In addition to being able to specify extra arguments using the
   134  `extra_arguments` configuration, the provisioner automatically defines certain
   135  commonly useful Ansible variables:
   136  
   137  -   `packer_build_name` is set to the name of the build that Packer is running.
   138      This is most useful when Packer is making multiple builds and you want to
   139      distinguish them slightly when using a common playbook.
   140  
   141  -   `packer_builder_type` is the type of the builder that was used to create the
   142      machine that the script is running on. This is useful if you want to run
   143      only certain parts of the playbook on systems built with certain builders.
   144  
   145  ## Debugging
   146  
   147  To debug underlying issues with Ansible, add `"-vvvv"` to `"extra_arguments"` to enable verbose logging.
   148  
   149  ``` json
   150  {
   151    "extra_arguments": [ "-vvvv" ]
   152  }
   153  ```
   154  
   155  ## Limitations
   156  
   157  ### Redhat / CentOS
   158  
   159  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`:
   160  
   161  ``` text
   162  ==> virtualbox-ovf: starting sftp subsystem
   163      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}
   164  ```
   165  
   166  ### chroot communicator
   167  
   168  Building within a chroot (e.g. `amazon-chroot`) requires changing the Ansible connection to chroot.
   169  
   170  ``` json
   171  {
   172    "builders": [
   173      {
   174        "type": "amazon-chroot",
   175        "mount_path": "/mnt/packer-amazon-chroot",
   176        "region": "us-east-1",
   177        "source_ami": "ami-123456"
   178      }
   179    ],
   180    "provisioners": [
   181      {
   182        "type": "ansible",
   183        "extra_arguments": [
   184          "--connection=chroot",
   185          "--inventory-file=/mnt/packer-amazon-chroot,"
   186        ],
   187        "playbook_file": "main.yml"
   188      }
   189    ]
   190  }
   191  ```
   192  
   193  ### winrm communicator
   194  
   195  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
   196  the connection plugin.  On versions of Ansible before 2.4.x, the following works as the connection plugin
   197  
   198  ``` python
   199  from __future__ import (absolute_import, division, print_function)
   200  __metaclass__ = type
   201  
   202  from ansible.plugins.connection.ssh import Connection as SSHConnection
   203  
   204  class Connection(SSHConnection):
   205      ''' ssh based connections for powershell via packer'''
   206  
   207      transport = 'packer'
   208      has_pipelining = True
   209      become_methods = []
   210      allow_executable = False
   211      module_implementation_preferences = ('.ps1', '')
   212  
   213      def __init__(self, *args, **kwargs):
   214          super(Connection, self).__init__(*args, **kwargs)
   215  ```
   216  
   217  Newer versions of Ansible require all plugins to have a documentation string. You can see if there is a
   218  plugin available for the version of Ansible you are using [here](https://github.com/hashicorp/packer/tree/master/examples/ansible/connection-plugin).
   219  
   220  To create the plugin yourself, you will need to copy all of the `options` from the `DOCUMENTATION` string
   221  from the [ssh.py Ansible connection plugin](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py)
   222  of the Ansible version you are using and add it to a packer.py file similar to as follows
   223  
   224  ``` python
   225  from __future__ import (absolute_import, division, print_function)
   226  __metaclass__ = type
   227  
   228  from ansible.plugins.connection.ssh import Connection as SSHConnection
   229  
   230  DOCUMENTATION = '''
   231      connection: packer
   232      short_description: ssh based connections for powershell via packer
   233      description:
   234          - This connection plugin allows ansible to communicate to the target packer
   235          machines via ssh based connections for powershell.
   236      author: Packer
   237      version_added: na
   238      options:
   239        **** Copy ALL the options from
   240        https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py
   241        for the version of Ansible you are using ****
   242  '''
   243  
   244  class Connection(SSHConnection):
   245      ''' ssh based connections for powershell via packer'''
   246  
   247      transport = 'packer'
   248      has_pipelining = True
   249      become_methods = []
   250      allow_executable = False
   251      module_implementation_preferences = ('.ps1', '')
   252  
   253      def __init__(self, *args, **kwargs):
   254          super(Connection, self).__init__(*args, **kwargs)
   255  ```
   256  
   257  This template should build a Windows Server 2012 image on Google Cloud Platform:
   258  
   259  ``` json
   260  {
   261    "variables": {},
   262    "provisioners": [
   263      {
   264        "type":  "ansible",
   265        "playbook_file": "./win-playbook.yml",
   266        "extra_arguments": [
   267          "--connection", "packer",
   268          "--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None"
   269        ]
   270      }
   271    ],
   272    "builders": [
   273      {
   274        "type": "googlecompute",
   275        "account_file": "{{user `account_file`}}",
   276        "project_id": "{{user `project_id`}}",
   277        "source_image": "windows-server-2012-r2-dc-v20160916",
   278        "communicator": "winrm",
   279        "zone": "us-central1-a",
   280        "disk_size": 50,
   281        "winrm_username": "packer",
   282        "winrm_use_ssl": true,
   283        "winrm_insecure": true,
   284        "metadata": {
   285          "sysprep-specialize-script-cmd": "winrm set winrm/config/service/auth @{Basic=\"true\"}"
   286        }
   287      }
   288    ]
   289  }
   290  ```
   291  
   292  ### Too many SSH keys
   293  
   294  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:
   295  
   296  ```console
   297      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}
   298  ```
   299  
   300  To unload all keys from your `ssh-agent`, run:
   301  
   302  ```console
   303  $ ssh-add -D
   304  ```
   305  
   306  ### Become: yes
   307  
   308  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.