Posted by: terryhowe | May 4, 2016

Ansible Vault Vars and Files

I’ve been talking a lot about Hashicorp Vault lately, but there is also regular old Ansible Vault.  Two of my favorite ways to use Ansible Vault are with include_vars and the file lookup.  With include_vars, you just need to encrypt your entire variables file:

ansible-vault encrypt roles/jenkins/vars/credentials.yml

The variables can be included in your task with no special decryption action:

- include_vars: "credentials.yml"

Similarly, the file lookup plugin automatically decrypts files completely. So, encrypt your certificate:

ansible-vault encrypt roles/project/files/ssl.cert

Use the file lookup plugin to decrypt it and upload it:

- copy: content="{{ lookup('file', 'ssl.cert') }}" dest=/project/config/ssl.cert mode=0400

Posted by: terryhowe | May 3, 2016

Ansible 2.0 Modules and Action Plugins

I posted yesterday about Action Plugins for Ansible 2.0 and I’d like to expand on that a little with the associated sample Ansible 2.0 module.  Modules live in the library directory and action plugins in action_plugin.  Here is my sample super simple action plugin:


from ansible.plugins.action import ActionBase


class ActionModule(ActionBase):

    def run(self, tmp=None, task_vars=None):

        if task_vars is None:
            task_vars = dict()
        result = super(ActionModule, self).run(tmp, task_vars)
        args = self._task.args.copy()
        if 'name' not in args:
            args['name'] = 'Pete'
        result.update(self._execute_module(module_args=args, task_vars=task_vars))

All this action plugin does is default the name to Pete if it is not set. Now the associated module:


#!/usr/bin/env python
DOCUMENTATION = '''
---
module: hello
version_added: "0.1"
short_description: Hello module
description:
    - Module to say hello.
options:
    name:
        description:
            - Name to greet.
        default: False
'''
EXAMPLES = '''
- action: hello name='bob'
'''


def main():
    argument_spec = dict(
        name = dict(required=True, type='str'),
    )
    module = AnsibleModule(argument_spec=argument_spec)
    result = { "changed": False, "rc" : 0}
    name = module.params.get('name')
    if name:
        result['msg'] = "Hello %s!" % name
    else:
        result['failed'] = True
        result['msg'] = "Empty name is invalid"
    if result.get('failed'):
        module.fail_json(**result)
    else:
        module.exit_json(**result)


from ansible.module_utils.basic import *
from ansible.module_utils.hashivault import *

if __name__ == '__main__':
    main()

This module returns a message “Hello %(name)s”. If the name is empty, it fails. Here is a sample playbook to run the action plugin and module:


---
- hosts: localhost
  tasks:
    - hello:
    - hello: name='bob'
    - hello: name=''

When this playbook is run, the results look like:


$ ansible-playbook -v -i dev-admin-nce test.yml 
Using /etc/ansible/ansible.cfg as config file

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [hello] *******************************************************************
ok: [localhost] => {"changed": false, "msg": "Hello Pete!", "rc": 0}

TASK [hello] *******************************************************************
ok: [localhost] => {"changed": false, "msg": "Hello bob!", "rc": 0}

TASK [hello] *******************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "Empty name is invalid", "rc": 0}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=1   

$

Posted by: terryhowe | May 2, 2016

Hashicorp Vault Ansible Module

I created a Ansible module for Hashicorp Vault.  The Module is generic and does just simple reads and writes to secrets.  It supports token, userpass, github and ldap authentication.  For the backend, it uses the hvac sdk package.

Ansible Hashicorp Vault Module

No doubt, there is something there that could be better, so throw out a pull request.  The git repository can be found here.

Posted by: terryhowe | May 2, 2016

Setting Ansible Module Defaults Using Action Plugins

In my last blog entry, I gave a simple example of an action plugin that calls a module.  To take that a bit further, here is an action plugin that sets some default value.  This can be handy if you are using a module and want to set some default values for that module that are specific to your application.

from ansible.plugins.action import ActionBase


class ActionModule(ActionBase):

    def run(self, tmp=None, task_vars=None):

        if task_vars is None:
            task_vars = dict()
        result = super(ActionModule, self).run(tmp, task_vars)
        args = self._task.args.copy()
        if 'authtype' not in args:
            args['authtype'] = 'userpass'
        if 'url' not in args:
            args['url'] = self._templar.template('https://vault.{{domain}}:8200')
        if 'username' not in args:
            args['username'] = self._templar.template('{{vault_username}}')
        if 'password' not in args:
            args['password'] = self._templar.template('{{vault_password}}')
        result.update(self._execute_module(module_args=args, task_vars=task_vars))
        self._task.register = args['register']
        return result

There are a couple things going on here. We are setting authtype to to userpass. We are also using the templar to set some arguments based on our variables.

The other thing going on here is we are changing the output after the module is called. Setting self._task.register will put the result back into the specified Ansible variable.

Posted by: terryhowe | May 2, 2016

Ansible 2.0 Action Plugins

Ansible action plugins are by far the most arcane plugins.  Finding documentation on 1.x plugins is hard enough to find and 2.0 is even more difficult.  When I tried to write my first 2.x action plugin, I got:


Unexpected Exception: No module named runner.return_data

A sample Ansible 2.0 action plugin does not use the runner return_data, it derives off ActionBase:


from ansible.plugins.action import ActionBase


class ActionModule(ActionBase):

    def run(self, tmp=None, task_vars=None):

        if task_vars is None:
            task_vars = dict()
        result = super(ActionModule, self).run(tmp, task_vars)
        result['msg'] = 'woot'
        return result

Posted by: terryhowe | March 23, 2016

Git Removing stale local brances with git prune

I’m always forgetting how to prune the local branches that have been removed from the remote.  Simple thing, but it isn’t sticking in the brain. Anyway, often when i write about something, I remember it.

git fetch; git remote prune origin

Posted by: terryhowe | March 23, 2016

Chrome DYLD shared region unnest error

I was getting a lot of message in /var/log/system.log like:

Mar 23 12:05:50 THowe-MBPro kernel[0]: Google Chrome He (map: 0xffffff803d2d8a50) triggered DYLD shared region unnest for map: 0xffffff803d2d8a50, region 0x7fff8d600000->0x7fff8d800000. While not abnormal for debuggers, this increases system memory footprint until the target exits.

It isn’t really a solution, but to stop the constant logging, you can do this:

sudo sysctl -w vm.shared_region_unnest_logging=0

Create key:

gpg --gen-key



List your key:

gpg --list-keys
pub 2048R/31F9D13A 2015-09-15
uid Terry Howe <terry@example.com>
sub 2048R/F5D49C12 2015-09-15



Configure your key:

git config --global user.signingkey 31F9D13A


Tag your release:

git tag -s 1.2.1


Push to gerrit

git push gerrit 1.2.1
Posted by: terryhowe | March 14, 2015

Regular Git Pull Requests

I’ve been doing so much OpenStack work lately, I’d forgotten how to do regular old git pull requests from a fork.  A little refresher, add the upstream repo:

git remote add upstream git@github.com:remoteowner:Repo.git

Verify it is there:

git remote -v

Update local information:

git remote update

And now you can see the upstream branches:

git branch -a

Update the local branch to upstream:

git reset --hard upstream/master

Push the upstream to fork ignoring the fact that it won’t be a fast forward:

git push origin +master

Posted by: terryhowe | March 4, 2015

tox pypy No module named gdbm

I don’t know how many times I’ve seen the error from pypy tests “No module named gdbm”.  The cause of this is an incompatibility in the .testrepository.  The solutions are either run the pypy tests first or remove the .testrepository, run the pypy tests, and then run all the tests.

Older Posts »

Categories

Follow

Get every new post delivered to your Inbox.