Skip to content

Commit

Permalink
Add: concept of preset to zapper-iot connector (#401)
Browse files Browse the repository at this point in the history
* Add: concept of preset for zapper-iot connector

* change: tplan -> test_plan

* renamed testplan to provisionplan

* copy SSH keys at the end of provisioning
  • Loading branch information
p-gentili authored Dec 18, 2024
1 parent acffcba commit a923829
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from testflinger_device_connectors.devices import ProvisioningError
from testflinger_device_connectors.devices.zapper_iot.parser import (
validate_provision_plan,
validate_url,
validate_urls,
)

logger = logging.getLogger(__name__)
Expand All @@ -37,16 +37,41 @@ def _validate_configuration(
Validate the job config and data and prepare the arguments
for the Zapper `provision` API.
"""
try:
provision_plan = self.job_data["provision_data"]["provision_plan"]
validate_provision_plan(provision_plan)
except KeyError as e:
raise ProvisioningError from e

username = self.job_data.get("test_data", {}).get(
"test_username", "ubuntu"
)
password = self.job_data.get("test_data", {}).get(
"test_password", "ubuntu"
)

provisioning_data = {
"username": username,
"password": password,
"preset": self.job_data["provision_data"].get("preset"),
"reboot_script": self.config["reboot_script"],
}

provision_plan = self.job_data["provision_data"].get("provision_plan")
if provision_plan:

try:
validate_provision_plan(provision_plan)

# Make sure the user created at provision time is
# the same used during the test phase.
provision_plan["config"]["username"] = username
provision_plan["config"]["password"] = password

provisioning_data["custom_provision_plan"] = provision_plan
except ValueError as e:
raise ProvisioningError from e

urls = self.job_data["provision_data"].get("urls", [])
try:
url = self.job_data["provision_data"]["url"]
validate_url(url)
except KeyError:
url = []
validate_urls(urls)
except ValueError as e:
raise ProvisioningError from e
provisioning_data["urls"] = urls

return ((provision_plan, url), {})
return ((), provisioning_data)
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import validators
import jsonschema
from jsonschema import validate
from typing import List

logger = logging.getLogger(__name__)

TPLAN_SCHEMA = {
TESTPLAN_SCHEMA = {
"type": "object",
"properties": {
"config": {
Expand Down Expand Up @@ -197,16 +198,25 @@


def validate_provision_plan(data):
"""for verify provision yaml"""
"""
Validate whether the provided custom testplan
is valid in terms of schema.
"""
try:
validate(instance=data, schema=TPLAN_SCHEMA)
validate(instance=data, schema=TESTPLAN_SCHEMA)
logger.info("the JSON data is valid")
except jsonschema.exceptions.ValidationError as err:
raise ValueError("the JSON data is invalid") from err


def validate_url(url):
"""for verify url"""
for link in url:
if not validators.url(link):
def validate_urls(urls: List[str]):
"""
Validate whether the provided URL
is valid in terms of format.
We cannot assert for resource availability here,
since this is not the host downloading the content.
"""
for url in urls:
if not validators.url(url):
raise ValueError("url format is not correct")
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import unittest

from testflinger_device_connectors.devices import ProvisioningError
from testflinger_device_connectors.devices.zapper_iot import DeviceConnector


class ZapperIoTTests(unittest.TestCase):
"""Test Cases for the Zapper IoT class."""

def test_validate_configuration(self):
"""
Test the function creates a proper provision_data
dictionary when valid data are provided.
"""

device = DeviceConnector()
device.job_data = {
"provision_data": {
"preset": "TestPreset",
"urls": ["http://test.tar.gz"],
}
}
device.config = {"reboot_script": ["cmd1", "cmd2"]}

args, kwargs = device._validate_configuration()

expected = {
"username": "ubuntu",
"password": "ubuntu",
"preset": "TestPreset",
"reboot_script": ["cmd1", "cmd2"],
"urls": ["http://test.tar.gz"],
}

self.assertEqual(args, ())
self.assertDictEqual(kwargs, expected)

def test_validate_configuration_provision_plan(self):
"""
Test the function validates a custom test plan
when provided.
"""

device = DeviceConnector()
device.job_data = {
"provision_data": {
"provision_plan": {
"config": {
"project_name": "name",
"username": "admin",
"password": "admin",
"serial_console": {
"port": "/dev/ttySanity1",
"baud_rate": 115200,
},
"network": "eth0",
"hostname": "C031051825-00136",
},
"run_stage": [
{"initial_login": {"method": "system-user"}},
],
}
}
}
device.config = {"reboot_script": ["cmd1", "cmd2"]}

args, kwargs = device._validate_configuration()

expected = {
"username": "ubuntu",
"password": "ubuntu",
"custom_provision_plan": {
"config": {
"project_name": "name",
"username": "ubuntu", # this gets overridden
"password": "ubuntu",
"serial_console": {
"port": "/dev/ttySanity1",
"baud_rate": 115200,
},
"network": "eth0",
"hostname": "C031051825-00136",
},
"run_stage": [
{"initial_login": {"method": "system-user"}},
],
},
"urls": [],
"reboot_script": ["cmd1", "cmd2"],
"preset": None,
}
self.maxDiff = None
self.assertEqual(args, ())
self.assertDictEqual(expected, kwargs)

def test_validate_configuration_invalid_url(self):
"""
Test the function raises an exception if one of
the url is not valid.
"""

device = DeviceConnector()
device.job_data = {
"provision_data": {
"urls": ["not-a-url"],
}
}
device.config = {"reboot_script": ["cmd1", "cmd2"]}

with self.assertRaises(ProvisioningError):
device._validate_configuration()

def test_validate_configuration_invalid_provision_plan(self):
"""
Test the function raises an exception if the
provided custom testplan is not valid.
"""

device = DeviceConnector()
device.job_data = {
"provision_data": {"provision_plan": {"key1": "value1"}}
}
device.config = {"reboot_script": []}

with self.assertRaises(ProvisioningError):
device._validate_configuration()

0 comments on commit a923829

Please sign in to comment.