diff --git a/Makefile b/Makefile index 52a882000..bab7d8de5 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ tf_vars := TF_VAR_client_machine_type=$(CLIENT_MACHINE_TYPE) \ TF_VAR_template_bucket_location=$(TEMPLATE_BUCKET_LOCATION) \ TF_VAR_clickhouse_connection_string=$(CLICKHOUSE_CONNECTION_STRING) \ TF_VAR_clickhouse_username=$(CLICKHOUSE_USERNAME) \ - TF_VAR_clickhouse_database=$(CLICKHOUSE_DATABASE) + TF_VAR_clickhouse_database=$(CLICKHOUSE_DATABASE) # Login for Packer and Docker (uses gcloud user creds) # Login for Terraform (uses application default creds) @@ -153,17 +153,24 @@ copy-public-builds: gsutil cp -r gs://e2b-prod-public-builds/firecrackers/* gs://$(GCP_PROJECT_ID)-fc-versions/ +.PHONY: migrate +migrate: + $(MAKE) -C packages/db migrate-postgres/up + # $(MAKE) -C packages/shared migrate-clickhouse/up + + .PHONY: generate -generate: generate/api generate/orchestrator generate/template-manager generate/envd generate/db +generate:generate/api +generate:generate/orchestrator +generate:generate/template-manager +generate:generate/envd +generate:generate/db +generate:generate/orchestrator/internal +generate:generate/shared generate/%: - @echo "Generating code for *$(notdir $@)*" $(MAKE) -C packages/$(notdir $@) generate @printf "\n\n" -.PHONY: migrate -migrate: - $(MAKE) -C packages/db migrate-postgres/up - # $(MAKE) -C packages/shared migrate-clickhouse/up .PHONY: switch-env switch-env: @@ -221,4 +228,4 @@ grafana-apply: .PHONY: connect-orchestrator connect-orchestrator: - $(MAKE) -C tests/integration connect-orchestrator \ No newline at end of file + $(MAKE) -C tests/integration connect-orchestrator diff --git a/packages/orchestrator/Makefile b/packages/orchestrator/Makefile index 6d37794b2..eb70b284e 100644 --- a/packages/orchestrator/Makefile +++ b/packages/orchestrator/Makefile @@ -13,7 +13,7 @@ init: generate: # You need to install protobuf (brew install protobuf) and following go packages: protoc-gen-go, protoc-gen-go-grpc # https://grpc.io/docs/languages/go/quickstart/ - @echo "Generating..." + @echo "Generating protoc..." @protoc --go_out=../shared/pkg/grpc/orchestrator/ --go_opt=paths=source_relative --go-grpc_out=../shared/pkg/grpc/orchestrator/ --go-grpc_opt=paths=source_relative orchestrator.proto @echo "Done" diff --git a/packages/orchestrator/go.mod b/packages/orchestrator/go.mod index a10b0b69e..1394cd478 100644 --- a/packages/orchestrator/go.mod +++ b/packages/orchestrator/go.mod @@ -98,6 +98,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-sqlite3 v1.14.27 // indirect github.com/mdlayher/genetlink v1.3.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.5.1 // indirect diff --git a/packages/orchestrator/go.sum b/packages/orchestrator/go.sum index 4d302ef76..56eb381be 100644 --- a/packages/orchestrator/go.sum +++ b/packages/orchestrator/go.sum @@ -688,6 +688,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU= +github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw= diff --git a/packages/orchestrator/internal/db/db.go b/packages/orchestrator/internal/db/db.go new file mode 100644 index 000000000..f5e6307fb --- /dev/null +++ b/packages/orchestrator/internal/db/db.go @@ -0,0 +1,132 @@ +package db + +import ( + "context" + "database/sql" + "errors" + "fmt" + "time" + + "github.com/e2b-dev/infra/packages/orchestrator/internal/pkg/database" +) + +type DB struct { + client *sql.DB + ops *database.Queries +} + +func New(ctx context.Context, client *sql.DB, schema string) (*DB, error) { + db := &DB{client: client, ops: database.New(client)} + + if _, err := db.client.ExecContext(ctx, schema); err != nil { + return nil, fmt.Errorf("problem initializing the database: %w", err) + } + + if err := db.ops.SetOrchestratorStatusRunning(ctx); err != nil { + return nil, err + } + + return db, nil +} + +func (db *DB) Close(ctx context.Context) error { + return errors.Join(db.ops.SetOrchestratorStatusTerminated(ctx), db.client.Close()) +} + +func (db *DB) Status(ctx context.Context) (*database.OrchestratorStatusRow, error) { + report, err := db.ops.OrchestratorStatus(ctx) + if err != nil { + return nil, err + } + out := report + + return &out, nil +} + +func (db *DB) CreateSandbox(ctx context.Context, params database.CreateSandboxParams) error { + return db.WithTx(ctx, func(ctx context.Context, op *database.Queries) error { + if _, err := op.IncGlobalVersion(ctx); err != nil { + return err + } + + if err := op.CreateSandbox(ctx, params); err != nil { + return err + } + return nil + }) +} + +func (db *DB) UpdateSandboxDeadline(ctx context.Context, id string, deadline time.Time) error { + return db.WithTx(ctx, func(ctx context.Context, op *database.Queries) error { + if _, err := op.IncGlobalVersion(ctx); err != nil { + return err + } + + if err := op.UpdateSandboxDeadline(ctx, database.UpdateSandboxDeadlineParams{ID: id, Deadline: deadline}); err != nil { + return err + } + + return nil + }) +} + +func (db *DB) SetSandboxTerminated(ctx context.Context, id string, duration time.Duration) error { + return db.WithTx(ctx, func(ctx context.Context, op *database.Queries) error { + if _, err := op.IncGlobalVersion(ctx); err != nil { + return err + } + + if err := op.ShutdownSandbox(ctx, database.ShutdownSandboxParams{ + ID: id, + DurationMs: duration.Milliseconds(), + Status: database.SandboxStatusTerminated, + }); err != nil { + return err + } + + return nil + }) +} + +func (db *DB) SetSandboxPaused(ctx context.Context, id string, duration time.Duration) error { + return db.WithTx(ctx, func(ctx context.Context, op *database.Queries) error { + if _, err := op.IncGlobalVersion(ctx); err != nil { + return err + } + + if err := op.ShutdownSandbox(ctx, database.ShutdownSandboxParams{ + ID: id, + DurationMs: duration.Milliseconds(), + Status: database.SandboxStatusPaused, + }); err != nil { + return err + } + + return nil + }) +} + +func (db *DB) WithTx(ctx context.Context, op func(context.Context, *database.Queries) error) (err error) { + tx, err := db.client.BeginTx(ctx, nil) + if err != nil { + return err + } + defer func() { + if err != nil { + err = errors.Join(err, tx.Rollback()) + } + }() + defer func() { + if p := recover(); p != nil { + tx.Rollback() + panic(p) + } + }() + defer func() { + if err == nil { + err = tx.Commit() + } + }() + + return op(ctx, db.ops.WithTx(tx)) +} diff --git a/packages/orchestrator/internal/db/queries.sql b/packages/orchestrator/internal/db/queries.sql new file mode 100644 index 000000000..740b8c506 --- /dev/null +++ b/packages/orchestrator/internal/db/queries.sql @@ -0,0 +1,76 @@ +-- name: GlobalVersion :one +SELECT version FROM status WHERE id = 1; + +-- name: SetOrchestratorStatusRunning :exec +UPDATE status +SET + version = version + 1, + updated_at = current_timestamp, + status = 'running' +WHERE + id = 1 AND status = 'initializing'; + +-- name: SetOrchestratorStatusTerminated :exec +UPDATE status +SET + version = version + 1, + updated_at = current_timestamp, + status = 'terminated' +WHERE + id = 1 AND status != 'terminated'; + +-- name: IncGlobalVersion :one +UPDATE status +SET + version = version + 1, + updated_at = current_timestamp +WHERE + id = 1 AND status != 'terminated' +RETURNING version; + +-- name: CreateSandbox :exec +INSERT INTO sandboxes(id, status, started_at, deadline, config, global_version) +VALUES ( + sqlc.arg('id'), + sqlc.arg('status'), + sqlc.arg('started_at'), + sqlc.arg('deadline'), + sqlc.arg('config'), + (SELECT version FROM status WHERE status.id = 1) +); + +-- name: ShutdownSandbox :exec +UPDATE sandboxes +SET + version = version + 1, + global_version = (SELECT version FROM status WHERE status.id = 1), + updated_at = current_timestamp, + duration_ms = sqlc.arg('duration_ms'), + status = sqlc.arg('status') +WHERE + sandboxes.id = sqlc.arg('id'); + +-- name: UpdateSandboxDeadline :exec +UPDATE sandboxes +SET + version = version + 1, + global_version = (SELECT version FROM status WHERE status.id = 1), + udpated_at = current_timestamp, + deadline = sqlc.arg('deadline'), + status = 'running' +WHERE + sandboxes.id = sqlc.arg('id'); + +-- name: OrchestratorStatus :one +SELECT + status.version AS global_version, + (SELECT count(*) FROM sandboxes) AS num_sandboxes, + (SELECT count(*) FROM sandboxes WHERE status = 'pending') AS pending_sandboxes, + (SELECT count(*) FROM sandboxes WHERE status = 'terminated') AS terminated_sandboxes, + (SELECT count(*) FROM sandboxes WHERE status = 'running') AS running_sandboxes, + (SELECT min(started_at) FROM sandboxes WHERE status = 'running') AS earliest_running_sandbox_started_at, + (SELECT max(updated_at) FROM sandboxes WHERE status = 'running') AS most_recent_running_sandbox_updated_at, + status.updated_at, + status.status +FROM + status; diff --git a/packages/orchestrator/internal/db/schema.sql b/packages/orchestrator/internal/db/schema.sql new file mode 100644 index 000000000..a6e386504 --- /dev/null +++ b/packages/orchestrator/internal/db/schema.sql @@ -0,0 +1,28 @@ +PRAGMA integrity_check; +PRAGMA foreign_keys = ON; + +CREATE TABLE sandboxes ( + id TEXT PRIMARY KEY NOT NULL, + started_at TIMESTAMP NOT NULL DEFAULT current_timestamp, + updated_at TIMESTAMP NOT NULL DEFAULT current_timestamp, + deadline TIMESTAMP NOT NULL, + status TEXT CHECK( status IN ('pending', 'running', 'paused', 'terminated')) + NOT NULL DEFAULT 'pending', + duration_ms INTEGER CHECK( duration_ms >= 0 ) + NOT NULL DEFAULT 0, + version INTEGER CHECK( version >= 0 ) + NOT NULL DEFAULT 0, + global_version INTEGER CHECK( global_version >= 0 ) + NOT NULL, + config BLOB +); + +CREATE TABLE status ( + id INTEGER PRIMARY KEY NOT NULL, + version INTEGER NOT NULL DEFAULT 0, + updated_at TIMESTAMP NOT NULL DEFAULT current_timestamp, + status TEXT CHECK( status IN ('initializing', 'running', 'draining', 'quarantined ', 'terminated')) + NOT NULL DEFAULT 'initializing' +); + +INSERT INTO status(id) VALUES(1); diff --git a/packages/orchestrator/internal/pkg/database/constants.go b/packages/orchestrator/internal/pkg/database/constants.go new file mode 100644 index 000000000..898281c0a --- /dev/null +++ b/packages/orchestrator/internal/pkg/database/constants.go @@ -0,0 +1,14 @@ +package database + +const ( + SandboxStatusPending = "pending" + SandboxStatusRunning = "running" + SandboxStatusPaused = "paused" + SandboxStatusTerminated = "terminated" + + OrchestratorStatusInitializing = "initializing" + OrchestratorStatusRunning = "running" + OrchestratorStatusDraining = "draining" + OrchestratorStatusTerminated = "terminated" + OrchestratorStatusQuarantined = "quarantined" +) diff --git a/packages/orchestrator/internal/pkg/database/db.go b/packages/orchestrator/internal/pkg/database/db.go new file mode 100644 index 000000000..bad7c4b9c --- /dev/null +++ b/packages/orchestrator/internal/pkg/database/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package database + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/packages/orchestrator/internal/pkg/database/helpers.go b/packages/orchestrator/internal/pkg/database/helpers.go new file mode 100644 index 000000000..6f079ea04 --- /dev/null +++ b/packages/orchestrator/internal/pkg/database/helpers.go @@ -0,0 +1,44 @@ +package database + +import ( + "time" +) + +const sqliteDateTimeFormat = "2006-01-02 15:04:05.000000000+00:00" + +func (osr *OrchestratorStatusRow) OldestSandboxStartTime() (out time.Time) { + var err error + switch tt := osr.EarliestRunningSandboxStartedAt.(type) { + case string: + out, err = time.Parse(sqliteDateTimeFormat, tt) + if err != nil { + panic(err) + } + + case time.Time: + out = tt + case *time.Time: + out = *tt + } + out = out.UTC() + return +} + +func (osr *OrchestratorStatusRow) MostRecentSandboxModification() (out time.Time) { + var err error + switch tt := osr.MostRecentRunningSandboxUpdatedAt.(type) { + case string: + out, err = time.Parse(time.DateTime, tt) + if err != nil { + panic(err) + } + case time.Time: + out = tt + case *time.Time: + out = *tt + } + + out = out.UTC() + + return +} diff --git a/packages/orchestrator/internal/pkg/database/models.go b/packages/orchestrator/internal/pkg/database/models.go new file mode 100644 index 000000000..ed2927e41 --- /dev/null +++ b/packages/orchestrator/internal/pkg/database/models.go @@ -0,0 +1,28 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package database + +import ( + "time" +) + +type Sandbox struct { + ID string + StartedAt time.Time + UpdatedAt time.Time + Deadline time.Time + Status string + DurationMs int64 + Version int64 + GlobalVersion int64 + Config []byte +} + +type Status struct { + ID int64 + Version int64 + UpdatedAt time.Time + Status string +} diff --git a/packages/orchestrator/internal/pkg/database/queries.sql.go b/packages/orchestrator/internal/pkg/database/queries.sql.go new file mode 100644 index 000000000..0f94edc54 --- /dev/null +++ b/packages/orchestrator/internal/pkg/database/queries.sql.go @@ -0,0 +1,190 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: queries.sql + +package database + +import ( + "context" + "time" +) + +const createSandbox = `-- name: CreateSandbox :exec +INSERT INTO sandboxes(id, status, started_at, deadline, duration_ms, config, global_version) +VALUES ( + ?1, + ?2, + ?3, + ?4, + 0, + ?5, + (SELECT version FROM status WHERE status.id = 1) +) +` + +type CreateSandboxParams struct { + ID string + Status string + StartedAt time.Time + Deadline time.Time + Config []byte +} + +func (q *Queries) CreateSandbox(ctx context.Context, arg CreateSandboxParams) error { + _, err := q.db.ExecContext(ctx, createSandbox, + arg.ID, + arg.Status, + arg.StartedAt, + arg.Deadline, + arg.Config, + ) + return err +} + +const globalVersion = `-- name: GlobalVersion :one +SELECT version FROM status WHERE id = 1 +` + +func (q *Queries) GlobalVersion(ctx context.Context) (int64, error) { + row := q.db.QueryRowContext(ctx, globalVersion) + var version int64 + err := row.Scan(&version) + return version, err +} + +const incGlobalVersion = `-- name: IncGlobalVersion :one +UPDATE status +SET + version = version + 1, + updated_at = current_timestamp +WHERE + id = 1 AND status != 'terminated' +RETURNING version +` + +func (q *Queries) IncGlobalVersion(ctx context.Context) (int64, error) { + row := q.db.QueryRowContext(ctx, incGlobalVersion) + var version int64 + err := row.Scan(&version) + return version, err +} + +const orchestratorStatus = `-- name: OrchestratorStatus :one +SELECT + status.version AS global_version, + (SELECT count(*) FROM sandboxes) AS num_sandboxes, + (SELECT count(*) FROM sandboxes WHERE status = 'pending') AS pending_sandboxes, + (SELECT count(*) FROM sandboxes WHERE status = 'terminated') AS terminated_sandboxes, + (SELECT count(*) FROM sandboxes WHERE status = 'running') AS running_sandboxes, + (SELECT min(started_at) FROM sandboxes WHERE status = 'running') AS earliest_running_sandbox_started_at, + (SELECT max(updated_at) FROM sandboxes WHERE status = 'running') AS most_recent_running_sandbox_updated_at, + status.updated_at, + status.status +FROM + status +` + +type OrchestratorStatusRow struct { + GlobalVersion int64 + NumSandboxes int64 + PendingSandboxes int64 + TerminatedSandboxes int64 + RunningSandboxes int64 + EarliestRunningSandboxStartedAt interface{} + MostRecentRunningSandboxUpdatedAt interface{} + UpdatedAt time.Time + Status string +} + +func (q *Queries) OrchestratorStatus(ctx context.Context) (OrchestratorStatusRow, error) { + row := q.db.QueryRowContext(ctx, orchestratorStatus) + var i OrchestratorStatusRow + err := row.Scan( + &i.GlobalVersion, + &i.NumSandboxes, + &i.PendingSandboxes, + &i.TerminatedSandboxes, + &i.RunningSandboxes, + &i.EarliestRunningSandboxStartedAt, + &i.MostRecentRunningSandboxUpdatedAt, + &i.UpdatedAt, + &i.Status, + ) + return i, err +} + +const setOrchestratorStatusRunning = `-- name: SetOrchestratorStatusRunning :exec +UPDATE status +SET + version = version + 1, + updated_at = current_timestamp, + status = 'running' +WHERE + id = 1 AND status = 'initializing' +` + +func (q *Queries) SetOrchestratorStatusRunning(ctx context.Context) error { + _, err := q.db.ExecContext(ctx, setOrchestratorStatusRunning) + return err +} + +const setOrchestratorStatusTerminated = `-- name: SetOrchestratorStatusTerminated :exec +UPDATE status +SET + version = version + 1, + updated_at = current_timestamp, + status = 'terminated' +WHERE + id = 1 AND status != 'terminated' +` + +func (q *Queries) SetOrchestratorStatusTerminated(ctx context.Context) error { + _, err := q.db.ExecContext(ctx, setOrchestratorStatusTerminated) + return err +} + +const shutdownSandbox = `-- name: ShutdownSandbox :exec +UPDATE sandboxes +SET + version = version + 1, + global_version = (SELECT version FROM status WHERE status.id = 1), + updated_at = current_timestamp, + duration_ms = ?1, + status = ?2 +WHERE + sandboxes.id = ?3 +` + +type ShutdownSandboxParams struct { + DurationMs int64 + Status string + ID string +} + +func (q *Queries) ShutdownSandbox(ctx context.Context, arg ShutdownSandboxParams) error { + _, err := q.db.ExecContext(ctx, shutdownSandbox, arg.DurationMs, arg.Status, arg.ID) + return err +} + +const updateSandboxDeadline = `-- name: UpdateSandboxDeadline :exec +UPDATE sandboxes +SET + version = version + 1, + global_version = (SELECT version FROM status WHERE status.id = 1), + udpated_at = current_timestamp, + deadline = ?1, + status = 'running' +WHERE + sandboxes.id = ?2 +` + +type UpdateSandboxDeadlineParams struct { + Deadline time.Time + ID string +} + +func (q *Queries) UpdateSandboxDeadline(ctx context.Context, arg UpdateSandboxDeadlineParams) error { + _, err := q.db.ExecContext(ctx, updateSandboxDeadline, arg.Deadline, arg.ID) + return err +} diff --git a/packages/orchestrator/internal/sandbox/checks.go b/packages/orchestrator/internal/sandbox/checks.go index e7e6a0fb4..3d4dbdcea 100644 --- a/packages/orchestrator/internal/sandbox/checks.go +++ b/packages/orchestrator/internal/sandbox/checks.go @@ -98,12 +98,14 @@ func (s *Sandbox) Healthcheck(ctx context.Context, alwaysReport bool) { address := fmt.Sprintf("http://%s:%d/health", s.Slot.HostIP(), consts.DefaultEnvdServerPort) - request, err := http.NewRequestWithContext(ctx, "GET", address, nil) + var request *http.Request // declare before use rather than := so that the defer works + request, err = http.NewRequestWithContext(ctx, "GET", address, nil) if err != nil { return } - response, err := httpClient.Do(request) + var response *http.Response // declare before use rather than := so that the defer works + response, err = httpClient.Do(request) if err != nil { return } @@ -121,6 +123,7 @@ func (s *Sandbox) Healthcheck(ctx context.Context, alwaysReport bool) { return } + // additional checks as needed ... } func isGTEVersion(curVersion, minVersion string) bool { diff --git a/packages/orchestrator/internal/server/healthcheck.go b/packages/orchestrator/internal/server/healthcheck.go index c7eef2e40..b611742a7 100644 --- a/packages/orchestrator/internal/server/healthcheck.go +++ b/packages/orchestrator/internal/server/healthcheck.go @@ -3,7 +3,7 @@ package server import ( "context" "encoding/json" - "log" + "errors" "net" "net/http" "sync" @@ -50,7 +50,7 @@ func NewHealthcheck(server *server, grpc *grpc.Server, grpcHealth *health.Server }, nil } -func (h *Healthcheck) Start(ctx context.Context, listener net.Listener) { +func (h *Healthcheck) Start(ctx context.Context, listener net.Listener) error { ticker := time.NewTicker(healthcheckFrequency) defer ticker.Stop() @@ -61,24 +61,49 @@ func (h *Healthcheck) Start(ctx context.Context, listener net.Listener) { Handler: routeMux, } + ctx, cancel := context.WithCancel(ctx) + defer cancel() + sig := make(chan struct{}) + go func() { - zap.L().Info("Starting health server") - if err := httpServer.Serve(listener); err != nil { - log.Fatal(err) + defer cancel() + defer close(sig) + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + err := h.report(ctx) + if err != nil { + zap.L().Error("Error reporting healthcheck", zap.Error(err)) + } + } } }() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - err := h.report(ctx) - if err != nil { - zap.L().Error("Error reporting healthcheck", zap.Error(err)) + shutdownErr := make(chan error) + go func() { + defer close(shutdownErr) + <-ctx.Done() + + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer shutdownCancel() + + if err := httpServer.Shutdown(shutdownCtx); err != nil { + select { + case <-shutdownCtx.Done(): + case shutdownErr <- err: } } + }() + + zap.L().Info("Starting health server") + if err := httpServer.Serve(listener); !errors.Is(err, http.ErrServerClosed) { + return err } + + <-sig + return <-shutdownErr } // report updates the health status. diff --git a/packages/orchestrator/internal/server/main.go b/packages/orchestrator/internal/server/main.go index 18fce8c3b..7d0353b3d 100644 --- a/packages/orchestrator/internal/server/main.go +++ b/packages/orchestrator/internal/server/main.go @@ -2,12 +2,14 @@ package server import ( "context" + "database/sql" "errors" "fmt" "math" "net" "os" "sync" + "sync/atomic" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" @@ -22,6 +24,7 @@ import ( "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" + "github.com/e2b-dev/infra/packages/orchestrator/internal/db" "github.com/e2b-dev/infra/packages/orchestrator/internal/dns" "github.com/e2b-dev/infra/packages/orchestrator/internal/proxy" "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox" @@ -42,6 +45,7 @@ type server struct { orchestrator.UnimplementedSandboxServiceServer sandboxes *smap.Map[*sandbox.Sandbox] dns *dns.DNS + db *db.DB proxy *proxy.SandboxProxy tracer trace.Tracer networkPool *network.Pool @@ -61,8 +65,10 @@ type Service struct { grpc *grpc.Server grpcHealth *health.Server dns *dns.DNS + db *db.DB proxy *proxy.SandboxProxy port uint16 + started atomic.Bool shutdown struct { once sync.Once op func(context.Context) error @@ -76,103 +82,125 @@ type Service struct { useClickhouseMetrics string } -func New(ctx context.Context, port uint, clientID string, version string, proxy *proxy.SandboxProxy) (*Service, error) { - if port > math.MaxUint16 { - return nil, fmt.Errorf("%d is larger than maximum possible port %d", port, math.MaxInt16) +type ServiceConf struct { + Version string + ClientID string + Schema string + Port uint +} + +func New( + ctx context.Context, + conf ServiceConf, + proxy *proxy.SandboxProxy, +) (*Service, error) { + if conf.Port > math.MaxUint16 { + return nil, fmt.Errorf("%d is larger than maximum possible port %d", conf.Port, math.MaxInt16) } - if clientID == "" { + if conf.ClientID == "" { return nil, errors.New("clientID is required") } - srv := &Service{version: version, port: uint16(port)} + srv := &Service{version: conf.Version, port: uint16(conf.Port)} templateCache, err := template.NewCache(ctx) if err != nil { return nil, fmt.Errorf("failed to create template cache: %w", err) } - networkPool, err := network.NewPool(ctx, network.NewSlotsPoolSize, network.ReusedSlotsPoolSize, clientID) + networkPool, err := network.NewPool(ctx, network.NewSlotsPoolSize, network.ReusedSlotsPoolSize, conf.ClientID) if err != nil { return nil, fmt.Errorf("failed to create network pool: %w", err) } // BLOCK: initialize services - { - srv.dns = dns.New() - srv.proxy = proxy - - opts := []logging.Option{ - logging.WithLogOnEvents(logging.StartCall, logging.PayloadReceived, logging.PayloadSent, logging.FinishCall), - logging.WithLevels(logging.DefaultServerCodeToLevel), - logging.WithFieldsFromContext(logging.ExtractFields), - } - srv.grpc = grpc.NewServer( - grpc.StatsHandler(e2bgrpc.NewStatsWrapper(otelgrpc.NewServerHandler())), - grpc.ChainUnaryInterceptor( - recovery.UnaryServerInterceptor(), - selector.UnaryServerInterceptor( - logging.UnaryServerInterceptor(logger.GRPCLogger(zap.L()), opts...), - logger.WithoutHealthCheck(), - ), + srv.dns = dns.New() + srv.proxy = proxy + + opts := []logging.Option{ + logging.WithLogOnEvents(logging.StartCall, logging.PayloadReceived, logging.PayloadSent, logging.FinishCall), + logging.WithLevels(logging.DefaultServerCodeToLevel), + logging.WithFieldsFromContext(logging.ExtractFields), + } + srv.grpc = grpc.NewServer( + grpc.StatsHandler(e2bgrpc.NewStatsWrapper(otelgrpc.NewServerHandler())), + grpc.ChainUnaryInterceptor( + recovery.UnaryServerInterceptor(), + selector.UnaryServerInterceptor( + logging.UnaryServerInterceptor(logger.GRPCLogger(zap.L()), opts...), + logger.WithoutHealthCheck(), ), - grpc.ChainStreamInterceptor( - selector.StreamServerInterceptor( - logging.StreamServerInterceptor(logger.GRPCLogger(zap.L()), opts...), - logger.WithoutHealthCheck(), - ), + ), + grpc.ChainStreamInterceptor( + selector.StreamServerInterceptor( + logging.StreamServerInterceptor(logger.GRPCLogger(zap.L()), opts...), + logger.WithoutHealthCheck(), ), - ) + ), + ) - devicePool, err := nbd.NewDevicePool() + devicePool, err := nbd.NewDevicePool() - if err != nil { - return nil, fmt.Errorf("failed to create device pool: %w", err) - } + if err != nil { + return nil, fmt.Errorf("failed to create device pool: %w", err) + } - useLokiMetrics := os.Getenv("WRITE_LOKI_METRICS") - useClickhouseMetrics := os.Getenv("WRITE_CLICKHOUSE_METRICS") - readClickhouseMetrics := os.Getenv("READ_CLICKHOUSE_METRICS") - - var clickhouseStore chdb.Store = nil - - if readClickhouseMetrics == "true" || useClickhouseMetrics == "true" { - clickhouseStore, err = chdb.NewStore(chdb.ClickHouseConfig{ - ConnectionString: os.Getenv("CLICKHOUSE_CONNECTION_STRING"), - Username: os.Getenv("CLICKHOUSE_USERNAME"), - Password: os.Getenv("CLICKHOUSE_PASSWORD"), - Database: os.Getenv("CLICKHOUSE_DATABASE"), - Debug: os.Getenv("CLICKHOUSE_DEBUG") == "true", - }) - if err != nil { - return nil, fmt.Errorf("failed to create clickhouse store: %w", err) - } - } + useLokiMetrics := os.Getenv("WRITE_LOKI_METRICS") + useClickhouseMetrics := os.Getenv("WRITE_CLICKHOUSE_METRICS") + readClickhouseMetrics := os.Getenv("READ_CLICKHOUSE_METRICS") - srv.server = &server{ - tracer: otel.Tracer(ServiceName), - dns: srv.dns, - proxy: srv.proxy, - sandboxes: smap.New[*sandbox.Sandbox](), - networkPool: networkPool, - templateCache: templateCache, - clientID: clientID, - devicePool: devicePool, - clickhouseStore: clickhouseStore, - useLokiMetrics: useLokiMetrics, - useClickhouseMetrics: useClickhouseMetrics, - } - _, err = meters.GetObservableUpDownCounter(meters.OrchestratorSandboxCountMeterName, func(ctx context.Context, observer metric.Int64Observer) error { - observer.Observe(int64(srv.server.sandboxes.Count())) + var clickhouseStore chdb.Store = nil - return nil + if readClickhouseMetrics == "true" || useClickhouseMetrics == "true" { + clickhouseStore, err = chdb.NewStore(chdb.ClickHouseConfig{ + ConnectionString: os.Getenv("CLICKHOUSE_CONNECTION_STRING"), + Username: os.Getenv("CLICKHOUSE_USERNAME"), + Password: os.Getenv("CLICKHOUSE_PASSWORD"), + Database: os.Getenv("CLICKHOUSE_DATABASE"), + Debug: os.Getenv("CLICKHOUSE_DEBUG") == "true", }) - if err != nil { - zap.L().Error("Error registering sandbox count metric", zap.Any("metric_name", meters.OrchestratorSandboxCountMeterName), zap.Error(err)) + return nil, fmt.Errorf("failed to create clickhouse store: %w", err) } } + srv.server = &server{ + tracer: otel.Tracer(ServiceName), + dns: srv.dns, + proxy: srv.proxy, + sandboxes: smap.New[*sandbox.Sandbox](), + networkPool: networkPool, + templateCache: templateCache, + clientID: conf.ClientID, + devicePool: devicePool, + clickhouseStore: clickhouseStore, + useLokiMetrics: useLokiMetrics, + useClickhouseMetrics: useClickhouseMetrics, + } + _, err = meters.GetObservableUpDownCounter(meters.OrchestratorSandboxCountMeterName, func(ctx context.Context, observer metric.Int64Observer) error { + observer.Observe(int64(srv.server.sandboxes.Count())) + + return nil + }) + + if err != nil { + zap.L().Error("Error registering sandbox count metric", zap.Any("metric_name", meters.OrchestratorSandboxCountMeterName), zap.Error(err)) + } + + // BLOCK: setup database + const dbpath = "./db/sandboxes.db" + drv, err := newDatabaseDriver(dbpath) + if err != nil { + return nil, err + } + + srv.db, err = db.New(ctx, drv, conf.Schema) + if err != nil { + return nil, fmt.Errorf("using database at %q: %w", dbpath, err) + } + + // BLOCK: register services and return orchestrator.RegisterSandboxServiceServer(srv.grpc, srv.server) srv.grpcHealth = health.NewServer() @@ -181,18 +209,39 @@ func New(ctx context.Context, port uint, clientID string, version string, proxy return srv, nil } +func newDatabaseDriver(path string) (*sql.DB, error) { + connStr := fmt.Sprintf("file:%s?_journal_mode=wal", path) + drv, err := sql.Open("sqlite3", connStr) + if err != nil { + return nil, fmt.Errorf("connecting to %q: %w", connStr, err) + } + return drv, nil +} + // Start launches func (srv *Service) Start(ctx context.Context) error { if srv.server == nil || srv.dns == nil || srv.grpc == nil { return errors.New("orchestrator services are not initialized") } + if !srv.started.CompareAndSwap(false, true) { + return errors.New("cannot start the orchestrator service more than once") + } + + zap.L().Info("starting orchestrator service") + + wg := sync.WaitGroup{} + wg.Add(1) + healthcheck, err := NewHealthcheck(srv.server, srv.grpc, srv.grpcHealth, srv.version) if err != nil { return fmt.Errorf("failed to create healthcheck: %w", err) } go func() { + defer zap.L().Info("DNS server returned") + defer wg.Done() + zap.L().Info("Starting DNS server") if err := srv.dns.Start("127.0.0.4", 53); err != nil { zap.L().Fatal("Failed running DNS server", zap.Error(err)) @@ -214,22 +263,37 @@ func (srv *Service) Start(ctx context.Context) error { zap.L().Info("Starting orchestrator server", zap.Uint16("port", srv.port)) + wg.Add(1) go func() { + defer zap.L().Info("gRPC service returned") + defer wg.Done() + + zap.L().Info("starting orchestrator server", zap.Uint16("port", srv.port)) if err := srv.grpc.Serve(grpcL); err != nil { - zap.L().Fatal("grpc server failed to serve", zap.Error(err)) + zap.L().Panic("grpc server failed to serve", zap.Error(err)) } }() - go healthcheck.Start(ctx, httpL) + wg.Add(1) + go func() { + defer zap.L().Info("healthcheck service returned") + defer wg.Done() + + if err := healthcheck.Start(ctx, httpL); err != nil { + zap.L().Panic("healthcheck server failed", zap.Error(err)) + } + }() // Start serving traffic go func() { if err := m.Serve(); err != nil { - zap.L().Fatal("failed to serve", zap.Error(err)) + zap.L().Panic("failed to serve", zap.Error(err)) } }() srv.shutdown.op = func(ctx context.Context) error { + defer zap.L().Info("orchestrator service has completed shutdown") + var errs []error srv.grpc.GracefulStop() @@ -240,6 +304,12 @@ func (srv *Service) Start(ctx context.Context) error { errs = append(errs, err) } + wg.Wait() + + if err := srv.db.Close(ctx); err != nil { + errs = append(errs, err) + } + if err := srv.dns.Close(ctx); err != nil { errs = append(errs, err) } diff --git a/packages/orchestrator/internal/server/sandboxes.go b/packages/orchestrator/internal/server/sandboxes.go index 79b83a9da..c8fd23b0d 100644 --- a/packages/orchestrator/internal/server/sandboxes.go +++ b/packages/orchestrator/internal/server/sandboxes.go @@ -13,9 +13,11 @@ import ( "golang.org/x/sync/semaphore" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/e2b-dev/infra/packages/orchestrator/internal/pkg/database" "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox" "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox/build" "github.com/e2b-dev/infra/packages/shared/pkg/grpc/orchestrator" @@ -66,27 +68,39 @@ func (s *server) Create(ctxConn context.Context, req *orchestrator.SandboxCreate ) if err != nil { zap.L().Error("failed to create sandbox, cleaning up", zap.Error(err)) + cleanupErr := cleanup.Run(ctx) - errMsg := fmt.Errorf("failed to cleanup sandbox: %w", errors.Join(err, context.Cause(ctx), cleanupErr)) - telemetry.ReportCriticalError(ctx, errMsg) + err = status.Errorf(codes.Internal, "failed to create sandbox: %v", errors.Join(err, context.Cause(ctx), cleanupErr)) + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.Internal, errMsg.Error()).Err() + return nil, err + } + + started, err := s.recordSandboxStart(ctx, sbx) + if err != nil { + zap.L().Error("failed to register sandbox, cleaning up", zap.Error(err)) + + cleanupErr := cleanup.Run(ctx) + + err = status.Errorf(codes.Internal, "failed to register sandbox: %v", errors.Join(err, context.Cause(ctx), cleanupErr)) + telemetry.ReportCriticalError(ctx, err) + + return nil, err } - s.sandboxes.Insert(req.Sandbox.SandboxId, sbx) go func() { ctx, childSpan := s.tracer.Start(context.Background(), "sandbox-create-stop") defer childSpan.End() - waitErr := sbx.Wait(ctx) - if waitErr != nil { - sbxlogger.I(sbx).Error("failed to wait for sandbox, cleaning up", zap.Error(waitErr)) + if err := sbx.Wait(ctx); err != nil { + sbxlogger.I(sbx).Error("failed to wait for sandbox, cleaning up", zap.Error(err)) } - cleanupErr := cleanup.Run(ctx) - if cleanupErr != nil { - sbxlogger.I(sbx).Error("failed to cleanup sandbox, will remove from cache", zap.Error(cleanupErr)) + ended := time.Now() + + if err := cleanup.Run(ctx); err != nil { + sbxlogger.I(sbx).Error("failed to cleanup sandbox, will remove from cache", zap.Error(err)) } // Remove the sandbox from cache only if the cleanup IDs match. @@ -104,7 +118,11 @@ func (s *server) Create(ctxConn context.Context, req *orchestrator.SandboxCreate return sbx.CleanupID == v.CleanupID }) - sbxlogger.E(sbx).Info("Sandbox killed") + if err := s.db.SetSandboxTerminated(ctx, req.Sandbox.SandboxId, ended.Sub(started)); err != nil { + sbxlogger.I(sbx).Error("failed to cleanup db record for sandbox", zap.Error(err)) + } + + sbxlogger.E(sbx).Info("sandbox killed") }() return &orchestrator.SandboxCreateResponse{ @@ -112,6 +130,32 @@ func (s *server) Create(ctxConn context.Context, req *orchestrator.SandboxCreate }, nil } +func (s *server) recordSandboxStart(ctx context.Context, sbx *sandbox.Sandbox) (time.Time, error) { + started := time.Now().UTC() + s.sandboxes.Insert(sbx.Config.SandboxId, sbx) + + // TODO: this could become JSON (pro: easier to read with + // external tools/code, con: larger size and slower + // serialization.) + confProto, err := proto.Marshal(sbx.Config) + if err != nil { + // TODO: decide if we want to return early and abort in this case. + sbxlogger.I(sbx).Error("failed to marshal sandbox config for the database", zap.Error(err)) + } + + if err := s.db.CreateSandbox(ctx, database.CreateSandboxParams{ + ID: sbx.Config.SandboxId, + Status: database.SandboxStatusRunning, + StartedAt: started, + Deadline: sbx.EndAt, + Config: confProto, + }); err != nil { + return started, err + } + + return started, nil +} + func (s *server) Update(ctx context.Context, req *orchestrator.SandboxUpdateRequest) (*emptypb.Empty, error) { ctx, childSpan := s.tracer.Start(ctx, "sandbox-update") defer childSpan.End() @@ -123,13 +167,15 @@ func (s *server) Update(ctx context.Context, req *orchestrator.SandboxUpdateRequ item, ok := s.sandboxes.Get(req.SandboxId) if !ok { - errMsg := fmt.Errorf("sandbox not found") - telemetry.ReportCriticalError(ctx, errMsg) - - return nil, status.New(codes.NotFound, errMsg.Error()).Err() + err := status.Errorf(codes.NotFound, "sandbox not found") + telemetry.ReportCriticalError(ctx, err) + return nil, err } item.EndAt = req.EndTime.AsTime() + if err := s.db.UpdateSandboxDeadline(ctx, req.SandboxId, item.EndAt); err != nil { + return nil, status.Errorf(codes.Internal, "db update sandbox: %v", err) + } return &emptypb.Empty{}, nil } @@ -178,10 +224,10 @@ func (s *server) Delete(ctxConn context.Context, in *orchestrator.SandboxDeleteR sbx, ok := s.sandboxes.Get(in.SandboxId) if !ok { - errMsg := fmt.Errorf("sandbox '%s' not found", in.SandboxId) - telemetry.ReportCriticalError(ctx, errMsg) + err := fmt.Errorf("sandbox '%s' not found", in.SandboxId) + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.NotFound, errMsg.Error()).Err() + return nil, status.Errorf(codes.NotFound, err.Error()) } // Don't allow connecting to the sandbox anymore. @@ -206,6 +252,10 @@ func (s *server) Delete(ctxConn context.Context, in *orchestrator.SandboxDeleteR sbxlogger.I(sbx).Error("error stopping sandbox", zap.String("sandbox_id", in.SandboxId), zap.Error(err)) } + if err := s.db.SetSandboxTerminated(ctx, in.SandboxId, sbx.EndAt.Sub(sbx.StartedAt)); err != nil { + sbxlogger.I(sbx).Error("error setting sandbox deleted", zap.String("sandbox_id", in.SandboxId), zap.Error(err)) + } + return &emptypb.Empty{}, nil } @@ -219,7 +269,7 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest if err != nil { telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.ResourceExhausted, err.Error()).Err() + return nil, status.Errorf(codes.ResourceExhausted, err.Error()) } releaseOnce := sync.OnceFunc(func() { @@ -229,20 +279,23 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest defer releaseOnce() s.pauseMu.Lock() - sbx, ok := s.sandboxes.Get(in.SandboxId) if !ok { s.pauseMu.Unlock() - errMsg := fmt.Errorf("sandbox not found") - telemetry.ReportCriticalError(ctx, errMsg) + err := fmt.Errorf("sandbox not found") + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.NotFound, errMsg.Error()).Err() + return nil, status.Errorf(codes.NotFound, err.Error()) } s.dns.Remove(in.SandboxId, sbx.Slot.HostIP()) s.sandboxes.Remove(in.SandboxId) + if err := s.db.SetSandboxPaused(ctx, in.SandboxId, time.Now().Sub(sbx.StartedAt)); err != nil { + sbxlogger.I(sbx).Error("error setting sandbox deleted", zap.String("sandbox_id", in.SandboxId), zap.Error(err)) + } + s.pauseMu.Unlock() snapshotTemplateFiles, err := storage.NewTemplateFiles( @@ -253,10 +306,10 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest sbx.Config.HugePages, ).NewTemplateCacheFiles() if err != nil { - errMsg := fmt.Errorf("error creating template files: %w", err) - telemetry.ReportCriticalError(ctx, errMsg) + err = fmt.Errorf("error creating template files: %w", err) + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.Internal, errMsg.Error()).Err() + return nil, status.Errorf(codes.Internal, err.Error()) } defer func() { @@ -266,8 +319,7 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest ctx, childSpan := s.tracer.Start(context.Background(), "sandbox-pause-stop") defer childSpan.End() - err := sbx.Stop(ctx) - if err != nil { + if err := sbx.Stop(ctx); err != nil { sbxlogger.I(sbx).Error("error stopping sandbox after snapshot", zap.String("sandbox_id", in.SandboxId), zap.Error(err)) } }() @@ -275,18 +327,18 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest err = os.MkdirAll(snapshotTemplateFiles.CacheDir(), 0o755) if err != nil { - errMsg := fmt.Errorf("error creating sandbox cache dir '%s': %w", snapshotTemplateFiles.CacheDir(), err) - telemetry.ReportCriticalError(ctx, errMsg) + err = fmt.Errorf("error creating sandbox cache dir '%s': %w", snapshotTemplateFiles.CacheDir(), err) + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.Internal, errMsg.Error()).Err() + return nil, status.Errorf(codes.Internal, err.Error()) } snapshot, err := sbx.Snapshot(ctx, s.tracer, snapshotTemplateFiles, releaseOnce) if err != nil { - errMsg := fmt.Errorf("error snapshotting sandbox '%s': %w", in.SandboxId, err) - telemetry.ReportCriticalError(ctx, errMsg) + err = fmt.Errorf("error snapshotting sandbox '%s': %w", in.SandboxId, err) + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.Internal, errMsg.Error()).Err() + return nil, status.Errorf(codes.Internal, err.Error()) } err = s.templateCache.AddSnapshot( @@ -302,10 +354,10 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest snapshot.RootfsDiff, ) if err != nil { - errMsg := fmt.Errorf("error adding snapshot to template cache: %w", err) - telemetry.ReportCriticalError(ctx, errMsg) + err = fmt.Errorf("error adding snapshot to template cache: %w", err) + telemetry.ReportCriticalError(ctx, err) - return nil, status.New(codes.Internal, errMsg.Error()).Err() + return nil, status.Errorf(codes.Internal, err.Error()) } telemetry.ReportEvent(ctx, "added snapshot to template cache") @@ -364,3 +416,22 @@ func (s *server) Pause(ctx context.Context, in *orchestrator.SandboxPauseRequest return &emptypb.Empty{}, nil } + +func (s *server) StatusReport(ctx context.Context, _ *emptypb.Empty) (*orchestrator.OrchestratorStatus, error) { + report, err := s.db.Status(ctx) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &orchestrator.OrchestratorStatus{ + GlobalVersion: report.GlobalVersion, + RunningSandboxes: report.RunningSandboxes, + PendingSandboxes: report.PendingSandboxes, + TerminatedSandboxes: report.TerminatedSandboxes, + NumSandboxes: report.NumSandboxes, + Status: report.Status, + UpdatedAt: timestamppb.New(report.UpdatedAt), + EarliestRunningSandboxStartedAt: timestamppb.New(report.OldestSandboxStartTime()), + MostRecentRunningSandboxUpdatedAt: timestamppb.New(report.MostRecentSandboxModification()), + }, nil +} diff --git a/packages/orchestrator/internal/server/sandboxes_test.go b/packages/orchestrator/internal/server/sandboxes_test.go index d7e72c136..0575c4e56 100644 --- a/packages/orchestrator/internal/server/sandboxes_test.go +++ b/packages/orchestrator/internal/server/sandboxes_test.go @@ -2,21 +2,28 @@ package server import ( "context" + "fmt" + "os" + "path/filepath" "reflect" "testing" "time" + "github.com/e2b-dev/infra/packages/orchestrator/internal/db" "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox" "github.com/e2b-dev/infra/packages/shared/pkg/grpc/orchestrator" "github.com/e2b-dev/infra/packages/shared/pkg/smap" + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "github.com/stretchr/testify/assert" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" ) var ( - startTime = time.Now() - endTime = time.Now().Add(time.Hour) + startTime = time.Now().UTC() + endTime = startTime.Add(time.Hour) ) func Test_server_List(t *testing.T) { @@ -80,3 +87,76 @@ func Test_server_List(t *testing.T) { }) } } + +func TestDatabaseSmokeTest(t *testing.T) { + ctx := t.Context() + + schemaPath, err := filepath.Abs("../db/schema.sql") + if err != nil { + t.Fatal(err) + } + + schema, err := os.ReadFile(schemaPath) + if err != nil { + t.Fatal(err) + } + + path := filepath.Join(t.TempDir(), fmt.Sprintf("%s.%d.%d.db", t.Name(), time.Now().UTC().Unix(), os.Getpid())) + drv, err := newDatabaseDriver(path) + if err != nil { + t.Fatal(err) + } + + srvDB, err := db.New(ctx, drv, string(schema)) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + if err := srvDB.Close(ctx); err != nil { + t.Fatal(err) + } + }) + + status, err := srvDB.Status(ctx) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, int64(1), status.GlobalVersion) + assert.Equal(t, int64(0), status.NumSandboxes) + assert.Equal(t, int64(0), status.RunningSandboxes) + + srv := &server{ + sandboxes: smap.New[*sandbox.Sandbox](), + db: srvDB, + } + + id := uuid.New() + sbxOriginal := &sandbox.Sandbox{ + Config: &orchestrator.SandboxConfig{SandboxId: id.String()}, + EndAt: time.Now().UTC().Add(time.Hour), + } + + started, err := srv.recordSandboxStart(ctx, sbxOriginal) + if err != nil { + t.Fatal(err) + } + + assert.True(t, started.Before(sbxOriginal.EndAt)) + + status, err = srvDB.Status(ctx) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, int64(2), status.GlobalVersion) + assert.Equal(t, int64(1), status.NumSandboxes) + assert.Equal(t, int64(1), status.RunningSandboxes) + assert.Equal(t, + started.Truncate(time.Millisecond), + status.OldestSandboxStartTime().Truncate(time.Millisecond), + ) +} diff --git a/packages/orchestrator/main.go b/packages/orchestrator/main.go index c25cb8d70..1fc586a24 100644 --- a/packages/orchestrator/main.go +++ b/packages/orchestrator/main.go @@ -2,6 +2,7 @@ package main import ( "context" + _ "embed" "errors" "flag" "fmt" @@ -22,6 +23,7 @@ import ( "github.com/e2b-dev/infra/packages/shared/pkg/logger" sbxlogger "github.com/e2b-dev/infra/packages/shared/pkg/logger/sandbox" "github.com/e2b-dev/infra/packages/shared/pkg/telemetry" + _ "github.com/mattn/go-sqlite3" ) const ( @@ -32,7 +34,10 @@ const ( var commitSHA string -func run() int32 { +//go:embed internal/db/schema.sql +var schema string + +func run() int { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -100,13 +105,20 @@ func run() int32 { defer sbxLoggerInternal.Sync() sbxlogger.SetSandboxLoggerInternal(sbxLoggerInternal) - log.Println("Starting orchestrator", "commit", commitSHA) + logger.Info("Starting orchestrator", zap.String("commit", commitSHA)) sessionProxy := proxy.New(proxyPort) - srv, err := server.New(ctx, port, clientID, commitSHA, sessionProxy) + srv, err := server.New(ctx, + server.ServiceConf{ + Version: commitSHA, + Port: port, + ClientID: clientID, + Schema: schema, + }, + sessionProxy) if err != nil { - zap.L().Fatal("failed to create server", zap.Error(err)) + zap.L().Panic("failed to create server", zap.Error(err)) } wg.Add(1) @@ -180,9 +192,9 @@ func run() int32 { wg.Wait() - return exitCode.Load() + return int(exitCode.Load()) } func main() { - os.Exit(int(run())) + os.Exit(run()) } diff --git a/packages/orchestrator/orchestrator.proto b/packages/orchestrator/orchestrator.proto index b84dacfa6..3e7dcc165 100644 --- a/packages/orchestrator/orchestrator.proto +++ b/packages/orchestrator/orchestrator.proto @@ -9,20 +9,20 @@ message SandboxConfig { // Data required for creating a new sandbox. string template_id = 1; string build_id = 2; - + string kernel_version = 3; string firecracker_version = 4; - + bool huge_pages = 5; - + string sandbox_id = 6; map env_vars = 7; - + // Metadata about the sandbox. map metadata = 8; optional string alias = 9; string envd_version = 10; - + int64 vcpu = 11; int64 ram_mb = 12; @@ -86,7 +86,17 @@ message SandboxListCachedBuildsResponse { repeated CachedBuildInfo builds = 1; } - +message OrchestratorStatus { + int64 global_version = 1; + int64 running_sandboxes = 2; + int64 pending_sandboxes = 4; + int64 terminated_sandboxes = 5; + int64 num_sandboxes = 6; + string status = 7; + google.protobuf.Timestamp updated_at = 8; + google.protobuf.Timestamp earliest_running_sandbox_started_at = 9; + google.protobuf.Timestamp most_recent_running_sandbox_updated_at = 10; +} service SandboxService { rpc Create(SandboxCreateRequest) returns (SandboxCreateResponse); @@ -96,4 +106,5 @@ service SandboxService { rpc Pause(SandboxPauseRequest) returns (google.protobuf.Empty); rpc ListCachedBuilds(google.protobuf.Empty) returns (SandboxListCachedBuildsResponse); + rpc StatusReport(google.protobuf.Empty) returns (OrchestratorStatus); } diff --git a/packages/shared/pkg/grpc/orchestrator/orchestrator.pb.go b/packages/shared/pkg/grpc/orchestrator/orchestrator.pb.go index 6ec1f395c..1bbdba9ed 100644 --- a/packages/shared/pkg/grpc/orchestrator/orchestrator.pb.go +++ b/packages/shared/pkg/grpc/orchestrator/orchestrator.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v5.29.3 +// protoc-gen-go v1.36.6 +// protoc v5.29.2 // source: orchestrator.proto package orchestrator @@ -13,6 +13,7 @@ import ( timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -23,10 +24,7 @@ const ( ) type SandboxConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // Data required for creating a new sandbox. TemplateId string `protobuf:"bytes,1,opt,name=template_id,json=templateId,proto3" json:"template_id,omitempty"` BuildId string `protobuf:"bytes,2,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"` @@ -34,9 +32,9 @@ type SandboxConfig struct { FirecrackerVersion string `protobuf:"bytes,4,opt,name=firecracker_version,json=firecrackerVersion,proto3" json:"firecracker_version,omitempty"` HugePages bool `protobuf:"varint,5,opt,name=huge_pages,json=hugePages,proto3" json:"huge_pages,omitempty"` SandboxId string `protobuf:"bytes,6,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` - EnvVars map[string]string `protobuf:"bytes,7,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + EnvVars map[string]string `protobuf:"bytes,7,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Metadata about the sandbox. - Metadata map[string]string `protobuf:"bytes,8,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Metadata map[string]string `protobuf:"bytes,8,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Alias *string `protobuf:"bytes,9,opt,name=alias,proto3,oneof" json:"alias,omitempty"` EnvdVersion string `protobuf:"bytes,10,opt,name=envd_version,json=envdVersion,proto3" json:"envd_version,omitempty"` Vcpu int64 `protobuf:"varint,11,opt,name=vcpu,proto3" json:"vcpu,omitempty"` @@ -48,15 +46,15 @@ type SandboxConfig struct { Snapshot bool `protobuf:"varint,16,opt,name=snapshot,proto3" json:"snapshot,omitempty"` BaseTemplateId string `protobuf:"bytes,17,opt,name=base_template_id,json=baseTemplateId,proto3" json:"base_template_id,omitempty"` AutoPause *bool `protobuf:"varint,18,opt,name=auto_pause,json=autoPause,proto3,oneof" json:"auto_pause,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SandboxConfig) Reset() { *x = SandboxConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxConfig) String() string { @@ -67,7 +65,7 @@ func (*SandboxConfig) ProtoMessage() {} func (x *SandboxConfig) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -209,22 +207,19 @@ func (x *SandboxConfig) GetAutoPause() bool { } type SandboxCreateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Sandbox *SandboxConfig `protobuf:"bytes,1,opt,name=sandbox,proto3" json:"sandbox,omitempty"` + StartTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` + EndTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` unknownFields protoimpl.UnknownFields - - Sandbox *SandboxConfig `protobuf:"bytes,1,opt,name=sandbox,proto3" json:"sandbox,omitempty"` - StartTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` - EndTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxCreateRequest) Reset() { *x = SandboxCreateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxCreateRequest) String() string { @@ -235,7 +230,7 @@ func (*SandboxCreateRequest) ProtoMessage() {} func (x *SandboxCreateRequest) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -272,20 +267,17 @@ func (x *SandboxCreateRequest) GetEndTime() *timestamppb.Timestamp { } type SandboxCreateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` unknownFields protoimpl.UnknownFields - - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxCreateResponse) Reset() { *x = SandboxCreateResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxCreateResponse) String() string { @@ -296,7 +288,7 @@ func (*SandboxCreateResponse) ProtoMessage() {} func (x *SandboxCreateResponse) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -319,21 +311,18 @@ func (x *SandboxCreateResponse) GetClientId() string { } type SandboxUpdateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + EndTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` unknownFields protoimpl.UnknownFields - - SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` - EndTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxUpdateRequest) Reset() { *x = SandboxUpdateRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxUpdateRequest) String() string { @@ -344,7 +333,7 @@ func (*SandboxUpdateRequest) ProtoMessage() {} func (x *SandboxUpdateRequest) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -374,20 +363,17 @@ func (x *SandboxUpdateRequest) GetEndTime() *timestamppb.Timestamp { } type SandboxDeleteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` unknownFields protoimpl.UnknownFields - - SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxDeleteRequest) Reset() { *x = SandboxDeleteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxDeleteRequest) String() string { @@ -398,7 +384,7 @@ func (*SandboxDeleteRequest) ProtoMessage() {} func (x *SandboxDeleteRequest) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -421,22 +407,19 @@ func (x *SandboxDeleteRequest) GetSandboxId() string { } type SandboxPauseRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + TemplateId string `protobuf:"bytes,2,opt,name=template_id,json=templateId,proto3" json:"template_id,omitempty"` + BuildId string `protobuf:"bytes,3,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"` unknownFields protoimpl.UnknownFields - - SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` - TemplateId string `protobuf:"bytes,2,opt,name=template_id,json=templateId,proto3" json:"template_id,omitempty"` - BuildId string `protobuf:"bytes,3,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxPauseRequest) Reset() { *x = SandboxPauseRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxPauseRequest) String() string { @@ -447,7 +430,7 @@ func (*SandboxPauseRequest) ProtoMessage() {} func (x *SandboxPauseRequest) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -484,23 +467,20 @@ func (x *SandboxPauseRequest) GetBuildId() string { } type RunningSandbox struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *SandboxConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + StartTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` + EndTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` unknownFields protoimpl.UnknownFields - - Config *SandboxConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - StartTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` - EndTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RunningSandbox) Reset() { *x = RunningSandbox{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *RunningSandbox) String() string { @@ -511,7 +491,7 @@ func (*RunningSandbox) ProtoMessage() {} func (x *RunningSandbox) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -555,20 +535,17 @@ func (x *RunningSandbox) GetEndTime() *timestamppb.Timestamp { } type SandboxListResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Sandboxes []*RunningSandbox `protobuf:"bytes,1,rep,name=sandboxes,proto3" json:"sandboxes,omitempty"` unknownFields protoimpl.UnknownFields - - Sandboxes []*RunningSandbox `protobuf:"bytes,1,rep,name=sandboxes,proto3" json:"sandboxes,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxListResponse) Reset() { *x = SandboxListResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxListResponse) String() string { @@ -579,7 +556,7 @@ func (*SandboxListResponse) ProtoMessage() {} func (x *SandboxListResponse) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -602,21 +579,18 @@ func (x *SandboxListResponse) GetSandboxes() []*RunningSandbox { } type CachedBuildInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` BuildId string `protobuf:"bytes,1,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"` ExpirationTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expiration_time,json=expirationTime,proto3" json:"expiration_time,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CachedBuildInfo) Reset() { *x = CachedBuildInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CachedBuildInfo) String() string { @@ -627,7 +601,7 @@ func (*CachedBuildInfo) ProtoMessage() {} func (x *CachedBuildInfo) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -657,20 +631,17 @@ func (x *CachedBuildInfo) GetExpirationTime() *timestamppb.Timestamp { } type SandboxListCachedBuildsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Builds []*CachedBuildInfo `protobuf:"bytes,1,rep,name=builds,proto3" json:"builds,omitempty"` unknownFields protoimpl.UnknownFields - - Builds []*CachedBuildInfo `protobuf:"bytes,1,rep,name=builds,proto3" json:"builds,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SandboxListCachedBuildsResponse) Reset() { *x = SandboxListCachedBuildsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_orchestrator_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_orchestrator_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SandboxListCachedBuildsResponse) String() string { @@ -681,7 +652,7 @@ func (*SandboxListCachedBuildsResponse) ProtoMessage() {} func (x *SandboxListCachedBuildsResponse) ProtoReflect() protoreflect.Message { mi := &file_orchestrator_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -703,170 +674,219 @@ func (x *SandboxListCachedBuildsResponse) GetBuilds() []*CachedBuildInfo { return nil } -var File_orchestrator_proto protoreflect.FileDescriptor +type OrchestratorStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + GlobalVersion int64 `protobuf:"varint,1,opt,name=global_version,json=globalVersion,proto3" json:"global_version,omitempty"` + RunningSandboxes int64 `protobuf:"varint,2,opt,name=running_sandboxes,json=runningSandboxes,proto3" json:"running_sandboxes,omitempty"` + PendingSandboxes int64 `protobuf:"varint,4,opt,name=pending_sandboxes,json=pendingSandboxes,proto3" json:"pending_sandboxes,omitempty"` + TerminatedSandboxes int64 `protobuf:"varint,5,opt,name=terminated_sandboxes,json=terminatedSandboxes,proto3" json:"terminated_sandboxes,omitempty"` + NumSandboxes int64 `protobuf:"varint,6,opt,name=num_sandboxes,json=numSandboxes,proto3" json:"num_sandboxes,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + EarliestRunningSandboxStartedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=earliest_running_sandbox_started_at,json=earliestRunningSandboxStartedAt,proto3" json:"earliest_running_sandbox_started_at,omitempty"` + MostRecentRunningSandboxUpdatedAt *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=most_recent_running_sandbox_updated_at,json=mostRecentRunningSandboxUpdatedAt,proto3" json:"most_recent_running_sandbox_updated_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} -var file_orchestrator_proto_rawDesc = []byte{ - 0x0a, 0x12, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0xac, 0x06, 0x0a, 0x0d, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, - 0x12, 0x25, 0x0a, 0x0e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x13, 0x66, 0x69, 0x72, 0x65, 0x63, - 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x66, 0x69, 0x72, 0x65, 0x63, 0x72, 0x61, 0x63, 0x6b, 0x65, - 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x75, 0x67, 0x65, - 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x68, 0x75, - 0x67, 0x65, 0x50, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6e, 0x64, 0x62, - 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x61, 0x6e, - 0x64, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x76, 0x61, - 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, - 0x6f, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x12, 0x38, - 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, - 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, - 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x76, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x64, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x63, 0x70, 0x75, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x76, 0x63, 0x70, 0x75, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x61, - 0x6d, 0x5f, 0x6d, 0x62, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x72, 0x61, 0x6d, 0x4d, - 0x62, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, - 0x78, 0x5f, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x53, 0x61, 0x6e, 0x64, 0x62, - 0x6f, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x2b, 0x0a, 0x12, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6d, 0x62, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x53, - 0x69, 0x7a, 0x65, 0x4d, 0x62, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x12, 0x28, 0x0a, 0x10, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x61, 0x73, - 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0a, 0x61, - 0x75, 0x74, 0x6f, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x48, - 0x01, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x50, 0x61, 0x75, 0x73, 0x65, 0x88, 0x01, 0x01, 0x1a, - 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x61, 0x6c, 0x69, - 0x61, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x70, 0x61, 0x75, 0x73, - 0x65, 0x22, 0xb2, 0x01, 0x0a, 0x14, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x07, 0x73, 0x61, - 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x53, 0x61, - 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x73, 0x61, 0x6e, - 0x64, 0x62, 0x6f, 0x78, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, - 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x34, 0x0a, 0x15, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, - 0x78, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x6c, 0x0a, 0x14, - 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, - 0x78, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x53, 0x61, - 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x49, - 0x64, 0x22, 0x70, 0x0a, 0x13, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x50, 0x61, 0x75, 0x73, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6e, 0x64, - 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x61, - 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x49, 0x64, 0x22, 0xc7, 0x01, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x53, - 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, - 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x44, 0x0a, - 0x13, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, - 0x67, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x52, 0x09, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, - 0x78, 0x65, 0x73, 0x22, 0x71, 0x0a, 0x0f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, - 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x4b, 0x0a, 0x1f, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, - 0x78, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x73, 0x32, 0xf6, 0x02, 0x0a, 0x0e, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x12, 0x15, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, - 0x78, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x37, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x53, 0x61, 0x6e, 0x64, - 0x62, 0x6f, 0x78, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x34, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, - 0x6f, 0x78, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, - 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, - 0x6f, 0x78, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x05, 0x50, 0x61, 0x75, 0x73, 0x65, - 0x12, 0x14, 0x2e, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x50, 0x61, 0x75, 0x73, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, - 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x53, 0x61, 0x6e, - 0x64, 0x62, 0x6f, 0x78, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d, - 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x65, 0x32, 0x62, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x69, 0x6e, 0x66, 0x72, 0x61, - 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, +func (x *OrchestratorStatus) Reset() { + *x = OrchestratorStatus{} + mi := &file_orchestrator_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } +func (x *OrchestratorStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrchestratorStatus) ProtoMessage() {} + +func (x *OrchestratorStatus) ProtoReflect() protoreflect.Message { + mi := &file_orchestrator_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrchestratorStatus.ProtoReflect.Descriptor instead. +func (*OrchestratorStatus) Descriptor() ([]byte, []int) { + return file_orchestrator_proto_rawDescGZIP(), []int{10} +} + +func (x *OrchestratorStatus) GetGlobalVersion() int64 { + if x != nil { + return x.GlobalVersion + } + return 0 +} + +func (x *OrchestratorStatus) GetRunningSandboxes() int64 { + if x != nil { + return x.RunningSandboxes + } + return 0 +} + +func (x *OrchestratorStatus) GetPendingSandboxes() int64 { + if x != nil { + return x.PendingSandboxes + } + return 0 +} + +func (x *OrchestratorStatus) GetTerminatedSandboxes() int64 { + if x != nil { + return x.TerminatedSandboxes + } + return 0 +} + +func (x *OrchestratorStatus) GetNumSandboxes() int64 { + if x != nil { + return x.NumSandboxes + } + return 0 +} + +func (x *OrchestratorStatus) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *OrchestratorStatus) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +func (x *OrchestratorStatus) GetEarliestRunningSandboxStartedAt() *timestamppb.Timestamp { + if x != nil { + return x.EarliestRunningSandboxStartedAt + } + return nil +} + +func (x *OrchestratorStatus) GetMostRecentRunningSandboxUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.MostRecentRunningSandboxUpdatedAt + } + return nil +} + +var File_orchestrator_proto protoreflect.FileDescriptor + +const file_orchestrator_proto_rawDesc = "" + + "\n" + + "\x12orchestrator.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xac\x06\n" + + "\rSandboxConfig\x12\x1f\n" + + "\vtemplate_id\x18\x01 \x01(\tR\n" + + "templateId\x12\x19\n" + + "\bbuild_id\x18\x02 \x01(\tR\abuildId\x12%\n" + + "\x0ekernel_version\x18\x03 \x01(\tR\rkernelVersion\x12/\n" + + "\x13firecracker_version\x18\x04 \x01(\tR\x12firecrackerVersion\x12\x1d\n" + + "\n" + + "huge_pages\x18\x05 \x01(\bR\thugePages\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x06 \x01(\tR\tsandboxId\x126\n" + + "\benv_vars\x18\a \x03(\v2\x1b.SandboxConfig.EnvVarsEntryR\aenvVars\x128\n" + + "\bmetadata\x18\b \x03(\v2\x1c.SandboxConfig.MetadataEntryR\bmetadata\x12\x19\n" + + "\x05alias\x18\t \x01(\tH\x00R\x05alias\x88\x01\x01\x12!\n" + + "\fenvd_version\x18\n" + + " \x01(\tR\venvdVersion\x12\x12\n" + + "\x04vcpu\x18\v \x01(\x03R\x04vcpu\x12\x15\n" + + "\x06ram_mb\x18\f \x01(\x03R\x05ramMb\x12\x17\n" + + "\ateam_id\x18\r \x01(\tR\x06teamId\x12,\n" + + "\x12max_sandbox_length\x18\x0e \x01(\x03R\x10maxSandboxLength\x12+\n" + + "\x12total_disk_size_mb\x18\x0f \x01(\x03R\x0ftotalDiskSizeMb\x12\x1a\n" + + "\bsnapshot\x18\x10 \x01(\bR\bsnapshot\x12(\n" + + "\x10base_template_id\x18\x11 \x01(\tR\x0ebaseTemplateId\x12\"\n" + + "\n" + + "auto_pause\x18\x12 \x01(\bH\x01R\tautoPause\x88\x01\x01\x1a:\n" + + "\fEnvVarsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1a;\n" + + "\rMetadataEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + + "\x06_aliasB\r\n" + + "\v_auto_pause\"\xb2\x01\n" + + "\x14SandboxCreateRequest\x12(\n" + + "\asandbox\x18\x01 \x01(\v2\x0e.SandboxConfigR\asandbox\x129\n" + + "\n" + + "start_time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tstartTime\x125\n" + + "\bend_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\aendTime\"4\n" + + "\x15SandboxCreateResponse\x12\x1b\n" + + "\tclient_id\x18\x01 \x01(\tR\bclientId\"l\n" + + "\x14SandboxUpdateRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x125\n" + + "\bend_time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\aendTime\"5\n" + + "\x14SandboxDeleteRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\"p\n" + + "\x13SandboxPauseRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x1f\n" + + "\vtemplate_id\x18\x02 \x01(\tR\n" + + "templateId\x12\x19\n" + + "\bbuild_id\x18\x03 \x01(\tR\abuildId\"\xc7\x01\n" + + "\x0eRunningSandbox\x12&\n" + + "\x06config\x18\x01 \x01(\v2\x0e.SandboxConfigR\x06config\x12\x1b\n" + + "\tclient_id\x18\x02 \x01(\tR\bclientId\x129\n" + + "\n" + + "start_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\tstartTime\x125\n" + + "\bend_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\aendTime\"D\n" + + "\x13SandboxListResponse\x12-\n" + + "\tsandboxes\x18\x01 \x03(\v2\x0f.RunningSandboxR\tsandboxes\"q\n" + + "\x0fCachedBuildInfo\x12\x19\n" + + "\bbuild_id\x18\x01 \x01(\tR\abuildId\x12C\n" + + "\x0fexpiration_time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x0eexpirationTime\"K\n" + + "\x1fSandboxListCachedBuildsResponse\x12(\n" + + "\x06builds\x18\x01 \x03(\v2\x10.CachedBuildInfoR\x06builds\"\x99\x04\n" + + "\x12OrchestratorStatus\x12%\n" + + "\x0eglobal_version\x18\x01 \x01(\x03R\rglobalVersion\x12+\n" + + "\x11running_sandboxes\x18\x02 \x01(\x03R\x10runningSandboxes\x12+\n" + + "\x11pending_sandboxes\x18\x04 \x01(\x03R\x10pendingSandboxes\x121\n" + + "\x14terminated_sandboxes\x18\x05 \x01(\x03R\x13terminatedSandboxes\x12#\n" + + "\rnum_sandboxes\x18\x06 \x01(\x03R\fnumSandboxes\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x129\n" + + "\n" + + "updated_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12h\n" + + "#earliest_running_sandbox_started_at\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\x1fearliestRunningSandboxStartedAt\x12m\n" + + "&most_recent_running_sandbox_updated_at\x18\n" + + " \x01(\v2\x1a.google.protobuf.TimestampR!mostRecentRunningSandboxUpdatedAt2\xb3\x03\n" + + "\x0eSandboxService\x127\n" + + "\x06Create\x12\x15.SandboxCreateRequest\x1a\x16.SandboxCreateResponse\x127\n" + + "\x06Update\x12\x15.SandboxUpdateRequest\x1a\x16.google.protobuf.Empty\x124\n" + + "\x04List\x12\x16.google.protobuf.Empty\x1a\x14.SandboxListResponse\x127\n" + + "\x06Delete\x12\x15.SandboxDeleteRequest\x1a\x16.google.protobuf.Empty\x125\n" + + "\x05Pause\x12\x14.SandboxPauseRequest\x1a\x16.google.protobuf.Empty\x12L\n" + + "\x10ListCachedBuilds\x12\x16.google.protobuf.Empty\x1a .SandboxListCachedBuildsResponse\x12;\n" + + "\fStatusReport\x12\x16.google.protobuf.Empty\x1a\x13.OrchestratorStatusB/Z-https://github.com/e2b-dev/infra/orchestratorb\x06proto3" + var ( file_orchestrator_proto_rawDescOnce sync.Once - file_orchestrator_proto_rawDescData = file_orchestrator_proto_rawDesc + file_orchestrator_proto_rawDescData []byte ) func file_orchestrator_proto_rawDescGZIP() []byte { file_orchestrator_proto_rawDescOnce.Do(func() { - file_orchestrator_proto_rawDescData = protoimpl.X.CompressGZIP(file_orchestrator_proto_rawDescData) + file_orchestrator_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_orchestrator_proto_rawDesc), len(file_orchestrator_proto_rawDesc))) }) return file_orchestrator_proto_rawDescData } -var file_orchestrator_proto_msgTypes = make([]protoimpl.MessageInfo, 12) -var file_orchestrator_proto_goTypes = []interface{}{ +var file_orchestrator_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_orchestrator_proto_goTypes = []any{ (*SandboxConfig)(nil), // 0: SandboxConfig (*SandboxCreateRequest)(nil), // 1: SandboxCreateRequest (*SandboxCreateResponse)(nil), // 2: SandboxCreateResponse @@ -877,41 +897,47 @@ var file_orchestrator_proto_goTypes = []interface{}{ (*SandboxListResponse)(nil), // 7: SandboxListResponse (*CachedBuildInfo)(nil), // 8: CachedBuildInfo (*SandboxListCachedBuildsResponse)(nil), // 9: SandboxListCachedBuildsResponse - nil, // 10: SandboxConfig.EnvVarsEntry - nil, // 11: SandboxConfig.MetadataEntry - (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp - (*emptypb.Empty)(nil), // 13: google.protobuf.Empty + (*OrchestratorStatus)(nil), // 10: OrchestratorStatus + nil, // 11: SandboxConfig.EnvVarsEntry + nil, // 12: SandboxConfig.MetadataEntry + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp + (*emptypb.Empty)(nil), // 14: google.protobuf.Empty } var file_orchestrator_proto_depIdxs = []int32{ - 10, // 0: SandboxConfig.env_vars:type_name -> SandboxConfig.EnvVarsEntry - 11, // 1: SandboxConfig.metadata:type_name -> SandboxConfig.MetadataEntry + 11, // 0: SandboxConfig.env_vars:type_name -> SandboxConfig.EnvVarsEntry + 12, // 1: SandboxConfig.metadata:type_name -> SandboxConfig.MetadataEntry 0, // 2: SandboxCreateRequest.sandbox:type_name -> SandboxConfig - 12, // 3: SandboxCreateRequest.start_time:type_name -> google.protobuf.Timestamp - 12, // 4: SandboxCreateRequest.end_time:type_name -> google.protobuf.Timestamp - 12, // 5: SandboxUpdateRequest.end_time:type_name -> google.protobuf.Timestamp + 13, // 3: SandboxCreateRequest.start_time:type_name -> google.protobuf.Timestamp + 13, // 4: SandboxCreateRequest.end_time:type_name -> google.protobuf.Timestamp + 13, // 5: SandboxUpdateRequest.end_time:type_name -> google.protobuf.Timestamp 0, // 6: RunningSandbox.config:type_name -> SandboxConfig - 12, // 7: RunningSandbox.start_time:type_name -> google.protobuf.Timestamp - 12, // 8: RunningSandbox.end_time:type_name -> google.protobuf.Timestamp + 13, // 7: RunningSandbox.start_time:type_name -> google.protobuf.Timestamp + 13, // 8: RunningSandbox.end_time:type_name -> google.protobuf.Timestamp 6, // 9: SandboxListResponse.sandboxes:type_name -> RunningSandbox - 12, // 10: CachedBuildInfo.expiration_time:type_name -> google.protobuf.Timestamp + 13, // 10: CachedBuildInfo.expiration_time:type_name -> google.protobuf.Timestamp 8, // 11: SandboxListCachedBuildsResponse.builds:type_name -> CachedBuildInfo - 1, // 12: SandboxService.Create:input_type -> SandboxCreateRequest - 3, // 13: SandboxService.Update:input_type -> SandboxUpdateRequest - 13, // 14: SandboxService.List:input_type -> google.protobuf.Empty - 4, // 15: SandboxService.Delete:input_type -> SandboxDeleteRequest - 5, // 16: SandboxService.Pause:input_type -> SandboxPauseRequest - 13, // 17: SandboxService.ListCachedBuilds:input_type -> google.protobuf.Empty - 2, // 18: SandboxService.Create:output_type -> SandboxCreateResponse - 13, // 19: SandboxService.Update:output_type -> google.protobuf.Empty - 7, // 20: SandboxService.List:output_type -> SandboxListResponse - 13, // 21: SandboxService.Delete:output_type -> google.protobuf.Empty - 13, // 22: SandboxService.Pause:output_type -> google.protobuf.Empty - 9, // 23: SandboxService.ListCachedBuilds:output_type -> SandboxListCachedBuildsResponse - 18, // [18:24] is the sub-list for method output_type - 12, // [12:18] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 13, // 12: OrchestratorStatus.updated_at:type_name -> google.protobuf.Timestamp + 13, // 13: OrchestratorStatus.earliest_running_sandbox_started_at:type_name -> google.protobuf.Timestamp + 13, // 14: OrchestratorStatus.most_recent_running_sandbox_updated_at:type_name -> google.protobuf.Timestamp + 1, // 15: SandboxService.Create:input_type -> SandboxCreateRequest + 3, // 16: SandboxService.Update:input_type -> SandboxUpdateRequest + 14, // 17: SandboxService.List:input_type -> google.protobuf.Empty + 4, // 18: SandboxService.Delete:input_type -> SandboxDeleteRequest + 5, // 19: SandboxService.Pause:input_type -> SandboxPauseRequest + 14, // 20: SandboxService.ListCachedBuilds:input_type -> google.protobuf.Empty + 14, // 21: SandboxService.StatusReport:input_type -> google.protobuf.Empty + 2, // 22: SandboxService.Create:output_type -> SandboxCreateResponse + 14, // 23: SandboxService.Update:output_type -> google.protobuf.Empty + 7, // 24: SandboxService.List:output_type -> SandboxListResponse + 14, // 25: SandboxService.Delete:output_type -> google.protobuf.Empty + 14, // 26: SandboxService.Pause:output_type -> google.protobuf.Empty + 9, // 27: SandboxService.ListCachedBuilds:output_type -> SandboxListCachedBuildsResponse + 10, // 28: SandboxService.StatusReport:output_type -> OrchestratorStatus + 22, // [22:29] is the sub-list for method output_type + 15, // [15:22] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_orchestrator_proto_init() } @@ -919,136 +945,14 @@ func file_orchestrator_proto_init() { if File_orchestrator_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_orchestrator_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxCreateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxCreateResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxUpdateRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxDeleteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxPauseRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RunningSandbox); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxListResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CachedBuildInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_orchestrator_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SandboxListCachedBuildsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_orchestrator_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_orchestrator_proto_msgTypes[0].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_orchestrator_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_orchestrator_proto_rawDesc), len(file_orchestrator_proto_rawDesc)), NumEnums: 0, - NumMessages: 12, + NumMessages: 13, NumExtensions: 0, NumServices: 1, }, @@ -1057,7 +961,6 @@ func file_orchestrator_proto_init() { MessageInfos: file_orchestrator_proto_msgTypes, }.Build() File_orchestrator_proto = out.File - file_orchestrator_proto_rawDesc = nil file_orchestrator_proto_goTypes = nil file_orchestrator_proto_depIdxs = nil } diff --git a/packages/shared/pkg/grpc/orchestrator/orchestrator_grpc.pb.go b/packages/shared/pkg/grpc/orchestrator/orchestrator_grpc.pb.go index dfc25ec5e..ea48065d5 100644 --- a/packages/shared/pkg/grpc/orchestrator/orchestrator_grpc.pb.go +++ b/packages/shared/pkg/grpc/orchestrator/orchestrator_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v5.29.3 +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.29.2 // source: orchestrator.proto package orchestrator @@ -16,8 +16,18 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + SandboxService_Create_FullMethodName = "/SandboxService/Create" + SandboxService_Update_FullMethodName = "/SandboxService/Update" + SandboxService_List_FullMethodName = "/SandboxService/List" + SandboxService_Delete_FullMethodName = "/SandboxService/Delete" + SandboxService_Pause_FullMethodName = "/SandboxService/Pause" + SandboxService_ListCachedBuilds_FullMethodName = "/SandboxService/ListCachedBuilds" + SandboxService_StatusReport_FullMethodName = "/SandboxService/StatusReport" +) // SandboxServiceClient is the client API for SandboxService service. // @@ -29,6 +39,7 @@ type SandboxServiceClient interface { Delete(ctx context.Context, in *SandboxDeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) Pause(ctx context.Context, in *SandboxPauseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) ListCachedBuilds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SandboxListCachedBuildsResponse, error) + StatusReport(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*OrchestratorStatus, error) } type sandboxServiceClient struct { @@ -40,8 +51,9 @@ func NewSandboxServiceClient(cc grpc.ClientConnInterface) SandboxServiceClient { } func (c *sandboxServiceClient) Create(ctx context.Context, in *SandboxCreateRequest, opts ...grpc.CallOption) (*SandboxCreateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SandboxCreateResponse) - err := c.cc.Invoke(ctx, "/SandboxService/Create", in, out, opts...) + err := c.cc.Invoke(ctx, SandboxService_Create_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -49,8 +61,9 @@ func (c *sandboxServiceClient) Create(ctx context.Context, in *SandboxCreateRequ } func (c *sandboxServiceClient) Update(ctx context.Context, in *SandboxUpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/SandboxService/Update", in, out, opts...) + err := c.cc.Invoke(ctx, SandboxService_Update_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -58,8 +71,9 @@ func (c *sandboxServiceClient) Update(ctx context.Context, in *SandboxUpdateRequ } func (c *sandboxServiceClient) List(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SandboxListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SandboxListResponse) - err := c.cc.Invoke(ctx, "/SandboxService/List", in, out, opts...) + err := c.cc.Invoke(ctx, SandboxService_List_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -67,8 +81,9 @@ func (c *sandboxServiceClient) List(ctx context.Context, in *emptypb.Empty, opts } func (c *sandboxServiceClient) Delete(ctx context.Context, in *SandboxDeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/SandboxService/Delete", in, out, opts...) + err := c.cc.Invoke(ctx, SandboxService_Delete_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -76,8 +91,9 @@ func (c *sandboxServiceClient) Delete(ctx context.Context, in *SandboxDeleteRequ } func (c *sandboxServiceClient) Pause(ctx context.Context, in *SandboxPauseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/SandboxService/Pause", in, out, opts...) + err := c.cc.Invoke(ctx, SandboxService_Pause_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -85,8 +101,19 @@ func (c *sandboxServiceClient) Pause(ctx context.Context, in *SandboxPauseReques } func (c *sandboxServiceClient) ListCachedBuilds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SandboxListCachedBuildsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SandboxListCachedBuildsResponse) - err := c.cc.Invoke(ctx, "/SandboxService/ListCachedBuilds", in, out, opts...) + err := c.cc.Invoke(ctx, SandboxService_ListCachedBuilds_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sandboxServiceClient) StatusReport(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*OrchestratorStatus, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OrchestratorStatus) + err := c.cc.Invoke(ctx, SandboxService_StatusReport_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -95,7 +122,7 @@ func (c *sandboxServiceClient) ListCachedBuilds(ctx context.Context, in *emptypb // SandboxServiceServer is the server API for SandboxService service. // All implementations must embed UnimplementedSandboxServiceServer -// for forward compatibility +// for forward compatibility. type SandboxServiceServer interface { Create(context.Context, *SandboxCreateRequest) (*SandboxCreateResponse, error) Update(context.Context, *SandboxUpdateRequest) (*emptypb.Empty, error) @@ -103,12 +130,16 @@ type SandboxServiceServer interface { Delete(context.Context, *SandboxDeleteRequest) (*emptypb.Empty, error) Pause(context.Context, *SandboxPauseRequest) (*emptypb.Empty, error) ListCachedBuilds(context.Context, *emptypb.Empty) (*SandboxListCachedBuildsResponse, error) + StatusReport(context.Context, *emptypb.Empty) (*OrchestratorStatus, error) mustEmbedUnimplementedSandboxServiceServer() } -// UnimplementedSandboxServiceServer must be embedded to have forward compatible implementations. -type UnimplementedSandboxServiceServer struct { -} +// UnimplementedSandboxServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedSandboxServiceServer struct{} func (UnimplementedSandboxServiceServer) Create(context.Context, *SandboxCreateRequest) (*SandboxCreateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Create not implemented") @@ -128,7 +159,11 @@ func (UnimplementedSandboxServiceServer) Pause(context.Context, *SandboxPauseReq func (UnimplementedSandboxServiceServer) ListCachedBuilds(context.Context, *emptypb.Empty) (*SandboxListCachedBuildsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListCachedBuilds not implemented") } +func (UnimplementedSandboxServiceServer) StatusReport(context.Context, *emptypb.Empty) (*OrchestratorStatus, error) { + return nil, status.Errorf(codes.Unimplemented, "method StatusReport not implemented") +} func (UnimplementedSandboxServiceServer) mustEmbedUnimplementedSandboxServiceServer() {} +func (UnimplementedSandboxServiceServer) testEmbeddedByValue() {} // UnsafeSandboxServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to SandboxServiceServer will @@ -138,6 +173,13 @@ type UnsafeSandboxServiceServer interface { } func RegisterSandboxServiceServer(s grpc.ServiceRegistrar, srv SandboxServiceServer) { + // If the following call pancis, it indicates UnimplementedSandboxServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&SandboxService_ServiceDesc, srv) } @@ -151,7 +193,7 @@ func _SandboxService_Create_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/SandboxService/Create", + FullMethod: SandboxService_Create_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SandboxServiceServer).Create(ctx, req.(*SandboxCreateRequest)) @@ -169,7 +211,7 @@ func _SandboxService_Update_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/SandboxService/Update", + FullMethod: SandboxService_Update_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SandboxServiceServer).Update(ctx, req.(*SandboxUpdateRequest)) @@ -187,7 +229,7 @@ func _SandboxService_List_Handler(srv interface{}, ctx context.Context, dec func } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/SandboxService/List", + FullMethod: SandboxService_List_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SandboxServiceServer).List(ctx, req.(*emptypb.Empty)) @@ -205,7 +247,7 @@ func _SandboxService_Delete_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/SandboxService/Delete", + FullMethod: SandboxService_Delete_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SandboxServiceServer).Delete(ctx, req.(*SandboxDeleteRequest)) @@ -223,7 +265,7 @@ func _SandboxService_Pause_Handler(srv interface{}, ctx context.Context, dec fun } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/SandboxService/Pause", + FullMethod: SandboxService_Pause_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SandboxServiceServer).Pause(ctx, req.(*SandboxPauseRequest)) @@ -241,7 +283,7 @@ func _SandboxService_ListCachedBuilds_Handler(srv interface{}, ctx context.Conte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/SandboxService/ListCachedBuilds", + FullMethod: SandboxService_ListCachedBuilds_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(SandboxServiceServer).ListCachedBuilds(ctx, req.(*emptypb.Empty)) @@ -249,6 +291,24 @@ func _SandboxService_ListCachedBuilds_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } +func _SandboxService_StatusReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SandboxServiceServer).StatusReport(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SandboxService_StatusReport_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SandboxServiceServer).StatusReport(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + // SandboxService_ServiceDesc is the grpc.ServiceDesc for SandboxService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -280,6 +340,10 @@ var SandboxService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListCachedBuilds", Handler: _SandboxService_ListCachedBuilds_Handler, }, + { + MethodName: "StatusReport", + Handler: _SandboxService_StatusReport_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "orchestrator.proto", diff --git a/sqlc.yaml b/sqlc.yaml new file mode 100644 index 000000000..118ef7041 --- /dev/null +++ b/sqlc.yaml @@ -0,0 +1,24 @@ +version: "2" +sql: + # ORCHESTRATOR PROCESS' LOCAL DATABASE + - engine: "sqlite" + queries: "packages/orchestrator/internal/db/queries.sql" + schema: "packages/orchestrator/internal/db/schema.sql" + # migrations are unnecessary right now because the DB never lives + # longer than the process. + gen: + go: + emit_pointers_for_null_types: true + package: "database" + out: "packages/orchestrator/internal/pkg/database" + overrides: + - db_type: "timestamp" + go_type: + import: "time" + type: "time.Time" + - db_type: "timestamp" + nullable: true + go_type: + import: "time" + type: "time.Time" + pointer: true