diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c54f284972..9ae408007f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -245,6 +245,15 @@ jobs: - uses: cashapp/activate-hermit@v1.1.3 - uses: ./.github/actions/build-cache - run: just build-docker cron + docker-build-http-ingress: + name: Build HTTP Ingress Docker Image + # if: github.event_name != 'pull_request' || github.event.action == 'enqueued' || contains( github.event.pull_request.labels.*.name, 'run-all') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: cashapp/activate-hermit@v1.1.3 + - uses: ./.github/actions/build-cache + - run: just build-docker http-ingress docker-build-runner: name: Build Runner Docker Images # if: github.event_name != 'pull_request' || github.event.action == 'enqueued' || contains( github.event.pull_request.labels.*.name, 'run-all') @@ -263,7 +272,7 @@ jobs: - uses: actions/checkout@v4 - uses: cashapp/activate-hermit@v1.1.3 - uses: ./.github/actions/build-cache - - name: Build JVM Docker Image + - name: Build JVM Docker Imag run: just build-docker runner-jvm console-e2e: name: Console e2e diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 801377fb2c..a218ba30c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,13 +91,32 @@ jobs: name: docker-cron-artifact path: artifacts/ftl-cron retention-days: 1 + build-http-ingress: + name: Build HTTP Ingress Docker Image + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Init Hermit + uses: cashapp/activate-hermit@v1.1.3 + - name: Build + run: | + just build-docker http-ingress + mkdir -p artifacts/ftl-provisioner + docker save -o artifacts/ftl-http-ingress/ftl-http-ingress.tar ftl0/ftl-http-ingress:latest + - name: Temporarily save Docker image + uses: actions/upload-artifact@v4 + with: + name: docker-http-ingress-artifact + path: artifacts/ftl-http-ingress + retention-days: 1 release-docker: name: Release Assets runs-on: ubuntu-latest permissions: contents: read packages: write - needs: [build-runners, build-controller, build-provisioner, build-cron] + needs: [build-runners, build-controller, build-provisioner, build-cron, build-http-ingress] steps: - name: Checkout code uses: actions/checkout@v4 @@ -130,6 +149,11 @@ jobs: with: name: docker-cron-artifact path: artifacts/ftl-cron + - name: Retrieve HTTP Ingress Docker image + uses: actions/download-artifact@v4 + with: + name: docker-http-ingress-artifact + path: artifacts/ftl-http-ingress - name: Load Runner Docker image run: docker load -i artifacts/ftl-runner/ftl-runner.tar - name: Load JVM Runner Docker image @@ -140,6 +164,8 @@ jobs: run: docker load -i artifacts/ftl-provisioner/ftl-provisioner.tar - name: Load Cron Docker image run: docker load -i artifacts/ftl-cron/ftl-cron.tar + - name: Load HTTP Ingress Docker image + run: docker load -i artifacts/ftl-http-ingress/ftl-http-ingress.tar - name: Log in to the Container registry uses: docker/login-action@v3 with: @@ -163,6 +189,9 @@ jobs: docker tag ftl0/ftl-cron:latest ftl0/ftl-cron:"$GITHUB_SHA" docker tag ftl0/ftl-cron:latest ftl0/ftl-cron:"$version" docker push -a ftl0/ftl-cron + docker tag ftl0/ftl-http-ingress:latest ftl0/ftl-http-ingress:"$GITHUB_SHA" + docker tag ftl0/ftl-http-ingress:latest ftl0/ftl-http-ingress:"$version" + docker push -a ftl0/ftl-http-ingress create-go-release: name: Release Go Binaries diff --git a/Dockerfile.http-ingress b/Dockerfile.http-ingress new file mode 100644 index 0000000000..70b50e298d --- /dev/null +++ b/Dockerfile.http-ingress @@ -0,0 +1,44 @@ +FROM ubuntu:24.04 AS builder +RUN apt-get update +RUN apt-get install -y curl git zip + +# Copy Hermit bin stubs and install all packages. This is done +# separately so that Docker will cache the tools correctly. +COPY ./bin /src/bin +ENV PATH="/src/bin:$PATH" +WORKDIR /src + +# Seed some of the most common tools - this will be cached +RUN go version +RUN node --version + +# Download Go dependencies separately so Docker will cache them +COPY go.mod go.sum ./ +RUN go mod download -x + +# Download PNPM dependencies separately so Docker will cache them +COPY frontend/console/package.json ./frontend/console/ +COPY frontend/vscode/package.json ./frontend/vscode/ +COPY pnpm-workspace.yaml pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +# Build +COPY . /src/ +RUN just errtrace +# Reset timestamps so that the build state is reset +RUN git ls-files -z | xargs -0 touch -r go.mod +RUN just build ftl-http-ingress + +# Finally create the runtime image. +FROM scratch + +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +WORKDIR /plugins/ + +WORKDIR /service/ +COPY --from=builder /src/build/release/ftl-http-ingress . + +EXPOSE 8893 + +CMD ["/service/ftl-http-ingress"] diff --git a/backend/controller/controller.go b/backend/controller/controller.go index 5470ba26bf..b38c1e3a8d 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -26,7 +26,6 @@ import ( "github.com/jackc/pgx/v5" "github.com/jellydator/ttlcache/v3" "github.com/jpillora/backoff" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "golang.org/x/exp/maps" "golang.org/x/sync/errgroup" "google.golang.org/protobuf/proto" @@ -42,7 +41,6 @@ import ( dalmodel "github.com/TBD54566975/ftl/backend/controller/dal/model" "github.com/TBD54566975/ftl/backend/controller/dsn" "github.com/TBD54566975/ftl/backend/controller/encryption" - "github.com/TBD54566975/ftl/backend/controller/ingress" "github.com/TBD54566975/ftl/backend/controller/leases" "github.com/TBD54566975/ftl/backend/controller/leases/dbleaser" "github.com/TBD54566975/ftl/backend/controller/observability" @@ -58,8 +56,6 @@ import ( frontend "github.com/TBD54566975/ftl/frontend/console" "github.com/TBD54566975/ftl/internal/configuration" cf "github.com/TBD54566975/ftl/internal/configuration/manager" - "github.com/TBD54566975/ftl/internal/cors" - ftlhttp "github.com/TBD54566975/ftl/internal/http" "github.com/TBD54566975/ftl/internal/log" ftlmaps "github.com/TBD54566975/ftl/internal/maps" "github.com/TBD54566975/ftl/internal/model" @@ -75,24 +71,14 @@ import ( // CommonConfig between the production controller and development server. type CommonConfig struct { - AllowOrigins []*url.URL `help:"Allow CORS requests to ingress endpoints from these origins." env:"FTL_CONTROLLER_ALLOW_ORIGIN"` - AllowHeaders []string `help:"Allow these headers in CORS requests. (Requires AllowOrigins)" env:"FTL_CONTROLLER_ALLOW_HEADERS"` NoConsole bool `help:"Disable the console."` IdleRunners int `help:"Number of idle runners to keep around (not supported in production)." default:"3"` WaitFor []string `help:"Wait for these modules to be deployed before becoming ready." placeholder:"MODULE"` CronJobTimeout time.Duration `help:"Timeout for cron jobs." default:"5m"` } -func (c *CommonConfig) Validate() error { - if len(c.AllowHeaders) > 0 && len(c.AllowOrigins) == 0 { - return fmt.Errorf("AllowOrigins must be set when AllowHeaders is used") - } - return nil -} - type Config struct { Bind *url.URL `help:"Socket to bind to." default:"http://127.0.0.1:8892" env:"FTL_CONTROLLER_BIND"` - IngressBind *url.URL `help:"Socket to bind to for ingress." default:"http://127.0.0.1:8891" env:"FTL_CONTROLLER_INGRESS_BIND"` Key model.ControllerKey `help:"Controller key (auto)." placeholder:"KEY"` DSN string `help:"DAL DSN." default:"${dsn}" env:"FTL_CONTROLLER_DSN"` Advertise *url.URL `help:"Endpoint the Controller should advertise (must be unique across the cluster, defaults to --bind if omitted)." env:"FTL_CONTROLLER_ADVERTISE"` @@ -170,21 +156,7 @@ func Start( admin := admin.NewAdminService(cm, sm, svc.dal) console := console.NewService(svc.dal, svc.timeline, admin) - ingressHandler := otelhttp.NewHandler(http.Handler(svc), "ftl.ingress") - if len(config.AllowOrigins) > 0 { - ingressHandler = cors.Middleware( - slices.Map(config.AllowOrigins, func(u *url.URL) string { return u.String() }), - config.AllowHeaders, - ingressHandler, - ) - } - g, ctx := errgroup.WithContext(ctx) - g.Go(func() error { - logger.Infof("HTTP ingress server listening on: %s", config.IngressBind) - - return ftlhttp.Serve(ctx, config.IngressBind, ingressHandler) - }) g.Go(func() error { return rpc.Serve(ctx, config.Bind, @@ -370,28 +342,6 @@ func New( return svc, nil } -func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { - start := time.Now() - method := strings.ToLower(r.Method) - requestKey := model.NewRequestKey(model.OriginIngress, fmt.Sprintf("%s %s", method, r.URL.Path)) - - sourceAddress := r.RemoteAddr - err := s.dal.CreateRequest(r.Context(), requestKey, sourceAddress) - if err != nil { - observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.None[*schemapb.Ref](), start, optional.Some("failed to create request")) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - routes := s.schemaState.Load().httpRoutes[r.Method] - if len(routes) == 0 { - http.NotFound(w, r) - observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.None[*schemapb.Ref](), start, optional.Some("route not found in dal")) - return - } - ingress.Handle(start, s.schemaState.Load().schema, requestKey, routes, w, r, s.timeline, s.callWithRequest) -} - func (s *Service) ProcessList(ctx context.Context, req *connect.Request[ftlv1.ProcessListRequest]) (*connect.Response[ftlv1.ProcessListResponse], error) { processes, err := s.dal.GetProcessList(ctx) if err != nil { @@ -487,15 +437,7 @@ func (s *Service) Status(ctx context.Context, req *connect.Request[ftlv1.StatusR }), Runners: protoRunners, Deployments: deployments, - IngressRoutes: slices.Map(status.IngressRoutes, func(r dalmodel.IngressRouteEntry) *ftlv1.StatusResponse_IngressRoute { - return &ftlv1.StatusResponse_IngressRoute{ - DeploymentKey: r.Deployment.String(), - Verb: &schemapb.Ref{Module: r.Module, Name: r.Verb}, - Method: r.Method, - Path: r.Path, - } - }), - Routes: routes, + Routes: routes, } return connect.NewResponse(resp), nil } @@ -1132,9 +1074,7 @@ func (s *Service) CreateDeployment(ctx context.Context, req *connect.Request[ftl } } - ingressRoutes := extractIngressRoutingEntries(req.Msg) - - dkey, err := s.dal.CreateDeployment(ctx, ms.Runtime.Language, module, artefacts, ingressRoutes) + dkey, err := s.dal.CreateDeployment(ctx, ms.Runtime.Language, module, artefacts) if err != nil { logger.Errorf(err, "Could not create deployment") return nil, fmt.Errorf("could not create deployment: %w", err) @@ -1764,16 +1704,12 @@ func (s *Service) syncRoutesAndSchema(ctx context.Context) (ret time.Duration, e } } - httpRoutes, err := s.dal.GetIngressRoutes(ctx) - if err != nil { - return 0, fmt.Errorf("failed to get ingress routes: %w", err) - } orderedModules := maps.Values(modulesByName) sort.SliceStable(orderedModules, func(i, j int) bool { return orderedModules[i].Name < orderedModules[j].Name }) combined := &schema.Schema{Modules: orderedModules} - s.schemaState.Store(schemaState{schema: combined, routes: newRoutes, httpRoutes: httpRoutes}) + s.schemaState.Store(schemaState{schema: combined, routes: newRoutes}) return time.Second, nil } @@ -1797,37 +1733,6 @@ func (s *Service) reapCallEvents(ctx context.Context) (time.Duration, error) { return *s.config.EventLogRetention / 20, nil } -func extractIngressRoutingEntries(req *ftlv1.CreateDeploymentRequest) []dal.IngressRoutingEntry { - var ingressRoutes []dal.IngressRoutingEntry - for _, decl := range req.Schema.Decls { - if verb, ok := decl.Value.(*schemapb.Decl_Verb); ok { - for _, metadata := range verb.Verb.Metadata { - if ingress, ok := metadata.Value.(*schemapb.Metadata_Ingress); ok { - ingressRoutes = append(ingressRoutes, dal.IngressRoutingEntry{ - Verb: verb.Verb.Name, - Method: ingress.Ingress.Method, - Path: ingressPathString(ingress.Ingress.Path), - }) - } - } - } - } - return ingressRoutes -} - -func ingressPathString(path []*schemapb.IngressPathComponent) string { - pathString := make([]string, len(path)) - for i, p := range path { - switch p.Value.(type) { - case *schemapb.IngressPathComponent_IngressPathLiteral: - pathString[i] = p.GetIngressPathLiteral().Text - case *schemapb.IngressPathComponent_IngressPathParameter: - pathString[i] = fmt.Sprintf("{%s}", p.GetIngressPathParameter().Name) - } - } - return "/" + strings.Join(pathString, "/") -} - func makeBackoff(min, max time.Duration) backoff.Backoff { return backoff.Backoff{ Min: min, @@ -1862,9 +1767,8 @@ type Route struct { } type schemaState struct { - schema *schema.Schema - routes map[string]Route - httpRoutes map[string][]dalmodel.IngressRoute + schema *schema.Schema + routes map[string]Route } func (r Route) String() string { diff --git a/backend/controller/dal/dal.go b/backend/controller/dal/dal.go index 450ae04f27..4e224886e1 100644 --- a/backend/controller/dal/dal.go +++ b/backend/controller/dal/dal.go @@ -115,10 +115,6 @@ func (d *DAL) GetStatus(ctx context.Context) (dalmodel.Status, error) { if err != nil { return dalmodel.Status{}, fmt.Errorf("could not get active deployments: %w", libdal.TranslatePGError(err)) } - ingressRoutes, err := d.db.GetActiveIngressRoutes(ctx) - if err != nil { - return dalmodel.Status{}, fmt.Errorf("could not get ingress routes: %w", libdal.TranslatePGError(err)) - } statusDeployments, err := slices.MapErr(deployments, func(in dalsql.GetActiveDeploymentsRow) (dalmodel.Deployment, error) { labels := model.Labels{} err = json.Unmarshal(in.Deployment.Labels, &labels) @@ -157,15 +153,6 @@ func (d *DAL) GetStatus(ctx context.Context) (dalmodel.Status, error) { Controllers: controllers, Deployments: statusDeployments, Runners: domainRunners, - IngressRoutes: slices.Map(ingressRoutes, func(in dalsql.GetActiveIngressRoutesRow) dalmodel.IngressRouteEntry { - return dalmodel.IngressRouteEntry{ - Deployment: in.DeploymentKey, - Module: in.Module, - Verb: in.Verb, - Method: in.Method, - Path: in.Path, - } - }), }, nil } @@ -196,17 +183,11 @@ func (d *DAL) UpsertModule(ctx context.Context, language, name string) (err erro return libdal.TranslatePGError(err) } -type IngressRoutingEntry struct { - Verb string - Method string - Path string -} - // CreateDeployment (possibly) creates a new deployment and associates // previously created artefacts with it. // // If an existing deployment with identical artefacts exists, it is returned. -func (d *DAL) CreateDeployment(ctx context.Context, language string, moduleSchema *schema.Module, artefacts []dalmodel.DeploymentArtefact, ingressRoutes []IngressRoutingEntry) (key model.DeploymentKey, err error) { +func (d *DAL) CreateDeployment(ctx context.Context, language string, moduleSchema *schema.Module, artefacts []dalmodel.DeploymentArtefact) (key model.DeploymentKey, err error) { logger := log.FromContext(ctx) // Start the parent transaction @@ -290,19 +271,6 @@ func (d *DAL) CreateDeployment(ctx context.Context, language string, moduleSchem } } - for _, ingressRoute := range ingressRoutes { - err = tx.db.CreateIngressRoute(ctx, dalsql.CreateIngressRouteParams{ - Key: deploymentKey, - Method: ingressRoute.Method, - Path: ingressRoute.Path, - Module: moduleSchema.Name, - Verb: ingressRoute.Verb, - }) - if err != nil { - return model.DeploymentKey{}, fmt.Errorf("failed to create ingress route: %w", libdal.TranslatePGError(err)) - } - } - return deploymentKey, nil } @@ -690,24 +658,6 @@ func (d *DAL) CreateRequest(ctx context.Context, key model.RequestKey, addr stri return nil } -func (d *DAL) GetIngressRoutes(ctx context.Context) (map[string][]dalmodel.IngressRoute, error) { - routes, err := d.db.GetIngressRoutes(ctx) - if err != nil { - return nil, libdal.TranslatePGError(err) - } - return slices.GroupBy(slices.Map(routes, func(row dalsql.GetIngressRoutesRow) dalmodel.IngressRoute { - return dalmodel.IngressRoute{ - Runner: row.RunnerKey, - Deployment: row.DeploymentKey, - Endpoint: row.Endpoint, - Path: row.Path, - Module: row.Module, - Verb: row.Verb, - Method: row.Method, - } - }), func(route dalmodel.IngressRoute) string { return route.Method }), nil -} - func (d *DAL) UpsertController(ctx context.Context, key model.ControllerKey, addr string) (int64, error) { id, err := d.db.UpsertController(ctx, key, addr) return id, libdal.TranslatePGError(err) diff --git a/backend/controller/dal/dal_test.go b/backend/controller/dal/dal_test.go index 42ad309276..9943ab676a 100644 --- a/backend/controller/dal/dal_test.go +++ b/backend/controller/dal/dal_test.go @@ -67,7 +67,7 @@ func TestDAL(t *testing.T) { Digest: testSha, Executable: true, Path: "dir/filename", - }}, nil) + }}) assert.NoError(t, err) }) diff --git a/backend/controller/dal/internal/sql/querier.go b/backend/controller/dal/internal/sql/querier.go index 03f0d9740d..055b410e5c 100644 --- a/backend/controller/dal/internal/sql/querier.go +++ b/backend/controller/dal/internal/sql/querier.go @@ -24,7 +24,6 @@ type Querier interface { CompleteEventForSubscription(ctx context.Context, name string, module string) error CreateAsyncCall(ctx context.Context, arg CreateAsyncCallParams) (int64, error) CreateDeployment(ctx context.Context, moduleName string, schema []byte, key model.DeploymentKey) error - CreateIngressRoute(ctx context.Context, arg CreateIngressRouteParams) error CreateRequest(ctx context.Context, origin Origin, key model.RequestKey, sourceAddr string) error DeleteSubscribers(ctx context.Context, deployment model.DeploymentKey) ([]model.SubscriberKey, error) DeleteSubscriptions(ctx context.Context, deployment model.DeploymentKey) ([]model.SubscriptionKey, error) @@ -34,7 +33,6 @@ type Querier interface { GetActiveControllers(ctx context.Context) ([]Controller, error) GetActiveDeploymentSchemas(ctx context.Context) ([]GetActiveDeploymentSchemasRow, error) GetActiveDeployments(ctx context.Context) ([]GetActiveDeploymentsRow, error) - GetActiveIngressRoutes(ctx context.Context) ([]GetActiveIngressRoutesRow, error) GetActiveRunners(ctx context.Context) ([]GetActiveRunnersRow, error) // Return the digests that exist in the database. GetArtefactDigests(ctx context.Context, digests [][]byte) ([][]byte, error) @@ -46,8 +44,6 @@ type Querier interface { GetDeploymentsWithArtefacts(ctx context.Context, digests [][]byte, schema []byte, count int64) ([]GetDeploymentsWithArtefactsRow, error) GetDeploymentsWithMinReplicas(ctx context.Context) ([]GetDeploymentsWithMinReplicasRow, error) GetExistingDeploymentForModule(ctx context.Context, name string) (GetExistingDeploymentForModuleRow, error) - // Get the runner endpoints corresponding to the given ingress route. - GetIngressRoutes(ctx context.Context) ([]GetIngressRoutesRow, error) GetModulesByID(ctx context.Context, ids []int64) ([]Module, error) GetNextEventForSubscription(ctx context.Context, consumptionDelay sqltypes.Duration, topic model.TopicKey, cursor optional.Option[model.TopicEventKey]) (GetNextEventForSubscriptionRow, error) GetProcessList(ctx context.Context) ([]GetProcessListRow, error) diff --git a/backend/controller/dal/internal/sql/queries.sql b/backend/controller/dal/internal/sql/queries.sql index 522472de3e..293df59a3a 100644 --- a/backend/controller/dal/internal/sql/queries.sql +++ b/backend/controller/dal/internal/sql/queries.sql @@ -191,23 +191,6 @@ FROM controllers c WHERE c.state <> 'dead' ORDER BY c.key; --- name: CreateIngressRoute :exec -INSERT INTO ingress_routes (deployment_id, module, verb, method, path) -VALUES ((SELECT id FROM deployments WHERE key = sqlc.arg('key')::deployment_key LIMIT 1), $2, $3, $4, $5); - --- name: GetIngressRoutes :many --- Get the runner endpoints corresponding to the given ingress route. -SELECT r.key AS runner_key, d.key AS deployment_key, endpoint, ir.path, ir.module, ir.verb, ir.method -FROM ingress_routes ir - INNER JOIN runners r ON ir.deployment_id = r.deployment_id - INNER JOIN deployments d ON ir.deployment_id = d.id; - --- name: GetActiveIngressRoutes :many -SELECT d.key AS deployment_key, ir.module, ir.verb, ir.method, ir.path -FROM ingress_routes ir - INNER JOIN deployments d ON ir.deployment_id = d.id -WHERE d.min_replicas > 0; - -- name: SucceedAsyncCall :one UPDATE async_calls SET diff --git a/backend/controller/dal/internal/sql/queries.sql.go b/backend/controller/dal/internal/sql/queries.sql.go index 3df2eb916c..d9dbae9d9d 100644 --- a/backend/controller/dal/internal/sql/queries.sql.go +++ b/backend/controller/dal/internal/sql/queries.sql.go @@ -171,30 +171,6 @@ func (q *Queries) CreateDeployment(ctx context.Context, moduleName string, schem return err } -const createIngressRoute = `-- name: CreateIngressRoute :exec -INSERT INTO ingress_routes (deployment_id, module, verb, method, path) -VALUES ((SELECT id FROM deployments WHERE key = $1::deployment_key LIMIT 1), $2, $3, $4, $5) -` - -type CreateIngressRouteParams struct { - Key model.DeploymentKey - Module string - Verb string - Method string - Path string -} - -func (q *Queries) CreateIngressRoute(ctx context.Context, arg CreateIngressRouteParams) error { - _, err := q.db.ExecContext(ctx, createIngressRoute, - arg.Key, - arg.Module, - arg.Verb, - arg.Method, - arg.Path, - ) - return err -} - const createRequest = `-- name: CreateRequest :exec INSERT INTO requests (origin, "key", source_addr) VALUES ($1, $2, $3) @@ -486,50 +462,6 @@ func (q *Queries) GetActiveDeployments(ctx context.Context) ([]GetActiveDeployme return items, nil } -const getActiveIngressRoutes = `-- name: GetActiveIngressRoutes :many -SELECT d.key AS deployment_key, ir.module, ir.verb, ir.method, ir.path -FROM ingress_routes ir - INNER JOIN deployments d ON ir.deployment_id = d.id -WHERE d.min_replicas > 0 -` - -type GetActiveIngressRoutesRow struct { - DeploymentKey model.DeploymentKey - Module string - Verb string - Method string - Path string -} - -func (q *Queries) GetActiveIngressRoutes(ctx context.Context) ([]GetActiveIngressRoutesRow, error) { - rows, err := q.db.QueryContext(ctx, getActiveIngressRoutes) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetActiveIngressRoutesRow - for rows.Next() { - var i GetActiveIngressRoutesRow - if err := rows.Scan( - &i.DeploymentKey, - &i.Module, - &i.Verb, - &i.Method, - &i.Path, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - const getActiveRunners = `-- name: GetActiveRunners :many SELECT DISTINCT ON (r.key) r.key AS runner_key, r.endpoint, @@ -867,55 +799,6 @@ func (q *Queries) GetExistingDeploymentForModule(ctx context.Context, name strin return i, err } -const getIngressRoutes = `-- name: GetIngressRoutes :many -SELECT r.key AS runner_key, d.key AS deployment_key, endpoint, ir.path, ir.module, ir.verb, ir.method -FROM ingress_routes ir - INNER JOIN runners r ON ir.deployment_id = r.deployment_id - INNER JOIN deployments d ON ir.deployment_id = d.id -` - -type GetIngressRoutesRow struct { - RunnerKey model.RunnerKey - DeploymentKey model.DeploymentKey - Endpoint string - Path string - Module string - Verb string - Method string -} - -// Get the runner endpoints corresponding to the given ingress route. -func (q *Queries) GetIngressRoutes(ctx context.Context) ([]GetIngressRoutesRow, error) { - rows, err := q.db.QueryContext(ctx, getIngressRoutes) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetIngressRoutesRow - for rows.Next() { - var i GetIngressRoutesRow - if err := rows.Scan( - &i.RunnerKey, - &i.DeploymentKey, - &i.Endpoint, - &i.Path, - &i.Module, - &i.Verb, - &i.Method, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - const getModulesByID = `-- name: GetModulesByID :many SELECT id, language, name FROM modules diff --git a/backend/controller/dal/model/model.go b/backend/controller/dal/model/model.go index b02b8ac09c..b3fa0b693f 100644 --- a/backend/controller/dal/model/model.go +++ b/backend/controller/dal/model/model.go @@ -93,28 +93,9 @@ type Controller struct { } type Status struct { - Controllers []Controller - Runners []Runner - Deployments []Deployment - IngressRoutes []IngressRouteEntry -} - -type IngressRoute struct { - Runner model.RunnerKey - Deployment model.DeploymentKey - Endpoint string - Path string - Module string - Verb string - Method string -} - -type IngressRouteEntry struct { - Deployment model.DeploymentKey - Module string - Verb string - Method string - Path string + Controllers []Controller + Runners []Runner + Deployments []Deployment } type DeploymentArtefact struct { diff --git a/backend/controller/sql/schema/20241125012728_remove_ingress.sql b/backend/controller/sql/schema/20241125012728_remove_ingress.sql new file mode 100644 index 0000000000..ba58833896 --- /dev/null +++ b/backend/controller/sql/schema/20241125012728_remove_ingress.sql @@ -0,0 +1,5 @@ +-- migrate:up +DROP TABLE IF EXISTS ingress_routes; + +-- migrate:down + diff --git a/backend/controller/timeline/internal/timeline_test.go b/backend/controller/timeline/internal/timeline_test.go index 0f706b59c7..b7eee0d379 100644 --- a/backend/controller/timeline/internal/timeline_test.go +++ b/backend/controller/timeline/internal/timeline_test.go @@ -59,7 +59,7 @@ func TestTimeline(t *testing.T) { Digest: testSha, Executable: true, Path: "dir/filename", - }}, nil) + }}) assert.NoError(t, err) time.Sleep(200 * time.Millisecond) }) @@ -337,7 +337,7 @@ func TestDeleteOldEvents(t *testing.T) { Digest: testSha, Executable: true, Path: "dir/filename", - }}, nil) + }}) assert.NoError(t, err) }) diff --git a/backend/controller/ingress/handler.go b/backend/ingress/handler.go similarity index 75% rename from backend/controller/ingress/handler.go rename to backend/ingress/handler.go index fe881e108a..ad1069a45b 100644 --- a/backend/controller/ingress/handler.go +++ b/backend/ingress/handler.go @@ -11,7 +11,6 @@ import ( "connectrpc.com/connect" "github.com/alecthomas/types/optional" - dalmodel "github.com/TBD54566975/ftl/backend/controller/dal/model" "github.com/TBD54566975/ftl/backend/controller/observability" "github.com/TBD54566975/ftl/backend/controller/timeline" "github.com/TBD54566975/ftl/backend/libdal" @@ -22,21 +21,12 @@ import ( "github.com/TBD54566975/ftl/internal/schema" ) -// Handle HTTP ingress routes. -func Handle( - startTime time.Time, - sch *schema.Schema, - requestKey model.RequestKey, - routes []dalmodel.IngressRoute, - w http.ResponseWriter, - r *http.Request, - timelineService *timeline.Service, - call func(context.Context, *connect.Request[ftlv1.CallRequest], optional.Option[model.RequestKey], optional.Option[model.RequestKey], string) (*connect.Response[ftlv1.CallResponse], error), -) { +// handleHTTP HTTP ingress routes. +func handleHTTP(startTime time.Time, sch *schema.Schema, requestKey model.RequestKey, routesForMethod []ingressRoute, w http.ResponseWriter, r *http.Request, verbClient CallClient) { logger := log.FromContext(r.Context()).Scope(fmt.Sprintf("ingress:%s:%s", r.Method, r.URL.Path)) logger.Debugf("Start ingress request") - route, err := GetIngressRoute(routes, r.Method, r.URL.Path) + route, err := getIngressRoute(routesForMethod, r.URL.Path) if err != nil { if errors.Is(err, libdal.ErrNotFound) { http.NotFound(w, r) @@ -48,28 +38,27 @@ func Handle( observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.None[*schemapb.Ref](), startTime, optional.Some("failed to resolve route")) return } - logger = logger.Module(route.Module) + logger = logger.Module(route.module) - verbRef := &schemapb.Ref{Module: route.Module, Name: route.Verb} + verbRef := &schemapb.Ref{Module: route.module, Name: route.verb} ingressEvent := timeline.Ingress{ - DeploymentKey: route.Deployment, RequestKey: requestKey, StartTime: startTime, - Verb: &schema.Ref{Name: route.Verb, Module: route.Module}, + Verb: &schema.Ref{Name: route.verb, Module: route.module}, RequestMethod: r.Method, RequestPath: r.URL.Path, RequestHeaders: r.Header.Clone(), ResponseHeaders: make(http.Header), } - body, err := BuildRequestBody(route, r, sch) + body, err := buildRequestBody(route, r, sch) if err != nil { // Only log at debug, as this is a client side error logger.Debugf("bad request: %s", err.Error()) http.Error(w, err.Error(), http.StatusBadRequest) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("bad request")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusBadRequest, err.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusBadRequest, err.Error()) return } ingressEvent.RequestBody = body @@ -80,30 +69,30 @@ func Handle( Body: body, }) - resp, err := call(r.Context(), creq, optional.Some(requestKey), optional.None[model.RequestKey](), r.RemoteAddr) + resp, err := verbClient.Call(r.Context(), creq) if err != nil { logger.Errorf(err, "failed to call verb") if connectErr := new(connect.Error); errors.As(err, &connectErr) { httpCode := connectCodeToHTTP(connectErr.Code()) http.Error(w, http.StatusText(httpCode), httpCode) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("failed to call verb: connect error")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, connectErr.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, connectErr.Error()) } else { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("failed to call verb: internal server error")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, err.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, err.Error()) } return } switch msg := resp.Msg.Response.(type) { case *ftlv1.CallResponse_Body: verb := &schema.Verb{} - err = sch.ResolveToType(&schema.Ref{Name: route.Verb, Module: route.Module}, verb) + err = sch.ResolveToType(&schema.Ref{Name: route.verb, Module: route.module}, verb) if err != nil { - logger.Errorf(err, "could not resolve schema type for verb %s", route.Verb) + logger.Errorf(err, "could not resolve schema type for verb %s", route.verb) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("could not resolve schema type for verb")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, err.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, err.Error()) return } var responseBody []byte @@ -114,7 +103,7 @@ func Handle( logger.Errorf(err, "could not unmarhal response for verb %s", verb) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("could not unmarhal response for verb")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, err.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, err.Error()) return } rawBody = response.Body @@ -124,7 +113,7 @@ func Handle( logger.Errorf(err, "could not create response for verb %s", verb) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("could not create response for verb")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, err.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, err.Error()) return } @@ -150,34 +139,32 @@ func Handle( responseBody = msg.Body rawBody = responseBody } + ingressEvent.ResponseBody = rawBody _, err = w.Write(responseBody) if err == nil { observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.None[string]()) - ingressEvent.ResponseBody = rawBody - timelineService.EnqueueEvent(r.Context(), &ingressEvent) } else { logger.Errorf(err, "could not write response body") observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("could not write response body")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, err.Error()) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, err.Error()) } case *ftlv1.CallResponse_Error_: http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.Some(verbRef), startTime, optional.Some("call response: internal server error")) - recordIngressErrorEvent(r.Context(), timelineService, &ingressEvent, http.StatusInternalServerError, msg.Error.Message) + recordIngressErrorEvent(r.Context(), &ingressEvent, http.StatusInternalServerError, msg.Error.Message) } } func recordIngressErrorEvent( ctx context.Context, - timelineService *timeline.Service, ingressEvent *timeline.Ingress, statusCode int, errorMsg string, ) { ingressEvent.ResponseStatus = statusCode ingressEvent.Error = optional.Some(errorMsg) - timelineService.EnqueueEvent(ctx, ingressEvent) + // TODO: record event in timeline, one it has been split out from the controller } // Copied from the Apache-licensed connect-go source. diff --git a/backend/controller/ingress/handler_test.go b/backend/ingress/handler_test.go similarity index 63% rename from backend/controller/ingress/handler_test.go rename to backend/ingress/handler_test.go index 6dda3605df..a9f9a90fb0 100644 --- a/backend/controller/ingress/handler_test.go +++ b/backend/ingress/handler_test.go @@ -1,4 +1,4 @@ -package ingress_test +package ingress import ( "bytes" @@ -13,11 +13,6 @@ import ( "github.com/alecthomas/assert/v2" "github.com/alecthomas/types/optional" - dalmodel "github.com/TBD54566975/ftl/backend/controller/dal/model" - "github.com/TBD54566975/ftl/backend/controller/encryption" - "github.com/TBD54566975/ftl/backend/controller/ingress" - "github.com/TBD54566975/ftl/backend/controller/sql/sqltest" - "github.com/TBD54566975/ftl/backend/controller/timeline" ftlv1 "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1" "github.com/TBD54566975/ftl/go-runtime/encoding" "github.com/TBD54566975/ftl/internal/log" @@ -63,27 +58,23 @@ func TestIngress(t *testing.T) { `) assert.NoError(t, err) - routes := []dalmodel.IngressRoute{ - {Path: "/getAlias", Module: "test", Verb: "getAlias"}, - {Path: "/getPath/{username}", Module: "test", Verb: "getPath"}, - {Path: "/postMissingTypes", Module: "test", Verb: "postMissingTypes"}, - {Path: "/postJsonPayload", Module: "test", Verb: "postJsonPayload"}, + routes := []ingressRoute{ + {path: "/getAlias", module: "test", verb: "getAlias"}, + {path: "/getPath/{username}", module: "test", verb: "getPath"}, + {path: "/postMissingTypes", module: "test", verb: "postMissingTypes"}, + {path: "/postJsonPayload", module: "test", verb: "postJsonPayload"}, } ctx := log.ContextWithNewDefaultLogger(context.Background()) - conn := sqltest.OpenForTesting(ctx, t) - encryption, err := encryption.New(ctx, conn, encryption.NewBuilder()) assert.NoError(t, err) - timelineSrv := timeline.New(ctx, conn, encryption) - for _, test := range []struct { name string method string path string query url.Values payload []byte - response optional.Option[ingress.HTTPResponse] + response optional.Option[HTTPResponse] statusCode int }{ {name: "InvalidRoute", @@ -94,25 +85,23 @@ func TestIngress(t *testing.T) { method: "GET", path: "/getAlias", query: url.Values{"alias": {"value"}}, - response: optional.Some(ingress.HTTPResponse{Body: []byte(`{}`)}), + response: optional.Some(HTTPResponse{Body: []byte(`{}`)}), statusCode: http.StatusOK}, } { t.Run(test.name, func(t *testing.T) { rec := httptest.NewRecorder() rec.Body = &bytes.Buffer{} - var response ingress.HTTPResponse + var response HTTPResponse var ok bool if response, ok = test.response.Get(); ok { - response = ingress.HTTPResponse{Body: []byte(`{}`)} + response = HTTPResponse{Body: []byte(`{}`)} } req := httptest.NewRequest(test.method, test.path, bytes.NewBuffer(test.payload)).WithContext(ctx) req.URL.RawQuery = test.query.Encode() reqKey := model.NewRequestKey(model.OriginIngress, "test") - ingress.Handle(time.Now(), sch, reqKey, routes, rec, req, timelineSrv, func(ctx context.Context, r *connect.Request[ftlv1.CallRequest], requestKey optional.Option[model.RequestKey], parentRequestKey optional.Option[model.RequestKey], requestSource string) (*connect.Response[ftlv1.CallResponse], error) { - body, err := encoding.Marshal(response) - assert.NoError(t, err) - return connect.NewResponse(&ftlv1.CallResponse{Response: &ftlv1.CallResponse_Body{Body: body}}), nil - }) + assert.NoError(t, err) + fv := &fakeVerbClient{response: response, t: t} + handleHTTP(time.Now(), sch, reqKey, routes, rec, req, fv) result := rec.Result() defer result.Body.Close() assert.Equal(t, test.statusCode, rec.Code, "%s: %s", result.Status, rec.Body.Bytes()) @@ -123,3 +112,14 @@ func TestIngress(t *testing.T) { }) } } + +type fakeVerbClient struct { + response HTTPResponse + t *testing.T +} + +func (r *fakeVerbClient) Call(ctx context.Context, req *connect.Request[ftlv1.CallRequest]) (*connect.Response[ftlv1.CallResponse], error) { + body, err := encoding.Marshal(r.response) + assert.NoError(r.t, err) + return connect.NewResponse(&ftlv1.CallResponse{Response: &ftlv1.CallResponse_Body{Body: body}}), nil +} diff --git a/backend/controller/ingress/ingress.go b/backend/ingress/ingress.go similarity index 82% rename from backend/controller/ingress/ingress.go rename to backend/ingress/ingress.go index 5a48025956..0d05271c2b 100644 --- a/backend/controller/ingress/ingress.go +++ b/backend/ingress/ingress.go @@ -5,15 +5,14 @@ import ( "math/rand" "strings" - "github.com/TBD54566975/ftl/backend/controller/dal/model" "github.com/TBD54566975/ftl/backend/libdal" "github.com/TBD54566975/ftl/internal/schema" "github.com/TBD54566975/ftl/internal/slices" ) -func GetIngressRoute(routes []model.IngressRoute, method string, path string) (*model.IngressRoute, error) { - var matchedRoutes = slices.Filter(routes, func(route model.IngressRoute) bool { - return matchSegments(route.Path, path, func(segment, value string) {}) +func getIngressRoute(routes []ingressRoute, path string) (*ingressRoute, error) { + var matchedRoutes = slices.Filter(routes, func(route ingressRoute) bool { + return matchSegments(route.path, path, func(segment, value string) {}) }) if len(matchedRoutes) == 0 { diff --git a/backend/controller/ingress/ingress_integration_test.go b/backend/ingress/ingress_integration_test.go similarity index 98% rename from backend/controller/ingress/ingress_integration_test.go rename to backend/ingress/ingress_integration_test.go index 5bd9f994c2..23864e381a 100644 --- a/backend/controller/ingress/ingress_integration_test.go +++ b/backend/ingress/ingress_integration_test.go @@ -189,8 +189,8 @@ func expectContentType(t testing.TB, resp *in.HTTPResponse, expected string) { // Run with CORS enabled via FTL_CONTROLLER_ALLOW_ORIGIN and FTL_CONTROLLER_ALLOW_HEADERS // This test is similar to TestHttpIngress above with the addition of CORS enabled in the controller. func TestHttpIngressWithCors(t *testing.T) { - os.Setenv("FTL_CONTROLLER_ALLOW_ORIGIN", "http://localhost:8892") - os.Setenv("FTL_CONTROLLER_ALLOW_HEADERS", "x-forwarded-capabilities") + os.Setenv("FTL_INGRESS_ALLOW_ORIGIN", "http://localhost:8892") + os.Setenv("FTL_INGRESS_ALLOW_HEADERS", "x-forwarded-capabilities") in.Run(t, in.CopyModule("httpingress"), in.Deploy("httpingress"), diff --git a/backend/controller/ingress/ingress_test.go b/backend/ingress/ingress_test.go similarity index 100% rename from backend/controller/ingress/ingress_test.go rename to backend/ingress/ingress_test.go diff --git a/backend/controller/ingress/request.go b/backend/ingress/request.go similarity index 96% rename from backend/controller/ingress/request.go rename to backend/ingress/request.go index 59f9b013dd..bd0362e44e 100644 --- a/backend/controller/ingress/request.go +++ b/backend/ingress/request.go @@ -11,15 +11,14 @@ import ( "github.com/alecthomas/types/optional" - "github.com/TBD54566975/ftl/backend/controller/dal/model" "github.com/TBD54566975/ftl/internal/schema" "github.com/TBD54566975/ftl/internal/slices" ) -// BuildRequestBody extracts the HttpRequest body from an HTTP request. -func BuildRequestBody(route *model.IngressRoute, r *http.Request, sch *schema.Schema) ([]byte, error) { +// buildRequestBody extracts the HttpRequest body from an HTTP request. +func buildRequestBody(route *ingressRoute, r *http.Request, sch *schema.Schema) ([]byte, error) { verb := &schema.Verb{} - err := sch.ResolveToType(&schema.Ref{Name: route.Verb, Module: route.Module}, verb) + err := sch.ResolveToType(&schema.Ref{Name: route.verb, Module: route.module}, verb) if err != nil { return nil, err } @@ -35,7 +34,7 @@ func BuildRequestBody(route *model.IngressRoute, r *http.Request, sch *schema.Sc if metadata, ok := verb.GetMetadataIngress().Get(); ok && metadata.Type == "http" { pathParametersMap := map[string]string{} - matchSegments(route.Path, r.URL.Path, func(segment, value string) { + matchSegments(route.path, r.URL.Path, func(segment, value string) { pathParametersMap[segment] = value }) pathParameters, err := manglePathParameters(pathParametersMap, request, sch) diff --git a/backend/controller/ingress/request_test.go b/backend/ingress/request_test.go similarity index 97% rename from backend/controller/ingress/request_test.go rename to backend/ingress/request_test.go index 764fa4df1c..98ff060a0b 100644 --- a/backend/controller/ingress/request_test.go +++ b/backend/ingress/request_test.go @@ -10,7 +10,6 @@ import ( "github.com/alecthomas/assert/v2" - "github.com/TBD54566975/ftl/backend/controller/dal/model" "github.com/TBD54566975/ftl/go-runtime/encoding" "github.com/TBD54566975/ftl/go-runtime/ftl" "github.com/TBD54566975/ftl/internal/schema" @@ -240,10 +239,10 @@ func TestBuildRequestBody(t *testing.T) { } r, err := http.NewRequest(test.method, requestURL, bytes.NewReader(body)) //nolint:noctx assert.NoError(t, err) - requestBody, err := BuildRequestBody(&model.IngressRoute{ - Path: test.routePath, - Module: "test", - Verb: test.verb, + requestBody, err := buildRequestBody(&ingressRoute{ + path: test.routePath, + module: "test", + verb: test.verb, }, r, sch) if test.err != "" { assert.EqualError(t, err, test.err) diff --git a/backend/controller/ingress/response.go b/backend/ingress/response.go similarity index 100% rename from backend/controller/ingress/response.go rename to backend/ingress/response.go diff --git a/backend/ingress/service.go b/backend/ingress/service.go new file mode 100644 index 0000000000..61bcb81c38 --- /dev/null +++ b/backend/ingress/service.go @@ -0,0 +1,193 @@ +package ingress + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" + "time" + + "connectrpc.com/connect" + "github.com/alecthomas/atomic" + "github.com/alecthomas/types/optional" + "github.com/jpillora/backoff" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" + "golang.org/x/sync/errgroup" + + "github.com/TBD54566975/ftl/backend/controller/observability" + ftlv1 "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1" + schemapb "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/schema" + "github.com/TBD54566975/ftl/internal/cors" + ftlhttp "github.com/TBD54566975/ftl/internal/http" + "github.com/TBD54566975/ftl/internal/log" + "github.com/TBD54566975/ftl/internal/model" + "github.com/TBD54566975/ftl/internal/rpc" + "github.com/TBD54566975/ftl/internal/schema" + "github.com/TBD54566975/ftl/internal/slices" +) + +type PullSchemaClient interface { + PullSchema(ctx context.Context, req *connect.Request[ftlv1.PullSchemaRequest]) (*connect.ServerStreamForClient[ftlv1.PullSchemaResponse], error) +} + +type CallClient interface { + Call(ctx context.Context, req *connect.Request[ftlv1.CallRequest]) (*connect.Response[ftlv1.CallResponse], error) +} + +type Config struct { + Bind *url.URL `help:"Socket to bind to for ingress." default:"http://127.0.0.1:8891" env:"FTL_INGRESS_BIND"` + AllowOrigins []*url.URL `help:"Allow CORS requests to ingress endpoints from these origins." env:"FTL_INGRESS_ALLOW_ORIGIN"` + AllowHeaders []string `help:"Allow these headers in CORS requests. (Requires AllowOrigins)" env:"FTL_INGRESS_ALLOW_HEADERS"` +} + +func (c *Config) Validate() error { + if len(c.AllowHeaders) > 0 && len(c.AllowOrigins) == 0 { + return fmt.Errorf("AllowOrigins must be set when AllowHeaders is used") + } + return nil +} + +type service struct { + // Complete schema synchronised from the database. + schemaState atomic.Value[schemaState] + callClient CallClient +} + +// Start the HTTP ingress service. Blocks until the context is cancelled. +func Start(ctx context.Context, config Config, pullSchemaClient PullSchemaClient, verbClient CallClient) error { + wg, ctx := errgroup.WithContext(ctx) + logger := log.FromContext(ctx).Scope("http-ingress") + svc := &service{ + callClient: verbClient, + } + + ingressHandler := otelhttp.NewHandler(http.Handler(svc), "ftl.ingress") + if len(config.AllowOrigins) > 0 { + ingressHandler = cors.Middleware( + slices.Map(config.AllowOrigins, func(u *url.URL) string { return u.String() }), + config.AllowHeaders, + ingressHandler, + ) + } + + // Start the HTTP server + wg.Go(func() error { + logger.Infof("HTTP ingress server listening on: %s", config.Bind) + return ftlhttp.Serve(ctx, config.Bind, ingressHandler) + }) + // Start watching for schema changes. + wg.Go(func() error { + rpc.RetryStreamingServerStream(ctx, "pull-schema", backoff.Backoff{}, &ftlv1.PullSchemaRequest{}, pullSchemaClient.PullSchema, func(ctx context.Context, resp *ftlv1.PullSchemaResponse) error { + existing := svc.schemaState.Load().protoSchema + newState := schemaState{ + protoSchema: &schemapb.Schema{}, + httpRoutes: make(map[string][]ingressRoute), + } + if resp.ChangeType != ftlv1.DeploymentChangeType_DEPLOYMENT_REMOVED { + found := false + if existing != nil { + for i := range existing.Modules { + if existing.Modules[i].Name == resp.ModuleName { + newState.protoSchema.Modules = append(newState.protoSchema.Modules, resp.Schema) + found = true + } else { + newState.protoSchema.Modules = append(newState.protoSchema.Modules, existing.Modules[i]) + } + } + } + if !found { + newState.protoSchema.Modules = append(newState.protoSchema.Modules, resp.Schema) + } + } else if existing != nil { + for i := range existing.Modules { + if existing.Modules[i].Name != resp.ModuleName { + newState.protoSchema.Modules = append(newState.protoSchema.Modules, existing.Modules[i]) + } + } + } + + newState.httpRoutes = extractIngressRoutingEntries(newState.protoSchema) + sch, err := schema.FromProto(newState.protoSchema) + if err != nil { + // Not much we can do here, we don't update the state with the broken schema. + logger.Errorf(err, "failed to parse schema") + return nil + } + newState.schema = sch + svc.schemaState.Store(newState) + return nil + }, rpc.AlwaysRetry()) + return nil + }) + err := wg.Wait() + if err != nil { + return fmt.Errorf("ingress service stopped: %w", err) + } + return nil +} + +func (s *service) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/healthz" { + w.WriteHeader(http.StatusOK) + return + } + start := time.Now() + method := strings.ToLower(r.Method) + requestKey := model.NewRequestKey(model.OriginIngress, fmt.Sprintf("%s %s", method, r.URL.Path)) + + routes := s.schemaState.Load().httpRoutes[r.Method] + if len(routes) == 0 { + http.NotFound(w, r) + observability.Ingress.Request(r.Context(), r.Method, r.URL.Path, optional.None[*schemapb.Ref](), start, optional.Some("route not found in dal")) + return + } + handleHTTP(start, s.schemaState.Load().schema, requestKey, routes, w, r, s.callClient) +} + +type schemaState struct { + protoSchema *schemapb.Schema + schema *schema.Schema + httpRoutes map[string][]ingressRoute +} + +type ingressRoute struct { + path string + module string + verb string + method string +} + +func extractIngressRoutingEntries(schema *schemapb.Schema) map[string][]ingressRoute { + var ingressRoutes = make(map[string][]ingressRoute) + for _, module := range schema.Modules { + for _, decl := range module.Decls { + if verb, ok := decl.Value.(*schemapb.Decl_Verb); ok { + for _, metadata := range verb.Verb.Metadata { + if ingress, ok := metadata.Value.(*schemapb.Metadata_Ingress); ok { + ingressRoutes[ingress.Ingress.Method] = append(ingressRoutes[ingress.Ingress.Method], ingressRoute{ + verb: verb.Verb.Name, + method: ingress.Ingress.Method, + path: ingressPathString(ingress.Ingress.Path), + module: module.Name, + }) + } + } + } + } + } + return ingressRoutes +} + +func ingressPathString(path []*schemapb.IngressPathComponent) string { + pathString := make([]string, len(path)) + for i, p := range path { + switch p.Value.(type) { + case *schemapb.IngressPathComponent_IngressPathLiteral: + pathString[i] = p.GetIngressPathLiteral().Text + case *schemapb.IngressPathComponent_IngressPathParameter: + pathString[i] = fmt.Sprintf("{%s}", p.GetIngressPathParameter().Name) + } + } + return "/" + strings.Join(pathString, "/") +} diff --git a/backend/controller/ingress/testdata/go/httpingress/ftl.toml b/backend/ingress/testdata/go/httpingress/ftl.toml similarity index 100% rename from backend/controller/ingress/testdata/go/httpingress/ftl.toml rename to backend/ingress/testdata/go/httpingress/ftl.toml diff --git a/backend/controller/ingress/testdata/go/httpingress/go.mod b/backend/ingress/testdata/go/httpingress/go.mod similarity index 97% rename from backend/controller/ingress/testdata/go/httpingress/go.mod rename to backend/ingress/testdata/go/httpingress/go.mod index 3a46d24866..d1d5b5592f 100644 --- a/backend/controller/ingress/testdata/go/httpingress/go.mod +++ b/backend/ingress/testdata/go/httpingress/go.mod @@ -47,4 +47,4 @@ require ( google.golang.org/protobuf v1.35.2 // indirect ) -replace github.com/TBD54566975/ftl => ./../../../../../.. +replace github.com/TBD54566975/ftl => ./../../../../.. diff --git a/backend/controller/ingress/testdata/go/httpingress/go.sum b/backend/ingress/testdata/go/httpingress/go.sum similarity index 100% rename from backend/controller/ingress/testdata/go/httpingress/go.sum rename to backend/ingress/testdata/go/httpingress/go.sum diff --git a/backend/controller/ingress/testdata/go/httpingress/httpingress.go b/backend/ingress/testdata/go/httpingress/httpingress.go similarity index 100% rename from backend/controller/ingress/testdata/go/httpingress/httpingress.go rename to backend/ingress/testdata/go/httpingress/httpingress.go diff --git a/backend/controller/ingress/testdata/go/httpingress/types.ftl.go b/backend/ingress/testdata/go/httpingress/types.ftl.go similarity index 100% rename from backend/controller/ingress/testdata/go/httpingress/types.ftl.go rename to backend/ingress/testdata/go/httpingress/types.ftl.go diff --git a/backend/controller/ingress/testdata/java/httpingress/ftl.toml b/backend/ingress/testdata/java/httpingress/ftl.toml similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/ftl.toml rename to backend/ingress/testdata/java/httpingress/ftl.toml diff --git a/backend/controller/ingress/testdata/java/httpingress/pom.xml b/backend/ingress/testdata/java/httpingress/pom.xml similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/pom.xml rename to backend/ingress/testdata/java/httpingress/pom.xml diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/ArrayType.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/ArrayType.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/ArrayType.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/ArrayType.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteRequest.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteRequest.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteRequest.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteRequest.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteResponse.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteResponse.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteResponse.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/DeleteResponse.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetRequest.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetRequest.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetRequest.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetRequest.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetResponse.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetResponse.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetResponse.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/GetResponse.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/Nested.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/Nested.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/Nested.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/Nested.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostRequest.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostRequest.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostRequest.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostRequest.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostResponse.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostResponse.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostResponse.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PostResponse.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutRequest.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutRequest.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutRequest.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutRequest.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutResponse.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutResponse.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutResponse.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/PutResponse.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/QueryParamRequest.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/QueryParamRequest.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/QueryParamRequest.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/QueryParamRequest.java diff --git a/backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/TestHTTP.java b/backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/TestHTTP.java similarity index 100% rename from backend/controller/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/TestHTTP.java rename to backend/ingress/testdata/java/httpingress/src/main/java/xyz/block/ftl/java/test/http/TestHTTP.java diff --git a/backend/protos/xyz/block/ftl/v1/controller.pb.go b/backend/protos/xyz/block/ftl/v1/controller.pb.go index caa6d65517..6fedeae0a1 100644 --- a/backend/protos/xyz/block/ftl/v1/controller.pb.go +++ b/backend/protos/xyz/block/ftl/v1/controller.pb.go @@ -1251,11 +1251,10 @@ type StatusResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Controllers []*StatusResponse_Controller `protobuf:"bytes,1,rep,name=controllers,proto3" json:"controllers,omitempty"` - Runners []*StatusResponse_Runner `protobuf:"bytes,2,rep,name=runners,proto3" json:"runners,omitempty"` - Deployments []*StatusResponse_Deployment `protobuf:"bytes,3,rep,name=deployments,proto3" json:"deployments,omitempty"` - IngressRoutes []*StatusResponse_IngressRoute `protobuf:"bytes,4,rep,name=ingress_routes,json=ingressRoutes,proto3" json:"ingress_routes,omitempty"` - Routes []*StatusResponse_Route `protobuf:"bytes,5,rep,name=routes,proto3" json:"routes,omitempty"` + Controllers []*StatusResponse_Controller `protobuf:"bytes,1,rep,name=controllers,proto3" json:"controllers,omitempty"` + Runners []*StatusResponse_Runner `protobuf:"bytes,2,rep,name=runners,proto3" json:"runners,omitempty"` + Deployments []*StatusResponse_Deployment `protobuf:"bytes,3,rep,name=deployments,proto3" json:"deployments,omitempty"` + Routes []*StatusResponse_Route `protobuf:"bytes,5,rep,name=routes,proto3" json:"routes,omitempty"` } func (x *StatusResponse) Reset() { @@ -1309,13 +1308,6 @@ func (x *StatusResponse) GetDeployments() []*StatusResponse_Deployment { return nil } -func (x *StatusResponse) GetIngressRoutes() []*StatusResponse_IngressRoute { - if x != nil { - return x.IngressRoutes - } - return nil -} - func (x *StatusResponse) GetRoutes() []*StatusResponse_Route { if x != nil { return x.Routes @@ -1708,75 +1700,6 @@ func (x *StatusResponse_Deployment) GetSchema() *schema.Module { return nil } -type StatusResponse_IngressRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DeploymentKey string `protobuf:"bytes,1,opt,name=deployment_key,json=deploymentKey,proto3" json:"deployment_key,omitempty"` - Verb *schema.Ref `protobuf:"bytes,2,opt,name=verb,proto3" json:"verb,omitempty"` - Method string `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"` - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` -} - -func (x *StatusResponse_IngressRoute) Reset() { - *x = StatusResponse_IngressRoute{} - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StatusResponse_IngressRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StatusResponse_IngressRoute) ProtoMessage() {} - -func (x *StatusResponse_IngressRoute) ProtoReflect() protoreflect.Message { - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[33] - 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 StatusResponse_IngressRoute.ProtoReflect.Descriptor instead. -func (*StatusResponse_IngressRoute) Descriptor() ([]byte, []int) { - return file_xyz_block_ftl_v1_controller_proto_rawDescGZIP(), []int{24, 3} -} - -func (x *StatusResponse_IngressRoute) GetDeploymentKey() string { - if x != nil { - return x.DeploymentKey - } - return "" -} - -func (x *StatusResponse_IngressRoute) GetVerb() *schema.Ref { - if x != nil { - return x.Verb - } - return nil -} - -func (x *StatusResponse_IngressRoute) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -func (x *StatusResponse_IngressRoute) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - type StatusResponse_Route struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1789,7 +1712,7 @@ type StatusResponse_Route struct { func (x *StatusResponse_Route) Reset() { *x = StatusResponse_Route{} - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[34] + mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1801,7 +1724,7 @@ func (x *StatusResponse_Route) String() string { func (*StatusResponse_Route) ProtoMessage() {} func (x *StatusResponse_Route) ProtoReflect() protoreflect.Message { - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[34] + mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1814,7 +1737,7 @@ func (x *StatusResponse_Route) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse_Route.ProtoReflect.Descriptor instead. func (*StatusResponse_Route) Descriptor() ([]byte, []int) { - return file_xyz_block_ftl_v1_controller_proto_rawDescGZIP(), []int{24, 4} + return file_xyz_block_ftl_v1_controller_proto_rawDescGZIP(), []int{24, 3} } func (x *StatusResponse_Route) GetModule() string { @@ -1850,7 +1773,7 @@ type ProcessListResponse_ProcessRunner struct { func (x *ProcessListResponse_ProcessRunner) Reset() { *x = ProcessListResponse_ProcessRunner{} - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[35] + mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1862,7 +1785,7 @@ func (x *ProcessListResponse_ProcessRunner) String() string { func (*ProcessListResponse_ProcessRunner) ProtoMessage() {} func (x *ProcessListResponse_ProcessRunner) ProtoReflect() protoreflect.Message { - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[35] + mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1912,7 +1835,7 @@ type ProcessListResponse_Process struct { func (x *ProcessListResponse_Process) Reset() { *x = ProcessListResponse_Process{} - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[36] + mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1924,7 +1847,7 @@ func (x *ProcessListResponse_Process) String() string { func (*ProcessListResponse_Process) ProtoMessage() {} func (x *ProcessListResponse_Process) ProtoReflect() protoreflect.Message { - mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[36] + mi := &file_xyz_block_ftl_v1_controller_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2145,7 +2068,7 @@ var file_xyz_block_ftl_v1_controller_proto_rawDesc = []byte{ 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0xe8, 0x08, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x74, 0x22, 0xfc, 0x06, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, @@ -2160,193 +2083,179 @@ var file_xyz_block_ftl_v1_controller_proto_rawDesc = []byte{ 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x0e, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, - 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x0d, 0x69, 0x6e, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x06, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x79, - 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x0a, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x1a, 0x9b, 0x01, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3e, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x9b, 0x01, 0x0a, 0x06, + 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0xf7, 0x01, 0x0a, 0x0a, 0x44, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, + 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, + 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x69, + 0x6e, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x1a, 0x0a, + 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x79, 0x7a, + 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x1a, 0x5b, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x22, 0x14, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xaf, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, + 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x6e, 0x0a, 0x0d, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0a, 0x64, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, - 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x1a, - 0xf7, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, - 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x12, 0x37, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x93, 0x01, 0x0a, 0x0c, 0x49, 0x6e, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, - 0x79, 0x12, 0x30, 0x0a, 0x04, 0x76, 0x65, 0x72, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x66, 0x52, 0x04, 0x76, - 0x65, 0x72, 0x62, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x1a, - 0x5b, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, - 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x14, 0x0a, 0x12, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0xaf, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x70, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0xda, 0x01, 0x0a, 0x07, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x72, + 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, + 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x72, + 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x78, 0x79, + 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, + 0x48, 0x00, 0x52, 0x06, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, + 0x07, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x5c, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x79, 0x7a, + 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x66, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0x9e, 0x0b, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x04, 0x50, 0x69, 0x6e, + 0x67, 0x12, 0x1d, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x5a, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x78, 0x79, 0x7a, + 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4b, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x78, 0x79, + 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x78, + 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x09, 0x70, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x6e, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0xda, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x6e, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, - 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, 0x75, - 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x5c, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x40, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x2e, 0x52, 0x65, 0x66, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, - 0x9e, 0x0b, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x2e, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x47, 0x65, 0x74, + 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x44, 0x69, 0x66, 0x66, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x78, - 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, - 0x01, 0x12, 0x5a, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x24, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x47, 0x65, - 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, - 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x65, - 0x66, 0x61, 0x63, 0x74, 0x44, 0x69, 0x66, 0x66, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x44, 0x69, 0x66, 0x66, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x65, 0x66, - 0x61, 0x63, 0x74, 0x44, 0x69, 0x66, 0x66, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x63, 0x0a, 0x0e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, - 0x63, 0x74, 0x12, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x72, 0x74, 0x65, - 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x79, - 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x2e, 0x78, 0x79, 0x7a, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x60, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x12, 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x44, 0x69, 0x66, 0x66, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x44, 0x69, 0x66, 0x66, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x72, + 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x12, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x28, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x2e, + 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x12, 0x2f, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x78, + 0x6e, 0x74, 0x41, 0x72, 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x65, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x6e, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x5d, 0x0a, 0x0c, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x12, 0x25, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x74, - 0x65, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, - 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x72, - 0x74, 0x65, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, - 0x01, 0x12, 0x65, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x75, 0x6e, - 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, - 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, + 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0d, 0x52, + 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x12, 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x5d, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x12, 0x25, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x12, 0x26, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6c, - 0x61, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x14, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, - 0x73, 0x12, 0x2d, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x28, 0x01, 0x12, 0x6c, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, + 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, + 0x14, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x2d, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x6c, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x78, 0x79, + 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x79, 0x7a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x66, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0x44, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x54, 0x42, 0x44, 0x35, 0x34, 0x35, 0x36, 0x36, 0x39, 0x37, 0x35, 0x2f, 0x66, 0x74, 0x6c, - 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, - 0x78, 0x79, 0x7a, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x66, 0x74, 0x6c, 0x2f, 0x76, 0x31, - 0x3b, 0x66, 0x74, 0x6c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x42, 0x44, 0x35, 0x34, 0x35, 0x36, 0x36, 0x39, 0x37, 0x35, + 0x2f, 0x66, 0x74, 0x6c, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x73, 0x2f, 0x78, 0x79, 0x7a, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2f, 0x66, 0x74, + 0x6c, 0x2f, 0x76, 0x31, 0x3b, 0x66, 0x74, 0x6c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -2361,7 +2270,7 @@ func file_xyz_block_ftl_v1_controller_proto_rawDescGZIP() []byte { return file_xyz_block_ftl_v1_controller_proto_rawDescData } -var file_xyz_block_ftl_v1_controller_proto_msgTypes = make([]protoimpl.MessageInfo, 37) +var file_xyz_block_ftl_v1_controller_proto_msgTypes = make([]protoimpl.MessageInfo, 36) var file_xyz_block_ftl_v1_controller_proto_goTypes = []any{ (*GetCertificationRequest)(nil), // 0: xyz.block.ftl.v1.GetCertificationRequest (*GetCertificationResponse)(nil), // 1: xyz.block.ftl.v1.GetCertificationResponse @@ -2396,79 +2305,76 @@ var file_xyz_block_ftl_v1_controller_proto_goTypes = []any{ (*StatusResponse_Controller)(nil), // 30: xyz.block.ftl.v1.StatusResponse.Controller (*StatusResponse_Runner)(nil), // 31: xyz.block.ftl.v1.StatusResponse.Runner (*StatusResponse_Deployment)(nil), // 32: xyz.block.ftl.v1.StatusResponse.Deployment - (*StatusResponse_IngressRoute)(nil), // 33: xyz.block.ftl.v1.StatusResponse.IngressRoute - (*StatusResponse_Route)(nil), // 34: xyz.block.ftl.v1.StatusResponse.Route - (*ProcessListResponse_ProcessRunner)(nil), // 35: xyz.block.ftl.v1.ProcessListResponse.ProcessRunner - (*ProcessListResponse_Process)(nil), // 36: xyz.block.ftl.v1.ProcessListResponse.Process - (*schema.Module)(nil), // 37: xyz.block.ftl.v1.schema.Module - (*structpb.Struct)(nil), // 38: google.protobuf.Struct - (*timestamppb.Timestamp)(nil), // 39: google.protobuf.Timestamp - (*schema.Ref)(nil), // 40: xyz.block.ftl.v1.schema.Ref - (*PingRequest)(nil), // 41: xyz.block.ftl.v1.PingRequest - (*PingResponse)(nil), // 42: xyz.block.ftl.v1.PingResponse + (*StatusResponse_Route)(nil), // 33: xyz.block.ftl.v1.StatusResponse.Route + (*ProcessListResponse_ProcessRunner)(nil), // 34: xyz.block.ftl.v1.ProcessListResponse.ProcessRunner + (*ProcessListResponse_Process)(nil), // 35: xyz.block.ftl.v1.ProcessListResponse.Process + (*schema.Module)(nil), // 36: xyz.block.ftl.v1.schema.Module + (*structpb.Struct)(nil), // 37: google.protobuf.Struct + (*timestamppb.Timestamp)(nil), // 38: google.protobuf.Timestamp + (*schema.Ref)(nil), // 39: xyz.block.ftl.v1.schema.Ref + (*PingRequest)(nil), // 40: xyz.block.ftl.v1.PingRequest + (*PingResponse)(nil), // 41: xyz.block.ftl.v1.PingResponse } var file_xyz_block_ftl_v1_controller_proto_depIdxs = []int32{ 2, // 0: xyz.block.ftl.v1.GetCertificationRequest.request:type_name -> xyz.block.ftl.v1.CertificateContent 3, // 1: xyz.block.ftl.v1.GetCertificationResponse.certificate:type_name -> xyz.block.ftl.v1.Certificate 2, // 2: xyz.block.ftl.v1.Certificate.content:type_name -> xyz.block.ftl.v1.CertificateContent 8, // 3: xyz.block.ftl.v1.GetArtefactDiffsResponse.client_artefacts:type_name -> xyz.block.ftl.v1.DeploymentArtefact - 37, // 4: xyz.block.ftl.v1.CreateDeploymentRequest.schema:type_name -> xyz.block.ftl.v1.schema.Module + 36, // 4: xyz.block.ftl.v1.CreateDeploymentRequest.schema:type_name -> xyz.block.ftl.v1.schema.Module 8, // 5: xyz.block.ftl.v1.CreateDeploymentRequest.artefacts:type_name -> xyz.block.ftl.v1.DeploymentArtefact - 38, // 6: xyz.block.ftl.v1.CreateDeploymentRequest.labels:type_name -> google.protobuf.Struct + 37, // 6: xyz.block.ftl.v1.CreateDeploymentRequest.labels:type_name -> google.protobuf.Struct 8, // 7: xyz.block.ftl.v1.GetDeploymentArtefactsRequest.have_artefacts:type_name -> xyz.block.ftl.v1.DeploymentArtefact 8, // 8: xyz.block.ftl.v1.GetDeploymentArtefactsResponse.artefact:type_name -> xyz.block.ftl.v1.DeploymentArtefact - 37, // 9: xyz.block.ftl.v1.GetDeploymentResponse.schema:type_name -> xyz.block.ftl.v1.schema.Module + 36, // 9: xyz.block.ftl.v1.GetDeploymentResponse.schema:type_name -> xyz.block.ftl.v1.schema.Module 8, // 10: xyz.block.ftl.v1.GetDeploymentResponse.artefacts:type_name -> xyz.block.ftl.v1.DeploymentArtefact - 38, // 11: xyz.block.ftl.v1.RegisterRunnerRequest.labels:type_name -> google.protobuf.Struct - 39, // 12: xyz.block.ftl.v1.StreamDeploymentLogsRequest.time_stamp:type_name -> google.protobuf.Timestamp + 37, // 11: xyz.block.ftl.v1.RegisterRunnerRequest.labels:type_name -> google.protobuf.Struct + 38, // 12: xyz.block.ftl.v1.StreamDeploymentLogsRequest.time_stamp:type_name -> google.protobuf.Timestamp 29, // 13: xyz.block.ftl.v1.StreamDeploymentLogsRequest.attributes:type_name -> xyz.block.ftl.v1.StreamDeploymentLogsRequest.AttributesEntry 30, // 14: xyz.block.ftl.v1.StatusResponse.controllers:type_name -> xyz.block.ftl.v1.StatusResponse.Controller 31, // 15: xyz.block.ftl.v1.StatusResponse.runners:type_name -> xyz.block.ftl.v1.StatusResponse.Runner 32, // 16: xyz.block.ftl.v1.StatusResponse.deployments:type_name -> xyz.block.ftl.v1.StatusResponse.Deployment - 33, // 17: xyz.block.ftl.v1.StatusResponse.ingress_routes:type_name -> xyz.block.ftl.v1.StatusResponse.IngressRoute - 34, // 18: xyz.block.ftl.v1.StatusResponse.routes:type_name -> xyz.block.ftl.v1.StatusResponse.Route - 36, // 19: xyz.block.ftl.v1.ProcessListResponse.processes:type_name -> xyz.block.ftl.v1.ProcessListResponse.Process - 40, // 20: xyz.block.ftl.v1.ResetSubscriptionRequest.subscription:type_name -> xyz.block.ftl.v1.schema.Ref - 38, // 21: xyz.block.ftl.v1.StatusResponse.Runner.labels:type_name -> google.protobuf.Struct - 38, // 22: xyz.block.ftl.v1.StatusResponse.Deployment.labels:type_name -> google.protobuf.Struct - 37, // 23: xyz.block.ftl.v1.StatusResponse.Deployment.schema:type_name -> xyz.block.ftl.v1.schema.Module - 40, // 24: xyz.block.ftl.v1.StatusResponse.IngressRoute.verb:type_name -> xyz.block.ftl.v1.schema.Ref - 38, // 25: xyz.block.ftl.v1.ProcessListResponse.ProcessRunner.labels:type_name -> google.protobuf.Struct - 38, // 26: xyz.block.ftl.v1.ProcessListResponse.Process.labels:type_name -> google.protobuf.Struct - 35, // 27: xyz.block.ftl.v1.ProcessListResponse.Process.runner:type_name -> xyz.block.ftl.v1.ProcessListResponse.ProcessRunner - 41, // 28: xyz.block.ftl.v1.ControllerService.Ping:input_type -> xyz.block.ftl.v1.PingRequest - 25, // 29: xyz.block.ftl.v1.ControllerService.ProcessList:input_type -> xyz.block.ftl.v1.ProcessListRequest - 23, // 30: xyz.block.ftl.v1.ControllerService.Status:input_type -> xyz.block.ftl.v1.StatusRequest - 0, // 31: xyz.block.ftl.v1.ControllerService.GetCertification:input_type -> xyz.block.ftl.v1.GetCertificationRequest - 4, // 32: xyz.block.ftl.v1.ControllerService.GetArtefactDiffs:input_type -> xyz.block.ftl.v1.GetArtefactDiffsRequest - 6, // 33: xyz.block.ftl.v1.ControllerService.UploadArtefact:input_type -> xyz.block.ftl.v1.UploadArtefactRequest - 9, // 34: xyz.block.ftl.v1.ControllerService.CreateDeployment:input_type -> xyz.block.ftl.v1.CreateDeploymentRequest - 13, // 35: xyz.block.ftl.v1.ControllerService.GetDeployment:input_type -> xyz.block.ftl.v1.GetDeploymentRequest - 11, // 36: xyz.block.ftl.v1.ControllerService.GetDeploymentArtefacts:input_type -> xyz.block.ftl.v1.GetDeploymentArtefactsRequest - 15, // 37: xyz.block.ftl.v1.ControllerService.RegisterRunner:input_type -> xyz.block.ftl.v1.RegisterRunnerRequest - 17, // 38: xyz.block.ftl.v1.ControllerService.UpdateDeploy:input_type -> xyz.block.ftl.v1.UpdateDeployRequest - 19, // 39: xyz.block.ftl.v1.ControllerService.ReplaceDeploy:input_type -> xyz.block.ftl.v1.ReplaceDeployRequest - 21, // 40: xyz.block.ftl.v1.ControllerService.StreamDeploymentLogs:input_type -> xyz.block.ftl.v1.StreamDeploymentLogsRequest - 27, // 41: xyz.block.ftl.v1.ControllerService.ResetSubscription:input_type -> xyz.block.ftl.v1.ResetSubscriptionRequest - 42, // 42: xyz.block.ftl.v1.ControllerService.Ping:output_type -> xyz.block.ftl.v1.PingResponse - 26, // 43: xyz.block.ftl.v1.ControllerService.ProcessList:output_type -> xyz.block.ftl.v1.ProcessListResponse - 24, // 44: xyz.block.ftl.v1.ControllerService.Status:output_type -> xyz.block.ftl.v1.StatusResponse - 1, // 45: xyz.block.ftl.v1.ControllerService.GetCertification:output_type -> xyz.block.ftl.v1.GetCertificationResponse - 5, // 46: xyz.block.ftl.v1.ControllerService.GetArtefactDiffs:output_type -> xyz.block.ftl.v1.GetArtefactDiffsResponse - 7, // 47: xyz.block.ftl.v1.ControllerService.UploadArtefact:output_type -> xyz.block.ftl.v1.UploadArtefactResponse - 10, // 48: xyz.block.ftl.v1.ControllerService.CreateDeployment:output_type -> xyz.block.ftl.v1.CreateDeploymentResponse - 14, // 49: xyz.block.ftl.v1.ControllerService.GetDeployment:output_type -> xyz.block.ftl.v1.GetDeploymentResponse - 12, // 50: xyz.block.ftl.v1.ControllerService.GetDeploymentArtefacts:output_type -> xyz.block.ftl.v1.GetDeploymentArtefactsResponse - 16, // 51: xyz.block.ftl.v1.ControllerService.RegisterRunner:output_type -> xyz.block.ftl.v1.RegisterRunnerResponse - 18, // 52: xyz.block.ftl.v1.ControllerService.UpdateDeploy:output_type -> xyz.block.ftl.v1.UpdateDeployResponse - 20, // 53: xyz.block.ftl.v1.ControllerService.ReplaceDeploy:output_type -> xyz.block.ftl.v1.ReplaceDeployResponse - 22, // 54: xyz.block.ftl.v1.ControllerService.StreamDeploymentLogs:output_type -> xyz.block.ftl.v1.StreamDeploymentLogsResponse - 28, // 55: xyz.block.ftl.v1.ControllerService.ResetSubscription:output_type -> xyz.block.ftl.v1.ResetSubscriptionResponse - 42, // [42:56] is the sub-list for method output_type - 28, // [28:42] is the sub-list for method input_type - 28, // [28:28] is the sub-list for extension type_name - 28, // [28:28] is the sub-list for extension extendee - 0, // [0:28] is the sub-list for field type_name + 33, // 17: xyz.block.ftl.v1.StatusResponse.routes:type_name -> xyz.block.ftl.v1.StatusResponse.Route + 35, // 18: xyz.block.ftl.v1.ProcessListResponse.processes:type_name -> xyz.block.ftl.v1.ProcessListResponse.Process + 39, // 19: xyz.block.ftl.v1.ResetSubscriptionRequest.subscription:type_name -> xyz.block.ftl.v1.schema.Ref + 37, // 20: xyz.block.ftl.v1.StatusResponse.Runner.labels:type_name -> google.protobuf.Struct + 37, // 21: xyz.block.ftl.v1.StatusResponse.Deployment.labels:type_name -> google.protobuf.Struct + 36, // 22: xyz.block.ftl.v1.StatusResponse.Deployment.schema:type_name -> xyz.block.ftl.v1.schema.Module + 37, // 23: xyz.block.ftl.v1.ProcessListResponse.ProcessRunner.labels:type_name -> google.protobuf.Struct + 37, // 24: xyz.block.ftl.v1.ProcessListResponse.Process.labels:type_name -> google.protobuf.Struct + 34, // 25: xyz.block.ftl.v1.ProcessListResponse.Process.runner:type_name -> xyz.block.ftl.v1.ProcessListResponse.ProcessRunner + 40, // 26: xyz.block.ftl.v1.ControllerService.Ping:input_type -> xyz.block.ftl.v1.PingRequest + 25, // 27: xyz.block.ftl.v1.ControllerService.ProcessList:input_type -> xyz.block.ftl.v1.ProcessListRequest + 23, // 28: xyz.block.ftl.v1.ControllerService.Status:input_type -> xyz.block.ftl.v1.StatusRequest + 0, // 29: xyz.block.ftl.v1.ControllerService.GetCertification:input_type -> xyz.block.ftl.v1.GetCertificationRequest + 4, // 30: xyz.block.ftl.v1.ControllerService.GetArtefactDiffs:input_type -> xyz.block.ftl.v1.GetArtefactDiffsRequest + 6, // 31: xyz.block.ftl.v1.ControllerService.UploadArtefact:input_type -> xyz.block.ftl.v1.UploadArtefactRequest + 9, // 32: xyz.block.ftl.v1.ControllerService.CreateDeployment:input_type -> xyz.block.ftl.v1.CreateDeploymentRequest + 13, // 33: xyz.block.ftl.v1.ControllerService.GetDeployment:input_type -> xyz.block.ftl.v1.GetDeploymentRequest + 11, // 34: xyz.block.ftl.v1.ControllerService.GetDeploymentArtefacts:input_type -> xyz.block.ftl.v1.GetDeploymentArtefactsRequest + 15, // 35: xyz.block.ftl.v1.ControllerService.RegisterRunner:input_type -> xyz.block.ftl.v1.RegisterRunnerRequest + 17, // 36: xyz.block.ftl.v1.ControllerService.UpdateDeploy:input_type -> xyz.block.ftl.v1.UpdateDeployRequest + 19, // 37: xyz.block.ftl.v1.ControllerService.ReplaceDeploy:input_type -> xyz.block.ftl.v1.ReplaceDeployRequest + 21, // 38: xyz.block.ftl.v1.ControllerService.StreamDeploymentLogs:input_type -> xyz.block.ftl.v1.StreamDeploymentLogsRequest + 27, // 39: xyz.block.ftl.v1.ControllerService.ResetSubscription:input_type -> xyz.block.ftl.v1.ResetSubscriptionRequest + 41, // 40: xyz.block.ftl.v1.ControllerService.Ping:output_type -> xyz.block.ftl.v1.PingResponse + 26, // 41: xyz.block.ftl.v1.ControllerService.ProcessList:output_type -> xyz.block.ftl.v1.ProcessListResponse + 24, // 42: xyz.block.ftl.v1.ControllerService.Status:output_type -> xyz.block.ftl.v1.StatusResponse + 1, // 43: xyz.block.ftl.v1.ControllerService.GetCertification:output_type -> xyz.block.ftl.v1.GetCertificationResponse + 5, // 44: xyz.block.ftl.v1.ControllerService.GetArtefactDiffs:output_type -> xyz.block.ftl.v1.GetArtefactDiffsResponse + 7, // 45: xyz.block.ftl.v1.ControllerService.UploadArtefact:output_type -> xyz.block.ftl.v1.UploadArtefactResponse + 10, // 46: xyz.block.ftl.v1.ControllerService.CreateDeployment:output_type -> xyz.block.ftl.v1.CreateDeploymentResponse + 14, // 47: xyz.block.ftl.v1.ControllerService.GetDeployment:output_type -> xyz.block.ftl.v1.GetDeploymentResponse + 12, // 48: xyz.block.ftl.v1.ControllerService.GetDeploymentArtefacts:output_type -> xyz.block.ftl.v1.GetDeploymentArtefactsResponse + 16, // 49: xyz.block.ftl.v1.ControllerService.RegisterRunner:output_type -> xyz.block.ftl.v1.RegisterRunnerResponse + 18, // 50: xyz.block.ftl.v1.ControllerService.UpdateDeploy:output_type -> xyz.block.ftl.v1.UpdateDeployResponse + 20, // 51: xyz.block.ftl.v1.ControllerService.ReplaceDeploy:output_type -> xyz.block.ftl.v1.ReplaceDeployResponse + 22, // 52: xyz.block.ftl.v1.ControllerService.StreamDeploymentLogs:output_type -> xyz.block.ftl.v1.StreamDeploymentLogsResponse + 28, // 53: xyz.block.ftl.v1.ControllerService.ResetSubscription:output_type -> xyz.block.ftl.v1.ResetSubscriptionResponse + 40, // [40:54] is the sub-list for method output_type + 26, // [26:40] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_xyz_block_ftl_v1_controller_proto_init() } @@ -2481,14 +2387,14 @@ func file_xyz_block_ftl_v1_controller_proto_init() { file_xyz_block_ftl_v1_controller_proto_msgTypes[10].OneofWrappers = []any{} file_xyz_block_ftl_v1_controller_proto_msgTypes[21].OneofWrappers = []any{} file_xyz_block_ftl_v1_controller_proto_msgTypes[31].OneofWrappers = []any{} - file_xyz_block_ftl_v1_controller_proto_msgTypes[36].OneofWrappers = []any{} + file_xyz_block_ftl_v1_controller_proto_msgTypes[35].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_xyz_block_ftl_v1_controller_proto_rawDesc, NumEnums: 0, - NumMessages: 37, + NumMessages: 36, NumExtensions: 0, NumServices: 1, }, diff --git a/backend/protos/xyz/block/ftl/v1/controller.proto b/backend/protos/xyz/block/ftl/v1/controller.proto index eb4f4b82ae..649d614f2e 100644 --- a/backend/protos/xyz/block/ftl/v1/controller.proto +++ b/backend/protos/xyz/block/ftl/v1/controller.proto @@ -141,14 +141,6 @@ message StatusResponse { } repeated Deployment deployments = 3; - message IngressRoute { - string deployment_key = 1; - schema.Ref verb = 2; - string method = 3; - string path = 4; - } - repeated IngressRoute ingress_routes = 4; - message Route { string module = 1; string deployment = 2; diff --git a/charts/ftl/templates/_helpers.tpl b/charts/ftl/templates/_helpers.tpl index 6cd2d181d5..c773eabaca 100644 --- a/charts/ftl/templates/_helpers.tpl +++ b/charts/ftl/templates/_helpers.tpl @@ -51,4 +51,9 @@ app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/name: {{ include "ftl.fullname" . }} app.kubernetes.io/component: cron app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} +{{- define "ftl-http-ingress.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ftl.fullname" . }} +app.kubernetes.io/component: http-ingress +app.kubernetes.io/instance: {{ .Release.Name }} {{- end -}} \ No newline at end of file diff --git a/charts/ftl/templates/controller-services.yaml b/charts/ftl/templates/controller-services.yaml index a77449f904..2fce5351cd 100644 --- a/charts/ftl/templates/controller-services.yaml +++ b/charts/ftl/templates/controller-services.yaml @@ -22,25 +22,3 @@ spec: selector: {{- include "ftl-controller.selectorLabels" . | nindent 4 }} type: {{ .Values.controller.service.type | default "ClusterIP" }} ---- -apiVersion: v1 -kind: Service -metadata: - labels: - {{- include "ftl.labels" . | nindent 4 }} - name: {{ include "ftl.fullname" . }}-controller-ingress - {{- if .Values.controller.ingressService.annotations }} - annotations: - {{- toYaml .Values.controller.ingressService.annotations | nindent 4 }} - {{- end }} -spec: - ports: - {{- range .Values.controller.ingressService.ports }} - - name: {{ .name }} - port: {{ .port }} - protocol: {{ .protocol | default "TCP" }} - targetPort: {{ .targetPort }} - {{- end }} - selector: - {{- include "ftl-controller.selectorLabels" . | nindent 4 }} - type: {{ .Values.controller.ingressService.type | default "ClusterIP" }} diff --git a/charts/ftl/templates/cron.yaml b/charts/ftl/templates/cron-deployment.yaml similarity index 100% rename from charts/ftl/templates/cron.yaml rename to charts/ftl/templates/cron-deployment.yaml diff --git a/charts/ftl/templates/http-ingress-deployment.yaml b/charts/ftl/templates/http-ingress-deployment.yaml new file mode 100644 index 0000000000..0b380a7730 --- /dev/null +++ b/charts/ftl/templates/http-ingress-deployment.yaml @@ -0,0 +1,83 @@ +{{- if .Values.ingress.enabled }} +{{ $version := printf "v%s" .Chart.Version -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ftl.fullname" . }}-http-ingress + labels: + {{- include "ftl.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.ingress.replicas }} + revisionHistoryLimit: {{ .Values.ingress.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "ftl-http-ingress.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "ftl-http-ingress.selectorLabels" . | nindent 8 }} + {{- if .Values.ingress.podAnnotations }} + annotations: + {{- toYaml .Values.ingress.podAnnotations | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ .Values.ingress.serviceAccountName }} + containers: + - name: app + image: "{{ .Values.ingress.image.repository }}:{{ .Values.ingress.image.tag | default $version }}" + imagePullPolicy: {{ .Values.ingress.image.pullPolicy }} + resources: + limits: + cpu: "{{ .Values.ingress.resources.limits.cpu }}" + memory: "{{ .Values.ingress.resources.limits.memory }}" + requests: + cpu: "{{ .Values.ingress.resources.requests.cpu }}" + memory: "{{ .Values.ingress.resources.requests.memory }}" + {{- if .Values.ingress.envFrom }} + envFrom: + {{- if .Values.ingress.envFrom }} + {{- toYaml .Values.ingress.envFrom | nindent 12 }} + {{- end }} + {{- end }} + env: + {{- if .Values.ingress.env }} + {{- toYaml .Values.ingress.env | nindent 12 }} + {{- end }} + + ports: + {{- range .Values.ingress.ports }} + - name: {{ .name }} + containerPort: {{ .containerPort }} + protocol: {{ .protocol | default "TCP" }} + {{- end }} + readinessProbe: + {{- if .Values.ingress.readinessProbe }} + {{- toYaml .Values.ingress.readinessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /healthz + port: 8891 + initialDelaySeconds: 1 + periodSeconds: 2 + timeoutSeconds: 2 + successThreshold: 1 + failureThreshold: 15 + {{- end }} + {{- if .Values.ingress.nodeSelector }} + nodeSelector: + {{- toYaml .Values.ingress.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.ingress.affinity }} + affinity: + {{- toYaml .Values.ingress.affinity | nindent 8 }} + {{- end }} + {{- if .Values.ingress.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml .Values.ingress.topologySpreadConstraints | nindent 8 }} + {{- end }} + {{- if .Values.ingress.tolerations }} + tolerations: + {{- toYaml .Values.ingress.tolerations | nindent 8 }} + {{- end }} + + {{- end }} \ No newline at end of file diff --git a/charts/ftl/templates/http-ingress-role.yaml b/charts/ftl/templates/http-ingress-role.yaml new file mode 100644 index 0000000000..a6cc35c0e2 --- /dev/null +++ b/charts/ftl/templates/http-ingress-role.yaml @@ -0,0 +1,8 @@ +{{- if .Values.ingress.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.ingress.serviceAccountName }} + namespace: {{ .Release.Namespace }} + +{{- end }} \ No newline at end of file diff --git a/charts/ftl/templates/http-ingress-services.yaml b/charts/ftl/templates/http-ingress-services.yaml new file mode 100644 index 0000000000..b41f350dbf --- /dev/null +++ b/charts/ftl/templates/http-ingress-services.yaml @@ -0,0 +1,24 @@ +{{- if .Values.ingress.enabled }} +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "ftl.labels" . | nindent 4 }} + name: {{ include "ftl.fullname" . }}-http-ingress + {{- if .Values.ingress.service.annotations }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + ports: + {{- range .Values.ingress.ports }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol | default "TCP" }} + targetPort: {{ .targetPort }} + {{- end }} + selector: + {{- include "ftl-http-ingress.selectorLabels" . | nindent 4 }} + type: {{ .Values.controller.ingressService.type | default "ClusterIP" }} + +{{- end }} \ No newline at end of file diff --git a/charts/ftl/templates/ingress.yaml b/charts/ftl/templates/ingress.yaml index 715ed42dad..cde404d51c 100644 --- a/charts/ftl/templates/ingress.yaml +++ b/charts/ftl/templates/ingress.yaml @@ -3,9 +3,9 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ftl.fullname" . }}-controller + name: {{ include "ftl.fullname" . }}-ingress annotations: - {{- toYaml .Values.ingress.annotations | nindent 4 }} + {{- toYaml .Values.ingress.ingressAnnotations | nindent 4 }} spec: rules: - http: @@ -21,7 +21,7 @@ spec: pathType: Prefix backend: service: - name: ftl-controller-ingress + name: ftl-http-ingress port: number: 8891 - path: /xyz.block.ftl.v1beta1.provisioner.ProvisionerService/ diff --git a/charts/ftl/values.yaml b/charts/ftl/values.yaml index 422544f371..f802b32f50 100644 --- a/charts/ftl/values.yaml +++ b/charts/ftl/values.yaml @@ -1,10 +1,6 @@ fullnameOverride: "" nameOverride: "" -ingress: - enabled: false - annotations: - kubernetes.io/ingress.class: nginx secrets: logEncryptionKey: null @@ -46,12 +42,8 @@ controller: fieldPath: status.podIP - name: FTL_CONTROLLER_BIND value: "http://$(MY_POD_IP):8892" - - name: FTL_CONTROLLER_INGRESS_BIND - value: "http://$(MY_POD_IP):8891" - name: FTL_CONTROLLER_ADVERTISE value: "http://$(MY_POD_IP):8892" - - name: FTL_CONTROLLER_ALLOW_ORIGIN - value: "*" - name: LOG_LEVEL value: "debug" - name: LOG_JSON @@ -66,9 +58,6 @@ controller: # value: "env=ftlDefault" ports: - - name: ingress - containerPort: 8891 - protocol: TCP - name: http containerPort: 8892 protocol: TCP @@ -250,4 +239,71 @@ istio: registry: repository: "" allowInsecure: false - create: false \ No newline at end of file + create: false + + +ingress: + enabled: false + env: + - name: MY_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: FTL_ENDPOINT + value: "http://ftl-controller:8892" + - name: FTL_INGRESS_BIND + value: "http://$(MY_POD_IP):8891" + - name: FTL_INGRESS_ALLOW_ORIGIN + value: "*" + - name: LOG_LEVEL + value: "debug" + - name: LOG_JSON + value: "true" + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + ports: + - name: ingress + containerPort: 8891 + protocol: TCP + port: 8891 + + ingressAnnotations: + kubernetes.io/ingress.class: nginx + replicas: 2 + revisionHistoryLimit: 0 + + image: + repository: "ftl0/ftl-http-ingress" + pullPolicy: IfNotPresent + + resources: + requests: + memory: 512Mi + cpu: 10m + limits: + memory: 512Mi + cpu: 2 + + envFrom: null + serviceAccountName: ftl-http-ingress + + readinessProbe: null + + service: + type: ClusterIP + annotations: null + ports: + - name: "http-8891" + port: 80 + protocol: TCP + targetPort: 8891 + + podAnnotations: + proxy.istio.io/config: | + holdApplicationUntilProxyStarts: true + nodeSelector: null + affinity: null + topologySpreadConstraints: null + tolerations: null diff --git a/cmd/ftl-cron/main.go b/cmd/ftl-cron/main.go index 7e26d76e8d..9fc18bf1c6 100644 --- a/cmd/ftl-cron/main.go +++ b/cmd/ftl-cron/main.go @@ -45,5 +45,5 @@ func main() { schemaClient := rpc.Dial(ftlv1connect.NewSchemaServiceClient, cli.CronConfig.ControllerEndpoint.String(), log.Error) err = cron.Start(ctx, schemaClient, verbClient) - kctx.FatalIfErrorf(err, "failed to start provisioner") + kctx.FatalIfErrorf(err, "failed to start cron") } diff --git a/cmd/ftl-http-ingress/main.go b/cmd/ftl-http-ingress/main.go new file mode 100644 index 0000000000..3f75537e5c --- /dev/null +++ b/cmd/ftl-http-ingress/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "context" + "fmt" + "net/url" + "os" + "strconv" + "time" + + "github.com/alecthomas/kong" + + "github.com/TBD54566975/ftl" + "github.com/TBD54566975/ftl/backend/ingress" + "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect" + _ "github.com/TBD54566975/ftl/internal/automaxprocs" // Set GOMAXPROCS to match Linux container CPU quota. + "github.com/TBD54566975/ftl/internal/log" + "github.com/TBD54566975/ftl/internal/observability" + "github.com/TBD54566975/ftl/internal/rpc" +) + +var cli struct { + Version kong.VersionFlag `help:"Show version."` + ObservabilityConfig observability.Config `embed:"" prefix:"o11y-"` + LogConfig log.Config `embed:"" prefix:"log-"` + HTTPIngressConfig ingress.Config `embed:""` + ConfigFlag string `name:"config" short:"C" help:"Path to FTL project cf file." env:"FTL_CONFIG" placeholder:"FILE"` + ControllerEndpoint *url.URL `name:"ftl-endpoint" help:"Controller endpoint." env:"FTL_ENDPOINT" default:"http://127.0.0.1:8892"` +} + +func main() { + t, err := strconv.ParseInt(ftl.Timestamp, 10, 64) + if err != nil { + panic(fmt.Sprintf("invalid timestamp %q: %s", ftl.Timestamp, err)) + } + kctx := kong.Parse(&cli, + kong.Description(`FTL - HTTP Ingress`), + kong.UsageOnError(), + kong.Vars{"version": ftl.Version, "timestamp": time.Unix(t, 0).Format(time.RFC3339)}, + ) + + ctx := log.ContextWithLogger(context.Background(), log.Configure(os.Stderr, cli.LogConfig)) + err = observability.Init(ctx, false, "", "ftl-cron", ftl.Version, cli.ObservabilityConfig) + kctx.FatalIfErrorf(err, "failed to initialize observability") + + verbClient := rpc.Dial(ftlv1connect.NewVerbServiceClient, cli.ControllerEndpoint.String(), log.Error) + schemaClient := rpc.Dial(ftlv1connect.NewSchemaServiceClient, cli.ControllerEndpoint.String(), log.Error) + + err = ingress.Start(ctx, cli.HTTPIngressConfig, schemaClient, verbClient) + kctx.FatalIfErrorf(err, "failed to start HTTP ingress") +} diff --git a/common/plugin/serve.go b/common/plugin/serve.go index cf1882e3f7..2862219d72 100644 --- a/common/plugin/serve.go +++ b/common/plugin/serve.go @@ -188,8 +188,11 @@ func cleanup(logger *log.Logger, pidFile string) error { } else if err != nil { return err } + if len(pidb) == 0 { + return nil + } pid, err := strconv.Atoi(string(pidb)) - if err != nil && !os.IsNotExist(err) { + if err != nil { return err } err = syscall.Kill(pid, syscall.SIGKILL) diff --git a/deployment/Dockerfile.cron.test b/deployment/Dockerfile.cron.test index 7dacd4e876..3aae385e46 100644 --- a/deployment/Dockerfile.cron.test +++ b/deployment/Dockerfile.cron.test @@ -3,6 +3,5 @@ FROM ubuntu:24.04 WORKDIR /root/ COPY docker-build/ftl-cron . -EXPOSE 8893 CMD ["/root/ftl-cron"] diff --git a/deployment/Dockerfile.http-ingress.test b/deployment/Dockerfile.http-ingress.test new file mode 100644 index 0000000000..2f4d690b53 --- /dev/null +++ b/deployment/Dockerfile.http-ingress.test @@ -0,0 +1,8 @@ +FROM ubuntu:24.04 + +WORKDIR /root/ + +COPY docker-build/ftl-http-ingress . +EXPOSE 8891 + +CMD ["/root/ftl-http-ingress"] diff --git a/deployment/Justfile b/deployment/Justfile index 4fc98e8312..af389ba45e 100755 --- a/deployment/Justfile +++ b/deployment/Justfile @@ -17,7 +17,7 @@ start: setup full-deploy rm: teardown -full-deploy: build-controller build-runners build-provisioner setup-istio-cluster build-cron +full-deploy: build-controller build-runners build-provisioner setup-istio-cluster build-cron build-http-ingress #!/bin/bash kubectl rollout restart deployment ftl-controller || true # if this exists already restart it to get the latest image just apply || sleep 5 # wait for CRDs to be created, the initial apply will usually fail @@ -28,6 +28,7 @@ wait-for-kube: while [ -z "$(kubectl get pod ftl-postgresql-0)" ]; do sleep 1; done kubectl wait --for=condition=ready pod/ftl-postgresql-0 --timeout=5m kubectl wait --for=condition=available deployment/ftl-controller --timeout=5m + kubectl wait --for=condition=available deployment/ftl-http-ingress --timeout=5m kubectl wait --for=condition=available deployment/registry --timeout=5m sleep 1 ftl status || sleep 5 && ftl status @@ -116,7 +117,7 @@ build-executables: # it is way faster than building in the docker files java -version #make sure hermit has downloaded Java mkdir -p "docker-build" - cd ../ && GOARCH=amd64 GOOS=linux CGO_ENABLED=0 just build ftl-controller ftl-runner ftl-initdb ftl ftl-provisioner ftl-provisioner-cloudformation ftl-cron + cd ../ && GOARCH=amd64 GOOS=linux CGO_ENABLED=0 just build ftl-controller ftl-runner ftl-initdb ftl ftl-provisioner ftl-provisioner-cloudformation ftl-cron ftl-http-ingress cp ../build/release/* ./docker-build/ build-controller: build-executables setup-registry setup-istio-cluster @@ -143,7 +144,12 @@ build-cron: build-executables setup-registry setup-istio-cluster docker tag ftl-cron:latest {{registry_local}}/ftl-cron:latest docker push {{registry_local}}/ftl-cron:latest -build: build-controller build-runners build-provisioner build-cron +build-http-ingress: build-executables setup-registry setup-istio-cluster + docker build --platform linux/amd64 -t ftl-http-ingress:latest -f Dockerfile.http-ingress.test . + docker tag ftl-http-ingress:latest {{registry_local}}/ftl-http-ingress:latest + docker push {{registry_local}}/ftl-http-ingress:latest + +build: build-controller build-runners build-provisioner build-cron build-http-ingress deploy path: #!/usr/bin/env bash diff --git a/deployment/values-release.yaml b/deployment/values-release.yaml index 38f743964e..fa318412f0 100644 --- a/deployment/values-release.yaml +++ b/deployment/values-release.yaml @@ -4,6 +4,11 @@ ingress: annotations: ingress.kubernetes.io/ssl-redirect: "false" kubernetes.io/ingress.class: traefik + ingressAnnotations: + ingress.kubernetes.io/ssl-redirect: "false" + kubernetes.io/ingress.class: traefik + + controller: podAnnotations: proxy.istio.io/config: | diff --git a/deployment/values.yaml b/deployment/values.yaml index d64c7390cf..b46ae4439c 100644 --- a/deployment/values.yaml +++ b/deployment/values.yaml @@ -1,7 +1,11 @@ fullnameOverride: "ftl" ingress: enabled: true - annotations: + image: + repository: "ftl:5000/ftl-http-ingress" + tag: "latest" + pullPolicy: Always + ingressAnnotations: ingress.kubernetes.io/ssl-redirect: "false" kubernetes.io/ingress.class: traefik controller: diff --git a/frontend/cli/cmd_dev.go b/frontend/cli/cmd_dev.go index 2127a49d71..d501784507 100644 --- a/frontend/cli/cmd_dev.go +++ b/frontend/cli/cmd_dev.go @@ -87,8 +87,8 @@ func (d *devCmd) Run( } // Default to allowing all origins and headers for console requests in local dev mode. - d.ServeCmd.AllowOrigins = []*url.URL{{Scheme: "*", Host: "*"}} - d.ServeCmd.AllowHeaders = []string{"*"} + d.ServeCmd.Ingress.AllowOrigins = []*url.URL{{Scheme: "*", Host: "*"}} + d.ServeCmd.Ingress.AllowHeaders = []string{"*"} devModeEndpointUpdates := make(chan scaling.DevModeEndpoints, 1) // cmdServe will notify this channel when startup commands are complete and the controller is ready diff --git a/frontend/cli/cmd_serve.go b/frontend/cli/cmd_serve.go index f691f47204..b31f562c2e 100644 --- a/frontend/cli/cmd_serve.go +++ b/frontend/cli/cmd_serve.go @@ -24,6 +24,7 @@ import ( "github.com/TBD54566975/ftl/backend/controller/scaling" "github.com/TBD54566975/ftl/backend/controller/scaling/localscaling" "github.com/TBD54566975/ftl/backend/cron" + "github.com/TBD54566975/ftl/backend/ingress" ftlv1 "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1" "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect" "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1beta1/provisioner/provisionerconnect" @@ -60,6 +61,7 @@ type serveCommonConfig struct { RegistryImage string `help:"The container image to start for the image registry" default:"registry:2" env:"FTL_REGISTRY_IMAGE" hidden:""` GrafanaImage string `help:"The container image to start for the automatic Grafana instance" default:"grafana/otel-lgtm" env:"FTL_GRAFANA_IMAGE" hidden:""` DisableGrafana bool `help:"Disable the automatic Grafana that is started if no telemetry collector is specified." default:"false"` + Ingress ingress.Config `embed:"" prefix:"ingress-"` controller.CommonConfig provisioner.CommonProvisionerConfig } @@ -186,7 +188,7 @@ func (s *serveCommonConfig) run( if addr.Hostname() == "127.0.0.1" { addr.Host = "localhost" + ":" + addr.Port() } - s.CommonConfig.AllowOrigins = append(s.CommonConfig.AllowOrigins, addr) + s.Ingress.AllowOrigins = append(s.Ingress.AllowOrigins, addr) } provisionerAddresses := make([]*url.URL, 0, s.Provisioners) @@ -207,7 +209,6 @@ func (s *serveCommonConfig) run( config := controller.Config{ CommonConfig: s.CommonConfig, Bind: controllerAddresses[i], - IngressBind: controllerIngressAddresses[i], Key: model.NewLocalControllerKey(i), DSN: dsn, Registry: registry, @@ -291,6 +292,14 @@ func (s *serveCommonConfig) run( } return nil }) + // Start Ingress + wg.Go(func() error { + err := ingress.Start(ctx, s.Ingress, schemaClient, vervClient) + if err != nil { + return fmt.Errorf("ingress failed: %w", err) + } + return nil + }) // Wait for controller to start, then run startup commands. start := time.Now() if err := waitForControllerOnline(ctx, s.StartupTimeout, controllerClient); err != nil { diff --git a/frontend/console/src/protos/xyz/block/ftl/v1/controller_pb.ts b/frontend/console/src/protos/xyz/block/ftl/v1/controller_pb.ts index 256dc242b2..4b439d5cbf 100644 --- a/frontend/console/src/protos/xyz/block/ftl/v1/controller_pb.ts +++ b/frontend/console/src/protos/xyz/block/ftl/v1/controller_pb.ts @@ -1030,11 +1030,6 @@ export class StatusResponse extends Message { */ deployments: StatusResponse_Deployment[] = []; - /** - * @generated from field: repeated xyz.block.ftl.v1.StatusResponse.IngressRoute ingress_routes = 4; - */ - ingressRoutes: StatusResponse_IngressRoute[] = []; - /** * @generated from field: repeated xyz.block.ftl.v1.StatusResponse.Route routes = 5; */ @@ -1051,7 +1046,6 @@ export class StatusResponse extends Message { { no: 1, name: "controllers", kind: "message", T: StatusResponse_Controller, repeated: true }, { no: 2, name: "runners", kind: "message", T: StatusResponse_Runner, repeated: true }, { no: 3, name: "deployments", kind: "message", T: StatusResponse_Deployment, repeated: true }, - { no: 4, name: "ingress_routes", kind: "message", T: StatusResponse_IngressRoute, repeated: true }, { no: 5, name: "routes", kind: "message", T: StatusResponse_Route, repeated: true }, ]); @@ -1249,61 +1243,6 @@ export class StatusResponse_Deployment extends Message { - /** - * @generated from field: string deployment_key = 1; - */ - deploymentKey = ""; - - /** - * @generated from field: xyz.block.ftl.v1.schema.Ref verb = 2; - */ - verb?: Ref; - - /** - * @generated from field: string method = 3; - */ - method = ""; - - /** - * @generated from field: string path = 4; - */ - path = ""; - - constructor(data?: PartialMessage) { - super(); - proto3.util.initPartial(data, this); - } - - static readonly runtime: typeof proto3 = proto3; - static readonly typeName = "xyz.block.ftl.v1.StatusResponse.IngressRoute"; - static readonly fields: FieldList = proto3.util.newFieldList(() => [ - { no: 1, name: "deployment_key", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 2, name: "verb", kind: "message", T: Ref }, - { no: 3, name: "method", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 4, name: "path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - ]); - - static fromBinary(bytes: Uint8Array, options?: Partial): StatusResponse_IngressRoute { - return new StatusResponse_IngressRoute().fromBinary(bytes, options); - } - - static fromJson(jsonValue: JsonValue, options?: Partial): StatusResponse_IngressRoute { - return new StatusResponse_IngressRoute().fromJson(jsonValue, options); - } - - static fromJsonString(jsonString: string, options?: Partial): StatusResponse_IngressRoute { - return new StatusResponse_IngressRoute().fromJsonString(jsonString, options); - } - - static equals(a: StatusResponse_IngressRoute | PlainMessage | undefined, b: StatusResponse_IngressRoute | PlainMessage | undefined): boolean { - return proto3.util.equals(StatusResponse_IngressRoute, a, b); - } -} - /** * @generated from message xyz.block.ftl.v1.StatusResponse.Route */ diff --git a/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.py b/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.py index afc0603377..687ffe1f92 100644 --- a/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.py +++ b/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.py @@ -28,7 +28,7 @@ from xyz.block.ftl.v1.schema import schema_pb2 as xyz_dot_block_dot_ftl_dot_v1_dot_schema_dot_schema__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!xyz/block/ftl/v1/controller.proto\x12\x10xyz.block.ftl.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1axyz/block/ftl/v1/ftl.proto\x1a$xyz/block/ftl/v1/schema/schema.proto\"w\n\x17GetCertificationRequest\x12>\n\x07request\x18\x01 \x01(\x0b\x32$.xyz.block.ftl.v1.CertificateContentR\x07request\x12\x1c\n\tsignature\x18\x02 \x01(\x0cR\tsignature\"[\n\x18GetCertificationResponse\x12?\n\x0b\x63\x65rtificate\x18\x01 \x01(\x0b\x32\x1d.xyz.block.ftl.v1.CertificateR\x0b\x63\x65rtificate\"O\n\x12\x43\x65rtificateContent\x12\x1a\n\x08identity\x18\x01 \x01(\tR\x08identity\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\"\x80\x01\n\x0b\x43\x65rtificate\x12>\n\x07\x63ontent\x18\x01 \x01(\x0b\x32$.xyz.block.ftl.v1.CertificateContentR\x07\x63ontent\x12\x31\n\x14\x63ontroller_signature\x18\x03 \x01(\x0cR\x13\x63ontrollerSignature\"@\n\x17GetArtefactDiffsRequest\x12%\n\x0e\x63lient_digests\x18\x01 \x03(\tR\rclientDigests\"\x94\x01\n\x18GetArtefactDiffsResponse\x12\'\n\x0fmissing_digests\x18\x01 \x03(\tR\x0emissingDigests\x12O\n\x10\x63lient_artefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\x0f\x63lientArtefacts\"1\n\x15UploadArtefactRequest\x12\x18\n\x07\x63ontent\x18\x01 \x01(\x0cR\x07\x63ontent\"0\n\x16UploadArtefactResponse\x12\x16\n\x06\x64igest\x18\x02 \x01(\x0cR\x06\x64igest\"`\n\x12\x44\x65ploymentArtefact\x12\x16\n\x06\x64igest\x18\x01 \x01(\tR\x06\x64igest\x12\x12\n\x04path\x18\x02 \x01(\tR\x04path\x12\x1e\n\nexecutable\x18\x03 \x01(\x08R\nexecutable\"\xd7\x01\n\x17\x43reateDeploymentRequest\x12\x37\n\x06schema\x18\x01 \x01(\x0b\x32\x1f.xyz.block.ftl.v1.schema.ModuleR\x06schema\x12\x42\n\tartefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\tartefacts\x12\x34\n\x06labels\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructH\x00R\x06labels\x88\x01\x01\x42\t\n\x07_labels\"\x94\x01\n\x18\x43reateDeploymentResponse\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12\x37\n\x15\x61\x63tive_deployment_key\x18\x02 \x01(\tH\x00R\x13\x61\x63tiveDeploymentKey\x88\x01\x01\x42\x18\n\x16_active_deployment_key\"\x93\x01\n\x1dGetDeploymentArtefactsRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12K\n\x0ehave_artefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\rhaveArtefacts\"x\n\x1eGetDeploymentArtefactsResponse\x12@\n\x08\x61rtefact\x18\x01 \x01(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\x08\x61rtefact\x12\x14\n\x05\x63hunk\x18\x02 \x01(\x0cR\x05\x63hunk\"=\n\x14GetDeploymentRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\"\x94\x01\n\x15GetDeploymentResponse\x12\x37\n\x06schema\x18\x01 \x01(\x0b\x32\x1f.xyz.block.ftl.v1.schema.ModuleR\x06schema\x12\x42\n\tartefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\tartefacts\"\x96\x01\n\x15RegisterRunnerRequest\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12\x1e\n\ndeployment\x18\x03 \x01(\tR\ndeployment\x12/\n\x06labels\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\"\x18\n\x16RegisterRunnerResponse\"_\n\x13UpdateDeployRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12!\n\x0cmin_replicas\x18\x02 \x01(\x05R\x0bminReplicas\"\x16\n\x14UpdateDeployResponse\"`\n\x14ReplaceDeployRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12!\n\x0cmin_replicas\x18\x02 \x01(\x05R\x0bminReplicas\"\x17\n\x15ReplaceDeployResponse\"\xaf\x03\n\x1bStreamDeploymentLogsRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12$\n\x0brequest_key\x18\x02 \x01(\tH\x00R\nrequestKey\x88\x01\x01\x12\x39\n\ntime_stamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\ttimeStamp\x12\x1b\n\tlog_level\x18\x04 \x01(\x05R\x08logLevel\x12]\n\nattributes\x18\x05 \x03(\x0b\x32=.xyz.block.ftl.v1.StreamDeploymentLogsRequest.AttributesEntryR\nattributes\x12\x18\n\x07message\x18\x06 \x01(\tR\x07message\x12\x19\n\x05\x65rror\x18\x07 \x01(\tH\x01R\x05\x65rror\x88\x01\x01\x1a=\n\x0f\x41ttributesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x0e\n\x0c_request_keyB\x08\n\x06_error\"\x1e\n\x1cStreamDeploymentLogsResponse\"\x0f\n\rStatusRequest\"\xe8\x08\n\x0eStatusResponse\x12M\n\x0b\x63ontrollers\x18\x01 \x03(\x0b\x32+.xyz.block.ftl.v1.StatusResponse.ControllerR\x0b\x63ontrollers\x12\x41\n\x07runners\x18\x02 \x03(\x0b\x32\'.xyz.block.ftl.v1.StatusResponse.RunnerR\x07runners\x12M\n\x0b\x64\x65ployments\x18\x03 \x03(\x0b\x32+.xyz.block.ftl.v1.StatusResponse.DeploymentR\x0b\x64\x65ployments\x12T\n\x0eingress_routes\x18\x04 \x03(\x0b\x32-.xyz.block.ftl.v1.StatusResponse.IngressRouteR\ringressRoutes\x12>\n\x06routes\x18\x05 \x03(\x0b\x32&.xyz.block.ftl.v1.StatusResponse.RouteR\x06routes\x1aT\n\nController\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x1a\x9b\x01\n\x06Runner\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12#\n\ndeployment\x18\x03 \x01(\tH\x00R\ndeployment\x88\x01\x01\x12/\n\x06labels\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labelsB\r\n\x0b_deployment\x1a\xf7\x01\n\nDeployment\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08language\x18\x02 \x01(\tR\x08language\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12!\n\x0cmin_replicas\x18\x04 \x01(\x05R\x0bminReplicas\x12\x1a\n\x08replicas\x18\x07 \x01(\x05R\x08replicas\x12/\n\x06labels\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\x12\x37\n\x06schema\x18\x06 \x01(\x0b\x32\x1f.xyz.block.ftl.v1.schema.ModuleR\x06schema\x1a\x93\x01\n\x0cIngressRoute\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12\x30\n\x04verb\x18\x02 \x01(\x0b\x32\x1c.xyz.block.ftl.v1.schema.RefR\x04verb\x12\x16\n\x06method\x18\x03 \x01(\tR\x06method\x12\x12\n\x04path\x18\x04 \x01(\tR\x04path\x1a[\n\x05Route\x12\x16\n\x06module\x18\x01 \x01(\tR\x06module\x12\x1e\n\ndeployment\x18\x02 \x01(\tR\ndeployment\x12\x1a\n\x08\x65ndpoint\x18\x03 \x01(\tR\x08\x65ndpoint\"\x14\n\x12ProcessListRequest\"\xaf\x03\n\x13ProcessListResponse\x12K\n\tprocesses\x18\x01 \x03(\x0b\x32-.xyz.block.ftl.v1.ProcessListResponse.ProcessR\tprocesses\x1an\n\rProcessRunner\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12/\n\x06labels\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\x1a\xda\x01\n\x07Process\x12\x1e\n\ndeployment\x18\x01 \x01(\tR\ndeployment\x12!\n\x0cmin_replicas\x18\x02 \x01(\x05R\x0bminReplicas\x12/\n\x06labels\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\x12P\n\x06runner\x18\x04 \x01(\x0b\x32\x33.xyz.block.ftl.v1.ProcessListResponse.ProcessRunnerH\x00R\x06runner\x88\x01\x01\x42\t\n\x07_runner\"\\\n\x18ResetSubscriptionRequest\x12@\n\x0csubscription\x18\x01 \x01(\x0b\x32\x1c.xyz.block.ftl.v1.schema.RefR\x0csubscription\"\x1b\n\x19ResetSubscriptionResponse2\x9e\x0b\n\x11\x43ontrollerService\x12J\n\x04Ping\x12\x1d.xyz.block.ftl.v1.PingRequest\x1a\x1e.xyz.block.ftl.v1.PingResponse\"\x03\x90\x02\x01\x12Z\n\x0bProcessList\x12$.xyz.block.ftl.v1.ProcessListRequest\x1a%.xyz.block.ftl.v1.ProcessListResponse\x12K\n\x06Status\x12\x1f.xyz.block.ftl.v1.StatusRequest\x1a .xyz.block.ftl.v1.StatusResponse\x12i\n\x10GetCertification\x12).xyz.block.ftl.v1.GetCertificationRequest\x1a*.xyz.block.ftl.v1.GetCertificationResponse\x12i\n\x10GetArtefactDiffs\x12).xyz.block.ftl.v1.GetArtefactDiffsRequest\x1a*.xyz.block.ftl.v1.GetArtefactDiffsResponse\x12\x63\n\x0eUploadArtefact\x12\'.xyz.block.ftl.v1.UploadArtefactRequest\x1a(.xyz.block.ftl.v1.UploadArtefactResponse\x12i\n\x10\x43reateDeployment\x12).xyz.block.ftl.v1.CreateDeploymentRequest\x1a*.xyz.block.ftl.v1.CreateDeploymentResponse\x12`\n\rGetDeployment\x12&.xyz.block.ftl.v1.GetDeploymentRequest\x1a\'.xyz.block.ftl.v1.GetDeploymentResponse\x12}\n\x16GetDeploymentArtefacts\x12/.xyz.block.ftl.v1.GetDeploymentArtefactsRequest\x1a\x30.xyz.block.ftl.v1.GetDeploymentArtefactsResponse0\x01\x12\x65\n\x0eRegisterRunner\x12\'.xyz.block.ftl.v1.RegisterRunnerRequest\x1a(.xyz.block.ftl.v1.RegisterRunnerResponse(\x01\x12]\n\x0cUpdateDeploy\x12%.xyz.block.ftl.v1.UpdateDeployRequest\x1a&.xyz.block.ftl.v1.UpdateDeployResponse\x12`\n\rReplaceDeploy\x12&.xyz.block.ftl.v1.ReplaceDeployRequest\x1a\'.xyz.block.ftl.v1.ReplaceDeployResponse\x12w\n\x14StreamDeploymentLogs\x12-.xyz.block.ftl.v1.StreamDeploymentLogsRequest\x1a..xyz.block.ftl.v1.StreamDeploymentLogsResponse(\x01\x12l\n\x11ResetSubscription\x12*.xyz.block.ftl.v1.ResetSubscriptionRequest\x1a+.xyz.block.ftl.v1.ResetSubscriptionResponseBDP\x01Z@github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1;ftlv1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!xyz/block/ftl/v1/controller.proto\x12\x10xyz.block.ftl.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1axyz/block/ftl/v1/ftl.proto\x1a$xyz/block/ftl/v1/schema/schema.proto\"w\n\x17GetCertificationRequest\x12>\n\x07request\x18\x01 \x01(\x0b\x32$.xyz.block.ftl.v1.CertificateContentR\x07request\x12\x1c\n\tsignature\x18\x02 \x01(\x0cR\tsignature\"[\n\x18GetCertificationResponse\x12?\n\x0b\x63\x65rtificate\x18\x01 \x01(\x0b\x32\x1d.xyz.block.ftl.v1.CertificateR\x0b\x63\x65rtificate\"O\n\x12\x43\x65rtificateContent\x12\x1a\n\x08identity\x18\x01 \x01(\tR\x08identity\x12\x1d\n\npublic_key\x18\x02 \x01(\x0cR\tpublicKey\"\x80\x01\n\x0b\x43\x65rtificate\x12>\n\x07\x63ontent\x18\x01 \x01(\x0b\x32$.xyz.block.ftl.v1.CertificateContentR\x07\x63ontent\x12\x31\n\x14\x63ontroller_signature\x18\x03 \x01(\x0cR\x13\x63ontrollerSignature\"@\n\x17GetArtefactDiffsRequest\x12%\n\x0e\x63lient_digests\x18\x01 \x03(\tR\rclientDigests\"\x94\x01\n\x18GetArtefactDiffsResponse\x12\'\n\x0fmissing_digests\x18\x01 \x03(\tR\x0emissingDigests\x12O\n\x10\x63lient_artefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\x0f\x63lientArtefacts\"1\n\x15UploadArtefactRequest\x12\x18\n\x07\x63ontent\x18\x01 \x01(\x0cR\x07\x63ontent\"0\n\x16UploadArtefactResponse\x12\x16\n\x06\x64igest\x18\x02 \x01(\x0cR\x06\x64igest\"`\n\x12\x44\x65ploymentArtefact\x12\x16\n\x06\x64igest\x18\x01 \x01(\tR\x06\x64igest\x12\x12\n\x04path\x18\x02 \x01(\tR\x04path\x12\x1e\n\nexecutable\x18\x03 \x01(\x08R\nexecutable\"\xd7\x01\n\x17\x43reateDeploymentRequest\x12\x37\n\x06schema\x18\x01 \x01(\x0b\x32\x1f.xyz.block.ftl.v1.schema.ModuleR\x06schema\x12\x42\n\tartefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\tartefacts\x12\x34\n\x06labels\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructH\x00R\x06labels\x88\x01\x01\x42\t\n\x07_labels\"\x94\x01\n\x18\x43reateDeploymentResponse\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12\x37\n\x15\x61\x63tive_deployment_key\x18\x02 \x01(\tH\x00R\x13\x61\x63tiveDeploymentKey\x88\x01\x01\x42\x18\n\x16_active_deployment_key\"\x93\x01\n\x1dGetDeploymentArtefactsRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12K\n\x0ehave_artefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\rhaveArtefacts\"x\n\x1eGetDeploymentArtefactsResponse\x12@\n\x08\x61rtefact\x18\x01 \x01(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\x08\x61rtefact\x12\x14\n\x05\x63hunk\x18\x02 \x01(\x0cR\x05\x63hunk\"=\n\x14GetDeploymentRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\"\x94\x01\n\x15GetDeploymentResponse\x12\x37\n\x06schema\x18\x01 \x01(\x0b\x32\x1f.xyz.block.ftl.v1.schema.ModuleR\x06schema\x12\x42\n\tartefacts\x18\x02 \x03(\x0b\x32$.xyz.block.ftl.v1.DeploymentArtefactR\tartefacts\"\x96\x01\n\x15RegisterRunnerRequest\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12\x1e\n\ndeployment\x18\x03 \x01(\tR\ndeployment\x12/\n\x06labels\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\"\x18\n\x16RegisterRunnerResponse\"_\n\x13UpdateDeployRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12!\n\x0cmin_replicas\x18\x02 \x01(\x05R\x0bminReplicas\"\x16\n\x14UpdateDeployResponse\"`\n\x14ReplaceDeployRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12!\n\x0cmin_replicas\x18\x02 \x01(\x05R\x0bminReplicas\"\x17\n\x15ReplaceDeployResponse\"\xaf\x03\n\x1bStreamDeploymentLogsRequest\x12%\n\x0e\x64\x65ployment_key\x18\x01 \x01(\tR\rdeploymentKey\x12$\n\x0brequest_key\x18\x02 \x01(\tH\x00R\nrequestKey\x88\x01\x01\x12\x39\n\ntime_stamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\ttimeStamp\x12\x1b\n\tlog_level\x18\x04 \x01(\x05R\x08logLevel\x12]\n\nattributes\x18\x05 \x03(\x0b\x32=.xyz.block.ftl.v1.StreamDeploymentLogsRequest.AttributesEntryR\nattributes\x12\x18\n\x07message\x18\x06 \x01(\tR\x07message\x12\x19\n\x05\x65rror\x18\x07 \x01(\tH\x01R\x05\x65rror\x88\x01\x01\x1a=\n\x0f\x41ttributesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x0e\n\x0c_request_keyB\x08\n\x06_error\"\x1e\n\x1cStreamDeploymentLogsResponse\"\x0f\n\rStatusRequest\"\xfc\x06\n\x0eStatusResponse\x12M\n\x0b\x63ontrollers\x18\x01 \x03(\x0b\x32+.xyz.block.ftl.v1.StatusResponse.ControllerR\x0b\x63ontrollers\x12\x41\n\x07runners\x18\x02 \x03(\x0b\x32\'.xyz.block.ftl.v1.StatusResponse.RunnerR\x07runners\x12M\n\x0b\x64\x65ployments\x18\x03 \x03(\x0b\x32+.xyz.block.ftl.v1.StatusResponse.DeploymentR\x0b\x64\x65ployments\x12>\n\x06routes\x18\x05 \x03(\x0b\x32&.xyz.block.ftl.v1.StatusResponse.RouteR\x06routes\x1aT\n\nController\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x1a\x9b\x01\n\x06Runner\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12#\n\ndeployment\x18\x03 \x01(\tH\x00R\ndeployment\x88\x01\x01\x12/\n\x06labels\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labelsB\r\n\x0b_deployment\x1a\xf7\x01\n\nDeployment\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08language\x18\x02 \x01(\tR\x08language\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12!\n\x0cmin_replicas\x18\x04 \x01(\x05R\x0bminReplicas\x12\x1a\n\x08replicas\x18\x07 \x01(\x05R\x08replicas\x12/\n\x06labels\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\x12\x37\n\x06schema\x18\x06 \x01(\x0b\x32\x1f.xyz.block.ftl.v1.schema.ModuleR\x06schema\x1a[\n\x05Route\x12\x16\n\x06module\x18\x01 \x01(\tR\x06module\x12\x1e\n\ndeployment\x18\x02 \x01(\tR\ndeployment\x12\x1a\n\x08\x65ndpoint\x18\x03 \x01(\tR\x08\x65ndpoint\"\x14\n\x12ProcessListRequest\"\xaf\x03\n\x13ProcessListResponse\x12K\n\tprocesses\x18\x01 \x03(\x0b\x32-.xyz.block.ftl.v1.ProcessListResponse.ProcessR\tprocesses\x1an\n\rProcessRunner\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x1a\n\x08\x65ndpoint\x18\x02 \x01(\tR\x08\x65ndpoint\x12/\n\x06labels\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\x1a\xda\x01\n\x07Process\x12\x1e\n\ndeployment\x18\x01 \x01(\tR\ndeployment\x12!\n\x0cmin_replicas\x18\x02 \x01(\x05R\x0bminReplicas\x12/\n\x06labels\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x06labels\x12P\n\x06runner\x18\x04 \x01(\x0b\x32\x33.xyz.block.ftl.v1.ProcessListResponse.ProcessRunnerH\x00R\x06runner\x88\x01\x01\x42\t\n\x07_runner\"\\\n\x18ResetSubscriptionRequest\x12@\n\x0csubscription\x18\x01 \x01(\x0b\x32\x1c.xyz.block.ftl.v1.schema.RefR\x0csubscription\"\x1b\n\x19ResetSubscriptionResponse2\x9e\x0b\n\x11\x43ontrollerService\x12J\n\x04Ping\x12\x1d.xyz.block.ftl.v1.PingRequest\x1a\x1e.xyz.block.ftl.v1.PingResponse\"\x03\x90\x02\x01\x12Z\n\x0bProcessList\x12$.xyz.block.ftl.v1.ProcessListRequest\x1a%.xyz.block.ftl.v1.ProcessListResponse\x12K\n\x06Status\x12\x1f.xyz.block.ftl.v1.StatusRequest\x1a .xyz.block.ftl.v1.StatusResponse\x12i\n\x10GetCertification\x12).xyz.block.ftl.v1.GetCertificationRequest\x1a*.xyz.block.ftl.v1.GetCertificationResponse\x12i\n\x10GetArtefactDiffs\x12).xyz.block.ftl.v1.GetArtefactDiffsRequest\x1a*.xyz.block.ftl.v1.GetArtefactDiffsResponse\x12\x63\n\x0eUploadArtefact\x12\'.xyz.block.ftl.v1.UploadArtefactRequest\x1a(.xyz.block.ftl.v1.UploadArtefactResponse\x12i\n\x10\x43reateDeployment\x12).xyz.block.ftl.v1.CreateDeploymentRequest\x1a*.xyz.block.ftl.v1.CreateDeploymentResponse\x12`\n\rGetDeployment\x12&.xyz.block.ftl.v1.GetDeploymentRequest\x1a\'.xyz.block.ftl.v1.GetDeploymentResponse\x12}\n\x16GetDeploymentArtefacts\x12/.xyz.block.ftl.v1.GetDeploymentArtefactsRequest\x1a\x30.xyz.block.ftl.v1.GetDeploymentArtefactsResponse0\x01\x12\x65\n\x0eRegisterRunner\x12\'.xyz.block.ftl.v1.RegisterRunnerRequest\x1a(.xyz.block.ftl.v1.RegisterRunnerResponse(\x01\x12]\n\x0cUpdateDeploy\x12%.xyz.block.ftl.v1.UpdateDeployRequest\x1a&.xyz.block.ftl.v1.UpdateDeployResponse\x12`\n\rReplaceDeploy\x12&.xyz.block.ftl.v1.ReplaceDeployRequest\x1a\'.xyz.block.ftl.v1.ReplaceDeployResponse\x12w\n\x14StreamDeploymentLogs\x12-.xyz.block.ftl.v1.StreamDeploymentLogsRequest\x1a..xyz.block.ftl.v1.StreamDeploymentLogsResponse(\x01\x12l\n\x11ResetSubscription\x12*.xyz.block.ftl.v1.ResetSubscriptionRequest\x1a+.xyz.block.ftl.v1.ResetSubscriptionResponseBDP\x01Z@github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1;ftlv1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -91,29 +91,27 @@ _globals['_STATUSREQUEST']._serialized_start=2770 _globals['_STATUSREQUEST']._serialized_end=2785 _globals['_STATUSRESPONSE']._serialized_start=2788 - _globals['_STATUSRESPONSE']._serialized_end=3916 - _globals['_STATUSRESPONSE_CONTROLLER']._serialized_start=3181 - _globals['_STATUSRESPONSE_CONTROLLER']._serialized_end=3265 - _globals['_STATUSRESPONSE_RUNNER']._serialized_start=3268 - _globals['_STATUSRESPONSE_RUNNER']._serialized_end=3423 - _globals['_STATUSRESPONSE_DEPLOYMENT']._serialized_start=3426 - _globals['_STATUSRESPONSE_DEPLOYMENT']._serialized_end=3673 - _globals['_STATUSRESPONSE_INGRESSROUTE']._serialized_start=3676 - _globals['_STATUSRESPONSE_INGRESSROUTE']._serialized_end=3823 - _globals['_STATUSRESPONSE_ROUTE']._serialized_start=3825 - _globals['_STATUSRESPONSE_ROUTE']._serialized_end=3916 - _globals['_PROCESSLISTREQUEST']._serialized_start=3918 - _globals['_PROCESSLISTREQUEST']._serialized_end=3938 - _globals['_PROCESSLISTRESPONSE']._serialized_start=3941 - _globals['_PROCESSLISTRESPONSE']._serialized_end=4372 - _globals['_PROCESSLISTRESPONSE_PROCESSRUNNER']._serialized_start=4041 - _globals['_PROCESSLISTRESPONSE_PROCESSRUNNER']._serialized_end=4151 - _globals['_PROCESSLISTRESPONSE_PROCESS']._serialized_start=4154 - _globals['_PROCESSLISTRESPONSE_PROCESS']._serialized_end=4372 - _globals['_RESETSUBSCRIPTIONREQUEST']._serialized_start=4374 - _globals['_RESETSUBSCRIPTIONREQUEST']._serialized_end=4466 - _globals['_RESETSUBSCRIPTIONRESPONSE']._serialized_start=4468 - _globals['_RESETSUBSCRIPTIONRESPONSE']._serialized_end=4495 - _globals['_CONTROLLERSERVICE']._serialized_start=4498 - _globals['_CONTROLLERSERVICE']._serialized_end=5936 + _globals['_STATUSRESPONSE']._serialized_end=3680 + _globals['_STATUSRESPONSE_CONTROLLER']._serialized_start=3095 + _globals['_STATUSRESPONSE_CONTROLLER']._serialized_end=3179 + _globals['_STATUSRESPONSE_RUNNER']._serialized_start=3182 + _globals['_STATUSRESPONSE_RUNNER']._serialized_end=3337 + _globals['_STATUSRESPONSE_DEPLOYMENT']._serialized_start=3340 + _globals['_STATUSRESPONSE_DEPLOYMENT']._serialized_end=3587 + _globals['_STATUSRESPONSE_ROUTE']._serialized_start=3589 + _globals['_STATUSRESPONSE_ROUTE']._serialized_end=3680 + _globals['_PROCESSLISTREQUEST']._serialized_start=3682 + _globals['_PROCESSLISTREQUEST']._serialized_end=3702 + _globals['_PROCESSLISTRESPONSE']._serialized_start=3705 + _globals['_PROCESSLISTRESPONSE']._serialized_end=4136 + _globals['_PROCESSLISTRESPONSE_PROCESSRUNNER']._serialized_start=3805 + _globals['_PROCESSLISTRESPONSE_PROCESSRUNNER']._serialized_end=3915 + _globals['_PROCESSLISTRESPONSE_PROCESS']._serialized_start=3918 + _globals['_PROCESSLISTRESPONSE_PROCESS']._serialized_end=4136 + _globals['_RESETSUBSCRIPTIONREQUEST']._serialized_start=4138 + _globals['_RESETSUBSCRIPTIONREQUEST']._serialized_end=4230 + _globals['_RESETSUBSCRIPTIONRESPONSE']._serialized_start=4232 + _globals['_RESETSUBSCRIPTIONRESPONSE']._serialized_end=4259 + _globals['_CONTROLLERSERVICE']._serialized_start=4262 + _globals['_CONTROLLERSERVICE']._serialized_end=5700 # @@protoc_insertion_point(module_scope) diff --git a/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.pyi b/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.pyi index 0a385d4b7b..f1672c3efd 100644 --- a/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.pyi +++ b/python-runtime/ftl/src/ftl/protos/xyz/block/ftl/v1/controller_pb2.pyi @@ -197,7 +197,7 @@ class StatusRequest(_message.Message): def __init__(self) -> None: ... class StatusResponse(_message.Message): - __slots__ = ("controllers", "runners", "deployments", "ingress_routes", "routes") + __slots__ = ("controllers", "runners", "deployments", "routes") class Controller(_message.Message): __slots__ = ("key", "endpoint", "version") KEY_FIELD_NUMBER: _ClassVar[int] @@ -235,17 +235,6 @@ class StatusResponse(_message.Message): labels: _struct_pb2.Struct schema: _schema_pb2.Module def __init__(self, key: _Optional[str] = ..., language: _Optional[str] = ..., name: _Optional[str] = ..., min_replicas: _Optional[int] = ..., replicas: _Optional[int] = ..., labels: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., schema: _Optional[_Union[_schema_pb2.Module, _Mapping]] = ...) -> None: ... - class IngressRoute(_message.Message): - __slots__ = ("deployment_key", "verb", "method", "path") - DEPLOYMENT_KEY_FIELD_NUMBER: _ClassVar[int] - VERB_FIELD_NUMBER: _ClassVar[int] - METHOD_FIELD_NUMBER: _ClassVar[int] - PATH_FIELD_NUMBER: _ClassVar[int] - deployment_key: str - verb: _schema_pb2.Ref - method: str - path: str - def __init__(self, deployment_key: _Optional[str] = ..., verb: _Optional[_Union[_schema_pb2.Ref, _Mapping]] = ..., method: _Optional[str] = ..., path: _Optional[str] = ...) -> None: ... class Route(_message.Message): __slots__ = ("module", "deployment", "endpoint") MODULE_FIELD_NUMBER: _ClassVar[int] @@ -258,14 +247,12 @@ class StatusResponse(_message.Message): CONTROLLERS_FIELD_NUMBER: _ClassVar[int] RUNNERS_FIELD_NUMBER: _ClassVar[int] DEPLOYMENTS_FIELD_NUMBER: _ClassVar[int] - INGRESS_ROUTES_FIELD_NUMBER: _ClassVar[int] ROUTES_FIELD_NUMBER: _ClassVar[int] controllers: _containers.RepeatedCompositeFieldContainer[StatusResponse.Controller] runners: _containers.RepeatedCompositeFieldContainer[StatusResponse.Runner] deployments: _containers.RepeatedCompositeFieldContainer[StatusResponse.Deployment] - ingress_routes: _containers.RepeatedCompositeFieldContainer[StatusResponse.IngressRoute] routes: _containers.RepeatedCompositeFieldContainer[StatusResponse.Route] - def __init__(self, controllers: _Optional[_Iterable[_Union[StatusResponse.Controller, _Mapping]]] = ..., runners: _Optional[_Iterable[_Union[StatusResponse.Runner, _Mapping]]] = ..., deployments: _Optional[_Iterable[_Union[StatusResponse.Deployment, _Mapping]]] = ..., ingress_routes: _Optional[_Iterable[_Union[StatusResponse.IngressRoute, _Mapping]]] = ..., routes: _Optional[_Iterable[_Union[StatusResponse.Route, _Mapping]]] = ...) -> None: ... + def __init__(self, controllers: _Optional[_Iterable[_Union[StatusResponse.Controller, _Mapping]]] = ..., runners: _Optional[_Iterable[_Union[StatusResponse.Runner, _Mapping]]] = ..., deployments: _Optional[_Iterable[_Union[StatusResponse.Deployment, _Mapping]]] = ..., routes: _Optional[_Iterable[_Union[StatusResponse.Route, _Mapping]]] = ...) -> None: ... class ProcessListRequest(_message.Message): __slots__ = ()