Skip to content

Commit

Permalink
Merge pull request #2 from tsladecek/1-tests
Browse files Browse the repository at this point in the history
1 tests
  • Loading branch information
tsladecek authored Mar 28, 2023
2 parents a94003f + c689c5f commit 8cba22a
Show file tree
Hide file tree
Showing 19 changed files with 525 additions and 15 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Basic Testing of package functionality

on: [push, pull_request]

jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pipenv
pipenv sync --dev --system
- name: Run Tests
run: pytest --disable-warnings
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ examples/out/*.yml
examples/out/*.json
out/
dist/
*egg-info*
*egg-info*
*.pytest_cache*
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exclude src/ksux/tests
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pydantic = "*"
"ruamel.yaml" = "*"

[dev-packages]
pytest = "*"
autopep8 = "*"

[requires]
python_version = "3.8"
77 changes: 75 additions & 2 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 17 additions & 6 deletions src/ksux/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import logging
import sys
from argparse import ArgumentParser
Expand All @@ -15,9 +16,10 @@ def main():
parser.add_argument('-o', '--out_dir', help='Output directory', default='out')
parser.add_argument('-p', '--patches_dir',
help='Patches directory. Script will read only files with yaml/yml/json extensions')
parser.add_argument('-e', '--out_ext', help='Extension of output files', choices=['yaml', 'json', 'yml'],
parser.add_argument('-e', '--output_extension', help='Extension of output files', choices=['yaml', 'json', 'yml'],
default='json')
parser.add_argument('--dry-run', help='Print manifests to stdout', action="store_true")
parser.add_argument('-q', '--quiet', help='Do not print debug, info and warning messages', action='store_true')
parser.add_argument('--version', help='Package version', action="store_true")

args = parser.parse_args()
Expand All @@ -26,17 +28,26 @@ def main():
print('VERSION')
exit(0)

if args.quiet:
logging.root.setLevel(logging.ERROR)
else:
logging.root.setLevel(logging.INFO)

manifests = patch_manifests(base_dir=args.base_dir, patches_dir=args.patches_dir)

if args.dry_run:
print('---')
for i, m in enumerate(manifests):
round_trip_dump(m, sys.stdout)
if args.output_extension in ['yaml', 'yml']:
print('---')
for i, m in enumerate(manifests):
round_trip_dump(m, sys.stdout)
print('---')
else:
print(json.dumps(manifests))

else:
save_manifests(patched_manifests=manifests, out_dir=args.out_dir, extension=args.out_ext)
save_manifests(patched_manifests=manifests, out_dir=args.out_dir, extension=args.output_extension)

if args.out_ext in ['yaml', 'yml']:
if args.output_extension in ['yaml', 'yml']:
logging.warning(
'Make sure to check the manifests, especially if your input was in json format and you had some "add" ops '
'in your patches. In this case it is impossible to preserve quotes correctly!')
2 changes: 1 addition & 1 deletion src/ksux/src/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def get_real_path(patch: Patch, op: Op, manifest: dict):
return path_real


def apply_patch(patch: Patch, op: Op, manifest: Union[Dict, CommentedMap]):
def apply_patch(patch: Patch, op: Op, manifest: Union[Dict, CommentedMap]) -> Union[Dict, CommentedMap]:
"""
Applies patch and updates a manifest
:param patch: Patch Object
Expand Down
6 changes: 4 additions & 2 deletions src/ksux/src/read_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from json import JSONDecodeError
from typing import Dict, List, Union

from ruamel.yaml import round_trip_load, CommentedMap, CommentedSeq
from ruamel.yaml import CommentedMap, CommentedSeq, YAML
from ruamel.yaml.composer import ComposerError


Expand All @@ -22,8 +22,10 @@ def read_json(path: str) -> List[Dict]:


def load_yaml(yaml_str: str, path: str) -> Union[CommentedMap, CommentedSeq]:
yaml = YAML()
yaml.preserve_quotes = True
try:
yaml_file = round_trip_load(yaml_str, preserve_quotes=True)
yaml_file = yaml.load(yaml_str)
except ComposerError:
logging.error(f'Failed to parse {path}. YAML invalid')
exit(1)
Expand Down
7 changes: 4 additions & 3 deletions src/ksux/src/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Optional, Union, List

from pydantic import BaseModel, validator
from ruamel.yaml import CommentedSeq, CommentedMap


class Target(BaseModel):
Expand Down Expand Up @@ -39,12 +40,12 @@ class Op(BaseModel):

@validator('action')
def check_value(cls, v, values, **kwargs):
if v == Action.add.name or v == Action.replace.name:
if v == Action.add or v == Action.replace:
if 'value' not in values or values['value'] is None:
raise ValueError(f'Value needs to be present for action {v}')

# For add the value needs to be a json
if v == Action.add.name and type(values['value']) not in [list, dict]:
# For add the value needs to be an object
if v == Action.add and type(values['value']) not in [list, dict, CommentedMap, CommentedSeq]:
raise ValueError('For add, the value needs to be a dict or a list')
return v

Expand Down
Empty file added src/ksux/tests/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions src/ksux/tests/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import pathlib

from pydantic import BaseSettings


class Settings(BaseSettings):
PARENT = pathlib.Path(__file__).parent.resolve()


settings = Settings()
28 changes: 28 additions & 0 deletions src/ksux/tests/data/patches/configmap_patch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
{
"name": "configmap_patch",
"target": {
"apiVersion": "v1",
"kind": "ConfigMap",
"name": "web"
},
"ops": [
{
"name": "add_key",
"path": "/data",
"action": "add",
"value": {
"Tyger_tyger": "burning_bright",
"in_the_forests": "of_the_night",
"what_immortal": "hand_or_eye",
"could_frame": "thy_fearful_symmetry"
}
},
{
"name": "add_key",
"path": "/data/key1",
"action": "remove"
}
]
}
]
33 changes: 33 additions & 0 deletions src/ksux/tests/data/patches/deployment_patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: deployment_patches
target:
apiVersion: apps/v1
kind: Deployment
name: web
ops:
- name: replace_image
path: /spec/template/spec/containers/nginx/image
value: nginx:1.23
action: replace
---
name: deployment_patches
target:
apiVersion: apps/v1
kind: Deployment
name: web
ops:
- name: replace label
path: /metadata/labels/app
value: new-label
action: replace
---
name: deployment_patches
target:
apiVersion: apps/v1
kind: Deployment
name: web-2
ops:
- name: replace_image
path: /spec/template/spec/containers/nginx/image
value: nginx:1.20
action: replace
18 changes: 18 additions & 0 deletions src/ksux/tests/data/patches/service_patch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- name: service_patches
target:
apiVersion: v1
kind: Service
name: nginx-service
ops:
- name: add_https_port
path: /spec/ports
value:
name: https
port: 443
protocol: TCP
targetPort: 443
action: add
- name: rename_http_port
path: /spec/ports/http/name
action: replace
value: new_name
28 changes: 28 additions & 0 deletions src/ksux/tests/data/read_file/service_in_json_format.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "svc",
"creationTimestamp": null,
"labels": {
"app": "svc"
}
},
"spec": {
"ports": [
{
"name": "80-80",
"protocol": "TCP",
"port": 80,
"targetPort": 80
}
],
"selector": {
"app": "svc"
},
"type": "ClusterIP"
},
"status": {
"loadBalancer": {}
}
}
Loading

0 comments on commit 8cba22a

Please sign in to comment.