You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This guide will help you to develop a new service within the platform. The platform is focused on a modular binary architecture, so the goal of the service is isolation while also getting the benefits of a shared platform.
Structure
OpenTDF services are located under the service directory. Each service should have a unique directory name, which is expected to relate to the service namespace.
Service Namespace
A service namespace is a unique identifier for the service. It is used to identify the service in the platform and to enable multiple gRPC services to be rolled up into a single service.
The namespace should be a unique identifier for the service. It should be a single word, all lowercase, and should not contain any special characters. It should be the same as the directory name for the service.
Registration
Services are registered with the platform using the service.RegisterService function. This function expects to be given a serviceregistry.Registration object.
// Optional to specify if the service requires a database connection
DBDBRegister
}
The goal of the registration is to define how your service should function so that during the sub-service start process, the platform can start the service as expected.
Config
Services utilize the ServiceConfig struct. This struct has some pre-defined properties and will dump anything else into ExtraProps.
To use this one can access it via the Config param in the RegistrationParams. By using this we can access our config params via the map[string]interface{} or we could map this to a custom config stuct
typeExampleServiceConfigstruct {
*config.ServiceConfigmyStringstringmyBoolbool
}
typeExampleServicestruct {
example.UnimplementedExampleServiceServerconfig*config.ServiceConfig
}
funcNewRegistration() serviceregistry.Registration {
// ...
RegisterFunc: func(srp serviceregistry.RegistrationParams) (any, serviceregistry.HandlerServer) {
// by adding the sdk to the service we can now use it in our handlerssvc:=ExampleService{
config: config.ServiceConfig
}
return&svc, func(ctx context.Context, mux*runtime.ServeMux, serverany) error {
// ... start the server and return handler (see below)
}
}
// ...
}
SDK usage
Every service has access to a shared instance of the SDK. This instance utilizes gRPC interprocess-communication, and it is highly advised to use this rather than generating a new SDK connection. The main benefit of using this SDK is that the platform will manage this for you.
Benefits of using bundled SDK:
platform manages connection
no need for a config mapping the platform endpoint
supports monolith and microservice deployment without service needing to know
with IPC doesn't leave memory or service mesh (depending on deployment)
The SDK is returned as part of the serviceregistry.RegistrationParams
typeExampleServicestruct {
example.UnimplementedExampleServiceServersdk*sdk.SDK
}
funcNewRegistration() serviceregistry.Registration {
// ...
RegisterFunc: func(srp serviceregistry.RegistrationParams) (any, serviceregistry.HandlerServer) {
// by adding the sdk to the service we can now use it in our handlerssvc:=ExampleService{
sdk: srp.SDK
}
return&svc, func(ctx context.Context, mux*runtime.ServeMux, serverany) error {
// ... start the server and return handler (see below)
}
}
// ...
}
Database usage
The platform utilizes Postgres for its database needs. There are times when a service needs access to a database to ensure persistence of one form or another. As with our other principles, this needs to be managed by the service, but facilitated by the platform.
Each service will be scoped to its own schema in the form of <platform_name>_<service_namespace>. Where the default platform name is opentdf and the service namespace is example the schema will be opentdf_example.
Scoping services to schemas will help to reduce the risk of services interacting with data outside of contracts (protos and generated SDKs).
Warning
Currently multiple connection pools will be created to the same database client. Enhancement and prevention of performance issues is captured in #681
Registration
Database registration is simple through the use of the serviceregistry.DBRegister type.
Migrations can be managed without installing goose locally through the opentdf cmd arguments
> go run ./service migrate
Run database migrations
Usage:
opentdf migrate [command]
Available Commands:
down Run database migration down one version
status Show the status of the database migrations
up Run database migrations up to the latest version
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Needs coverage
Developing a new platform service
This guide will help you to develop a new service within the platform. The platform is focused on a modular binary architecture, so the goal of the service is isolation while also getting the benefits of a shared platform.
Structure
OpenTDF services are located under the
service
directory. Each service should have a unique directory name, which is expected to relate to the service namespace.Service Namespace
A service namespace is a unique identifier for the service. It is used to identify the service in the platform and to enable multiple gRPC services to be rolled up into a single service.
The namespace should be a unique identifier for the service. It should be a single word, all lowercase, and should not contain any special characters. It should be the same as the directory name for the service.
Registration
Services are registered with the platform using the
service.RegisterService
function. This function expects to be given aserviceregistry.Registration
object.platform/service/pkg/serviceregistry/serviceregistry.go
Lines 48 to 55 in 459e82a
The goal of the registration is to define how your service should function so that during the sub-service start process, the platform can start the service as expected.
Config
Services utilize the
ServiceConfig
struct. This struct has some pre-defined properties and will dump anything else intoExtraProps
.platform/service/pkg/serviceregistry/serviceregistry.go
Lines 21 to 25 in 192ff6d
To use this one can access it via the
Config
param in theRegistrationParams
. By using this we can access our config params via themap[string]interface{}
or we could map this to a custom config stuctSDK usage
Every service has access to a shared instance of the SDK. This instance utilizes gRPC interprocess-communication, and it is highly advised to use this rather than generating a new SDK connection. The main benefit of using this SDK is that the platform will manage this for you.
Benefits of using bundled SDK:
The SDK is returned as part of the
serviceregistry.RegistrationParams
Database usage
The platform utilizes Postgres for its database needs. There are times when a service needs access to a database to ensure persistence of one form or another. As with our other principles, this needs to be managed by the service, but facilitated by the platform.
Each service will be scoped to its own schema in the form of
<platform_name>_<service_namespace>
. Where the default platform name isopentdf
and the service namespace isexample
the schema will beopentdf_example
.Scoping services to schemas will help to reduce the risk of services interacting with data outside of contracts (protos and generated SDKs).
Warning
Currently multiple connection pools will be created to the same database client. Enhancement and prevention of performance issues is captured in #681
Registration
Database registration is simple through the use of the
serviceregistry.DBRegister
type.platform/service/pkg/serviceregistry/serviceregistry.go
Lines 42 to 46 in 459e82a
Migrations
Database migrations are enabled through two libraries
Migrations can be managed without installing goose locally through the opentdf cmd arguments
> go run ./service migrate Run database migrations Usage: opentdf migrate [command] Available Commands: down Run database migration down one version status Show the status of the database migrations up Run database migrations up to the latest version
Well Known
TBD
Readiness Check
TBD
Resources
Examples
gRPC service
This is a minimal service registration which
gRPC service with Database
Roll-up registration
This example shows how one might want to roll-up services if there are many gRPC services under a namespace.
HTTP-only service
Warning
It is advised to use the grpc-gateway to generate an HTTP interface rather than rolling an HTTP-only service
This example shows how to register an HTTP-only service.
Lifecycle
Beta Was this translation helpful? Give feedback.
All reactions