Skip to content

Commit

Permalink
Merge branch 'release/0.5.1'
Browse files Browse the repository at this point in the history
Signed-off-by: Takuya Sawada <[email protected]>
  • Loading branch information
eternalharvest committed Apr 17, 2015
2 parents e63c059 + 5d67c0d commit 9df1f36
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ insert_final_newline = true
trim_trailling_whitespace = true
charset = utf-8

[r53update]
[*.py]
indent_style = tab
indent_size = 2
39 changes: 30 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
R53Update is a command line utility for Amazon Route 53 which is one of the AWS (Amazon Web Services). This tools is useful to anyone who wants to operate server with dynamic IP. You can operate not only the server which is hosted on Amazon EC2 but also on-premise servers.


[![GitHub version](https://badge.fury.io/gh/eternalharvest%2Fr53update.svg)]() [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)]()
[![GitHub version](https://badge.fury.io/gh/tuntunkun%2Fr53update.svg)]() [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)]()


## Requirements
Expand All @@ -12,35 +12,56 @@ R53Update is a command line utility for Amazon Route 53 which is one of the AWS
* pre-configured Amazon Route53 hosted zone
* python2.6+ and pip command

### Amazon Route 53 hosted zone
To create Amazon Route 53 hosted zone, please refer to the following url.
http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingHostedZone.html

To install python and pip command,
### Python & PIP
If you want to install python and pip via binary installer, you can generally do so through the basic package-management tool that comes with your distribution.
If you're on Debian-based distribution, you can use apt-get:
```bash
sudo apt-get install python{,-pip} build-essentials
sudo apt-get install python{,-dev,-pip} build-essentials
```

or
If you're on a Redhat-based distribution like Fedora, CentOS, etc... try yum:
```bash
sudo yum -y groupinstall "Development Tools"
sudo yum -y install python{,-pip}
sudo yum -y install python{,-devel,-pip}
```


## Install

```bash
git clone https://github.com/eternalharvest/r53update && cd r53update
sudo pip install -r requirements.txt
sudo cp r53update /usr/local/bin
sudo -H pip install git+https://github.com/tuntunkun/r53update
```

## Usage

If you have already configured AWS profile and Route 53 hosted zone, it is very simple to use.
```bash
r53update www example.com
```

### Configurable Variable

| Variable | Option | Default | Description |
|-----------|------------|------------|---------------------------------------------|
| PROFILE | --profile | default | profile name which is configured by aws-cli |
| METHOD | --method | localhost | detection method of global IP |
| IFACE | --iface | n/a | name of the network interface |

### The method of global IP detection
You can specify the method of global IP detection by '--method' option.
Available method is as follows.

| Method Name | Method | Multiple IP | Description |
|---------------|--------|---------------|----------------------------------------|
| opendns.com | DNS | not supported | |
| ifconfig.me | HTTP | not supported | |
| ipecho.net | HTTP | not supported | |
| icanhazip.com | HTTP | not supported | |
| localhost | NIC | supported | require '--iface' option |

## License
(C)2015 Takuya Sawada.

Expand Down
2 changes: 1 addition & 1 deletion bash_completion.d/r53update
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/bash
#
# R53Update Dynamic DNS Updater v0.5.0
# R53Update Dynamic DNS Updater
# (C)2014 Takuya Sawada All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
3 changes: 3 additions & 0 deletions r53update/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__all__ = ['main']

from r53update import main
61 changes: 33 additions & 28 deletions r53update → r53update/r53update.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# R53Update Dynamic DNS Updater v0.5.0
# R53Update Dynamic DNS Updater
# (C)2014 Takuya Sawada All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -19,6 +19,7 @@
from boto.route53.connection import Route53Connection
from boto.route53.record import ResourceRecordSets
from botocore.session import Session
from pkg_resources import get_distribution

import sys
import argparse
Expand Down Expand Up @@ -144,34 +145,34 @@ def __init__(self, parent):
def __call__(self, prefix, **kwargs):
return (x for x in netifaces.interfaces() if x.startswith(prefix))

# Resolver Completer
class ResolverCompleter(object):
# Method Completer
class MethodCompleter(object):
def __init__(self, parent):
self.__parent = parent

def __call__(self, prefix, **kwargs):
return (x for x in self.__parent._gipresolvers if x.startswith(prefix))
return (x for x in self.__parent._gipmethods if x.startswith(prefix))

##
# Global IP Resolver
class GlobalIP_Resolver(object):
# Global IP Detection Method
class GlobalIP_DetectionMethod(object):
def __init__(self, app):
self._app = app

def resolveGlobalIP():
raise NotImplementedError()

class HTTP_GlobalIP_Resolver(GlobalIP_Resolver):
class HTTP_GlobalIP_DetectionMethod(GlobalIP_DetectionMethod):
def __init__(self, app, url):
super(R53UpdateApp.HTTP_GlobalIP_Resolver, self).__init__(app)
super(R53UpdateApp.HTTP_GlobalIP_DetectionMethod, self).__init__(app)
self._url = url

def resolveGlobalIP(self):
return urllib2.urlopen(self._url).read().rstrip()

class DNS_GlobalIP_Resolver(GlobalIP_Resolver):
class DNS_GlobalIP_DetectionMethod(GlobalIP_DetectionMethod):
def __init__(self, app, hostname, resolvername):
super(R53UpdateApp.DNS_GlobalIP_Resolver, self).__init__(app)
super(R53UpdateApp.DNS_GlobalIP_DetectionMethod, self).__init__(app)
self._hostname = hostname
self._resolvername = resolvername

Expand All @@ -180,9 +181,9 @@ def resolveGlobalIP(self, ns=False):
resolver.nameservers = self._app._opts.dns if ns else self.resolveGlobalIP(True)
return map(lambda x: x.to_text(), resolver.query(self._resolvername if ns else self._hostname, 'A'))

class NETIFACES_GlobalIP_Resolver(GlobalIP_Resolver):
class NETIFACES_GlobalIP_DetectionMethod(GlobalIP_DetectionMethod):
def __init__(self, app):
super(R53UpdateApp.NETIFACES_GlobalIP_Resolver, self).__init__(app)
super(R53UpdateApp.NETIFACES_GlobalIP_DetectionMethod, self).__init__(app)

def resolveGlobalIP(self):
try:
Expand All @@ -209,20 +210,20 @@ def _pre_init(self):
self.logger.addHandler(handler)

# create mapping of global ip resolvers
self._gipresolvers = dict()
self._gipresolvers['ifconfig.me'] = R53UpdateApp.HTTP_GlobalIP_Resolver(self, 'http://ifconfig.me/ip')
self._gipresolvers['ipecho.net'] = R53UpdateApp.HTTP_GlobalIP_Resolver(self, 'http://ipecho.net/plain')
self._gipresolvers['icanhazip.com'] = R53UpdateApp.HTTP_GlobalIP_Resolver(self, 'http://icanhazip.com')
self._gipresolvers['opendns.com'] = R53UpdateApp.DNS_GlobalIP_Resolver(self, 'myip.opendns.com', 'resolver1.opendns.com')
self._gipresolvers['localhost'] = R53UpdateApp.NETIFACES_GlobalIP_Resolver(self)
self._gipmethods = dict()
self._gipmethods['ifconfig.me'] = R53UpdateApp.HTTP_GlobalIP_DetectionMethod(self, 'http://ifconfig.me/ip')
self._gipmethods['ipecho.net'] = R53UpdateApp.HTTP_GlobalIP_DetectionMethod(self, 'http://ipecho.net/plain')
self._gipmethods['icanhazip.com'] = R53UpdateApp.HTTP_GlobalIP_DetectionMethod(self, 'http://icanhazip.com')
self._gipmethods['opendns.com'] = R53UpdateApp.DNS_GlobalIP_DetectionMethod(self, 'myip.opendns.com', 'resolver1.opendns.com')
self._gipmethods['localhost'] = R53UpdateApp.NETIFACES_GlobalIP_DetectionMethod(self)

# optional argument
self._parser.add_argument('--profile', type=str, metavar='PROFILE', default='',
help='プロファイル名').completer = R53UpdateApp.ProfileCompleter(self)
self._parser.add_argument('--resolver', type=str, metavar='RESOLVER',
default='opendns.com', help='グローバルIP 取得方法').completer = R53UpdateApp.ResolverCompleter(self)
help='name of a profile to use, or "default" to use the default profile').completer = R53UpdateApp.ProfileCompleter(self)
self._parser.add_argument('--method', type=str, metavar='METHOD',
default='opendns.com', help='detection method of global IP').completer = R53UpdateApp.MethodCompleter(self)
self._parser.add_argument('--iface', type=str, metavar='IFACE',
help='インターフェイス名').completer = R53UpdateApp.NetifacesCompleter(self)
help='name of network interface').completer = R53UpdateApp.NetifacesCompleter(self)
self._parser.add_argument('--dns', nargs='+', type=str, metavar='DNS',
default=['8.8.8.8', '8.8.4.4'], help='default: 8.8.8.8, 8.8.4.4')
self._parser.add_argument('--ttl', type=int, metavar='TTL',
Expand All @@ -249,17 +250,17 @@ def _post_init(self, opts):
if opts.debug:
self.logger.setLevel(logging.DEBUG)

if opts.resolver == 'localhost' and not opts.iface:
if opts.method == 'localhost' and not opts.iface:
raise Exception("you must specify network interface with '--iface' option")

if opts.iface:
if opts.iface not in netifaces.interfaces():
raise Exception("interface name '%s' not found" % opts.iface)
self._opts.resolver = 'localhost'
self._opts.method = 'localhost'

def __get_global_ip(self):
self.logger.debug('resolving global ip adreess with \'%s\'', self._opts.resolver)
gips = self._gipresolvers[self._opts.resolver].resolveGlobalIP()
self.logger.debug('resolving global ip adreess with \'%s\'', self._opts.method)
gips = self._gipmethods[self._opts.method].resolveGlobalIP()
return gips if type(gips) is list else [gips]

def __get_records_from_host(self, fqdn):
Expand Down Expand Up @@ -326,12 +327,16 @@ def _run(self):

def show_version(self):
print >>sys.stderr, "Copyrights (c)2014 Takuya Sawada All rights reserved."
print >>sys.stderr, "Route53Update Dynamic DNS Updater 0.5.0"
print >>sys.stderr, "Route53Update Dynamic DNS Updater v%s" % get_distribution("r53update").version


if __name__ == '__main__':

def main():
try:
R53UpdateApp(sys.argv)()
except Exception, e:
print >>sys.stderr, "%s" % e
sys.exit(1)

if __name__ == '__main__':
main()
6 changes: 0 additions & 6 deletions requirements.txt

This file was deleted.

52 changes: 52 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# R53Update Dynamic DNS Updater
# (C)2014 Takuya Sawada All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# See the License for the specific language governing permissions and
# limitations under the License.
#
from setuptools import setup

setup(
name = 'r53update',
version='0.5.1',
description='R53Update Dynamic DNS Updater',
author='Takuya Sawada',
author_email='[email protected]',
url='https://github.com/tuntunkun/r53updaten',
license='Apache License 2.0',
packages = ['r53update'],
install_requires = [
'argparse==1.3.0',
'boto==2.36.0',
'awscli==1.7.15',
'dnspython==1.12.0',
'netifaces==0.10.4'
],
classifiers = [
'Development Status :: 4 - Beta',
'Environment :: Console',
'Operating System :: POSIX',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Topic :: System :: Networking',
'Topic :: Utilities'
],
entry_points = {
'console_scripts': [
'r53update=r53update:main'
]
}
)

0 comments on commit 9df1f36

Please sign in to comment.