zbuilder 0.2.3__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zbuilder-0.2.3 → zbuilder-0.2.4}/PKG-INFO +2 -2
- {zbuilder-0.2.3 → zbuilder-0.2.4}/pyproject.toml +5 -3
- {zbuilder-0.2.3 → zbuilder-0.2.4}/pyproject.toml.orig +5 -3
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/base.py +1 -1
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/cfg.py +2 -4
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/cli.py +31 -35
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/dns/__init__.py +11 -14
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/dns/aws.py +11 -10
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/dns/bind.py +6 -6
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/dns/powerdns.py +10 -10
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/helpers.py +30 -30
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/ipam/__init__.py +5 -5
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/ipam/phpipam.py +15 -16
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/options.py +1 -1
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/vm/aws.py +8 -8
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/vm/kvm.py +46 -47
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/vm/proxmox.py +34 -33
- {zbuilder-0.2.3 → zbuilder-0.2.4}/LICENSE +0 -0
- {zbuilder-0.2.3 → zbuilder-0.2.4}/README.md +0 -0
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/__init__.py +0 -0
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/plugins.py +2 -2
- {zbuilder-0.2.3 → zbuilder-0.2.4}/src/zbuilder/vm/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zbuilder
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Create VMs
|
|
5
5
|
Author: Nikos Chasiotis
|
|
6
6
|
Author-email: Nikos Chasiotis <hasiotis@gmail.com>
|
|
@@ -29,7 +29,7 @@ Requires-Dist: massedit>=0.71.0
|
|
|
29
29
|
Requires-Dist: ruamel-yaml>=0.19.1
|
|
30
30
|
Requires-Dist: boto3>=1.43.73
|
|
31
31
|
Requires-Dist: tabulate>=0.10.0
|
|
32
|
-
Requires-Dist: libvirt-python>=
|
|
32
|
+
Requires-Dist: libvirt-python>=12,<13
|
|
33
33
|
Requires-Dist: pycdlib>=1.14,<2
|
|
34
34
|
Requires-Dist: proxmoxer>=1.1,<3 ; extra == 'proxmox'
|
|
35
35
|
Requires-Python: >=3.12, <4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "zbuilder"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
4
4
|
description = "Create VMs"
|
|
5
5
|
license = "GPL-3.0-or-later"
|
|
6
6
|
license-files = ["LICENSE"]
|
|
@@ -32,7 +32,7 @@ dependencies = [
|
|
|
32
32
|
"ruamel-yaml>=0.19.1",
|
|
33
33
|
"boto3>=1.43.73",
|
|
34
34
|
"tabulate>=0.10.0",
|
|
35
|
-
"libvirt-python>=
|
|
35
|
+
"libvirt-python>=12,<13",
|
|
36
36
|
"pycdlib>=1.14,<2",
|
|
37
37
|
]
|
|
38
38
|
|
|
@@ -73,12 +73,14 @@ default-groups = ["dev"]
|
|
|
73
73
|
|
|
74
74
|
[[tool.uv.dependency-metadata]]
|
|
75
75
|
name = "libvirt-python"
|
|
76
|
-
version = "
|
|
76
|
+
version = "12.8.0"
|
|
77
77
|
requires-dist = []
|
|
78
78
|
|
|
79
79
|
[tool.ruff]
|
|
80
80
|
line-length = 120
|
|
81
81
|
|
|
82
|
+
[tool.ruff.lint]
|
|
83
|
+
|
|
82
84
|
[tool.pytest.ini_options]
|
|
83
85
|
testpaths = ["tests"]
|
|
84
86
|
filterwarnings = ["ignore:This process .* is multi-threaded, use of fork.*:DeprecationWarning:multiprocessing.popen_fork"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "zbuilder"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
4
4
|
description = "Create VMs"
|
|
5
5
|
authors = [{ name = "Nikos Chasiotis", email = "hasiotis@gmail.com" }]
|
|
6
6
|
license = "GPL-3.0-or-later"
|
|
@@ -35,7 +35,7 @@ dependencies = [
|
|
|
35
35
|
"tabulate>=0.10.0",
|
|
36
36
|
# The kvm provider. libvirt-python compiles against libvirt-dev, which has
|
|
37
37
|
# to be present before `uv sync` - see the dependency-metadata block below.
|
|
38
|
-
"libvirt-python>=
|
|
38
|
+
"libvirt-python>=12,<13",
|
|
39
39
|
"pycdlib>=1.14,<2",
|
|
40
40
|
]
|
|
41
41
|
|
|
@@ -84,7 +84,7 @@ default-groups = ["dev"]
|
|
|
84
84
|
# built the normal way at install time, which does need the libvirt headers.
|
|
85
85
|
[[tool.uv.dependency-metadata]]
|
|
86
86
|
name = "libvirt-python"
|
|
87
|
-
version = "
|
|
87
|
+
version = "12.8.0"
|
|
88
88
|
requires-dist = []
|
|
89
89
|
|
|
90
90
|
[build-system]
|
|
@@ -94,6 +94,8 @@ build-backend = "uv_build"
|
|
|
94
94
|
[tool.ruff]
|
|
95
95
|
line-length = 120
|
|
96
96
|
|
|
97
|
+
[tool.ruff.lint]
|
|
98
|
+
|
|
97
99
|
[tool.pytest.ini_options]
|
|
98
100
|
testpaths = [ "tests" ]
|
|
99
101
|
filterwarnings = [
|
|
@@ -14,7 +14,7 @@ class UnsupportedAction(click.ClickException):
|
|
|
14
14
|
"""Raised when a provider does not implement an optional action"""
|
|
15
15
|
|
|
16
16
|
def __init__(self, provider, action):
|
|
17
|
-
super().__init__("Provider [{}] does not implement action [{}]"
|
|
17
|
+
super().__init__(f"Provider [{provider}] does not implement action [{action}]")
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class Provider(ABC):
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
import zbuilder.helpers
|
|
4
5
|
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
6
|
CONFIG_PATH = "~/.config/zbuilder/zbuilder.yaml"
|
|
8
7
|
CONFIG_EMPTY = """# ZBuilder configuration
|
|
9
8
|
main: {}
|
|
@@ -14,8 +13,7 @@ providers: {}
|
|
|
14
13
|
|
|
15
14
|
def initConfig(fname):
|
|
16
15
|
Path(fname).parent.mkdir(parents=True, exist_ok=True)
|
|
17
|
-
Path(fname).
|
|
18
|
-
Path(fname).open("w").write(CONFIG_EMPTY)
|
|
16
|
+
Path(fname).write_text(CONFIG_EMPTY)
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
def load(touch=False):
|
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
import os
|
|
2
|
+
import sys
|
|
3
3
|
import time
|
|
4
|
+
|
|
4
5
|
import click
|
|
5
|
-
import tabulate
|
|
6
|
-
import dpath.util
|
|
7
6
|
import distutils.dir_util
|
|
7
|
+
import dpath.util
|
|
8
|
+
import tabulate
|
|
9
|
+
from click.shell_completion import get_completion_class
|
|
8
10
|
|
|
9
|
-
import zbuilder.vm
|
|
10
11
|
import zbuilder.cfg
|
|
11
12
|
import zbuilder.plugins
|
|
12
|
-
|
|
13
|
+
import zbuilder.vm
|
|
13
14
|
from zbuilder.helpers import (
|
|
15
|
+
fixKeys,
|
|
14
16
|
getHosts,
|
|
15
17
|
getProviders,
|
|
16
|
-
runPlaybook,
|
|
17
|
-
fixKeys,
|
|
18
|
-
runCmd,
|
|
19
18
|
humanize_time,
|
|
19
|
+
runCmd,
|
|
20
|
+
runPlaybook,
|
|
20
21
|
)
|
|
21
|
-
from zbuilder.options import
|
|
22
|
-
|
|
23
|
-
from click.shell_completion import get_completion_class
|
|
22
|
+
from zbuilder.options import common_options, pass_state
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
@click.group()
|
|
@@ -42,11 +41,11 @@ def init(state, template):
|
|
|
42
41
|
tmpl_path = dpath.util.get(cfg, "/main/templates/path")
|
|
43
42
|
TEMPLATE_PATH = os.path.join(os.path.expanduser(tmpl_path), template)
|
|
44
43
|
if os.path.exists(TEMPLATE_PATH):
|
|
45
|
-
click.echo("Initializing {} based zbuilder environment"
|
|
44
|
+
click.echo(f"Initializing {template} based zbuilder environment")
|
|
46
45
|
distutils.dir_util.copy_tree(TEMPLATE_PATH, os.getcwd())
|
|
47
46
|
else:
|
|
48
|
-
click.echo("Template path dose not exist: [{}]"
|
|
49
|
-
exit(1)
|
|
47
|
+
click.echo(f"Template path dose not exist: [{TEMPLATE_PATH}]")
|
|
48
|
+
sys.exit(1)
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
@cli.command()
|
|
@@ -57,7 +56,7 @@ def build(state):
|
|
|
57
56
|
start_time = time.time()
|
|
58
57
|
click.echo("Building VMs")
|
|
59
58
|
vmProviders = getHosts(state)
|
|
60
|
-
for
|
|
59
|
+
for vmProvider in vmProviders.values():
|
|
61
60
|
vmProvider["cloud"].build(vmProvider["hosts"])
|
|
62
61
|
click.echo("Fixing ssh keys VMs")
|
|
63
62
|
fixKeys(state)
|
|
@@ -65,7 +64,7 @@ def build(state):
|
|
|
65
64
|
click.echo("Running bootstrap.yml")
|
|
66
65
|
runPlaybook(state, "bootstrap.yml")
|
|
67
66
|
end_time = time.time()
|
|
68
|
-
click.echo("Time elapsed: {
|
|
67
|
+
click.echo(f"Time elapsed: {humanize_time(end_time - start_time)}")
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
@cli.command()
|
|
@@ -75,7 +74,7 @@ def up(state):
|
|
|
75
74
|
"""Boot the VMs"""
|
|
76
75
|
click.echo("Booting VMs")
|
|
77
76
|
vmProviders = getHosts(state)
|
|
78
|
-
for
|
|
77
|
+
for vmProvider in vmProviders.values():
|
|
79
78
|
vmProvider["cloud"].up(vmProvider["hosts"])
|
|
80
79
|
|
|
81
80
|
|
|
@@ -86,7 +85,7 @@ def halt(state):
|
|
|
86
85
|
"""Halt the VMs"""
|
|
87
86
|
click.echo("Halting VMs")
|
|
88
87
|
vmProviders = getHosts(state)
|
|
89
|
-
for
|
|
88
|
+
for vmProvider in vmProviders.values():
|
|
90
89
|
vmProvider["cloud"].halt(vmProvider["hosts"])
|
|
91
90
|
|
|
92
91
|
|
|
@@ -97,7 +96,7 @@ def destroy(state):
|
|
|
97
96
|
"""Destroy the VMs"""
|
|
98
97
|
click.echo("Destroying VMs")
|
|
99
98
|
vmProviders = getHosts(state)
|
|
100
|
-
for
|
|
99
|
+
for vmProvider in vmProviders.values():
|
|
101
100
|
zbuilder_env = None
|
|
102
101
|
for h in vmProvider["hosts"]:
|
|
103
102
|
if "ZBUILDER_ENV" in vmProvider["hosts"][h]:
|
|
@@ -108,7 +107,7 @@ def destroy(state):
|
|
|
108
107
|
zbuilder_env = vmProvider["hosts"][h]["ZBUILDER_ENV"]
|
|
109
108
|
break
|
|
110
109
|
if zbuilder_env:
|
|
111
|
-
if click.confirm(" The ZBUILDER_ENV is set to [{}] Do you want to continue?"
|
|
110
|
+
if click.confirm(f" The ZBUILDER_ENV is set to [{zbuilder_env}] Do you want to continue?"):
|
|
112
111
|
vmProvider["cloud"].destroy(vmProvider["hosts"])
|
|
113
112
|
else:
|
|
114
113
|
click.echo(" Aborting!")
|
|
@@ -128,7 +127,6 @@ def fixkeys(state):
|
|
|
128
127
|
@cli.group()
|
|
129
128
|
def dns():
|
|
130
129
|
"""DNS management"""
|
|
131
|
-
pass
|
|
132
130
|
|
|
133
131
|
|
|
134
132
|
@dns.command(name="update")
|
|
@@ -138,7 +136,7 @@ def dns_update(state):
|
|
|
138
136
|
"""Update DNS records"""
|
|
139
137
|
click.echo("Updating DNS records")
|
|
140
138
|
vmProviders = getHosts(state)
|
|
141
|
-
for
|
|
139
|
+
for vmProvider in vmProviders.values():
|
|
142
140
|
vmProvider["cloud"].dnsupdate(vmProvider["hosts"])
|
|
143
141
|
|
|
144
142
|
|
|
@@ -149,14 +147,13 @@ def remove(state):
|
|
|
149
147
|
"""Remove DNS records"""
|
|
150
148
|
click.echo("Removing DNS records")
|
|
151
149
|
vmProviders = getHosts(state)
|
|
152
|
-
for
|
|
150
|
+
for vmProvider in vmProviders.values():
|
|
153
151
|
vmProvider["cloud"].dnsremove(vmProvider["hosts"])
|
|
154
152
|
|
|
155
153
|
|
|
156
154
|
@cli.group()
|
|
157
155
|
def snapshot():
|
|
158
156
|
"""Manage VM snapshots"""
|
|
159
|
-
pass
|
|
160
157
|
|
|
161
158
|
|
|
162
159
|
@snapshot.command()
|
|
@@ -166,7 +163,7 @@ def create(state):
|
|
|
166
163
|
"""Create VM snapshots"""
|
|
167
164
|
click.echo("Creating VMs snapshots")
|
|
168
165
|
vmProviders = getHosts(state)
|
|
169
|
-
for
|
|
166
|
+
for vmProvider in vmProviders.values():
|
|
170
167
|
vmProvider["cloud"].snapCreate(vmProvider["hosts"])
|
|
171
168
|
|
|
172
169
|
|
|
@@ -177,7 +174,7 @@ def restore(state):
|
|
|
177
174
|
"""Restore VM snapshots"""
|
|
178
175
|
click.echo("Restoring VMs snapshots")
|
|
179
176
|
vmProviders = getHosts(state)
|
|
180
|
-
for
|
|
177
|
+
for vmProvider in vmProviders.values():
|
|
181
178
|
vmProvider["cloud"].snapRestore(vmProvider["hosts"])
|
|
182
179
|
|
|
183
180
|
|
|
@@ -188,7 +185,7 @@ def delete(state):
|
|
|
188
185
|
"""Delete VM snapshots"""
|
|
189
186
|
click.echo("Deleting VMs snapshots")
|
|
190
187
|
vmProviders = getHosts(state)
|
|
191
|
-
for
|
|
188
|
+
for vmProvider in vmProviders.values():
|
|
192
189
|
vmProvider["cloud"].snapDelete(vmProvider["hosts"])
|
|
193
190
|
|
|
194
191
|
|
|
@@ -207,7 +204,7 @@ def summary(state):
|
|
|
207
204
|
"""Display environment summary"""
|
|
208
205
|
vmProviders = getHosts(state)
|
|
209
206
|
data = []
|
|
210
|
-
for
|
|
207
|
+
for vmProvider in vmProviders.values():
|
|
211
208
|
for h, v in vmProvider["hosts"].items():
|
|
212
209
|
data.append([vmProvider["cloud"].factory, h, vmProvider["cloud"].params(v)])
|
|
213
210
|
click.echo(tabulate.tabulate(data, headers=["Provider", "Host", "Parameters"], tablefmt="psql"))
|
|
@@ -227,7 +224,6 @@ def providers(state):
|
|
|
227
224
|
@cli.group()
|
|
228
225
|
def config():
|
|
229
226
|
"""Zbuilder configuration"""
|
|
230
|
-
pass
|
|
231
227
|
|
|
232
228
|
|
|
233
229
|
@config.command()
|
|
@@ -255,9 +251,9 @@ def main(state, args):
|
|
|
255
251
|
sub_path, value = args[1].split("=")
|
|
256
252
|
if "," in value:
|
|
257
253
|
value = value.split(",")
|
|
258
|
-
cfg_path = "main/{}/{}"
|
|
254
|
+
cfg_path = f"main/{base_path}/{sub_path}"
|
|
259
255
|
|
|
260
|
-
click.echo("Setting config /{} to {}"
|
|
256
|
+
click.echo(f"Setting config /{cfg_path} to {value}")
|
|
261
257
|
dpath.util.new(cfg, cfg_path, value)
|
|
262
258
|
zbuilder.cfg.save(cfg)
|
|
263
259
|
|
|
@@ -277,9 +273,9 @@ def provider(state, args):
|
|
|
277
273
|
value = True
|
|
278
274
|
if value in ["False", "false"]:
|
|
279
275
|
value = False
|
|
280
|
-
cfg_path = "providers/{}/{}"
|
|
276
|
+
cfg_path = f"providers/{base_path}/{sub_path}"
|
|
281
277
|
|
|
282
|
-
click.echo("Setting config /{} to {}"
|
|
278
|
+
click.echo(f"Setting config /{cfg_path} to {value}")
|
|
283
279
|
dpath.util.new(cfg, cfg_path, value)
|
|
284
280
|
zbuilder.cfg.save(cfg)
|
|
285
281
|
|
|
@@ -298,7 +294,7 @@ def update(state, yes):
|
|
|
298
294
|
tmpl_path = dpath.util.get(cfg, "/main/templates/path")
|
|
299
295
|
if tmpl_repo and tmpl_path:
|
|
300
296
|
click.echo(" * Updating templates")
|
|
301
|
-
runCmd("git -C {
|
|
297
|
+
runCmd(f"git -C {tmpl_path} pull || git clone {tmpl_repo} {tmpl_path}")
|
|
302
298
|
except KeyError:
|
|
303
299
|
pass
|
|
304
300
|
|
|
@@ -313,7 +309,7 @@ def plugins(state):
|
|
|
313
309
|
p = zbuilder.vm.vmProvider(plugin)
|
|
314
310
|
if p.enabled():
|
|
315
311
|
click.echo(f" - {plugin:8}: enabled")
|
|
316
|
-
except Exception:
|
|
312
|
+
except Exception: # noqa: BLE001, S110 - a provider that can't even construct just isn't listed
|
|
317
313
|
pass
|
|
318
314
|
|
|
319
315
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import time
|
|
2
|
+
|
|
2
3
|
import click
|
|
4
|
+
import dns.exception
|
|
3
5
|
import dns.resolver
|
|
4
6
|
|
|
5
7
|
import zbuilder.cfg
|
|
@@ -8,34 +10,29 @@ import zbuilder.plugins
|
|
|
8
10
|
|
|
9
11
|
def waitDNS(hostname, ip):
|
|
10
12
|
synced = False
|
|
11
|
-
click.echo(" - Waiting for host [{}] DNS to sync"
|
|
13
|
+
click.echo(f" - Waiting for host [{hostname}] DNS to sync")
|
|
12
14
|
while not synced:
|
|
13
15
|
try:
|
|
14
16
|
answers = dns.resolver.query(hostname, "A")
|
|
15
17
|
ttl = answers.rrset.ttl
|
|
16
18
|
rip = answers[0].address
|
|
17
19
|
if rip == ip:
|
|
18
|
-
click.echo(" - Host [{}] is synced with ip [{}]"
|
|
20
|
+
click.echo(f" - Host [{hostname}] is synced with ip [{rip}]")
|
|
19
21
|
synced = True
|
|
20
22
|
else:
|
|
21
|
-
click.echo(
|
|
22
|
-
" - Host [{}] is not synced with ip [{} != {}], sleeping for [{}]".format(
|
|
23
|
-
hostname, ip, rip, ttl + 1
|
|
24
|
-
)
|
|
25
|
-
)
|
|
23
|
+
click.echo(f" - Host [{hostname}] is not synced with ip [{ip} != {rip}], sleeping for [{ttl + 1}]")
|
|
26
24
|
time.sleep(ttl + 1)
|
|
27
25
|
except dns.resolver.NXDOMAIN:
|
|
28
26
|
click.echo(" Sleeping 20s due to NXDOMAIN")
|
|
29
27
|
time.sleep(20)
|
|
30
|
-
except
|
|
31
|
-
click.
|
|
32
|
-
exit()
|
|
28
|
+
except dns.exception.DNSException as e:
|
|
29
|
+
raise click.ClickException(str(e)) from e
|
|
33
30
|
|
|
34
31
|
|
|
35
32
|
def getProvider(zone, cfg):
|
|
36
|
-
for
|
|
33
|
+
for v in cfg.values():
|
|
37
34
|
if "dns" in v and "zones" in v["dns"] and zone == v["dns"]["zones"]:
|
|
38
|
-
return dnsProvider(
|
|
35
|
+
return dnsProvider(v["type"], v)
|
|
39
36
|
return None
|
|
40
37
|
|
|
41
38
|
|
|
@@ -50,7 +47,7 @@ def dnsUpdate(ips):
|
|
|
50
47
|
provider.update(host, zone, ip)
|
|
51
48
|
waitList[hostname] = ip
|
|
52
49
|
else:
|
|
53
|
-
click.echo("No DNS provider found for zone [{}]"
|
|
50
|
+
click.echo(f"No DNS provider found for zone [{zone}]")
|
|
54
51
|
|
|
55
52
|
for hostname, ip in waitList.items():
|
|
56
53
|
waitDNS(hostname, ip)
|
|
@@ -65,7 +62,7 @@ def dnsRemove(hosts):
|
|
|
65
62
|
if provider:
|
|
66
63
|
provider.remove(host, zone)
|
|
67
64
|
else:
|
|
68
|
-
click.echo("No DNS provider found for zone [{}]"
|
|
65
|
+
click.echo(f"No DNS provider found for zone [{zone}]")
|
|
69
66
|
|
|
70
67
|
|
|
71
68
|
def dnsProvider(factory, cfg=None):
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import click
|
|
2
1
|
import boto3
|
|
2
|
+
import click
|
|
3
|
+
from botocore.exceptions import BotoCoreError, ClientError
|
|
3
4
|
|
|
4
5
|
from zbuilder.base import DNSProvider
|
|
5
6
|
|
|
@@ -21,8 +22,8 @@ class dnsProvider(DNSProvider):
|
|
|
21
22
|
response = self.route53.list_hosted_zones_by_name(DNSName=zone)
|
|
22
23
|
if response["HostedZones"]:
|
|
23
24
|
zoneID = response["HostedZones"][0]["Id"]
|
|
24
|
-
fqdn = "{}.{}"
|
|
25
|
-
click.echo(" - Update record [{}] with ip [{}]"
|
|
25
|
+
fqdn = f"{host}.{zone}"
|
|
26
|
+
click.echo(f" - Update record [{fqdn}] with ip [{ip}]")
|
|
26
27
|
|
|
27
28
|
oldIP = None
|
|
28
29
|
record_set = self.route53.list_resource_record_sets(
|
|
@@ -57,14 +58,14 @@ class dnsProvider(DNSProvider):
|
|
|
57
58
|
ChangeInfoID = response["ChangeInfo"]["Id"]
|
|
58
59
|
waiter = self.route53.get_waiter("resource_record_sets_changed")
|
|
59
60
|
waiter.wait(Id=ChangeInfoID)
|
|
60
|
-
except
|
|
61
|
-
click.echo(" Error: [{}]"
|
|
61
|
+
except (BotoCoreError, ClientError) as e:
|
|
62
|
+
click.echo(f" Error: [{e}]")
|
|
62
63
|
|
|
63
64
|
def remove(self, host, zone):
|
|
64
65
|
response = self.route53.list_hosted_zones_by_name(DNSName=zone)
|
|
65
66
|
if response["HostedZones"]:
|
|
66
67
|
zoneID = response["HostedZones"][0]["Id"]
|
|
67
|
-
fqdn = "{}.{}"
|
|
68
|
+
fqdn = f"{host}.{zone}"
|
|
68
69
|
ip = None
|
|
69
70
|
record_set = self.route53.list_resource_record_sets(
|
|
70
71
|
HostedZoneId=zoneID,
|
|
@@ -76,7 +77,7 @@ class dnsProvider(DNSProvider):
|
|
|
76
77
|
ip = rs["ResourceRecords"][0]["Value"]
|
|
77
78
|
|
|
78
79
|
if ip is not None:
|
|
79
|
-
click.echo(" - Remove record [{}] with IP [{}]"
|
|
80
|
+
click.echo(f" - Remove record [{fqdn}] with IP [{ip}]")
|
|
80
81
|
try:
|
|
81
82
|
response = self.route53.change_resource_record_sets(
|
|
82
83
|
HostedZoneId=zoneID,
|
|
@@ -95,7 +96,7 @@ class dnsProvider(DNSProvider):
|
|
|
95
96
|
],
|
|
96
97
|
},
|
|
97
98
|
)
|
|
98
|
-
except
|
|
99
|
-
click.echo(" Error: [{}]"
|
|
99
|
+
except (BotoCoreError, ClientError) as e:
|
|
100
|
+
click.echo(f" Error: [{e}]")
|
|
100
101
|
else:
|
|
101
|
-
click.echo(" - DNS record [{}] does not exist"
|
|
102
|
+
click.echo(f" - DNS record [{fqdn}] does not exist")
|
|
@@ -22,27 +22,27 @@ class dnsProvider(DNSProvider):
|
|
|
22
22
|
response = dns.query.tcp(update, srv)
|
|
23
23
|
if response.rcode():
|
|
24
24
|
err = dns.rcode.to_text(response.rcode())
|
|
25
|
-
click.echo(" Failed to update DNS record [{}] on server [{}]"
|
|
25
|
+
click.echo(f" Failed to update DNS record [{err}] on server [{srv}]")
|
|
26
26
|
|
|
27
27
|
def update(self, host, zone, ip):
|
|
28
28
|
if ip is None:
|
|
29
29
|
click.echo(" - Skipping due to empty ip")
|
|
30
30
|
return
|
|
31
|
-
fqdn = "{}.{}"
|
|
32
|
-
click.echo(" - Creating/Updating record [{}] with ip [{}]"
|
|
31
|
+
fqdn = f"{host}.{zone}"
|
|
32
|
+
click.echo(f" - Creating/Updating record [{fqdn}] with ip [{ip}]")
|
|
33
33
|
update = dns.update.Update(zone, keyring=self.keyring)
|
|
34
34
|
update.replace(host, 300, "a", str(ip))
|
|
35
35
|
self._dns_query(update)
|
|
36
36
|
|
|
37
37
|
def remove(self, host, zone):
|
|
38
|
-
fqdn = "{}.{}"
|
|
39
|
-
click.echo(" - Removing record {}"
|
|
38
|
+
fqdn = f"{host}.{zone}"
|
|
39
|
+
click.echo(f" - Removing record {fqdn}")
|
|
40
40
|
update = dns.update.Update(zone, keyring=self.keyring)
|
|
41
41
|
update.delete(host)
|
|
42
42
|
self._dns_query(update)
|
|
43
43
|
|
|
44
44
|
def config(self):
|
|
45
|
-
return "server: {}, keyname: {
|
|
45
|
+
return f"server: {self.server}, keyname: {self.keyname}"
|
|
46
46
|
|
|
47
47
|
def status(self):
|
|
48
48
|
return "PASS"
|
|
@@ -12,7 +12,7 @@ class dnsProvider(DNSProvider):
|
|
|
12
12
|
self.url = self.cfg["url"] + "api/v1"
|
|
13
13
|
|
|
14
14
|
def _get_record(self, fqdn):
|
|
15
|
-
uri = "{}/servers/localhost/search-data"
|
|
15
|
+
uri = f"{self.url}/servers/localhost/search-data"
|
|
16
16
|
params = {"q": fqdn, "object-type": "record", "max": 1}
|
|
17
17
|
r = requests.get(uri, params=params, headers={"X-API-Key": self.apikey})
|
|
18
18
|
if r.status_code == 404:
|
|
@@ -21,10 +21,10 @@ class dnsProvider(DNSProvider):
|
|
|
21
21
|
return r.json()
|
|
22
22
|
|
|
23
23
|
def update(self, host, zone, ip):
|
|
24
|
-
fqdn = "{}.{}"
|
|
24
|
+
fqdn = f"{host}.{zone}"
|
|
25
25
|
r = self._get_record(fqdn)
|
|
26
26
|
|
|
27
|
-
uri = "{}/servers/localhost/zones/{}"
|
|
27
|
+
uri = f"{self.url}/servers/localhost/zones/{zone}"
|
|
28
28
|
payload = {
|
|
29
29
|
"rrsets": [
|
|
30
30
|
{
|
|
@@ -38,17 +38,17 @@ class dnsProvider(DNSProvider):
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
if not r:
|
|
41
|
-
click.echo(" - Creating record [{}] with ip [{}]"
|
|
41
|
+
click.echo(f" - Creating record [{fqdn}] with ip [{ip}]")
|
|
42
42
|
else:
|
|
43
|
-
click.echo(" - Updating record [{}] with ip [{}]"
|
|
43
|
+
click.echo(f" - Updating record [{fqdn}] with ip [{ip}]")
|
|
44
44
|
|
|
45
45
|
r = requests.patch(uri, json=payload, headers={"X-API-Key": self.apikey})
|
|
46
46
|
|
|
47
47
|
def remove(self, host, zone):
|
|
48
|
-
fqdn = "{}.{}"
|
|
48
|
+
fqdn = f"{host}.{zone}"
|
|
49
49
|
r = self._get_record(fqdn)
|
|
50
50
|
|
|
51
|
-
uri = "{}/servers/localhost/zones/{}"
|
|
51
|
+
uri = f"{self.url}/servers/localhost/zones/{zone}"
|
|
52
52
|
payload = {
|
|
53
53
|
"rrsets": [
|
|
54
54
|
{
|
|
@@ -61,13 +61,13 @@ class dnsProvider(DNSProvider):
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
if r:
|
|
64
|
-
click.echo(" - Removing record {}"
|
|
64
|
+
click.echo(f" - Removing record {fqdn}")
|
|
65
65
|
r = requests.patch(uri, json=payload, headers={"X-API-Key": self.apikey})
|
|
66
66
|
else:
|
|
67
|
-
click.echo(" - No such record {}"
|
|
67
|
+
click.echo(f" - No such record {fqdn}")
|
|
68
68
|
|
|
69
69
|
def config(self):
|
|
70
|
-
return "url: {
|
|
70
|
+
return f"url: {self.cfg['url']}"
|
|
71
71
|
|
|
72
72
|
def status(self):
|
|
73
73
|
return "PASS"
|