Compare commits
No commits in common. "4626ec797d78e18fc68e3de5eef6ac237b9ad5ac" and "6dd44dfe8775e1de73efc717dad172a0470a30d5" have entirely different histories.
4626ec797d
...
6dd44dfe87
113
README.md
113
README.md
@ -27,118 +27,7 @@ collections:
|
|||||||
|
|
||||||
## Using this collection
|
## Using this collection
|
||||||
|
|
||||||
### Deploy happyDomain
|
TODO
|
||||||
|
|
||||||
To setup happyDomain as a local service (support Docker, openrc and systemd), use the role `happydns.happydomain.happydomain`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
roles:
|
|
||||||
- name: happydns.happydomain.happydomain
|
|
||||||
use_container: no # yes if you want to use Docker instead
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create a user account on your happyDomain instance
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tasks:
|
|
||||||
- happydns.happydomain.user:
|
|
||||||
username: frederic@happydomain.org
|
|
||||||
password: "mySuperS3cur3P4$$w0rd"
|
|
||||||
```
|
|
||||||
|
|
||||||
This will create and enabled the user (no need to validate the email).
|
|
||||||
|
|
||||||
|
|
||||||
### Register a NS provider
|
|
||||||
|
|
||||||
Eg. for an AXFR/DDNS provider:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tasks:
|
|
||||||
- happydns.happydomain.provider:
|
|
||||||
name: test
|
|
||||||
type: DDNSServer
|
|
||||||
data:
|
|
||||||
server: 192.168.0.42
|
|
||||||
keyname: ddns
|
|
||||||
algorithm: hmac-sha256
|
|
||||||
keyblob: yourBASE64Secret==
|
|
||||||
happydomain_username: frederic@happydomain.org
|
|
||||||
happydomain_password: "mySuperS3cur3P4$$w0rd"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Handle a new domain name in happyDomain
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tasks:
|
|
||||||
- happydns.happydomain.domain:
|
|
||||||
provider: test
|
|
||||||
domain: happydomain.tf
|
|
||||||
happydomain_username: frederic@happydomain.org
|
|
||||||
happydomain_password: "mySuperS3cur3P4$$w0rd"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create a new record for a domain
|
|
||||||
|
|
||||||
First, you need a zoneid:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tasks:
|
|
||||||
- happydns.happydomain.domain:
|
|
||||||
provider: test
|
|
||||||
domain: happydomain.tf
|
|
||||||
happydomain_username: frederic@happydomain.org
|
|
||||||
happydomain_password: "mySuperS3cur3P4$$w0rd"
|
|
||||||
register: my_zone
|
|
||||||
```
|
|
||||||
|
|
||||||
Note the `register`ed variable.
|
|
||||||
|
|
||||||
Then, use the `happydns.happydomain.service` module:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tasks:
|
|
||||||
- happydns.happydomain.service:
|
|
||||||
happydomain_username: frederic@happydomain.org
|
|
||||||
happydomain_password: "mySuperS3cur3P4$$w0rd"
|
|
||||||
domain: happydomain.tf
|
|
||||||
zone: "{{ my_zone.current_zone }}"
|
|
||||||
subdomain: "test"
|
|
||||||
type: abstract.Server
|
|
||||||
service:
|
|
||||||
A: 127.0.0.1
|
|
||||||
AAAA: "::1"
|
|
||||||
apply_changes: yes
|
|
||||||
```
|
|
||||||
|
|
||||||
This will add two records under `test.happydomain.tf`: A and AAAA (part of `abstract.Server`).
|
|
||||||
|
|
||||||
|
|
||||||
### Remove a given record
|
|
||||||
|
|
||||||
You'll also need a zoneid, see previous section. Then:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
tasks:
|
|
||||||
- happydns.happydomain.service:
|
|
||||||
happydomain_username: frederic@happydomain.org
|
|
||||||
happydomain_password: "mySuperS3cur3P4$$w0rd"
|
|
||||||
domain: happydomain.tf
|
|
||||||
zone: "{{ my_zone.current_zone }}"
|
|
||||||
subdomain: "test"
|
|
||||||
type: scvs.TXT
|
|
||||||
service:
|
|
||||||
content: "This is a test record"
|
|
||||||
state: absent
|
|
||||||
apply_changes: yes
|
|
||||||
```
|
|
||||||
|
|
||||||
This will remove all records matching:
|
|
||||||
|
|
||||||
```
|
|
||||||
test IN TXT "This is a test record"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
namespace: happydns
|
namespace: happydns
|
||||||
name: happydomain
|
name: happydomain
|
||||||
version: 0.3.0
|
version: 0.2.3
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- happyDomain Team <happydomain.org>
|
- happyDomain Team <happydomain.org>
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
---
|
|
||||||
'''
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
|
|
||||||
from happydomain.api import HappyDomain
|
|
||||||
|
|
||||||
def main():
|
|
||||||
module = AnsibleModule(
|
|
||||||
argument_spec=dict(
|
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
|
||||||
happydomain_username=dict(type='str', aliases=['email']),
|
|
||||||
happydomain_password=dict(type='str', aliases=['passwd'], no_log=True),
|
|
||||||
happydomain_token=dict(type='str'),
|
|
||||||
happydomain_scheme=dict(type='str', default='http'),
|
|
||||||
happydomain_host=dict(type='str', default='localhost'),
|
|
||||||
happydomain_port=dict(type='int', default='8081'),
|
|
||||||
happydomain_baseurl=dict(type='str', default=''),
|
|
||||||
provider=dict(type='str'),
|
|
||||||
domain=dict(type='str', aliases=['name']),
|
|
||||||
import_zone=dict(type='bool', default=False),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
p = module.params
|
|
||||||
result = {
|
|
||||||
"changed": False
|
|
||||||
}
|
|
||||||
found = False
|
|
||||||
|
|
||||||
a = HappyDomain(
|
|
||||||
scheme=p['happydomain_scheme'],
|
|
||||||
host=p['happydomain_host'],
|
|
||||||
port=p['happydomain_port'],
|
|
||||||
baseurl=p['happydomain_baseurl'],
|
|
||||||
token=p['happydomain_token'],
|
|
||||||
)
|
|
||||||
|
|
||||||
if p['happydomain_password'] is not None:
|
|
||||||
a.login(p['happydomain_username'], p['happydomain_password'])
|
|
||||||
|
|
||||||
domains = a.domain_list()
|
|
||||||
|
|
||||||
for d in domains:
|
|
||||||
if d.domain == p['domain'] or d.domain == p['domain'] + ".":
|
|
||||||
found = True
|
|
||||||
|
|
||||||
if p['state'] == 'absent':
|
|
||||||
d.delete()
|
|
||||||
result['changed'] = True
|
|
||||||
result['msg'] = "domain " + p['domain'] + " deleted"
|
|
||||||
|
|
||||||
elif len(d.zone_history) == 0 and p['import_zone']:
|
|
||||||
result['changed'] = True
|
|
||||||
result['current_zone'] = d.current_zone.id
|
|
||||||
result['msg'] += " and zone imported"
|
|
||||||
else:
|
|
||||||
result['current_zone'] = d.current_zone
|
|
||||||
break
|
|
||||||
|
|
||||||
if not found:
|
|
||||||
providers = a.provider_list()
|
|
||||||
provider_found = False
|
|
||||||
for s in providers:
|
|
||||||
if s._comment == p['provider']:
|
|
||||||
provider_found = True
|
|
||||||
|
|
||||||
dn = s.domain_add(p['domain'])
|
|
||||||
result['msg'] = "domain " + p['domain'] + " added"
|
|
||||||
|
|
||||||
if p['import_zone']:
|
|
||||||
result['current_zone'] = dn.current_zone.id
|
|
||||||
result['msg'] += " and zone imported"
|
|
||||||
|
|
||||||
if not provider_found:
|
|
||||||
module.fail_json(msg="No provider found with name " + p['provider'])
|
|
||||||
return
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,79 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
---
|
|
||||||
'''
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
|
|
||||||
from happydomain.api import HappyDomain
|
|
||||||
|
|
||||||
def main():
|
|
||||||
module = AnsibleModule(
|
|
||||||
argument_spec=dict(
|
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
|
||||||
happydomain_username=dict(type='str', aliases=['email']),
|
|
||||||
happydomain_password=dict(type='str', aliases=['passwd'], no_log=True),
|
|
||||||
happydomain_token=dict(type='str'),
|
|
||||||
happydomain_scheme=dict(type='str', default='http'),
|
|
||||||
happydomain_host=dict(type='str', default='localhost'),
|
|
||||||
happydomain_port=dict(type='int', default='8081'),
|
|
||||||
happydomain_baseurl=dict(type='str', default=''),
|
|
||||||
type=dict(type='str'),
|
|
||||||
name=dict(type='str', aliases=['comment']),
|
|
||||||
data=dict(type='dict'),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
p = module.params
|
|
||||||
changed = False
|
|
||||||
found = False
|
|
||||||
|
|
||||||
a = HappyDomain(
|
|
||||||
scheme=p['happydomain_scheme'],
|
|
||||||
host=p['happydomain_host'],
|
|
||||||
port=p['happydomain_port'],
|
|
||||||
baseurl=p['happydomain_baseurl'],
|
|
||||||
token=p['happydomain_token'],
|
|
||||||
)
|
|
||||||
|
|
||||||
if p['happydomain_password'] is not None:
|
|
||||||
a.login(p['happydomain_username'], p['happydomain_password'])
|
|
||||||
|
|
||||||
providers = a.provider_list()
|
|
||||||
|
|
||||||
for s in providers:
|
|
||||||
if s._srctype == p['type'] and s._comment == p['name']:
|
|
||||||
found = True
|
|
||||||
|
|
||||||
if p['state'] == 'absent':
|
|
||||||
s.delete()
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
for k in p['data']:
|
|
||||||
if k not in s.args or p['data'][k] != s.args[k]:
|
|
||||||
s.args = p['data']
|
|
||||||
changed = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if changed:
|
|
||||||
s.update()
|
|
||||||
break
|
|
||||||
|
|
||||||
if not found and p['state'] != 'absent':
|
|
||||||
a.provider_add(p['type'], p['name'], p['data'])
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
module.exit_json(
|
|
||||||
changed=changed,
|
|
||||||
msg="provider " + p['name'] + ((" created" if not found else " altered") if p['state'] != 'absent' else " deleted"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,109 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
---
|
|
||||||
'''
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
|
|
||||||
from happydomain.api import HappyDomain
|
|
||||||
|
|
||||||
def main():
|
|
||||||
module = AnsibleModule(
|
|
||||||
argument_spec=dict(
|
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
|
||||||
happydomain_username=dict(type='str', aliases=['email']),
|
|
||||||
happydomain_password=dict(type='str', aliases=['passwd'], no_log=True),
|
|
||||||
happydomain_token=dict(type='str'),
|
|
||||||
happydomain_scheme=dict(type='str', default='http'),
|
|
||||||
happydomain_host=dict(type='str', default='localhost'),
|
|
||||||
happydomain_port=dict(type='int', default='8081'),
|
|
||||||
happydomain_baseurl=dict(type='str', default=''),
|
|
||||||
domain=dict(type='str', aliases=['name']),
|
|
||||||
zone=dict(type='str'),
|
|
||||||
type=dict(type='str'),
|
|
||||||
subdomain=dict(type='str'),
|
|
||||||
service=dict(type='dict'),
|
|
||||||
erase_others=dict(type='bool'),
|
|
||||||
apply_changes=dict(type='bool'),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
p = module.params
|
|
||||||
result = {
|
|
||||||
"changed": False
|
|
||||||
}
|
|
||||||
|
|
||||||
a = HappyDomain(
|
|
||||||
scheme=p['happydomain_scheme'],
|
|
||||||
host=p['happydomain_host'],
|
|
||||||
port=p['happydomain_port'],
|
|
||||||
baseurl=p['happydomain_baseurl'],
|
|
||||||
token=p['happydomain_token'],
|
|
||||||
)
|
|
||||||
|
|
||||||
if p['happydomain_password'] is not None:
|
|
||||||
a.login(p['happydomain_username'], p['happydomain_password'])
|
|
||||||
|
|
||||||
domains = a.domain_list()
|
|
||||||
|
|
||||||
for d in domains:
|
|
||||||
if d.domain == p['domain'] or d.domain == p['domain'] + ".":
|
|
||||||
for z in d.zone_history:
|
|
||||||
if z == p['zone']:
|
|
||||||
zone = d.get_zone(z)
|
|
||||||
|
|
||||||
if p['subdomain'].removesuffix(d.domain) in zone.services:
|
|
||||||
for s in zone.services[p['subdomain'].removesuffix(d.domain)]:
|
|
||||||
if s._svctype == p['type']:
|
|
||||||
differ = False
|
|
||||||
|
|
||||||
for k in s.service:
|
|
||||||
if k not in p['service'] or s.service[k] != p['service'][k]:
|
|
||||||
differ = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if p['erase_others']:
|
|
||||||
if differ:
|
|
||||||
s.delete()
|
|
||||||
result['changed'] = True
|
|
||||||
elif not differ:
|
|
||||||
if p['state'] == 'absent':
|
|
||||||
s.delete()
|
|
||||||
result['changed'] = True
|
|
||||||
else:
|
|
||||||
module.exit_json(**result)
|
|
||||||
return
|
|
||||||
|
|
||||||
if p['state'] != 'absent':
|
|
||||||
zone.add_zone_service(
|
|
||||||
p['subdomain'].removesuffix(d.domain),
|
|
||||||
p['type'],
|
|
||||||
p['service'],
|
|
||||||
)
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
|
|
||||||
if p['apply_changes']:
|
|
||||||
zone.apply_changes()
|
|
||||||
result['published'] = True
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
module.fail_json(msg="No zone found with id " + p['zone'])
|
|
||||||
return
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
module.fail_json(msg="No domain found with name " + p['domain'])
|
|
||||||
return
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,73 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
---
|
|
||||||
'''
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
|
|
||||||
from happydomain.admin import Admin
|
|
||||||
|
|
||||||
def main():
|
|
||||||
module = AnsibleModule(
|
|
||||||
argument_spec=dict(
|
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
|
||||||
username=dict(type='str', aliases=['name', 'email', 'happydomain_username']),
|
|
||||||
password=dict(type='str', aliases=['passwd', 'happydomain_password'], no_log=True),
|
|
||||||
allowcommercials=dict(type='bool'),
|
|
||||||
email_verified=dict(type='bool', default=True),
|
|
||||||
socket=dict(type='path', default='/var/lib/happydomain/happydomain.sock'),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
p = module.params
|
|
||||||
changed = False
|
|
||||||
found = False
|
|
||||||
|
|
||||||
a = Admin(socket=p['socket'])
|
|
||||||
|
|
||||||
users = a.authuser_list()
|
|
||||||
|
|
||||||
for u in users:
|
|
||||||
if u.Email == p['username']:
|
|
||||||
found = True
|
|
||||||
|
|
||||||
if p['state'] == 'absent':
|
|
||||||
u.Delete()
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
changed = u.ResetPassword(p['password'])
|
|
||||||
|
|
||||||
changedProp = False
|
|
||||||
if u.AllowCommercials != p['allowcommercials']:
|
|
||||||
u.AllowCommercials = p['allowcommercials']
|
|
||||||
changedProp = True
|
|
||||||
|
|
||||||
if u.EmailVerification is None and p['email_verified']:
|
|
||||||
now = datetime.now()
|
|
||||||
now = now.replace(microsecond=0)
|
|
||||||
u.EmailVerification = now.isoformat()
|
|
||||||
changedProp = True
|
|
||||||
|
|
||||||
if changedProp:
|
|
||||||
u.Update()
|
|
||||||
changed = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not found and p['state'] != 'absent':
|
|
||||||
a.authuser_create(p['username'], p['password'], p['allowcommercials'], p['email_verified'])
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
module.exit_json(
|
|
||||||
changed=changed,
|
|
||||||
msg="user " + p['username'] + ((" created" if not found else " altered") if p['state'] != 'absent' else " deleted"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -77,9 +77,3 @@
|
|||||||
enabled: yes
|
enabled: yes
|
||||||
state: started
|
state: started
|
||||||
when: ansible_service_mgr == "systemd"
|
when: ansible_service_mgr == "systemd"
|
||||||
|
|
||||||
- name: Install happydomain python package
|
|
||||||
ansible.builtin.pip:
|
|
||||||
name:
|
|
||||||
- happydomain
|
|
||||||
- requests_unixsocket
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user