annet 0.15.1__tar.gz → 0.15.2__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.

Potentially problematic release.


This version of annet might be problematic. Click here for more details.

Files changed (143) hide show
  1. {annet-0.15.1/annet.egg-info → annet-0.15.2}/PKG-INFO +1 -1
  2. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/v37/storage.py +22 -1
  3. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/devdb/data/devdb.json +23 -19
  4. {annet-0.15.1 → annet-0.15.2}/annet/argparse.py +2 -0
  5. {annet-0.15.1 → annet-0.15.2}/annet/cli.py +1 -1
  6. {annet-0.15.1 → annet-0.15.2}/annet/cli_args.py +8 -1
  7. {annet-0.15.1 → annet-0.15.2}/annet/lib.py +19 -2
  8. {annet-0.15.1 → annet-0.15.2}/annet/output.py +9 -2
  9. {annet-0.15.1 → annet-0.15.2/annet.egg-info}/PKG-INFO +1 -1
  10. {annet-0.15.1 → annet-0.15.2}/AUTHORS +0 -0
  11. {annet-0.15.1 → annet-0.15.2}/LICENSE +0 -0
  12. {annet-0.15.1 → annet-0.15.2}/MANIFEST.in +0 -0
  13. {annet-0.15.1 → annet-0.15.2}/README.md +0 -0
  14. {annet-0.15.1 → annet-0.15.2}/annet/__init__.py +0 -0
  15. {annet-0.15.1 → annet-0.15.2}/annet/adapters/__init__.py +0 -0
  16. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/__init__.py +0 -0
  17. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/__init__.py +0 -0
  18. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/client.py +0 -0
  19. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/manufacturer.py +0 -0
  20. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/models.py +0 -0
  21. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/query.py +0 -0
  22. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/status_client.py +0 -0
  23. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/common/storage_opts.py +0 -0
  24. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/provider.py +0 -0
  25. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/v24/__init__.py +0 -0
  26. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/v24/storage.py +0 -0
  27. {annet-0.15.1 → annet-0.15.2}/annet/adapters/netbox/v37/__init__.py +0 -0
  28. {annet-0.15.1 → annet-0.15.2}/annet/annet.py +0 -0
  29. {annet-0.15.1 → annet-0.15.2}/annet/annlib/__init__.py +0 -0
  30. {annet-0.15.1 → annet-0.15.2}/annet/annlib/command.py +0 -0
  31. {annet-0.15.1 → annet-0.15.2}/annet/annlib/diff.py +0 -0
  32. {annet-0.15.1 → annet-0.15.2}/annet/annlib/errors.py +0 -0
  33. {annet-0.15.1 → annet-0.15.2}/annet/annlib/filter_acl.py +0 -0
  34. {annet-0.15.1 → annet-0.15.2}/annet/annlib/jsontools.py +0 -0
  35. {annet-0.15.1 → annet-0.15.2}/annet/annlib/lib.py +0 -0
  36. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/__init__.py +0 -0
  37. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/db.py +0 -0
  38. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/devdb/__init__.py +0 -0
  39. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/views/__init__.py +0 -0
  40. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/views/dump.py +0 -0
  41. {annet-0.15.1 → annet-0.15.2}/annet/annlib/netdev/views/hardware.py +0 -0
  42. {annet-0.15.1 → annet-0.15.2}/annet/annlib/output.py +0 -0
  43. {annet-0.15.1 → annet-0.15.2}/annet/annlib/patching.py +0 -0
  44. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rbparser/__init__.py +0 -0
  45. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rbparser/acl.py +0 -0
  46. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rbparser/deploying.py +0 -0
  47. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rbparser/ordering.py +0 -0
  48. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rbparser/platform.py +0 -0
  49. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rbparser/syntax.py +0 -0
  50. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rulebook/__init__.py +0 -0
  51. {annet-0.15.1 → annet-0.15.2}/annet/annlib/rulebook/common.py +0 -0
  52. {annet-0.15.1 → annet-0.15.2}/annet/annlib/tabparser.py +0 -0
  53. {annet-0.15.1 → annet-0.15.2}/annet/annlib/types.py +0 -0
  54. {annet-0.15.1 → annet-0.15.2}/annet/api/__init__.py +0 -0
  55. {annet-0.15.1 → annet-0.15.2}/annet/configs/context.yml +0 -0
  56. {annet-0.15.1 → annet-0.15.2}/annet/configs/logging.yaml +0 -0
  57. {annet-0.15.1 → annet-0.15.2}/annet/connectors.py +0 -0
  58. {annet-0.15.1 → annet-0.15.2}/annet/deploy.py +0 -0
  59. {annet-0.15.1 → annet-0.15.2}/annet/diff.py +0 -0
  60. {annet-0.15.1 → annet-0.15.2}/annet/executor.py +0 -0
  61. {annet-0.15.1 → annet-0.15.2}/annet/filtering.py +0 -0
  62. {annet-0.15.1 → annet-0.15.2}/annet/gen.py +0 -0
  63. {annet-0.15.1 → annet-0.15.2}/annet/generators/__init__.py +0 -0
  64. {annet-0.15.1 → annet-0.15.2}/annet/generators/base.py +0 -0
  65. {annet-0.15.1 → annet-0.15.2}/annet/generators/common/__init__.py +0 -0
  66. {annet-0.15.1 → annet-0.15.2}/annet/generators/common/initial.py +0 -0
  67. {annet-0.15.1 → annet-0.15.2}/annet/generators/entire.py +0 -0
  68. {annet-0.15.1 → annet-0.15.2}/annet/generators/exceptions.py +0 -0
  69. {annet-0.15.1 → annet-0.15.2}/annet/generators/jsonfragment.py +0 -0
  70. {annet-0.15.1 → annet-0.15.2}/annet/generators/partial.py +0 -0
  71. {annet-0.15.1 → annet-0.15.2}/annet/generators/perf.py +0 -0
  72. {annet-0.15.1 → annet-0.15.2}/annet/generators/ref.py +0 -0
  73. {annet-0.15.1 → annet-0.15.2}/annet/generators/result.py +0 -0
  74. {annet-0.15.1 → annet-0.15.2}/annet/hardware.py +0 -0
  75. {annet-0.15.1 → annet-0.15.2}/annet/implicit.py +0 -0
  76. {annet-0.15.1 → annet-0.15.2}/annet/parallel.py +0 -0
  77. {annet-0.15.1 → annet-0.15.2}/annet/patching.py +0 -0
  78. {annet-0.15.1 → annet-0.15.2}/annet/reference.py +0 -0
  79. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/__init__.py +0 -0
  80. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/arista/__init__.py +0 -0
  81. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/arista/iface.py +0 -0
  82. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/aruba/__init__.py +0 -0
  83. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/aruba/ap_env.py +0 -0
  84. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/aruba/misc.py +0 -0
  85. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/cisco/__init__.py +0 -0
  86. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/cisco/iface.py +0 -0
  87. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/cisco/misc.py +0 -0
  88. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/cisco/vlandb.py +0 -0
  89. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/common.py +0 -0
  90. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/deploying.py +0 -0
  91. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/huawei/__init__.py +0 -0
  92. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/huawei/aaa.py +0 -0
  93. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/huawei/bgp.py +0 -0
  94. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/huawei/iface.py +0 -0
  95. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/huawei/misc.py +0 -0
  96. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/huawei/vlandb.py +0 -0
  97. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/juniper/__init__.py +0 -0
  98. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/nexus/__init__.py +0 -0
  99. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/nexus/iface.py +0 -0
  100. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/patching.py +0 -0
  101. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/ribbon/__init__.py +0 -0
  102. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/arista.deploy +0 -0
  103. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/arista.order +0 -0
  104. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/arista.rul +0 -0
  105. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/aruba.deploy +0 -0
  106. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/aruba.order +0 -0
  107. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/aruba.rul +0 -0
  108. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/cisco.deploy +0 -0
  109. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/cisco.order +0 -0
  110. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/cisco.rul +0 -0
  111. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/huawei.deploy +0 -0
  112. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/huawei.order +0 -0
  113. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/huawei.rul +0 -0
  114. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/juniper.rul +0 -0
  115. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/nexus.deploy +0 -0
  116. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/nexus.order +0 -0
  117. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/nexus.rul +0 -0
  118. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/nokia.rul +0 -0
  119. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/optixtrans.deploy +0 -0
  120. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/optixtrans.order +0 -0
  121. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/optixtrans.rul +0 -0
  122. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/pc.order +0 -0
  123. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/pc.rul +0 -0
  124. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/ribbon.deploy +0 -0
  125. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/ribbon.rul +0 -0
  126. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/routeros.order +0 -0
  127. {annet-0.15.1 → annet-0.15.2}/annet/rulebook/texts/routeros.rul +0 -0
  128. {annet-0.15.1 → annet-0.15.2}/annet/storage.py +0 -0
  129. {annet-0.15.1 → annet-0.15.2}/annet/tabparser.py +0 -0
  130. {annet-0.15.1 → annet-0.15.2}/annet/text_term_format.py +0 -0
  131. {annet-0.15.1 → annet-0.15.2}/annet/tracing.py +0 -0
  132. {annet-0.15.1 → annet-0.15.2}/annet/types.py +0 -0
  133. {annet-0.15.1 → annet-0.15.2}/annet.egg-info/SOURCES.txt +0 -0
  134. {annet-0.15.1 → annet-0.15.2}/annet.egg-info/dependency_links.txt +0 -0
  135. {annet-0.15.1 → annet-0.15.2}/annet.egg-info/entry_points.txt +0 -0
  136. {annet-0.15.1 → annet-0.15.2}/annet.egg-info/requires.txt +0 -0
  137. {annet-0.15.1 → annet-0.15.2}/annet.egg-info/top_level.txt +0 -0
  138. {annet-0.15.1 → annet-0.15.2}/annet_generators/__init__.py +0 -0
  139. {annet-0.15.1 → annet-0.15.2}/annet_generators/example/__init__.py +0 -0
  140. {annet-0.15.1 → annet-0.15.2}/annet_generators/example/lldp.py +0 -0
  141. {annet-0.15.1 → annet-0.15.2}/requirements.txt +0 -0
  142. {annet-0.15.1 → annet-0.15.2}/setup.cfg +0 -0
  143. {annet-0.15.1 → annet-0.15.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: annet
3
- Version: 0.15.1
3
+ Version: 0.15.2
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  from logging import getLogger
2
- from typing import Optional, List, Union, Dict
2
+ from typing import Any, Optional, List, Union, Dict
3
3
  from ipaddress import ip_interface
4
4
  from collections import defaultdict
5
5
 
@@ -145,6 +145,7 @@ class NetboxStorageV37(Storage):
145
145
  def _load_devices(self, query: NetboxQuery) -> List[api_models.Device]:
146
146
  if not query.globs:
147
147
  return []
148
+ query = _hostname_dot_hack(query)
148
149
  return [
149
150
  device
150
151
  for device in self.netbox.dcim_all_devices(
@@ -223,3 +224,23 @@ def _match_query(query: NetboxQuery, device_data: api_models.Device) -> bool:
223
224
  if subquery.strip() in device_data.name:
224
225
  return True
225
226
  return False
227
+
228
+
229
+ def _hostname_dot_hack(netbox_query: NetboxQuery) -> NetboxQuery:
230
+ # there is no proper way to lookup host by its hostname
231
+ # ie find "host" with fqdn "host.example.com"
232
+ # besides using name__ic (ie startswith)
233
+ # since there is no direct analogue for this field in netbox
234
+ # so we need to add a dot to hostnames (top-level fqdn part)
235
+ # so we would not receive devices with a common name prefix
236
+ def add_dot(raw_query: Any) -> Any:
237
+ if isinstance(raw_query, str) and "." not in raw_query:
238
+ raw_query = raw_query + "."
239
+ return raw_query
240
+
241
+ raw_query = netbox_query.query
242
+ if isinstance(raw_query, list):
243
+ for i, name in enumerate(raw_query):
244
+ raw_query[i] = add_dot(name)
245
+
246
+ return NetboxQuery(raw_query)
@@ -6,18 +6,19 @@
6
6
  "Cisco.ASR": " ASR",
7
7
  "Cisco.ASR.ASR9000": " 9\\d{3}",
8
8
  "Cisco.XRV": "XRv",
9
- "Cisco.Catalyst": "Catalyst",
10
- "Cisco.Catalyst.C2900": " 29\\d\\d",
11
- "Cisco.Catalyst.C2900.C2950": " 2950",
12
- "Cisco.Catalyst.C2900.C2960": " 2960",
13
- "Cisco.Catalyst.C2900.C2960.C2960Plus": " 2960-Plus",
14
- "Cisco.Catalyst.C2900.C2960.C2960S": " 2960S",
15
- "Cisco.Catalyst.C2900.C2960.C2960X": " 2960X",
16
- "Cisco.Catalyst.C3500": " 35\\d\\d",
17
- "Cisco.Catalyst.C3600": " 36\\d\\d",
18
- "Cisco.Catalyst.C3700": " 37\\d\\d",
19
- "Cisco.Catalyst.C4900": " 49\\d\\d",
20
- "Cisco.Catalyst.C6500": " 65\\d\\d",
9
+ "Cisco.Catalyst": " (Catalyst |WS-C)",
10
+ "Cisco.Catalyst.C2900": "29\\d\\d",
11
+ "Cisco.Catalyst.C2900.C2950": "2950",
12
+ "Cisco.Catalyst.C2900.C2960": "2960",
13
+ "Cisco.Catalyst.C2900.C2960.C2960Plus": "2960-Plus",
14
+ "Cisco.Catalyst.C2900.C2960.C2960S": "2960S",
15
+ "Cisco.Catalyst.C2900.C2960.C2960X": "2960X",
16
+ "Cisco.Catalyst.C2900.C2960.C2960G": "2960G",
17
+ "Cisco.Catalyst.C3500": "35\\d\\d",
18
+ "Cisco.Catalyst.C3600": "36\\d\\d",
19
+ "Cisco.Catalyst.C3700": "37\\d\\d",
20
+ "Cisco.Catalyst.C4900": "49\\d\\d",
21
+ "Cisco.Catalyst.C6500": "65\\d\\d",
21
22
  "Cisco.Nexus": " [Nn]exus",
22
23
  "Cisco.Nexus.N3x": " 3\\d\\d\\d",
23
24
  "Cisco.Nexus.N3x.N3100": " 31\\d\\d",
@@ -52,13 +53,13 @@
52
53
  "Huawei.CE.CE8800.CE8850": " CE8850",
53
54
  "Huawei.CE.CE8800.CE8851": " CE8851",
54
55
  "Huawei.CE.CE9800": " CE98\\d\\d",
55
- "Huawei.Quidway": " S\\d+",
56
- "Huawei.Quidway.S2x": " S2\\d{3}",
57
- "Huawei.Quidway.S2x.S2300": " S23\\d\\d",
58
- "Huawei.Quidway.S2x.S2700": " S27\\d\\d",
59
- "Huawei.Quidway.S5300": " S53\\d\\d",
60
- "Huawei.Quidway.S5700": " S57\\d\\d",
61
- "Huawei.Quidway.S6700": " S67\\d\\d",
56
+ "Huawei.Quidway": " (LS-)?S",
57
+ "Huawei.Quidway.S2x": "2\\d{3}",
58
+ "Huawei.Quidway.S2x.S2300": "23\\d\\d",
59
+ "Huawei.Quidway.S2x.S2700": "27\\d\\d",
60
+ "Huawei.Quidway.S5300": "53\\d\\d",
61
+ "Huawei.Quidway.S5700": "57\\d\\d",
62
+ "Huawei.Quidway.S6700": "67\\d\\d",
62
63
  "Huawei.NE": " NE\\d+",
63
64
  "Huawei.NE.NE40E": " NE40E",
64
65
  "Huawei.NE.NE8000": " NE8000",
@@ -111,6 +112,9 @@
111
112
  "PC.Whitebox.Edgecore": "[Ee]dge-?[Cc]ore",
112
113
  "PC.Whitebox.Edgecore.AS": "AS",
113
114
  "PC.Whitebox.Edgecore.AS9736": "AS9736",
115
+ "PC.Whitebox.NVIDIA": "NVIDIA",
116
+ "PC.Whitebox.NVIDIA.SN": " SN",
117
+ "PC.Whitebox.NVIDIA.SN.SN5600": " SN5600",
114
118
  "PC.Moxa": "[Mm]oxa",
115
119
  "PC.Moxa.NPort": " [Nn][Pp]ort",
116
120
  "PC.Moxa.NPort.6610": "6610",
@@ -107,6 +107,8 @@ class Arg:
107
107
  default = self.kwargs.get("default", None)
108
108
  if isinstance(default, ConvertibleDefault) and "type" in self.kwargs:
109
109
  default = self.kwargs["default"] = default.convert(self.kwargs["type"])
110
+ elif isinstance(default, Callable):
111
+ default = self.kwargs["default"] = default()
110
112
  elif default is False and "action" not in self.kwargs:
111
113
  self.kwargs["action"] = "store_true"
112
114
  self.default = default
@@ -273,7 +273,7 @@ def file_patch(args: cli_args.FilePatchOptions):
273
273
  def context():
274
274
  """ A group of commands for manipulating context.
275
275
 
276
- By default, the context file is located in '~/.annushka/context.yml',
276
+ By default, the context file is located in '~/.annet/context.yml',
277
277
  but it can be set with the ANN_CONTEXT_CONFIG_PATH environment variable.
278
278
  """
279
279
  context_touch()
@@ -8,6 +8,7 @@ import os
8
8
 
9
9
  from valkit.common import valid_string_list
10
10
 
11
+ import annet.lib
11
12
  from annet.argparse import Arg, ArgGroup, DefaultFromEnv
12
13
  from annet.hardware import hardware_connector
13
14
  from annet.storage import Query, get_storage
@@ -69,6 +70,11 @@ opt_expand_path = Arg(
69
70
  help="Use full paths of Entire-generators and no just names when writing them to the file system"
70
71
  )
71
72
 
73
+ opt_dest_force_create_dir = Arg(
74
+ "--dest-force-create-dir", default=False,
75
+ help="Output generated data to dir, even for blackboxes"
76
+ )
77
+
72
78
  opt_old = Arg(
73
79
  "old",
74
80
  help="A path to a file (or a directory with a batch of files) that contains the old config"
@@ -228,7 +234,7 @@ opt_log_json = Arg(
228
234
  )
229
235
 
230
236
  opt_log_dest = Arg(
231
- "--log-dest", default="deploy/",
237
+ "--log-dest", default=annet.lib.get_default_log_dest,
232
238
  help="Log to a specified file, directory, or '-' (stdout)"
233
239
  )
234
240
 
@@ -425,6 +431,7 @@ class FileOutOptions(ArgGroup):
425
431
  expand_path = opt_expand_path
426
432
  no_label = opt_no_label
427
433
  no_color = opt_no_color
434
+ dest_force_create_dir = opt_dest_force_create_dir
428
435
 
429
436
  def __init__(self, *args, **kwargs):
430
437
  super().__init__(*args, **kwargs)
@@ -37,8 +37,20 @@ from annet.annlib.lib import ( # pylint: disable=unused-import
37
37
  from contextlog import get_logger
38
38
 
39
39
 
40
- _TEMPLATE_CONTEXT_PATH: Optional[str] = None
41
- _DEFAULT_CONTEXT_PATH: Optional[str] = None
40
+ _HOMEDIR_PATH: Optional[str] = None # defaults to ~/.annet
41
+ _TEMPLATE_CONTEXT_PATH: Optional[str] = None # defaults to annet/configs/context.yml
42
+ _DEFAULT_CONTEXT_PATH: Optional[str] = None # defaults to ~/.annet/context.yml
43
+
44
+
45
+ def get_homedir_path() -> str:
46
+ if _HOMEDIR_PATH is None:
47
+ set_homedir_path("~/.annet/")
48
+ return _HOMEDIR_PATH
49
+
50
+
51
+ def set_homedir_path(path: str) -> None:
52
+ global _HOMEDIR_PATH # pylint: disable=global-statement
53
+ _HOMEDIR_PATH = path
42
54
 
43
55
 
44
56
  def get_template_context_path() -> str:
@@ -63,6 +75,11 @@ def set_default_context_path(path: str) -> None:
63
75
  _DEFAULT_CONTEXT_PATH = path
64
76
 
65
77
 
78
+ def get_default_log_dest() -> str:
79
+ homedir = get_homedir_path()
80
+ return os.path.join(homedir, "deploy/")
81
+
82
+
66
83
  @lru_cache(maxsize=1)
67
84
  def _get_template_context():
68
85
  with open(get_template_context_path()) as f:
@@ -24,6 +24,9 @@ from annet.connectors import Connector
24
24
  from annet.storage import Device, storage_connector
25
25
 
26
26
 
27
+ BLACKBOX_FILENAME = "config.cfg"
28
+
29
+
27
30
  class _DriverConnector(Connector["OutputDriver"]):
28
31
  name = "OutputDriver"
29
32
  ep_name = "output"
@@ -77,7 +80,8 @@ class OutputDriverBasic(OutputDriver):
77
80
  yield from items_iter
78
81
 
79
82
  dest = arg_out.dest
80
- dir_mode = dir_or_file_output(dest, query_result_count, suggest_dir=(os.sep in first_result[0]))
83
+ suggest_dir = arg_out.dest_force_create_dir or os.sep in first_result[0]
84
+ dir_mode = dir_or_file_output(dest, query_result_count, suggest_dir=suggest_dir)
81
85
  _reassembled_items = list(_reassemble_items())
82
86
 
83
87
  for output_no, (label, output, is_fail) in enumerate(_reassembled_items):
@@ -99,6 +103,9 @@ class OutputDriverBasic(OutputDriver):
99
103
  print_label(label, back_color=label_color)
100
104
  writer.write(sys.stdout)
101
105
  elif dir_mode:
106
+ if arg_out.dest_force_create_dir and os.sep not in label:
107
+ label = os.path.join(label, BLACKBOX_FILENAME)
108
+
102
109
  if label.startswith(LABEL_NEW_PREFIX):
103
110
  label = label[len(LABEL_NEW_PREFIX):]
104
111
  if label.startswith(os.sep):
@@ -114,7 +121,7 @@ class OutputDriverBasic(OutputDriver):
114
121
  label = os.sep.join(parts[1:])
115
122
  if not arg_out.expand_path:
116
123
  label = os.path.basename(label)
117
- if query_result_count > 1:
124
+ if query_result_count > 1 or arg_out.dest_force_create_dir:
118
125
  label = os.path.join(hostname, label)
119
126
  file_dest = os.path.join(dest, "errors") if is_fail else dest
120
127
  out_file = os.path.normpath(os.path.join(file_dest, label))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: annet
3
- Version: 0.15.1
3
+ Version: 0.15.2
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes