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

Feat user group mgmt #151

Merged
merged 3 commits into from
Jun 22, 2024
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,8 @@ Network Trash Folder
Temporary Items
.apdisk
*.icloud

# virlutils test
5f0d96_inventory.ini
5f0d96_inventory.yaml
5f0d96_testbed.yaml
15 changes: 14 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,17 @@ With those settings, navigate to **View > Testing** in VSCode. The view should

### Code Style

Additionally, the code should follow any stylistic and architectural guidelines prescribed by the project. The project now uses [black](https://black.readthedocs.io/) to ensure consistent code formatting. When you installed the requirements_dev.txt in your virtual environment, it installed the `black` command. For each file that you are modifying, run `black ./virl/path/to/file.py` before you commit the file or submit a pull request.
Additionally, the code should follow any stylistic and architectural guidelines prescribed by the project. The project now uses [black](https://black.readthedocs.io/) and [isort](https://pycqa.github.io/isort/) to ensure consistent code formatting. When you installed the requirements_dev.txt in your virtual environment, it installed the `black` and `isort` commands. For each file that you are modifying, run the following before you commit the file or submit a pull request:

```sh
black ./virl/path/to/file.py
isort ./virl/path/to/file.py
```

### Linting

We use flake 8 to lint our code. Please keep the repository clean by running:

```sh
flake8
```
290 changes: 263 additions & 27 deletions README.md

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions examples/plugins/csv_inv.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from virl.api import GeneratorPlugin
import click
import csv
from virl.api import VIRLServer
from virl.helpers import get_current_lab, get_cml_client, safe_join_existing_lab, get_node_mgmt_ip

import click

from virl.api import GeneratorPlugin, VIRLServer
from virl.helpers import (get_cml_client, get_current_lab, get_node_mgmt_ip,
safe_join_existing_lab)


class CSVInventory(GeneratorPlugin, generator="csv"):
Expand Down
7 changes: 4 additions & 3 deletions examples/plugins/retitle_cmd.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from virl.api import CommandPlugin
import click
from virl.api import VIRLServer
from virl.helpers import get_cml_client, get_current_lab, safe_join_existing_lab

from virl.api import CommandPlugin, VIRLServer
from virl.helpers import (get_cml_client, get_current_lab,
safe_join_existing_lab)


class RetitleCommand(CommandPlugin, command="retitle"):
Expand Down
15 changes: 8 additions & 7 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
pip
Flask
Sphinx
black
bumpversion
wheel
watchdog
coverage
flake8
Flask
isort
pip
requests-mock
tox
coverage
Sphinx
twine
watchdog
wheel
white
requests-mock
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# coding: utf-8
from setuptools import setup, find_packages # noqa: H301
from setuptools import find_packages, setup # noqa: H301

from virl import __version__

NAME = "virlutils"
Expand Down
11 changes: 6 additions & 5 deletions tests/v2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import functools
import logging
import os
import unittest
from click.testing import CliRunner
from .mocks import MockCMLServer
import functools
import pdb
import sys
import traceback
import pdb
import unittest

import requests_mock
import respx
from click.testing import CliRunner
from httpx import Response
from virl2_client import ClientLibrary

from .mocks import MockCMLServer

# set to warning to hide unwanted HTTP requests
logger = logging.getLogger("httpx")
Expand Down
9 changes: 6 additions & 3 deletions tests/v2/bad_plugins.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from . import BaseCMLTest
from virl.api.plugin import _test_enable_plugins
from click.testing import CliRunner
import os

from click.testing import CliRunner

from virl.api.plugin import _test_enable_plugins

from . import BaseCMLTest

try:
from unittest.mock import patch
except ImportError:
Expand Down
6 changes: 4 additions & 2 deletions tests/v2/cluster.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import unittest
from . import BaseCMLTest, CLIENT_VERSION
from .mocks.github import MockGitHub # noqa

from click.testing import CliRunner

from . import CLIENT_VERSION, BaseCMLTest
from .mocks.github import MockGitHub # noqa

try:
from unittest.mock import patch
except ImportError:
Expand Down
3 changes: 2 additions & 1 deletion tests/v2/console.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from . import BaseCMLTest
from click.testing import CliRunner

from . import BaseCMLTest

try:
from unittest.mock import patch
except ImportError:
Expand Down
8 changes: 5 additions & 3 deletions tests/v2/definitions.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from . import BaseCMLTest
from click.testing import CliRunner
import textwrap
import os
import textwrap
import traceback

from click.testing import CliRunner

from . import BaseCMLTest


class CMLDefinitionsTest(BaseCMLTest):

Expand Down
6 changes: 4 additions & 2 deletions tests/v2/down.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from . import BaseCMLTest
from click.testing import CliRunner
import os

from click.testing import CliRunner

from . import BaseCMLTest


class CMLTestDown(BaseCMLTest):
def setup_mocks(self, m):
Expand Down
6 changes: 4 additions & 2 deletions tests/v2/extract.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from . import BaseCMLTest
from click.testing import CliRunner
import os

from click.testing import CliRunner

from . import BaseCMLTest


class CMLExtractTests(BaseCMLTest):
def test_cml_extract(self):
Expand Down
3 changes: 2 additions & 1 deletion tests/v2/generate_ansible.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from . import BaseCMLTest
from click.testing import CliRunner

from . import BaseCMLTest


class Tests(BaseCMLTest):
data = {
Expand Down
5 changes: 3 additions & 2 deletions tests/v2/generate_nso.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import requests_mock
from click.testing import CliRunner

from . import BaseCMLTest
from .mocks.nso import MockNSOServer
from click.testing import CliRunner
import requests_mock


class Tests(BaseCMLTest):
Expand Down
3 changes: 2 additions & 1 deletion tests/v2/generate_pyats.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from . import BaseCMLTest
from click.testing import CliRunner

from . import BaseCMLTest


class Tests(BaseCMLTest):
def test_virl_generate_pyats(self):
Expand Down
9 changes: 6 additions & 3 deletions tests/v2/good_plugins.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from . import BaseCMLTest
from virl.api.plugin import _test_enable_plugins
from click.testing import CliRunner
import os

from click.testing import CliRunner

from virl.api.plugin import _test_enable_plugins

from . import BaseCMLTest


class CMLGoodPluginTest(BaseCMLTest):
def setUp(self):
Expand Down
150 changes: 150 additions & 0 deletions tests/v2/groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
from click.testing import CliRunner

from . import BaseCMLTest


class TestCMLGroups(BaseCMLTest):
get_users = [
{
"id": "00000000-0000-4000-a000-000000000000",
"created": "2022-09-30T10:03:53+00:00",
"modified": "2024-06-21T15:16:42+00:00",
"username": "admin",
"fullname": "",
"email": "",
"description": "",
"admin": True,
"directory_dn": "",
"groups": [],
"labs": [],
"opt_in": True,
"resource_pool": None,
"tour_version": "2.6.1+build.11",
"pubkey_info": "",
},
{
"id": "9e4e75b4-aaab-47af-9edb-9364460a81ae",
"created": "2024-06-19T20:29:02+00:00",
"modified": "2024-06-21T10:42:20+00:00",
"username": "user",
"fullname": "",
"email": "",
"description": "",
"admin": False,
"directory_dn": "",
"groups": ["48c9c605-552f-4666-bd23-5b68cf4de665"],
"labs": [],
"opt_in": True,
"resource_pool": None,
"tour_version": "",
"pubkey_info": "",
},
]
post_groups = {
"id": "48c9c605-552f-4666-bd23-5b68cf4de665",
"created": "2024-02-29T21:44:13+00:00",
"modified": "2024-02-29T21:45:04+00:00",
"name": "group",
"description": "",
"members": ["00000000-0000-4000-a000-000000000000"],
"labs": [
{"id": "88119b68-9d08-40c4-90f5-6dc533fd0254", "permission": "read_write"},
],
}

patch_groups = post_groups

get_groups = [
{
"id": "48c9c605-552f-4666-bd23-5b68cf4de665",
"created": "2024-02-29T21:44:13+00:00",
"modified": "2024-02-29T21:45:04+00:00",
"name": "group",
"description": "",
"members": ["00000000-0000-4000-a000-000000000000"],
"labs": [
{"id": "88119b68-9d08-40c4-90f5-6dc533fd0254", "permission": "read_write"},
],
},
]

def test_cml_groups_ls(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "users", json=self.get_users)
self.setup_func("get", m, "groups", json=self.get_groups)
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "ls"])
self.assertEqual(0, result.exit_code)

def test_cml_groups_ls_verbose(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "users", json=self.get_users)
self.setup_func("get", m, "groups", json=self.get_groups)
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "ls", "--verbose"])
self.assertEqual(0, result.exit_code)

def test_cml_groups_create_group(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "users", json=self.get_users)
self.setup_func("post", m, "groups", json=self.post_groups)
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "create", "group"])
self.assertEqual(0, result.exit_code)

def test_cml_groups_create_group_fail(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "users", json=self.get_users)
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "create", "group"])
self.assertEqual(1, result.exit_code)

def test_cml_groups_update_group(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "users", json=self.get_users)
self.setup_func("get", m, "groups", json=self.get_groups)
self.setup_func("patch", m, "groups/48c9c605-552f-4666-bd23-5b68cf4de665", json=self.patch_groups)
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "update", "group"])
self.assertEqual(0, result.exit_code)

def test_cml_groups_update_group_fail(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "users", json=self.get_users)
self.setup_func("get", m, "groups", json=self.get_groups)
self.setup_func("patch", m, "groups/48c9c605-552f-4666-bd23-5b68cf4de665", json=self.patch_groups)
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "update", "nonexistent_group"])
self.assertEqual(1, result.exit_code)

def test_cml_groups_delete_group(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "groups", json=self.get_groups)
self.setup_func("delete", m, "groups/48c9c605-552f-4666-bd23-5b68cf4de665")
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "delete", "group"])
self.assertEqual(0, result.exit_code)

def test_cml_groups_delete_group_fail(self):
with self.get_context() as m:
self.setup_mocks(m)
self.setup_func("get", m, "groups", json=self.get_groups)
self.setup_func("delete", m, "groups/48c9c605-552f-4666-bd23-5b68cf4de665")
virl = self.get_virl()
runner = CliRunner()
result = runner.invoke(virl, ["groups", "delete", "nonexistent_group"])
self.assertEqual(1, result.exit_code)
3 changes: 2 additions & 1 deletion tests/v2/id.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from . import BaseCMLTest
from click.testing import CliRunner

from . import BaseCMLTest


class CMLIdTest(BaseCMLTest):
def test_cml_id(self):
Expand Down
3 changes: 2 additions & 1 deletion tests/v2/ls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from . import BaseCMLTest
from click.testing import CliRunner

from . import BaseCMLTest


class TestCMLLs(BaseCMLTest):
def test_cml_ls_all(self):
Expand Down
Loading
Loading