Skip to content

Commit

Permalink
Merge pull request #3 from tenable/feature/additional-testing-and-imp…
Browse files Browse the repository at this point in the history
…rovements

Additional Testing & other improments
  • Loading branch information
SteveMcGrath authored Jan 7, 2025
2 parents ca5d8d8 + 0c4e684 commit dee0bd1
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 36 deletions.
15 changes: 5 additions & 10 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Pull package data
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Setup up uv
run: curl -LsSf https://astral.sh/uv/0.4.5/install.sh | sh
- uses: astral-sh/setup-uv@v5

- name: Install dependencies
run: uv sync --all-extras --dev
Expand All @@ -41,8 +36,8 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.8"
- uses: yezz123/setup-uv@v4
python-version: "3.12"
- uses: astral-sh/setup-uv@v5
- uses: snyk/actions/setup@master
- name: Export a requirements file for Snyk
run: |
Expand Down
2 changes: 1 addition & 1 deletion tenint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
from .models.configuration import Configuration, Settings # noqa F401
from .connector import Connector # noqa F401

__version__ = '0.1.6'
__version__ = '0.1.7'
12 changes: 7 additions & 5 deletions tenint/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

@app.command('init')
def init_connector(
path: Annotated[Path, Option(help='initialization path')] = Path('.'),
path: Annotated[
Path, Option(help='initialization path', dir_okay=True, file_okay=False)
] = Path('.'),
):
is_dirty = False
for fn in ('pyproject.toml', 'connector.py'):
Expand All @@ -35,16 +37,16 @@ def init_connector(
with src.open('rb') as sobj, dest.open('wb') as dobj:
dobj.write(sobj.read())

tests = dest.joinpath('tests')
tests = path.joinpath('tests')
if not tests.exists():
tests.mkdir()
src = tests.joinpath('test_connector.py')
dest = tmpl.joinpath('test_connector.py')
src = tmpl.joinpath('test_connector.py')
dest = tests.joinpath('test_connector.py')
with dest.open('wb') as dobj, src.open('rb') as sobj:
dobj.write(sobj.read())
else:
console.print(
'[yellow bold]NOTE[/yellod bold]: skipped adding tests. tests folder exists.'
'[yellow bold]NOTE[/yellow bold]: skipped adding tests. tests folder exists.'
)

console.print(
Expand Down
11 changes: 10 additions & 1 deletion tenint/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,15 @@ def cmd_run(
case_sensitive=False,
),
] = LogLevel.info,
since: Annotated[
int | None,
Option(
'--since',
'-s',
envvar='SINCE',
help='When did the last successful run start?',
),
] = None,
):
"""
Invoke the connector
Expand All @@ -214,7 +223,7 @@ def cmd_run(

try:
config = self.fetch_config(json_data, filename)
self.main(config=config)
self.main(config=config, since=since)
except (ValidationError, ConfigurationError) as exc:
self.console.print(exc)
status_code = 2
Expand Down
4 changes: 2 additions & 2 deletions tenint/models/configuration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Self
from typing import Any

from pydantic import BaseModel, ConfigDict, Field, computed_field, model_validator
from pydantic import BaseModel, ConfigDict, Field, computed_field

from .credentials import Credential

Expand Down
14 changes: 3 additions & 11 deletions tenint/models/credentials.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Literal

from pydantic import AnyHttpUrl, BaseModel, ConfigDict, computed_field
from pydantic import AnyHttpUrl, BaseModel, ConfigDict, SecretStr, computed_field


def credential_schema(schema: dict[str, Any]) -> None:
Expand Down Expand Up @@ -41,14 +41,10 @@ class TenableVMCredential(Credential):
'Tenable Vulnerability Management'
)
slug: Literal['tvm'] = 'tvm'
<<<<<<< HEAD
description: str = 'Tenable Vulnerability Management Credential'
=======
definition: str = 'Tenable Vulnerability Management Credential'
>>>>>>> fe11665 (Updated Credentials to include description)
url: AnyHttpUrl = 'https://cloud.tenable.com'
access_key: str
secret_key: str
secret_key: SecretStr


class TenableSCCredential(Credential):
Expand All @@ -59,11 +55,7 @@ class TenableSCCredential(Credential):
prefix: Literal['tio'] = 'tsc'
name: Literal['Tenable Security Center'] = 'Tenable Security Center'
slug: Literal['tvm'] = 'tsc'
<<<<<<< HEAD
description: str = 'Tenable Security Center Credential'
=======
definition: str = 'Tenable Security Center Credential'
>>>>>>> fe11665 (Updated Credentials to include description)
url: AnyHttpUrl
access_key: str
secret_key: str
secret_key: SecretStr
4 changes: 3 additions & 1 deletion tenint/models/marketplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import tomllib
from pathlib import Path

from pydantic import AnyHttpUrl, BaseModel, EmailStr, Field
from pydantic import AnyHttpUrl, BaseModel, EmailStr

from .pyproject import PyProject

Expand All @@ -14,6 +14,7 @@ class MarketplaceConnector(BaseModel):
description: str
icon_url: AnyHttpUrl
image_url: str
timeout: int
marketplace_tag: str
connector_owner: str
support_contact: EmailStr
Expand Down Expand Up @@ -54,6 +55,7 @@ def load_from_pyproject(
description=obj.project.description,
icon_url=icon_url,
image_url=image_url,
timeout=obj.tool.tenint.connector.timeout,
marketplace_tag=obj.project.version,
connector_owner=obj.project.authors[0].name,
support_contact=obj.project.authors[0].email,
Expand Down
2 changes: 1 addition & 1 deletion tenint/templates/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AppSettings(Settings):


@connector.job
def main(config: AppSettings):
def main(config: AppSettings, since: int | None = None):
log.debug('This is a debug test')
log.info('this is an info test')
log.warning('this is a warning')
Expand Down
Empty file.
41 changes: 41 additions & 0 deletions tests/models/test_marketplace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from tenint.models.marketplace import MarketplaceConnector


def test_load_from_pyproject(tmpdir):
pf = tmpdir.join('pyproject-pass.toml')
pf.write("""
[project]
name = "example-connector"
version = "0.0.1"
description = "Example Description"
dependencies = []
[project.optional-dependencies]
testing = []
[project.urls]
support = "https://example.com/support"
[[project.authors]]
name = "Company"
email = "[email protected]"
[tool.tenint.connector]
title = "Example Connector"
tags = ["tvm", "example"]
""")
mp = MarketplaceConnector.load_from_pyproject(
pf,
icon_url='https://somewhere.com/img.png',
image_url='tenable/connector-example',
)
assert mp.name == 'Example Connector'
assert mp.slug == 'example-connector'
assert mp.description == 'Example Description'
assert str(mp.icon_url) == 'https://somewhere.com/img.png'
assert mp.image_url == 'tenable/connector-example'
assert mp.timeout == 3600
assert mp.marketplace_tag == '0.0.1'
assert mp.connector_owner == 'Company'
assert mp.support_contact == '[email protected]'
assert mp.tags == ['tvm', 'example']
32 changes: 32 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from typer.testing import CliRunner

from tenint.cli import app

runner = CliRunner()


def test_init_command(tmp_path):
result = runner.invoke(app, ['init', '--path', str(tmp_path)])
if result.exception:
raise result.exception
assert result.exit_code == 0
assert 'Now that you have' in result.stdout
assert 'skipped' not in result.stdout


def test_init_skip_single_file(tmp_path):
pyfile = tmp_path.joinpath('pyproject.toml')
with pyfile.open('w') as fobj:
fobj.write('something')
result = runner.invoke(app, ['init', '--path', str(tmp_path)])
assert result.exit_code == 0
assert 'Now that you have' in result.stdout
assert 'pyproject.toml as it already exists' in result.stdout


def test_init_skip_tests(tmp_path):
tmp_path.joinpath('tests').mkdir()
result = runner.invoke(app, ['init', '--path', str(tmp_path)])
assert result.exit_code == 0
assert 'Now that you have' in result.stdout
assert 'skipped adding tests' in result.stdout
4 changes: 2 additions & 2 deletions tests/test_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AppSettings(Settings):

@pytest.fixture
def main():
def main(config: dict[str, Any]):
def main(config: dict[str, Any], since: int | None = None):
log = logging.getLogger('main-test')
log.debug('This is a debug test')
log.info('This is an info test')
Expand Down Expand Up @@ -119,7 +119,7 @@ def test_connector_run_fail(AppSettings):
connector = Connector(settings=AppSettings)

@connector.job
def failmain(config: dict):
def failmain(config: dict, since: None = None):
raise Exception('I have failed')

result = runner.invoke(connector.app, ['run', '-j', '{"is_bool": true}'])
Expand Down
3 changes: 1 addition & 2 deletions uv.lock

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

0 comments on commit dee0bd1

Please sign in to comment.