Compare commits

..

5 commits

460 changed files with 3539 additions and 107 deletions

View file

@ -1,3 +1,15 @@
## 0.2.0a20 (2026-05-04)
### Feat
- multi layers support
### Fix
- load indefine if no default value
- user-data-ansible can set a personalise source
- test if password is set in a forbidden file even if it also in legitimate file
## 0.2.0a19 (2026-01-21)
### Fix

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project]
name = "rougail.user_data_yaml"
version = "0.2.0a19"
version = "0.2.0a20"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md"
description = "Rougail user_data yaml"

View file

@ -18,20 +18,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from ruamel.yaml import YAML
from pathlib import Path
from itertools import chain
from rougail.error import ExtensionError
from tiramisu.error import ValueOptionError, PropertiesOptionError, LeadershipError
from rougail.utils import undefined
from tiramisu import MetaConfig
from .i18n import _
from .__version__ import __version__
class RougailUserDataYaml:
has_several_layers = True
def __init__(
self,
config,
*,
rougailconfig=None,
**kwargs,
) -> None:
if rougailconfig is None:
from rougail import RougailConfig
@ -45,11 +51,22 @@ class RougailUserDataYaml:
if "yaml" not in user_data:
raise ExtensionError(_("yaml is not set in step.user_data"))
self.rougailconfig = rougailconfig
self.filenames = self.rougailconfig["yaml.filename"]
self.filenames = []
for filename in self.rougailconfig["yaml.filename"]:
filename = Path(filename)
if filename.is_file():
self.filenames.append(filename)
else:
for name in sorted(chain(filename.glob('*.yml'), filename.glob('*.yaml'))):
self.filenames.append(name)
self.file_with_secrets = self.rougailconfig["yaml.file_with_secrets"]
self.config = config
self.errors = []
self.warnings = []
self.source = _('the YAML file "{0}"')
def count_layers(self):
return len(self.filenames)
def run(
self,
@ -59,48 +76,42 @@ class RougailUserDataYaml:
if self.file_with_secrets == "last":
last_filename_idx = len(self.filenames) - 1
for idx, filename in enumerate(self.filenames):
filename = Path(filename)
if filename.is_file():
filenames = [filename]
else:
filenames = list(filename.glob('*.yml')) + list(filename.glob('*.yaml'))
for filename in sorted(filenames):
file_values = self.open(filename)
if not file_values:
continue
values = {}
if not isinstance(file_values, dict):
self.errors.append(
_(
'cannot load "{0}", the root value is not a dict but "{1}"'
).format(filename, file_values)
)
else:
self.parse(
values,
"",
file_values,
filename,
)
if self.file_with_secrets == "none":
allow_secrets_variables = False
elif self.file_with_secrets == "first":
allow_secrets_variables = idx == 0
elif self.file_with_secrets == "last":
allow_secrets_variables = idx == last_filename_idx
else:
allow_secrets_variables = True
user_data.append(
{
"source": _('the YAML file "{0}"').format(filename),
"errors": self.errors,
"warnings": self.warnings,
"values": values,
"options": {
"allow_secrets_variables": allow_secrets_variables,
},
}
file_values = self.open(filename)
if not file_values:
continue
values = {}
if not isinstance(file_values, dict):
self.errors.append(
_(
'cannot load "{0}", the root value is not a dict but "{1}"'
).format(filename, file_values)
)
else:
self.parse(
values,
"",
file_values,
filename,
)
if self.file_with_secrets == "none":
allow_secrets_variables = False
elif self.file_with_secrets == "first":
allow_secrets_variables = idx == 0
elif self.file_with_secrets == "last":
allow_secrets_variables = idx == last_filename_idx
else:
allow_secrets_variables = True
user_data.append(
{
"source": self.source.format(filename),
"errors": self.errors,
"warnings": self.warnings,
"values": values,
"options": {
"allow_secrets_variables": allow_secrets_variables,
},
}
)
return user_data
def open(self, filename: str) -> dict:
@ -136,7 +147,7 @@ class RougailUserDataYaml:
for val in value:
for key in keys:
values.setdefault(path + "." + key, []).append(
val.get(key, None)
val.get(key, undefined)
)
else:

View file

@ -1 +1 @@
__version__ = "0.2.0a19"
__version__ = "0.2.0a20"

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"proxy_mode",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"proxy_mode",
null
]
]
]

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"proxy_mode",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"proxy_mode",
null
]
]
]

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,12 @@
{
"errors": [],
"warnings": [
[
[
"the value \"1\" is an invalid string, it's not a string, it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/001/config/03/config.yml\"",
"proxy_mode",
null
]
]
]
}

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"proxy_mode",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"proxy_mode",
null
]
]
]

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "foo"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "foo"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "foo"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "foo"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "Manual proxy configuration"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "Manual proxy configuration"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,12 @@
{
"errors": [],
"warnings": [
[
[
"the value \"foo\" is an invalid choice, only \"Auto-detect proxy settings for this network\", \"Automatic proxy configuration URL\", \"Manual proxy configuration\", \"No proxy\" and \"Use system proxy settings\" are allowed, it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/010/config/04/config.yml\"",
"proxy_mode",
null
]
]
]
}

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net"
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net"
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net"
}

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,12 @@
{
"errors": [],
"warnings": [
[
[
"the value \"192.168.0.1\" is an invalid domain name, must not be an IP, it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/030/config/02/config.yml\"",
"manual.http_proxy.address",
null
]
]
]
}

View file

@ -0,0 +1,12 @@
{
"errors": [],
"warnings": [
[
[
"the value \"not a valid domain name.com\" is an invalid domain name, must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed, it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/030/config/03/config.yml\"",
"manual.http_proxy.address",
null
]
]
]
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net"
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net"
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "192.168.0.1"
}

View file

@ -0,0 +1,4 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "192.168.0.1"
}

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,9 @@
[
[
[
"mandatory variable but has no value",
"manual.http_proxy.address",
null
]
]
]

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,12 @@
{
"errors": [],
"warnings": [
[
[
"the value \"not a valid domain name.com\" is an invalid domain name, could be a IP, otherwise must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed, it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/031/config/03/config.yml\"",
"manual.http_proxy.address",
null
]
]
]
}

View file

@ -0,0 +1,5 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080"
}

View file

@ -0,0 +1,5 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080"
}

View file

@ -0,0 +1,5 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "3128"
}

View file

@ -0,0 +1,5 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "3128"
}

View file

@ -0,0 +1,5 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080"
}

View file

@ -0,0 +1,5 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,12 @@
{
"errors": [],
"warnings": [
[
[
"the value \"100000\" is an invalid port, must be between 1 and 65535, it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/032/config/03/config.yml\"",
"manual.http_proxy.port",
null
]
]
]
}

View file

@ -0,0 +1,6 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080",
"manual.use_for_https": true
}

View file

@ -0,0 +1,6 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080",
"manual.use_for_https": true
}

View file

@ -0,0 +1,6 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080",
"manual.use_for_https": false
}

View file

@ -0,0 +1,6 @@
{
"proxy_mode": "No proxy",
"manual.http_proxy.address": "example.net",
"manual.http_proxy.port": "8080",
"manual.use_for_https": false
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,8 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "http.proxy.net",
"manual.http_proxy.port": "3128",
"manual.use_for_https": false,
"manual.https_proxy.address": "https.proxy.net",
"manual.https_proxy.port": "8080"
}

View file

@ -0,0 +1,8 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "http.proxy.net",
"manual.http_proxy.port": "3128",
"manual.use_for_https": false,
"manual.https_proxy.address": "https.proxy.net",
"manual.https_proxy.port": "8080"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,8 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "http.proxy.net",
"manual.http_proxy.port": "3128",
"manual.use_for_https": false,
"manual.https_proxy.address": "https.proxy.net",
"manual.https_proxy.port": "3128"
}

View file

@ -0,0 +1,8 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "http.proxy.net",
"manual.http_proxy.port": "3128",
"manual.use_for_https": false,
"manual.https_proxy.address": "https.proxy.net",
"manual.https_proxy.port": "3128"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "Manual proxy configuration"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "Manual proxy configuration"
}

View file

@ -0,0 +1,4 @@
{
"errors": [],
"warnings": []
}

View file

@ -0,0 +1,26 @@
{
"errors": [],
"warnings": [
[
[
"family \"manual\" (Manual proxy configuration) has property disabled, so cannot access to \"address\" (HTTP address), it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/050/config/02/config.yml\"",
"manual.http_proxy.address",
null
]
],
[
[
"family \"manual\" (Manual proxy configuration) has property disabled, so cannot access to \"port\" (HTTP Port), it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/050/config/02/config.yml\"",
"manual.http_proxy.port",
null
]
],
[
[
"family \"manual\" (Manual proxy configuration) has property disabled, so cannot access to \"use_for_https\" (Also use this proxy for HTTPS), it will be ignored when loading from the YAML file \"../rougail-tutorials_builder/examples/050/config/02/config.yml\"",
"manual.use_for_https",
null
]
]
]
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,3 @@
{
"proxy_mode": "No proxy"
}

View file

@ -0,0 +1,8 @@
{
"proxy_mode": "Manual proxy configuration",
"manual.http_proxy.address": "http.proxy.net",
"manual.http_proxy.port": "3128",
"manual.use_for_https": false,
"manual.https_proxy.address": "http.proxy.net",
"manual.https_proxy.port": "3128"
}

Some files were not shown because too many files have changed in this diff Show more