Skip to content

Commit

Permalink
Merge pull request #6 from trento-project/docs
Browse files Browse the repository at this point in the history
Documentation and project description
  • Loading branch information
CDimonaco authored Jan 15, 2025
2 parents 732ce82 + 63bfcff commit e2b8477
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 4 deletions.
136 changes: 132 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,134 @@
# Workbench - Trento agent operators
# Workbench - Trento Agent Operators

This library contains the code of `agent-operators`, an `operator` is a unit of code who can perform
write operations on target machines.
This library contains the code for `agent-operators`. An `operator` is a unit of code that can perform write operations on target machines.

Each operator know how to perform the actions and how to rollback them in case of a failure.
Each operator knows how to execute actions and how to roll them back in case of failure.

## Install

Install the library

`go get github.com/trento-project/workbench`

Install the cli tool

`go install github.com/trento-project/workbench`


## Moving Parts

### Operator

![flowchart](./flow_chart.png)

An operator is a unit of code that can perform write operations on target machines.
A write operation can either fail or succeed. If it succeeds, the operation displays a diff highlighting the changes before and after the commit phase.

The operator accepts arguments to specify how to perform the operations. The arguments are in the form of a `map[string]any`, and each operator knows how to extract and validate them.
It follows a transactional approach, where each operation has distinct stages:

- PLAN
- COMMIT
- VERIFY
- ROLLBACK


The documentation for each of the operators can be found in the operators go source.

#### PLAN

The goal of the PLAN stage is to collect information about the operations and verify prerequisites.
This is also the phase where information for diffing is gathered by collecting the `before` state.

Additionally, during this phase, it is important to ensure that any resources modified during the COMMIT phase are backed up. This allows restoration during the ROLLBACK phase or manual recovery by system administrators if the rollback fails.

If an error occurs during the PLAN phase, no rollback is needed; the operation is simply aborted with the plan error.

#### COMMIT

The COMMIT phase executes the actual write operations on the system, utilizing the information collected during the PLAN phase.
If an error occurs during this phase, a rollback is triggered.

The COMMIT phase should be idempotent. If a requested change has already been applied, the commit operation is simply skipped without returning an error.
Idempotency should be implemented appropriately based on the type of operations to be performed.

#### VERIFY

The VERIFY phase ensures that the actions applied during the COMMIT phase have produced the expected results on the system.
If an error occurs during this phase, the rollback process is initiated.

This phase is also when the `after` state is recorded for the diff, highlighting changes made during the commit phase.

#### ROLLBACK

The ROLLBACK phase must implement mechanisms to revert any changes made during the COMMIT phase.
It can use information collected during the PLAN phase to restore the system to its previous state.
The rollback implementation may vary depending on the type of operation performed during the COMMIT phase.
Be sure to provide clear error messages and log actions appropriately.

If the rollback fails, the error is returned without further action.

### Executor

The Executor is a wrapper around an operator. The operator implements the phase interface and must be wrapped in an Executor.

The Executor manages operations transactionally.
For library users, the Executor is transparent—using an Operator means it is already wrapped within an Executor.

### Registry

The Registry holds all available operators. Each operator has a version. By default, if no version is specified when requesting an operator, the latest version is fetched from the Registry.

To use an operator, it must be fetched using the `GetOperatorBuilder` function, providing the operator name as an argument.

```go
builder, err := registry.GetOperatorBuilder(operatorName)
op := builder("test-cli", opArgs)
report := op.Run(ctx)
// the report contains the success or the error of the execution
```

The operator name follows this format: `<operatorname>@<version>`.

The Registry returns an Operator Builder:

```go
type OperatorBuilder func(operationID string, arguments OperatorArguments) Operator
```

The `operationID` is a unique identifier for the operation, and `arguments` are modeled as `map[string]any`.

### CLI

The Workbench library also exposes a `CLI` to run operators without importing the library. The CLI is intended only for testing and development purposes.

The CLI follows the same rules as the library, implementing only the operators exposed by the registry.

#### Usage

```
Usage:
workbench [OPTIONS]
Application Options:
-a, --arguments= JSON arguments for an operator
-v, --verbose Log verbosity
Help Options:
-h, --help Show this help message
```

The CLI accepts the name of an operator as an argument, following the same convention `<operatorname>@<version>`, and requires the `-a` option to pass the arguments.

The arguments must be provided as a JSON string.

#### Example

```bash
sudo ./workbench -a '{"solution": "HANA"}' saptuneapplysolution
```

Using `sudo` may be necessary depending on the type of operator being executed.
In this example, the `saptuneapplysolution` operator is called with the argument `solution` set to `HANA`.

The CLI will perform the operations, log any errors, and finally display the diff when the execution succeeds.
Binary file added flow_chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions pkg/operator/saptuneapplysolution_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,33 @@ type saptuneApplySolutionArguments struct {
solution string
}

// SaptuneApplySolution is an operator responsible for applying a saptune solution.
//
// The operator requires an argument in the form of a map containing a key named "solution".
// This value will be passed to the saptune command-line tool.
//
// All considerations related to applying a solution using the saptune CLI apply here as well.
//
// # Execution Phases
//
// - PLAN:
// The operator checks for the presence of the saptune binary and verifies its version.
// The minimum required version is 3.1.0. If saptune is not installed or the version does not meet the minimum requirement,
// the operation will fail. The current state of the applied saptune solution is collected as the "before" diff.
//
// - COMMIT:
// The operator checks if the requested solution is already applied. If it is, no action is taken,
// ensuring idempotency without returning an error. If the solution is not applied, the saptune command
// to apply the solution will be executed.
//
// - VERIFY:
// The operator verifies whether the solution has been correctly applied to the system.
// If not, an error is raised. If successful, the current state of the applied solution is collected as the "after" diff.
//
// - ROLLBACK:
// If an error occurs during the COMMIT or VERIFY phase, the saptune revert command is executed
// to undo the applied solution.

type SaptuneApplySolution struct {
baseOperation
executor support.CmdExecutor
Expand Down

0 comments on commit e2b8477

Please sign in to comment.