Skip to content

Commit

Permalink
feat: Start and Stop service Starlark instructions for Docker (#694)
Browse files Browse the repository at this point in the history
## Description:
Add `plan.start_service` and `plan.stop_service` Starlark instructions
for the Docker backend. Support for the K8S backend first requires an
update to the Gateway to manage the port forwarder connection during
stop and start operations. The k8s backend code itself is ready and the
changes (small) are in this PR.

No new backend methods are introduced, the goal being to re-use the
current code as much as possible. All the changes under `api/` and
`cli/` are related to the renaming of the API method `StartServices` to
`AddServices`. Most of the code added is unit and integration tests. The
map of service registrations at the service network layer is used as
part of the existing start service process so I am using this map to
store the service status and config required for the restart process. I
thought about using a map of created `Services` but it is not as clean
as leveraging the map of service registrations.

Added some PR comments to help with the review.

Follow-up work in subsequent PRs:

- Update gateway to manage the port forwarder connection during stop and
start operations and enable support for k8s.
- Update documentation.

## Is this change user facing?
YES

## References (if applicable):
#673
  • Loading branch information
laurentluce committed Jun 9, 2023
1 parent 69043bf commit 10b6b91
Show file tree
Hide file tree
Showing 50 changed files with 2,328 additions and 753 deletions.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -272,14 +272,14 @@ func NewStarlarkExecutionError(errorMessage string) *kurtosis_core_rpc_api_bindi

// ==============================================================================================
//
// Start Service
// Add Services
//
// ==============================================================================================

func NewStartServicesResponse(
func NewAddServicesResponse(
successfulServicesInfo map[string]*kurtosis_core_rpc_api_bindings.ServiceInfo,
failedServicesErrors map[string]string) *kurtosis_core_rpc_api_bindings.StartServicesResponse {
return &kurtosis_core_rpc_api_bindings.StartServicesResponse{
failedServicesErrors map[string]string) *kurtosis_core_rpc_api_bindings.AddServicesResponse {
return &kurtosis_core_rpc_api_bindings.AddServicesResponse{
SuccessfulServiceNameToServiceInfo: successfulServicesInfo,
FailedServiceNameToError: failedServicesErrors,
}
Expand Down
8 changes: 4 additions & 4 deletions api/protobuf/core/api_container_service.proto
Expand Up @@ -18,7 +18,7 @@ service ApiContainerService {
rpc RunStarlarkPackage(RunStarlarkPackageArgs) returns (stream StarlarkRunResponseLine) {};

// Start services by creating containers for them
rpc StartServices(StartServicesArgs) returns (StartServicesResponse) {};
rpc AddServices(AddServicesArgs) returns (AddServicesResponse) {};

// Returns the IDs of the current services in the enclave
rpc GetServices(GetServicesArgs) returns (GetServicesResponse) {};
Expand Down Expand Up @@ -110,7 +110,7 @@ message ServiceInfo {
string maybe_public_ip_addr = 4;

// Mapping defining the ports that the service can be reached at *outside* the enclave, in the user_defined_port_id -> port_info where user_defined_port_id
// corresponds to the ID that was passed in in StartServiceArgs
// corresponds to the ID that was passed in in AddServiceArgs
// NOTE: Will be empty if the service isn't running, the service didn't define any ports, or the backend doesn't support reporting public service info
map<string, Port> maybe_public_ports = 5;

Expand Down Expand Up @@ -291,11 +291,11 @@ message StarlarkRunFinishedEvent {
// ==============================================================================================
// Start Service
// ==============================================================================================
message StartServicesArgs {
message AddServicesArgs {
map<string, ServiceConfig> service_names_to_configs = 1;
}

message StartServicesResponse {
message AddServicesResponse {
// A map of Service Names to info describing that newly started service
map<string, ServiceInfo> successful_service_name_to_service_info = 1;

Expand Down
Expand Up @@ -11,7 +11,7 @@ interface IApiContainerServiceService extends grpc.ServiceDefinition<grpc.Untype
runStarlarkScript: grpc.MethodDefinition<api_container_service_pb.RunStarlarkScriptArgs, api_container_service_pb.StarlarkRunResponseLine>;
uploadStarlarkPackage: grpc.MethodDefinition<api_container_service_pb.StreamedDataChunk, google_protobuf_empty_pb.Empty>;
runStarlarkPackage: grpc.MethodDefinition<api_container_service_pb.RunStarlarkPackageArgs, api_container_service_pb.StarlarkRunResponseLine>;
startServices: grpc.MethodDefinition<api_container_service_pb.StartServicesArgs, api_container_service_pb.StartServicesResponse>;
addServices: grpc.MethodDefinition<api_container_service_pb.AddServicesArgs, api_container_service_pb.AddServicesResponse>;
getServices: grpc.MethodDefinition<api_container_service_pb.GetServicesArgs, api_container_service_pb.GetServicesResponse>;
getExistingAndHistoricalServiceIdentifiers: grpc.MethodDefinition<google_protobuf_empty_pb.Empty, api_container_service_pb.GetExistingAndHistoricalServiceIdentifiersResponse>;
removeService: grpc.MethodDefinition<api_container_service_pb.RemoveServiceArgs, api_container_service_pb.RemoveServiceResponse>;
Expand All @@ -37,7 +37,7 @@ export interface IApiContainerServiceServer extends grpc.UntypedServiceImplement
runStarlarkScript: grpc.handleServerStreamingCall<api_container_service_pb.RunStarlarkScriptArgs, api_container_service_pb.StarlarkRunResponseLine>;
uploadStarlarkPackage: grpc.handleClientStreamingCall<api_container_service_pb.StreamedDataChunk, google_protobuf_empty_pb.Empty>;
runStarlarkPackage: grpc.handleServerStreamingCall<api_container_service_pb.RunStarlarkPackageArgs, api_container_service_pb.StarlarkRunResponseLine>;
startServices: grpc.handleUnaryCall<api_container_service_pb.StartServicesArgs, api_container_service_pb.StartServicesResponse>;
addServices: grpc.handleUnaryCall<api_container_service_pb.AddServicesArgs, api_container_service_pb.AddServicesResponse>;
getServices: grpc.handleUnaryCall<api_container_service_pb.GetServicesArgs, api_container_service_pb.GetServicesResponse>;
getExistingAndHistoricalServiceIdentifiers: grpc.handleUnaryCall<google_protobuf_empty_pb.Empty, api_container_service_pb.GetExistingAndHistoricalServiceIdentifiersResponse>;
removeService: grpc.handleUnaryCall<api_container_service_pb.RemoveServiceArgs, api_container_service_pb.RemoveServiceResponse>;
Expand Down Expand Up @@ -66,9 +66,9 @@ export class ApiContainerServiceClient extends grpc.Client {
uploadStarlarkPackage(metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<google_protobuf_empty_pb.Empty>): grpc.ClientWritableStream<api_container_service_pb.StreamedDataChunk>;
runStarlarkPackage(argument: api_container_service_pb.RunStarlarkPackageArgs, metadataOrOptions?: grpc.Metadata | grpc.CallOptions | null): grpc.ClientReadableStream<api_container_service_pb.StarlarkRunResponseLine>;
runStarlarkPackage(argument: api_container_service_pb.RunStarlarkPackageArgs, metadata?: grpc.Metadata | null, options?: grpc.CallOptions | null): grpc.ClientReadableStream<api_container_service_pb.StarlarkRunResponseLine>;
startServices(argument: api_container_service_pb.StartServicesArgs, callback: grpc.requestCallback<api_container_service_pb.StartServicesResponse>): grpc.ClientUnaryCall;
startServices(argument: api_container_service_pb.StartServicesArgs, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<api_container_service_pb.StartServicesResponse>): grpc.ClientUnaryCall;
startServices(argument: api_container_service_pb.StartServicesArgs, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<api_container_service_pb.StartServicesResponse>): grpc.ClientUnaryCall;
addServices(argument: api_container_service_pb.AddServicesArgs, callback: grpc.requestCallback<api_container_service_pb.AddServicesResponse>): grpc.ClientUnaryCall;
addServices(argument: api_container_service_pb.AddServicesArgs, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<api_container_service_pb.AddServicesResponse>): grpc.ClientUnaryCall;
addServices(argument: api_container_service_pb.AddServicesArgs, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<api_container_service_pb.AddServicesResponse>): grpc.ClientUnaryCall;
getServices(argument: api_container_service_pb.GetServicesArgs, callback: grpc.requestCallback<api_container_service_pb.GetServicesResponse>): grpc.ClientUnaryCall;
getServices(argument: api_container_service_pb.GetServicesArgs, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<api_container_service_pb.GetServicesResponse>): grpc.ClientUnaryCall;
getServices(argument: api_container_service_pb.GetServicesArgs, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<api_container_service_pb.GetServicesResponse>): grpc.ClientUnaryCall;
Expand Down
Expand Up @@ -5,6 +5,28 @@ var grpc = require('@grpc/grpc-js');
var api_container_service_pb = require('./api_container_service_pb.js');
var google_protobuf_empty_pb = require('google-protobuf/google/protobuf/empty_pb.js');

function serialize_api_container_api_AddServicesArgs(arg) {
if (!(arg instanceof api_container_service_pb.AddServicesArgs)) {
throw new Error('Expected argument of type api_container_api.AddServicesArgs');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_api_container_api_AddServicesArgs(buffer_arg) {
return api_container_service_pb.AddServicesArgs.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_api_container_api_AddServicesResponse(arg) {
if (!(arg instanceof api_container_service_pb.AddServicesResponse)) {
throw new Error('Expected argument of type api_container_api.AddServicesResponse');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_api_container_api_AddServicesResponse(buffer_arg) {
return api_container_service_pb.AddServicesResponse.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_api_container_api_DownloadFilesArtifactArgs(arg) {
if (!(arg instanceof api_container_service_pb.DownloadFilesArtifactArgs)) {
throw new Error('Expected argument of type api_container_api.DownloadFilesArtifactArgs');
Expand Down Expand Up @@ -192,28 +214,6 @@ function deserialize_api_container_api_StarlarkRunResponseLine(buffer_arg) {
return api_container_service_pb.StarlarkRunResponseLine.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_api_container_api_StartServicesArgs(arg) {
if (!(arg instanceof api_container_service_pb.StartServicesArgs)) {
throw new Error('Expected argument of type api_container_api.StartServicesArgs');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_api_container_api_StartServicesArgs(buffer_arg) {
return api_container_service_pb.StartServicesArgs.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_api_container_api_StartServicesResponse(arg) {
if (!(arg instanceof api_container_service_pb.StartServicesResponse)) {
throw new Error('Expected argument of type api_container_api.StartServicesResponse');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_api_container_api_StartServicesResponse(buffer_arg) {
return api_container_service_pb.StartServicesResponse.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_api_container_api_StoreFilesArtifactFromServiceArgs(arg) {
if (!(arg instanceof api_container_service_pb.StoreFilesArtifactFromServiceArgs)) {
throw new Error('Expected argument of type api_container_api.StoreFilesArtifactFromServiceArgs');
Expand Down Expand Up @@ -374,16 +374,16 @@ runStarlarkPackage: {
responseDeserialize: deserialize_api_container_api_StarlarkRunResponseLine,
},
// Start services by creating containers for them
startServices: {
path: '/api_container_api.ApiContainerService/StartServices',
addServices: {
path: '/api_container_api.ApiContainerService/AddServices',
requestStream: false,
responseStream: false,
requestType: api_container_service_pb.StartServicesArgs,
responseType: api_container_service_pb.StartServicesResponse,
requestSerialize: serialize_api_container_api_StartServicesArgs,
requestDeserialize: deserialize_api_container_api_StartServicesArgs,
responseSerialize: serialize_api_container_api_StartServicesResponse,
responseDeserialize: deserialize_api_container_api_StartServicesResponse,
requestType: api_container_service_pb.AddServicesArgs,
responseType: api_container_service_pb.AddServicesResponse,
requestSerialize: serialize_api_container_api_AddServicesArgs,
requestDeserialize: deserialize_api_container_api_AddServicesArgs,
responseSerialize: serialize_api_container_api_AddServicesResponse,
responseDeserialize: deserialize_api_container_api_AddServicesResponse,
},
// Returns the IDs of the current services in the enclave
getServices: {
Expand Down
Expand Up @@ -19,12 +19,12 @@ export class ApiContainerServiceClient {
metadata?: grpcWeb.Metadata
): grpcWeb.ClientReadableStream<api_container_service_pb.StarlarkRunResponseLine>;

startServices(
request: api_container_service_pb.StartServicesArgs,
addServices(
request: api_container_service_pb.AddServicesArgs,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.RpcError,
response: api_container_service_pb.StartServicesResponse) => void
): grpcWeb.ClientReadableStream<api_container_service_pb.StartServicesResponse>;
response: api_container_service_pb.AddServicesResponse) => void
): grpcWeb.ClientReadableStream<api_container_service_pb.AddServicesResponse>;

getServices(
request: api_container_service_pb.GetServicesArgs,
Expand Down Expand Up @@ -153,10 +153,10 @@ export class ApiContainerServicePromiseClient {
metadata?: grpcWeb.Metadata
): grpcWeb.ClientReadableStream<api_container_service_pb.StarlarkRunResponseLine>;

startServices(
request: api_container_service_pb.StartServicesArgs,
addServices(
request: api_container_service_pb.AddServicesArgs,
metadata?: grpcWeb.Metadata
): Promise<api_container_service_pb.StartServicesResponse>;
): Promise<api_container_service_pb.AddServicesResponse>;

getServices(
request: api_container_service_pb.GetServicesArgs,
Expand Down

0 comments on commit 10b6b91

Please sign in to comment.