Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
66 changes: 66 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## Available Commands
(Explore more advanced options in the code, this is basic usage demonstration)

### generate-item-yaml
Generate an `item.yaml` file (basic draft) in the appropriate directory from a Jinja2 template

Usage:
`python -m cli.cli generate-item-yaml TYPE NAME`

Example:
`python -m cli.cli generate-item-yaml function aggregate`

---

### item-to-function
Creates a `function.yaml` file based on a provided `item.yaml` file.

Usage:
`python -m cli.cli item-to-function --item-path PATH`

Example:
`python -m cli.cli item-to-function --item-path functions/src/aggregate`

---

### function-to-item
Creates a `item.yaml` file based on a provided `function.yaml` file.

Usage:
`python -m cli.cli function-to-item PATH`

Example:
`python -m cli.cli function-to-item --path functions/src/aggregate`

---

### run-tests
Run assets test suite.

Usage:
`python -m cli.cli run-tests -r PATH -s TYPE -fn NAME`

Example:
`python -m cli.cli run-tests -r functions/src/aggregate -s py -fn aggregate`

---

### build-marketplace
Build and push (create a PR) the updated marketplace/<TYPE> directory (e.g: marketplace/functions)

Usage:
`python -m cli.cli build-marketplace -s SOURCE-DIR -sn TYPE -m MARKETPLACE-DIR -c CHANNEL -v -f`

Example:
`python -m cli.cli build-marketplace -s ./functions/src -sn functions -m marketplace -c master -v -f`

---

### update-readme
Regenerate the `README.md` files in each of the asset directories (functions/modules).

Usage:
`python -m cli.cli update-readme --asset TYPE`

Example:
`python -m cli.cli update-readme --asset functions --asset modules`
7 changes: 2 additions & 5 deletions cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,19 @@
from cli.functions.function_to_item import function_to_item_cli
from cli.functions.item_to_function import item_to_function_cli
from cli.marketplace.build import build_marketplace_cli
from cli.functions.new_function_item import new_item as new_function_item
from cli.common.test_suite import test_suite
from cli.common.item_yaml import update_functions_yaml
from cli.common.update_readme import update_readme
from cli.common.generate_item_yaml import generate_item_yaml

@click.group()
def cli():
pass


cli.add_command(new_function_item)
cli.add_command(generate_item_yaml, name="generate-item-yaml")
cli.add_command(item_to_function_cli, name="item-to-function")
cli.add_command(function_to_item_cli, name="function-to-item")
cli.add_command(test_suite, name="run-tests")
cli.add_command(build_marketplace_cli, name="build-marketplace")
cli.add_command(update_functions_yaml, name="update-functions-yaml")
cli.add_command(update_readme, name="update-readme")

if __name__ == "__main__":
Expand Down
55 changes: 55 additions & 0 deletions cli/common/generate_item_yaml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import sys
from pathlib import Path
from datetime import datetime
import click
from jinja2 import Environment, FileSystemLoader

TEMPLATES = {
"function": "cli/utils/function_item_template.yaml.j2",
"module": "cli/utils/module_item_template.yaml.j2",
}


@click.command()
@click.argument("type", type=click.Choice(list(TEMPLATES.keys())))
@click.argument("name")
@click.option("--overwrite", is_flag=True, help="Replace existing file instead of raising an error.")
def generate_item_yaml(type: str, name: str, overwrite: bool = False):
"""
Generate an item.yaml file from a template.

type: one of the supported types (currently only `function` or `module`)
name: the function/module name (also used as the directory name)
overwrite: whether to overwrite existing item.yaml file
"""
# Construct the target path
path = Path(f"{type}s/src/{name}").resolve()
output_file = path / "item.yaml"

if not overwrite and output_file.exists():
click.echo(f"Error: {output_file} already exists.", err=True)
sys.exit(1)

if not path.exists():
click.echo(f"Error: {path} does not exist.", err=True)
sys.exit(1)

# Render parameters
params = {
"example": f"{name}.ipynb",
"generationDate": datetime.utcnow().strftime("%Y-%m-%d"),
"name": name,
"filename": f"{name}.py",
}

# Load and render template
env = Environment(loader=FileSystemLoader("."))

Check warning

Code scanning / CodeQL

Jinja2 templating with autoescape=False Medium

Using jinja2 templates with autoescape=False can potentially allow XSS attacks.

Copilot Autofix

AI 10 days ago

To fix the problem, we should pass a safe value for autoescape while creating the Jinja2 Environment. The most robust and future-proof way is to use Jinja2’s select_autoescape function, which will auto-enable escaping for html and xml templates, and otherwise leave it disabled (as is safe for YAML). This is the officially recommended approach and the least disruptive.

  • Import select_autoescape from Jinja2.
  • Change line 46 to:
    env = Environment(loader=FileSystemLoader("."), autoescape=select_autoescape(['html', 'xml']))

No further changes are needed unless CLI generates HTML/XML templates in the future, in which case this configuration would protect those, too.


Suggested changeset 1
cli/common/generate_item_yaml.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/cli/common/generate_item_yaml.py b/cli/common/generate_item_yaml.py
--- a/cli/common/generate_item_yaml.py
+++ b/cli/common/generate_item_yaml.py
@@ -2,7 +2,7 @@
 from pathlib import Path
 from datetime import datetime
 import click
-from jinja2 import Environment, FileSystemLoader
+from jinja2 import Environment, FileSystemLoader, select_autoescape
 
 TEMPLATES = {
     "function": "cli/utils/function_item_template.yaml.j2",
@@ -43,7 +43,7 @@
     }
 
     # Load and render template
-    env = Environment(loader=FileSystemLoader("."))
+    env = Environment(loader=FileSystemLoader("."), autoescape=select_autoescape(['html', 'xml']))
     template = env.get_template(TEMPLATES[type])
     rendered = template.render(params)
 
EOF
@@ -2,7 +2,7 @@
from pathlib import Path
from datetime import datetime
import click
from jinja2 import Environment, FileSystemLoader
from jinja2 import Environment, FileSystemLoader, select_autoescape

TEMPLATES = {
"function": "cli/utils/function_item_template.yaml.j2",
@@ -43,7 +43,7 @@
}

# Load and render template
env = Environment(loader=FileSystemLoader("."))
env = Environment(loader=FileSystemLoader("."), autoescape=select_autoescape(['html', 'xml']))
template = env.get_template(TEMPLATES[type])
rendered = template.render(params)

Copilot is powered by AI and may make mistakes. Always verify output.
template = env.get_template(TEMPLATES[type])
rendered = template.render(params)

output_file.write_text(rendered)
click.echo(f"Created {output_file}")


if __name__ == "__main__":
generate_item_yaml()
54 changes: 0 additions & 54 deletions cli/common/item_yaml.py

This file was deleted.

67 changes: 0 additions & 67 deletions cli/functions/new_function_item.py

This file was deleted.

22 changes: 22 additions & 0 deletions cli/utils/function_item_template.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: v1
categories: [] {# List of category names #}
description: '' {# Short description #}
doc: '' {# Path to README.md if exists #}
example: {{ example|default('') }} {# Path to example notebook #}
generationDate: {{ generationDate|default('') }} {# Automatically generated ISO8086 datetime #}
hidden: false {# Hide function from the UI #}
icon: '' {# Path to icon file #}
labels: {# Key values label pairs #}
author: Iguazio
maintainers: [] {# List of maintainers #}
mlrunVersion: '' {# Function’s MLRun version requirement, should follow python’s versioning schema #}
name: {{ name|default('') }} {# Function name #}
platformVersion: '' {# Function’s Iguazio version requirement, should follow python’s versioning schema #}
spec:
filename: {{ filename|default('') }} {# Implementation file #}
handler: '' {# Handler function name #}
image: mlrun/mlrun {# Base image name #}
kind: '' {# Function kind #}
requirements: [] {# List of Pythonic library requirements #}
url: ''
version: 1.0.0 {# Function version, should follow standard semantic versioning schema #}
21 changes: 0 additions & 21 deletions cli/utils/item_template.yaml

This file was deleted.

16 changes: 16 additions & 0 deletions cli/utils/module_item_template.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
categories: [] {# List of category names #}
description: '' {# Short description #}
example: {{ example|default('') }} {# Path to example notebook #}
generationDate: {{ generationDate|default('') }} {# Automatically generated ISO8086 datetime #}
hidden: false {# Hide Module from the UI #}
labels:
author: Iguazio
mlrunVersion: '' {# Module’s MLRun version requirement, should follow python’s versioning schema #}
name: {{ name|default('') }} {# Module name #}
spec:
filename: {{ filename|default('') }} {# Implementation file #}
image: mlrun/mlrun {# Base image name #}
kind: '' {# Module kind #}
requirements: [] {# List of Pythonic library requirements #}
version: 1.0.0 {# Module version, should follow standard semantic versioning schema #}
2 changes: 1 addition & 1 deletion functions/src/aggregate/item.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ generationDate: 2022-08-28:17-25
hidden: false
icon: ''
labels:
author: avia
author: Iguazio
maintainers: []
marketplaceType: ''
mlrunVersion: 1.7.0
Expand Down
2 changes: 1 addition & 1 deletion functions/src/arc_to_parquet/item.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ generationDate: 2022-08-28:17-25
hidden: false
icon: ''
labels:
author: avi
author: Iguazio
maintainers: []
marketplaceType: ''
mlrunVersion: 1.7.0
Expand Down
2 changes: 1 addition & 1 deletion functions/src/auto_trainer/item.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ generationDate: 2022-08-28:17-25
hidden: false
icon: ''
labels:
author: yonish
author: Iguazio
maintainers: []
marketplaceType: ''
mlrunVersion: 1.7.0
Expand Down
2 changes: 1 addition & 1 deletion functions/src/azureml_serving/function.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
hash: c0f404820b8f0fe92d2d1cfe9dbcc068be1a13bf
project: ''
labels:
author: yonish
author: Iguazio
categories:
- machine-learning
- model-serving
Expand Down
2 changes: 1 addition & 1 deletion functions/src/azureml_serving/item.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ generationDate: 2022-08-28:17-25
hidden: false
icon: ''
labels:
author: yonish
author: Iguazio
maintainers: []
marketplaceType: ''
mlrunVersion: 1.1.0
Expand Down
2 changes: 1 addition & 1 deletion functions/src/azureml_utils/item.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ generationDate: 2022-08-28:17-25
hidden: false
icon: ''
labels:
author: yonish
author: Iguazio
maintainers: []
marketplaceType: ''
mlrunVersion: 1.7.0
Expand Down
Loading
Loading