├── hosts ├── groups.yml └── README.md /hosts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # ToDo: 4 | # * read in children groups from the yaml file as well. 5 | 6 | import requests 7 | import sys 8 | import json 9 | import yaml 10 | 11 | username = 'user' 12 | password = 'password' 13 | foreman_url = "https://your.foreman.server.com/hosts" 14 | 15 | # Read in the yaml groups file 16 | f = open('groups.yml') 17 | groups = yaml.safe_load(f) 18 | f.close() 19 | 20 | # Create a new http session with the following auth details and disabling ssl verification. 21 | s = requests.Session() 22 | s.auth = (username, password) 23 | s.verify = False 24 | 25 | # To test and see a url 26 | #print s.url 27 | 28 | def get_hosts(hostfilter): 29 | payload = {'search': hostfilter + ' ', 'format': 'json', } 30 | r = s.get(foreman_url, params=payload) 31 | return r.json() 32 | 33 | if len(sys.argv) == 2 and (sys.argv[1] == '--list'): 34 | 35 | # Create an empty dict to hold the results 36 | data = {} 37 | 38 | # Search for each of the group/filters 39 | for groupname, groupinfo in groups.iteritems(): 40 | hosts = get_hosts(groupinfo['hostfilter']) 41 | data[groupname] = {'hosts': hosts} 42 | if "vars" in groupinfo: 43 | data[groupname].update({'vars': groupinfo['vars']}) 44 | 45 | print json.dumps(data, indent=2) 46 | 47 | sys.exit(0) 48 | 49 | elif len(sys.argv) == 3 and (sys.argv[1] == '--host'): 50 | 51 | hostname = sys.argv[2] 52 | payload = {'format': 'json'} 53 | r = s.get(foreman_url + "/" + hostname + "/" + "facts", params=payload) 54 | facts = r.json() 55 | print json.dumps(facts[hostname], indent=2) 56 | 57 | sys.exit(0) 58 | 59 | else: 60 | print "usage: --list ..OR.. --host " 61 | sys.exit(1) 62 | -------------------------------------------------------------------------------- /groups.yml: -------------------------------------------------------------------------------- 1 | rhel_dev: 2 | hostfilter: 'facts.osfamily = RedHat and last_report > "6 hours ago" and environment = development' 3 | rhel_test: 4 | hostfilter: 'facts.osfamily = RedHat and last_report > "6 hours ago" and environment = testing' 5 | rhel: 6 | hostfilter: 'facts.osfamily = RedHat and last_report > "6 hours ago"' 7 | rhel5: 8 | hostfilter: 'facts.lsbmajdistrelease = 5 and facts.osfamily = RedHat and last_report > "6 hours ago"' 9 | rhel6: 10 | hostfilter: 'facts.lsbmajdistrelease = 6 and facts.osfamily = RedHat and last_report > "6 hours ago"' 11 | vmware: 12 | hostfilter: 'facts.virtual = vmware and last_report > "6 hours ago"' 13 | solaris: 14 | hostfilter: 'facts.osfamily = Solaris and last_report > "6 hours ago"' 15 | vars: 16 | ansible_python_interpreter: /opt/csw/bin/python 17 | solaris_test: 18 | hostfilter: 'facts.osfamily = Solaris and last_report > "6 hours ago" and environment = testing' 19 | vars: 20 | ansible_python_interpreter: /opt/csw/bin/python 21 | solaris_dev: 22 | hostfilter: 'facts.osfamily = Solaris and last_report > "6 hours ago" and environment = development' 23 | vars: 24 | ansible_python_interpreter: /opt/csw/bin/python 25 | solaris10: 26 | hostfilter: 'facts.operatingsystemrelease = 5.10 and facts.osfamily = Solaris and last_report > "6 hours ago"' 27 | vars: 28 | ansible_python_interpreter: /opt/csw/bin/python 29 | solaris9: 30 | hostfilter: 'facts.operatingsystemrelease = 5.9 and facts.osfamily = Solaris and last_report > "6 hours ago"' 31 | vars: 32 | ansible_python_interpreter: /opt/csw/bin/python 33 | zones: 34 | hostfilter: 'facts.virtual = zone and last_report > "6 hours ago"' 35 | vars: 36 | ansible_python_interpreter: /opt/csw/bin/python 37 | globalzones: 38 | hostfilter: 'facts.is_virtual = false and facts.operatingsystemrelease = 5.10 and facts.operatingsystem = Solaris and last_report > "6 hours ago"' 39 | vars: 40 | ansible_python_interpreter: /opt/csw/bin/python 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | foreman-ansible 2 | =============== 3 | 4 | An Ansible ENC (external node classifier) to get, group and classify nodes based on the Puppet facts in The Foreman. 5 | 6 | This project is for you if you use Foreman (http://theforeman.org/) and Puppet (https://puppetlabs.com) to handle your configuration management (and possibly provisioning) and you want to make use of the the Puppet facts in Foreman to drive the excellent config management/deployment/orchestration tool Ansible (http://ansible.cc/). 7 | 8 | How it works 9 | ============ 10 | 11 | The Foreman provides an excellent api which allows you get lists of nodes based on certain "facts" about the nodes. We make use of this, and Ansible's ability to drop in new ENC's, to get lists of nodes based on specified criteria. This allows us to group and classify your nodes based on any puppet fact. 12 | 13 | In foreman-ansible we handle the grouping of nodes in a simple groups.yml YAML file. To group your nodes in another way, simply add another stanza in the groups.yml for the grouping you'd like. I've included a sample groups.yml file. 14 | 15 | How you use it 16 | ============== 17 | 18 | - Install the requests python library (http://docs.python-requests.org/en/latest/) 19 | 20 | pip install requests 21 | 22 | - Clone the repo: 23 | 24 | git clone https://github.com/romeotheriault/foreman-ansible.git 25 | 26 | - Make the script executable: 27 | 28 | chmod +x hosts 29 | 30 | - Edit 'hosts' and change the url variable to point to your foreman instance, and input a valid username and password 31 | - Edit 'groups.yml' and change any of the groupnames and search queries to suit your needs 32 | - Test it out: 33 | 34 | ./hosts --list 35 | ./hosts --host 36 | 37 | - Point ansible at it: 38 | 39 | ansible -m ping -i /path/to/hosts/file 40 | 41 | - Or move hosts and groups.yml file into /etc/ansible/ and ansible will use it as the default. 42 | 43 | 44 | Still to do 45 | =========== 46 | 47 | - Make code more robust 48 | - Add the ability to return children groups 49 | - Probably more 50 | 51 | Pull requests welcome if others find this useful. 52 | --------------------------------------------------------------------------------