Implemented Classes
In order to facilitate the management of the lifecycle of DTs via the web application interfaces, it was necessary to develop specific code within the project client. The code was designed to facilitate efficient API calls through the use of Gitbeaker as a wrapper, as this approach simplifies interactions with GitLab’s REST API and reduces the complexity of the project code.
The APIs have been integrated into the front-end by wiring up API endpoints to front-end components, ensuring a seamless data flow. Unit and integration testing was done to ensure the coverage of all functional requirements and solve all problems regarding data consistency, performance, or user experience.
Given below is our implementation of these classes in TypeScript:
GitlabInstance
The GitlabInstance
class was created in order to manage the APIs and
information related to the GitLab profile, the project, and the user-specific
data stored in their account.
The username and the token required to instantiate the Gitbeaker Gitlab component, which is required for making the API calls, are retrieved from the session storage, taking the access_token of the user already logged into the DTaaS application.
The initialisation of the GitlabInstance
object is concluded with the
execution of the init()
method, which enables the retrieval and storage of
the projectId
and triggerToken
attributes. The projectId is a unique
identifier for projects in GitLab and it is essential for subsequent API calls.
For example, it is passed to the method that retrieves a trigger token,
which is used to trigger CI/CD pipelines in GitLab.
The objective of the getDTSubfolders
method was to retrieve the names and
corresponding descriptions of the DTs of the user, so that these could be shown
at the front-end interface. This approach would obviate the user from having to
input the name of a DT; hence, saving the user from possible error and
inefficiencies arising from manual input. The user interface makes it easier
for the user to deal with DTs by automatizing their selection and manages them
more accurately. This implementation also eliminates the necessity for manual
input from users for the access token and the username, which are automatically
provided via the GitLab OAuth login.
Furthermore, logs maintained in the GitlabInstance
class improve awareness
and transparency over the operations conducted. The final three methods are
employed in conjunction to oversee the execution of a DT. In particular,
individual logs are saved for each job in the pipeline, and the status of the
latter is monitored so that, once the entire pipeline is complete, the results
can be displayed in detail within the user interface. In this way, all statuses
of each operation are logged for better debugging and performance analysis,
including possible errors. Having trace logs exposed to the user means
troubleshooting will be more effective and insight into execution and
management of DTs will be gained, improving system reliability and user
confidence.
DigitalTwin
The DigitalTwin class was created in order to manage the APIs and information related to a specific DT.
The creation of a DigitalTwin object requires a pre-existing GitlabInstance to be associated with the object. It was determined that matching a different GitlabInstance for each DigitalTwin would be the optimal approach to ensure the maintenance of independence between the various DTs. The api attribute of GitlabInstance facilitates the execution of Gitbeaker APIs pertinent to the DT.
The class allows a pipeline to be started and stopped, thus giving the user full control of the execution. The execute() method uses the previous methods internally. This approach ensures that there are no errors due to missing design information during the execution of the pipeline. Responsibilities have been divided into smaller methods in order to make the code more modular, facilitating debugging and testing. In both execute() and stop(), the status of operations executed on the DT is monitored, keeping track of them via the logs attribute of GitlabInstance. Errors are identified and tracked, providing a complete view and the ability to monitor performance.
The descriptionFiles
, lifecycleFiles
and configFiles
attributes are used
to keep track of the files within the corresponding GitLab folder of the
DT, thus enabling the read and modify features.
The create() method enables the creation of a DT and saves all its files
in the user’s corresponding GitLab folder. Additionally, if the DT is
configured as common, it is also added to GitLab’s shared folder,
making it part of the Library and accessible to other users.
Similarly, the delete() method removes a DT from GitLab. If the DT was part of the Library, it is also removed from the shared folder.
A crucial aspect of these two methods is their integration with the
DevOps infrastructure. When a DT is created or deleted, the
.gitlab-ci.yml
file of the parent pipeline is updated to add or remove
the trigger_DTName section associated with the DT. This ensures that a
user-created DT can be executed via the web interface without requiring
manual updates to pipeline configuration files on GitLab. Instead, these
files are automatically updated, providing an effortless user experience
and maintaining alignment with the infrastructure.
LibraryAsset
The LibraryAsset class was created in order to manage the APIs and information related to a specific library asset.
It is similar to the DigitalTwin class, but contains only the methods required to display files. This focused design reflects its limited scope and ensures simplicity and clarity for use cases involving the library.
Ref: Vanessa Scherma, Design and implementation of an integrated DevOps framework for Digital Twins as a Service software platform, Master's Degree Thesis, Politecnico Di Torino, 2024.