Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Initial Codebase for Integrations CLI #1488

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5253511
Move schema folder to resources
Swiddis Mar 28, 2023
43e374b
Move schema documentation to docs
Swiddis Mar 28, 2023
18d71a7
Move rest of schema documentation to docs
Swiddis Mar 28, 2023
ea46eb9
Pull CLI from 2.x
Swiddis Mar 30, 2023
472508d
Commit CLI project to Poetry
Swiddis Mar 31, 2023
3c11c47
Use returns Result for validation
Swiddis Mar 31, 2023
1766927
Pylint maintenance
Swiddis Mar 31, 2023
d0cf5c1
Add catalog selection support
Swiddis Mar 31, 2023
5d86173
Tweak catalog schema to pass validation for catalog
Swiddis Mar 31, 2023
9265e58
Refactor validation logic
Swiddis Apr 3, 2023
15f7a13
Reformat
Swiddis Apr 3, 2023
d5d1dd1
Add poetry to CI
Swiddis Apr 3, 2023
861d573
Merge remote-tracking branch 'upstream/main' into cli-main
Swiddis Apr 3, 2023
99c72e9
Refresh poetry lock
Swiddis Apr 3, 2023
b921d94
Add install to poetry steps
Swiddis Apr 3, 2023
a7fa6f8
Refactor project with builds and scripts
Swiddis Apr 4, 2023
7592d2f
Fix catalog schema
Swiddis Apr 10, 2023
74747bb
Add better component handling
Swiddis Apr 10, 2023
baf1edb
Modify template http dashboard
Swiddis Apr 10, 2023
00cc117
Modify dashboards and add upload script
Swiddis Apr 11, 2023
f3dfc4c
Fix update.sh
Swiddis Apr 11, 2023
6e4ea43
Fix broken dashboard
Swiddis Apr 11, 2023
9775001
Switch from poetry
Swiddis Apr 11, 2023
c144a2b
Add helper script and update readme
Swiddis Apr 11, 2023
6801fd5
Update readme with workflow
Swiddis Apr 12, 2023
c4a482f
Fix shell scripts and make upload dynamic
Swiddis Apr 12, 2023
082a3fc
Switch to Pytest
Swiddis Apr 12, 2023
693cc82
Tweak CI
Swiddis Apr 12, 2023
c1b917d
Fix CI attempt
Swiddis Apr 13, 2023
10971b3
Use CI from SQL cli
Swiddis Apr 13, 2023
abd0692
Switch to lru_cache for compatibility
Swiddis Apr 13, 2023
67ef7d6
Add integrations to branch
Swiddis Apr 13, 2023
86209e3
Handle get-mapping failures
Swiddis Apr 13, 2023
0f7a629
Simplify test docker
Swiddis Apr 13, 2023
1a178f3
Add work on adding subcomponent validation to integrations
Swiddis Apr 13, 2023
cdc62a7
Revert "Add work on adding subcomponent validation to integrations"
Swiddis Apr 14, 2023
fc1836e
Add dependency management and clean handling of unnecessary fields
Swiddis Apr 14, 2023
92d9917
Remove dependence on nginx
Swiddis Apr 14, 2023
f6a8385
Setting path doesn't set url
Swiddis Apr 14, 2023
81ea966
Fix zipping
Swiddis Apr 15, 2023
bbe3232
Remove testing integrations folder
Swiddis Apr 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/python-poetry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Python Poetry CI
on: pull_request

jobs:
ci:
strategy:
fail-fast: false
matrix:
python-version: ["3.10"]
poetry-version: ["1.0"]
os: [ubuntu-18.04, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Run image
uses: abatilo/actions-poetry@v2
with:
poetry-version: ${{ matrix.poetry-version }}
- name: Run Integrations CLI unit tests
run: cd scripts/integrations-cli && poetry install && poetry run python -m unittest
180 changes: 180 additions & 0 deletions scripts/integrations-cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Directories used by CLI
artifacts
integrations

# Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

### Python Patch ###
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
poetry.toml

# ruff
.ruff_cache/

# LSP config files
pyrightconfig.json

# End of https://www.toptal.com/developers/gitignore/api/python
3 changes: 3 additions & 0 deletions scripts/integrations-cli/helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import constants, validate
from .catalog import CatalogManager
from .create import IntegrationBuilder
22 changes: 22 additions & 0 deletions scripts/integrations-cli/helpers/catalog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import json
import os
from functools import cache

from returns.io import impure_safe

from . import constants, validate


@impure_safe
def _load_catalog_file() -> dict:
catalog_path = os.path.join(constants.SCHEMA_ROOT, "observability/catalog.json")
with open(catalog_path, "r", encoding="utf-8") as catalog_file:
return json.load(catalog_file)


class CatalogManager:
@cache
def __init__(self):
catalog = _load_catalog_file().bind_result(validate.validate_catalog)
# For now just re-throw exceptions on catalog load failure
self.catalog = catalog.unwrap()._inner_value
25 changes: 25 additions & 0 deletions scripts/integrations-cli/helpers/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import glob
import json
import os

SCHEMA_ROOT = "../../src/main/resources/schema"

DEFAULT_CONFIG = {
"template-name": "default",
"version": {"integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0"},
"description": "",
"identification": "",
"catalog": "observability",
"components": [],
"collection": [],
"repository": {"url": "https://example.com/"},
}

SCHEMAS = {}

# For now, assume we're running in the current relative directory
if os.path.isdir(SCHEMA_ROOT):
for filename in glob.glob(os.path.join(SCHEMA_ROOT, "**/*.schema"), recursive=True):
schema_name = os.path.split(filename)[1]
with open(filename, "r", encoding="utf-8") as schema_file:
SCHEMAS[schema_name] = json.load(schema_file)
61 changes: 61 additions & 0 deletions scripts/integrations-cli/helpers/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import json
import os
import re
from copy import deepcopy
from urllib import parse

from .constants import DEFAULT_CONFIG
from .validate import validate_config


class IntegrationBuilder:
def __init__(self):
self.path = None
self.config = deepcopy(DEFAULT_CONFIG)

def with_name(self, name: str) -> "IntegrationBuilder":
self.config["template-name"] = name
return self

def with_path(self, path: str) -> "IntegrationBuilder":
self.path = path
self.config["repository"]["url"] = f"file://{path}"
return self

def with_schema_version(self, version: str) -> "IntegrationBuilder":
if not re.match(r"^\d+\.\d+\.\d+", version):
raise ValueError("Invalid version")
self.config["version"]["schema"] = version
return self

def with_resource_version(self, version: str) -> "IntegrationBuilder":
if not re.match(r"^\^?\d+\.\d+\.\d+", version):
raise ValueError("Invalid version")
self.config["version"]["resource"] = version
return self

def with_description(self, desc: str) -> "IntegrationBuilder":
self.config["description"] = desc
return self

def with_catalog(self, catalog: str) -> "IntegrationBuilder":
self.config["catalog"] = catalog
return self

def with_repository(self, repo_url: str) -> "IntegrationBuilder":
if not parse.urlparse(repo_url, allow_fragments=False):
raise ValueError("Invalid URL")
self.config["repository"]["url"] = repo_url
return self

def with_component(self, component: dict) -> "IntegrationBuilder":
self.config["components"].append(component)
return self

def build(self):
assert self.path is not None
os.makedirs(self.path, exist_ok=True)
files = {"config.json": validate_config(self.config).unwrap()}
for filename, data in files.items():
with open(os.path.join(self.path, filename), "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=2)
29 changes: 29 additions & 0 deletions scripts/integrations-cli/helpers/validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import jsonschema
from returns.result import Failure, Result, safe

from .constants import SCHEMAS


@safe(
exceptions=(
jsonschema.exceptions.ValidationError,
jsonschema.exceptions.SchemaError,
)
)
def validate_instance(instance: dict, schema: dict) -> dict:
jsonschema.validate(instance, schema)
return instance


def validate_config(config: dict) -> Result[dict, Exception]:
try:
return validate_instance(config, SCHEMAS["integration.schema"])
except KeyError as err:
return Failure(err)


def validate_catalog(catalog: dict) -> Result[dict, Exception]:
try:
return validate_instance(catalog, SCHEMAS["catalog.schema"])
except KeyError as err:
return Failure(err)
Loading