#! /usr/bin/python
#
# Create Webfaction website using Ansible and the Webfaction API
#
# ------------------------------------------
#
# (c) Quentin Stafford-Fraser 2015
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
DOCUMENTATION = '''
- - -
module : webfaction_site
short_description : Add or remove a website on a Webfaction host
description :
- Add or remove a website on a Webfaction host . Further documentation at http : / / github . com / quentinsf / ansible - webfaction .
author : Quentin Stafford - Fraser ( @quentinsf )
version_added : " 2.0 "
notes :
- Sadly , you I ( do ) need to know your webfaction hostname for the C ( host ) parameter . But at least , unlike the API , you don ' t need to know the IP address - you can use a DNS name.
- If a site of the same name exists in the account but on a different host , the operation will exit .
- " You can run playbooks that use this on a local machine, or on a Webfaction host, or elsewhere, since the scripts use the remote webfaction API - the location is not important. However, running them on multiple hosts I(simultaneously) is best avoided. If you don ' t specify I(localhost) as your host, you may want to add C(serial: 1) to the plays. "
- See ` the webfaction API < http : / / docs . webfaction . com / xmlrpc - api / > ` _ for more info .
options :
name :
description :
- The name of the website
required : true
state :
description :
- Whether the website should exist
required : false
choices : [ ' present ' , ' absent ' ]
default : " present "
host :
description :
- The webfaction host on which the site should be created .
required : true
https :
description :
- Whether or not to use HTTPS
required : false
choices : BOOLEANS
default : ' false '
site_apps :
description :
- A mapping of URLs to apps
required : false
subdomains :
description :
- A list of subdomains associated with this site .
required : false
default : null
login_name :
description :
- The webfaction account to use
required : true
login_password :
description :
- The webfaction password to use
required : true
'''
EXAMPLES = '''
- name : create website
webfaction_site :
name : testsite1
state : present
host : myhost . webfaction . com
subdomains :
- ' testsite1.my_domain.org '
site_apps :
- [ ' testapp1 ' , ' / ' ]
https : no
login_name : " {{ webfaction_user}} "
login_password : " {{ webfaction_passwd}} "
'''
import socket
import xmlrpclib
webfaction = xmlrpclib . ServerProxy ( ' https://api.webfaction.com/ ' )
def main ( ) :
module = AnsibleModule (
argument_spec = dict (
name = dict ( required = True ) ,
state = dict ( required = False , choices = [ ' present ' , ' absent ' ] , default = ' present ' ) ,
# You can specify an IP address or hostname.
host = dict ( required = True ) ,
https = dict ( required = False , choices = BOOLEANS , default = False ) ,
subdomains = dict ( required = False , default = [ ] ) ,
site_apps = dict ( required = False , default = [ ] ) ,
login_name = dict ( required = True ) ,
login_password = dict ( required = True ) ,
) ,
supports_check_mode = True
)
site_name = module . params [ ' name ' ]
site_state = module . params [ ' state ' ]
site_host = module . params [ ' host ' ]
site_ip = socket . gethostbyname ( site_host )
session_id , account = webfaction . login (
module . params [ ' login_name ' ] ,
module . params [ ' login_password ' ]
)
site_list = webfaction . list_websites ( session_id )
site_map = dict ( [ ( i [ ' name ' ] , i ) for i in site_list ] )
existing_site = site_map . get ( site_name )
result = { }
# Here's where the real stuff happens
if site_state == ' present ' :
# Does a site with this name already exist?
if existing_site :
# If yes, but it's on a different IP address, then fail.
# If we wanted to allow relocation, we could add a 'relocate=true' option
# which would get the existing IP address, delete the site there, and create it
# at the new address. A bit dangerous, perhaps, so for now we'll require manual
# deletion if it's on another host.
if existing_site [ ' ip ' ] != site_ip :
module . fail_json ( msg = " Website already exists with a different IP address. Please fix by hand. " )
# If it's on this host and the key parameters are the same, nothing needs to be done.
if ( existing_site [ ' https ' ] == module . boolean ( module . params [ ' https ' ] ) ) and \
( set ( existing_site [ ' subdomains ' ] ) == set ( module . params [ ' subdomains ' ] ) ) and \
( dict ( existing_site [ ' website_apps ' ] ) == dict ( module . params [ ' site_apps ' ] ) ) :
module . exit_json (
changed = False
)
positional_args = [
session_id , site_name , site_ip ,
module . boolean ( module . params [ ' https ' ] ) ,
module . params [ ' subdomains ' ] ,
]
for a in module . params [ ' site_apps ' ] :
positional_args . append ( ( a [ 0 ] , a [ 1 ] ) )
if not module . check_mode :
# If this isn't a dry run, create or modify the site
result . update (
webfaction . create_website (
* positional_args
) if not existing_site else webfaction . update_website (
* positional_args
)
)
elif site_state == ' absent ' :
# If the site's already not there, nothing changed.
if not existing_site :
module . exit_json (
changed = False ,
)
if not module . check_mode :
# If this isn't a dry run, delete the site
result . update (
webfaction . delete_website ( session_id , site_name , site_ip )
)
else :
module . fail_json ( msg = " Unknown state specified: {} " . format ( site_state ) )
module . exit_json (
changed = True ,
result = result
)
from ansible . module_utils . basic import *
main ( )