|
1 |
| -## Chainloop Control Plane |
| 1 | +# Control Plane |
2 | 2 |
|
3 |
| -### Testing |
| 3 | +## Structure overview |
4 | 4 |
|
5 |
| -We've implemented two kinds of tests, unit tests (`make run test-unit`) and integration tests. The latter talks to a containerized database and hence are expensive to run. |
| 5 | +The control plane is a [Go](https://go.dev/) service that leverages [protocol buffers](https://github.com/protocolbuffers/protobuf) and [gRPC](https://grpc.io/) for its API, [ent](https://entgo.io) as ORM, [wire](https://github.com/google/wire/) for dependency injection and the [kratos framework](https://github.com/go-kratos/kratos) for additional utilities such middlewares, configuration management or error handling. |
6 | 6 |
|
7 |
| -Note: to run all the tests just run `make test` |
| 7 | +It's implemented following(ish) [Hexagonal architecture](https://netflixtechblog.com/ready-for-changes-with-hexagonal-architecture-b315ec967749) with the following top to down layers. |
| 8 | + |
| 9 | +- API definition layer `./api/`. proto definitions and generated code for the external gRPC API |
| 10 | +- Server layer `./internal/server`. Definition and registration of the HTTP and gRPC servers and middlewares. |
| 11 | +- Service layer `./internal/service`. Implementation of the protocol buffer services. |
| 12 | +- Business layer `./internal/biz`. Implementation of use-cases referenced by the service layer and definition of the data repository abstractions. |
| 13 | +- Data layer `./internal/data`. Implementation of data repositories interfaces defined in the business layer. |
| 14 | + |
| 15 | +## System Dependencies |
| 16 | + |
| 17 | +The control plane has 4 main dependencies |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +- OpenID Connect (OIDC) provider. Chainloop authentication backend is delegated to a OIDC provider (i.e Google, GitHub or [Auth0](https://auth0.com/)) for single sign on. |
| 22 | +- The persistance layer requires a [PostgreSQL](https://www.postgresql.org/) database. |
| 23 | +- Sensitive information provided by the user such as OCI registry credentials is sent to a secret storage backend. Currently we support both [Hashicorp Vault](https://www.vaultproject.io/) and [AWS Secret Manager](https://aws.amazon.com/secrets-manager/). |
| 24 | +- In addition to those third party dependencies, the control plane also has a dependency on Chainloop own [Artifact CAS](../artifact-cas). It is used to upload the received attestation to the end-user storage backend. |
| 25 | + |
| 26 | +> NOTE: The control plane does not store attestation or artifact data, these get forwarded to the user storage backend through the Artifact CAS. |
| 27 | +
|
| 28 | +## Runbook |
| 29 | + |
| 30 | +We leverage `make` for most development tasks. Run `make -C app/controlplane` to see a list of the available tasks. |
| 31 | + |
| 32 | +### Run the project in development |
| 33 | + |
| 34 | +Refer to [development guide](../../devel/README.md) for more information but in a nutshell. |
| 35 | + |
| 36 | +``` |
| 37 | +# Run external dependencies (Dex for OIDC, bitnami/postgreSQL container for persistence and Vault for secret management) |
| 38 | +
|
| 39 | +docker compose -f devel/docker-compose.yml up |
| 40 | +
|
| 41 | +# Run the control plane |
| 42 | +make -C app/controlplane run |
| 43 | +``` |
| 44 | + |
| 45 | +Next, follow the steps that can be found [here](../../devel/README.md#4---using-the-cli-pointing-to-the-local-environment) to configure the CLI |
| 46 | + |
| 47 | +### Run tests |
| 48 | + |
| 49 | +We've implemented two kinds of tests, unit tests (`make run test-unit`) and integration tests. The latter launch a containerized database and hence they are expensive to run. |
| 50 | + |
| 51 | +To run all the tests `make test` |
| 52 | + |
| 53 | +### Generate API code from protocol buffer defintions (\*.proto) |
| 54 | + |
| 55 | +We leverage buf.io to lint and generate proto files. Make sure you [install buf](https://docs.buf.build/installation) first. |
| 56 | + |
| 57 | +Once done, generating the API code is as easy as executing |
| 58 | + |
| 59 | +``` |
| 60 | +make api |
| 61 | +``` |
| 62 | + |
| 63 | +### Update Application data model |
| 64 | + |
| 65 | +We use [ent](https://entgo.io) as database Object Relational Mapping (ORM). |
| 66 | + |
| 67 | +The way a change in the data model will works is |
| 68 | + |
| 69 | +- Add a new/update an existing entity via a schema update. Schemas can be found at `internal/data/ent/schema` |
| 70 | +- Generate the code changes associated with that schema change. `make generate` |
| 71 | +- Restarting the control plane will cause the schema change to be automatically migrated. |
| 72 | + |
| 73 | +### Update configuration schema |
| 74 | + |
| 75 | +The service runtime configuration is implemented by using [kratos built-in config module](https://go-kratos.dev/en/docs/component/config/). |
| 76 | + |
| 77 | +Meaning that the configuration schema is defined at `internal/conf/conf.proto`. |
| 78 | + |
| 79 | +To regenerate it run: |
| 80 | + |
| 81 | +``` |
| 82 | +make config |
| 83 | +``` |
| 84 | + |
| 85 | +### Update dependency injection |
| 86 | + |
| 87 | +In order to enforce inversion of control and prevent import cycles we use [wire](https://github.com/google/wire/) for dependency injection. |
| 88 | + |
| 89 | +Wire has a fairly steep learning curve, so we recommend taking a look [at their tutorial](https://github.com/google/wire/blob/main/_tutorial/README.md). In practice, in this project you will find a couple of wire_gen.go files (i.e `cmd/wire_gen.go`) and different provider defined. |
| 90 | + |
| 91 | +If you need to re-generate the injection code after a change just run `make generate` |
| 92 | + |
| 93 | +## Contribution guidelines |
| 94 | + |
| 95 | +Please make sure to review the [Contribution guidelines](../../CONTRIBUTING.md) and feel free to reach out if you have any questions! |
| 96 | + |
| 97 | +Welcome! |
0 commit comments