I make a program to automate check yaml files with some lint rule, but the output is not what I expected.
this is my testing environment:
The file that needs to be checked:
yaml file: Single file with multiple yamls separated by “—”
Input:
input () is used three times to get the path of the YAML file or directory, the key string to be searched, and the value to be matched against the key.
The user’s input is then stored in the directory, key, and value variables, respectively.
example input:
directory = input("Enter the path: ") yamls
key = input("Enter the key string : ") spec.ports[*].name
value = input("Enter the value : ") http
Output:
So, each line is telling you that the script found a key-value pair in a specific YAML file that matches the key and value you were searching for
The output is a series of print statements from the Python script. Each line represents a match found in the YAML files that were searched.
example output:
key = spec.ports[0].name, value = http, ....yamls6.yaml
key = spec.ports[1].name, value = http, ....yamls6.yaml
key = spec.ports[2].name, value = http, ....yamls6.yaml
key = spec.ports[0].name, value = http, ....yamls7.yaml
key = spec.ports[1].name, value = http, ....yamls7.yaml
This is the key that was found in the YAML file. It’s a path to a specific value in the YAML structure. In this case, it’s the name of the first port specified in the spec section.
value = http : This is the value associated with the key in the YAML file.
….yamls6.yaml: This is the relative path to the YAML file where the match was found.
here is the yaml file example that have multiple yamls:
apiVersion: v1
kind: Service
metadata:
name: service1
spec:
ports:
- name: http
port: 8181
targetPort: 8181
protocol: TCP
selector:
app: appsA
---
apiVersion: v1
kind: Service
metadata:
name: service2
spec:
ports:
- name: http
port: 8081
targetPort: 8081
protocol: TCP
selector:
app: appsB
---
apiVersion: v1
kind: Service
metadata:
name: service3
spec:
ports:
- name: http
port: 8082
targetPort: 8082
protocol: TCP
selector:
app: appsC
This is my code,
import os
from ruamel.yaml import YAML
from jsonpath_ng import parse
from jsonpath_ng.jsonpath import Fields
from jsonpath_ng.jsonpath import Index
def check_yaml(file_path, key_pattern, value_pattern):
yaml = YAML(typ='safe')
try:
with open(file_path, 'r') as stream:
all_data = list(yaml.load_all(stream))
for data in all_data:
jsonpath_expr = parse(key_pattern)
matches = [match for match in jsonpath_expr.find(data)]
for match in matches:
if str(match.value) == value_pattern:
relative_path = os.path.relpath(file_path, start='serviceA/test/')
# Convert the Path object to a string
path_str = str(match.full_path)
# Extract the index from the string
index = path_str.split('[')[-1].split(']')[0]
# Replace '*' with the index
modified_key_pattern = key_pattern.replace('*', str(index), 1)
print(f"key = {modified_key_pattern}, value = {match.value}, {relative_path}")
except Exception as e:
print(f"Error checking {file_path}: {e}")
def flatten_dict(d, parent_key='', sep='.'):
items = []
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, dict):
items.extend(flatten_dict(v, new_key, sep=sep).items())
elif isinstance(v, list):
for i, item in enumerate(v):
if isinstance(item, dict):
items.extend(flatten_dict(item, f"{new_key}[{i}]", sep=sep).items())
else:
items.append((f"{new_key}[{i}]", item))
else:
items.append((new_key, v))
return dict(items)
def main():
directory = input("Enter the path of the YAML file or directory which has YAML files: ")
key = input("Enter the key string to be searched in YAML files: ")
value = input("Enter the value to be matched against the key: ")
if os.path.isdir(directory):
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".yaml"):
check_yaml(os.path.join(root, file), key, value)
elif os.path.isfile(directory):
check_yaml(directory, key, value)
if __name__ == "__main__":
main()
this is the output it gives
key = spec.ports[0].name, value = http, ....yamls2.yaml
key = spec.ports[0].name, value = http, ....yamls3.yaml
key = spec.ports[0].name, value = http, ....yamls6.yaml
key = spec.ports[0].name, value = http, ....yamls6.yaml
key = spec.ports[0].name, value = http, ....yamls6.yaml
key = spec.ports[0].name, value = http, ....yamls7.yaml
key = spec.ports[0].name, value = http, ....yamlsyaml
key = spec.ports[0].name, value = http, ....yamlsconfigaa.yaml
key = spec.ports[0].name, value = http, ....yamlsconfigbb.yaml
this is my expectation
key = spec.ports[0].name, value = http, ....yamls2.yaml
key = spec.ports[0].name, value = http, ....yamls3.yaml
key = spec.ports[0].name, value = http, ....yamls6.yaml
key = spec.ports[1].name, value = http, ....yamls6.yaml
key = spec.ports[2].name, value = http, ....yamls6.yaml
key = spec.ports[0].name, value = http, ....yamls7.yaml
key = spec.ports[1].name, value = http, ....yamls7.yaml
key = spec.ports[0].name, value = http, ....yamlsyaml
key = spec.ports[0].name, value = http, ....yamlsconfigaa.yaml
key = spec.ports[0].name, value = http, ....yamlsconfigbb.yaml
here is my thought:
The issue might be that the ‘‘ in the key_pattern is not being replaced because it’s not found. The str.replace() function only replaces the first occurrence of the old substring with the new substring. If the ‘‘ is not found in the key_pattern, the function will not do anything.
what should I change? thank you in advance for your help
kuma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1