diff --git a/agent/README.rst b/agent/README.rst index b2d6ac93..330dbd85 100644 --- a/agent/README.rst +++ b/agent/README.rst @@ -45,6 +45,10 @@ The following configuration options are supported: - Unique identifier for this agent +- **identifier**: + + - Additional identifier such as a serial number that will be sent to the server and can be used for cross-referencing with other systems + - **polling_interval**: - Time to sleep between polling for new tests (default: 10s) diff --git a/agent/testflinger_agent/agent.py b/agent/testflinger_agent/agent.py index 06d7b072..d10713d0 100644 --- a/agent/testflinger_agent/agent.py +++ b/agent/testflinger_agent/agent.py @@ -37,7 +37,12 @@ def _post_initial_agent_data(self): self._post_advertised_images() queues = self.client.config.get("job_queues", []) - self.client.post_agent_data({"queues": queues, "location": location}) + identifier = self.client.config.get("identifier") + agent_data = {"queues": queues, "location": location} + if identifier: + agent_data["identifier"] = identifier + + self.client.post_agent_data(agent_data) def _post_advertised_queues(self): """ diff --git a/agent/testflinger_agent/schema.py b/agent/testflinger_agent/schema.py index 723d7972..db4da1cf 100644 --- a/agent/testflinger_agent/schema.py +++ b/agent/testflinger_agent/schema.py @@ -17,6 +17,8 @@ SCHEMA_V1 = { voluptuous.Required("agent_id"): str, + voluptuous.Optional("identifier"): str, + voluptuous.Optional("location"): str, voluptuous.Required("polling_interval", default=10): int, voluptuous.Required("server_address"): str, voluptuous.Required( diff --git a/agent/testflinger_agent/tests/test_agent.py b/agent/testflinger_agent/tests/test_agent.py index 1773f4fd..56a59bbc 100644 --- a/agent/testflinger_agent/tests/test_agent.py +++ b/agent/testflinger_agent/tests/test_agent.py @@ -20,6 +20,7 @@ def agent(self, requests_mock): self.tmpdir = tempfile.mkdtemp() self.config = { "agent_id": "test01", + "identifier": "12345-123456", "polling_interval": "2", "server_address": "127.0.0.1:8000", "job_queues": ["test"], @@ -215,6 +216,7 @@ def test_post_agent_data(self, agent): agent._post_initial_agent_data() mock_post_agent_data.assert_called_with( { + "identifier": self.config["identifier"], "queues": self.config["job_queues"], "location": self.config["location"], } diff --git a/agent/testflinger_agent/tests/test_config.py b/agent/testflinger_agent/tests/test_config.py index d25cd88d..30c30fd8 100644 --- a/agent/testflinger_agent/tests/test_config.py +++ b/agent/testflinger_agent/tests/test_config.py @@ -21,8 +21,10 @@ GOOD_CONFIG = """ agent_id: test01 +identifier: 12345-123456 polling_interval: 10 server_address: 127.0.0.1:8000 +location: earth job_queues: - test """ diff --git a/docs/.wordlist.txt b/docs/.wordlist.txt index 8a7f7108..417470c7 100644 --- a/docs/.wordlist.txt +++ b/docs/.wordlist.txt @@ -4,6 +4,7 @@ APIs artifact artifacts balancer +BG CharmHub CLI CM3 @@ -70,6 +71,7 @@ runtime SDWire SecureBoot SKU +SSID subdirectories subfolders subtree @@ -85,5 +87,8 @@ USB UUID VM webhook +WPA xenial yaml +LTS +virtualenv diff --git a/docs/how-to/cancel-job.rst b/docs/how-to/cancel-job.rst new file mode 100644 index 00000000..1a87c5e7 --- /dev/null +++ b/docs/how-to/cancel-job.rst @@ -0,0 +1,13 @@ +Cancel a job +=============== + +You can cancel a Testflinger job at any point. However, if the job is in the middle of provisioning, it will finish provisioning before cancelling it completely. This prevents accidentally leaving a system in a bad, partially provisioned state. + +To cancel a job, run Testflinger CLI with the ``cancel`` argument and provide the job ID: + +.. code-block:: shell + + $ testflinger-cli cancel + + +If a job reaches the global timeout or any timeout for a specific operation, such as the output timeout, Testflinger will cancel the job automatically to release resources. In this case, you can resubmit the job or extend the timeout to allow more execution time. diff --git a/docs/how-to/change-server.rst b/docs/how-to/change-server.rst new file mode 100644 index 00000000..79f9d8de --- /dev/null +++ b/docs/how-to/change-server.rst @@ -0,0 +1,36 @@ +Connect to a different server +============================== + +By default, Testflinger CLI uses the default Testflinger server located at ``https://testflinger.canonical.com``. To specify a different server to use, you can either run Testflinger CLI with the ``--server`` parameter, or set an environment variable. + + +Specify the server in command line +--------------------------------------- + +Run the Testflinger CLI command with an ``--server `` argument. The server URI must start with either ``http://`` or ``https://``. For example: + +.. code-block:: shell + + $ testflinger-cli --server https://testflinger.example.com jobs + +However, if the environment variable ``TESTFLINGER_SERVER`` is set, this argument will be ignored. + + +Set an environment variable +----------------------------- + +If you want to use a server URI for all operations, you can set the environment variable ``TESTFLINGER_SERVER``. This variable overwrites the default server address and the string specified by the ``--server`` argument. + +To set an environment variable on Ubuntu: + +.. code-block:: shell + + $ export TESTFLINGER_SERVER="https://testflinger.example.com" + +If you want to change the environment variable permanently, add the export command to a system-wide or user-specific configuration file. + +To verify that the variable has been set, run: + +.. code-block:: shell + + $ printenv TESTFLINGER_SERVER diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index a5ddc12f..ecea6efa 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -1,6 +1,15 @@ How-to guides -============= +============== These how-to guides cover key operations and processes in Testflinger. +Work with jobs via Testflinger CLI +----------------------------------- +.. toctree:: + :maxdepth: 1 + + install-cli + change-server + submit-job + cancel-job diff --git a/docs/how-to/install-cli.rst b/docs/how-to/install-cli.rst new file mode 100644 index 00000000..978a3be1 --- /dev/null +++ b/docs/how-to/install-cli.rst @@ -0,0 +1,33 @@ +Install Testflinger CLI +======================== + +The ``testflinger-cli`` client is a command line tool used for interacting with Testflinger servers. You can use the client to submit test jobs to the devices under test (DUT), check the job status and get testing results. + +You can either install ``testflinger-cli`` through Snap or check out the code from our GitHub repository and run the tool in a Python virtual environment. + + +Install via Snap +----------------- +The most convenient way to get the CLI tool is via snap: + +.. code-block:: shell + + $ sudo snap install testflinger-cli + + +Install in virtual environment +------------------------------- + +If you are using the CLI from an automated test runner, such as Jenkins, you may want to install the tool in a virtual environment instead. + +To run it from the source code, please make sure that the ``python3-click`` and ``python3-requests`` packages are installed, and then run the following commands: + +.. code-block:: shell + + $ git clone https://github.com/canonical/testflinger + $ cd cli + $ virtualenv -p python3 env + $ . env/bin/activate + $ pip install . + + diff --git a/docs/how-to/submit-job.rst b/docs/how-to/submit-job.rst new file mode 100644 index 00000000..ddb04db1 --- /dev/null +++ b/docs/how-to/submit-job.rst @@ -0,0 +1,21 @@ +Submit a test job +=================== + +Once you have a YAML or JSON file with your :doc:`job definition <../reference/job-schema>`, you can submit the job to the main Testflinger server using the CLI: + +.. code-block:: shell + + $ testflinger-cli submit example-job.yaml + + +If you want to submit the jobs to a Testflinger server other than the default one, see :doc:`change-server`. + +If the job is successful submitted, you will see a ``job_id`` returned by Testflinger: + +.. code-block:: shell + + Job submitted successfully! + job_id: 2bac1457-0000-0000-0000-15f23f69fd39 + + +You can use the ``job_id`` to further monitor and manager the submitted job. diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 83ef8a42..cc32f893 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -9,6 +9,7 @@ Working with device connectors .. toctree:: :maxdepth: 1 + job-schema device-connector-types device-connector-conf diff --git a/docs/reference/job-schema.rst b/docs/reference/job-schema.rst new file mode 100644 index 00000000..3633e877 --- /dev/null +++ b/docs/reference/job-schema.rst @@ -0,0 +1,73 @@ +Test job schema +================= + +Test jobs can be defined in either YAML or JSON format. + +The following table lists the key elements that a job definition file should contain. + +.. list-table:: Test job schema + :header-rows: 1 + + * - Field + - Type + - Default + - Description + * - ``job_queue`` + - String + - / + - Name of the job queue to which you want to submit the job. This field is mandatory. + * - ``global_timeout`` + - integer + - | 14400 + | (4 hours) + - | (Optional) Maximum time (in seconds) a job is allowed to run. If the global timeout is reached while a job is still running, Testflinger will close the job immediately. + | You can set a global timeout larger than the default value, but the per-device configuration might have a more restrict timeout and overwrite the global value. + * - ``output_timeout`` + - integer + - | 900 + | (15 minutes) + - (Optional) Maximum time (in seconds) Testflinger should wait in the ``test`` phase to get output from the job. If the timeout is reached before the test phase has any output, Testflinger will cancel the job. This value should be smaller than, or equal to, the ``global_timeout``. + * - ``allocation_timeout`` + - integer + - | 7200 + | (2 hours) + - (Optional) Maximum time (in seconds) Testflinger should wait in the ``allocate`` phase for multi-device jobs to reach the ``allocated`` state. If the timeout is reached before all devices are allocated, Testflinger will cancel the job. + * - ``_data`` + - dictionary + - / + - | (Optional) Sections that define the configurations and commands about how the job should be executed in each of the test phases. If any phase encounters a non-zero exit code, no further phases will be executed. + | Supported test phases include: + | - provision + | - firmware_update + | - test + | - allocate + | - reserve + | For detailed information about how to define the data to include in each test phase, see :doc:`test-phases`. + +Example jobs in YAML +---------------------------- + +The following example YAML file defines a job that provisions the Ubuntu Core 22 system on a Raspberry Pi 4 device. The job retrieves the image from the given URL, provisions the image on the device at IP address ``DEVICE_IP``, and prints the distribution-specific information on the provisioned device: + +.. code-block:: yaml + + job_queue: rpi4b + global-timeout: 28800 + output-timeout: 3600 + provision_data: + url: https://cdimage.ubuntu.com/ubuntu-core/22/stable/current/ubuntu-core-22-arm64+raspi.img.xz + test_data: + test_cmds: | + ssh -t ubuntu@DEVICE_IP lsb_release -a + +Data specified in the ``provision_data`` section varies on device types. For example, to provision server images on a MAAS device, the ``distro`` field should be used to indicate the system version. The following YAML file defines a job that provisions the Ubuntu 22.04 LTS (Jammy Jellyfish) server install image on a MAAS device and prints the information about its processors and network interface configurations: + +.. code-block:: yaml + + job_queue: maas-x86-node + provision_data: + distro: jammy + test_data: + test_cmds: | + ssh ubuntu@$DEVICE_IP cat /proc/cpuinfo + ssh ubuntu@$DEVICE_IP ifconfig diff --git a/docs/reference/testflinger-agent-conf.rst b/docs/reference/testflinger-agent-conf.rst index be23425d..795584ec 100644 --- a/docs/reference/testflinger-agent-conf.rst +++ b/docs/reference/testflinger-agent-conf.rst @@ -12,6 +12,8 @@ The following configuration options are supported by the Testflinger Agent: - Description * - ``agent_id`` - Unique identifier for this agent + * - ``identifier`` + - Additional identifier such as a serial number that will be sent to the server and can be used for cross-referencing with other systems * - ``polling_interval`` - Time to sleep between polling for new tests (default: 10s) * - ``server_address``