// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 syntax = "proto3"; package hashicorp.vagrant; option go_package = "github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"; import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; import "google/rpc/status.proto"; import "google/protobuf/struct.proto"; import "protostructure.proto"; import "plugin.proto"; // The service that is implemented for the server backend. service Vagrant { // GetVersionInfo returns information about the server. This RPC call does // NOT require authentication. It can be used by clients to determine if they // are capable of talking to this server. rpc GetVersionInfo(google.protobuf.Empty) returns (GetVersionInfoResponse); rpc UpsertBasis(UpsertBasisRequest) returns (UpsertBasisResponse); rpc GetBasis(GetBasisRequest) returns (GetBasisResponse); rpc FindBasis(FindBasisRequest) returns (FindBasisResponse); rpc ListBasis(google.protobuf.Empty) returns (ListBasisResponse); // UpsertProject upserts the project. rpc UpsertProject(UpsertProjectRequest) returns (UpsertProjectResponse); // GetProject returns the project. rpc GetProject(GetProjectRequest) returns (GetProjectResponse); rpc FindProject(FindProjectRequest) returns (FindProjectResponse); // ListProjects returns a list of all the projects. There is no equivalent // ListApplications because applications are a part of projects and you // can use GetProject to get more information about the project. rpc ListProjects(google.protobuf.Empty) returns (ListProjectsResponse); // UpsertTarget upserts a target with a project. If the target // is already registered this does nothing. rpc UpsertTarget(UpsertTargetRequest) returns (UpsertTargetResponse); rpc DeleteTarget(DeleteTargetRequest) returns (google.protobuf.Empty); rpc GetTarget(GetTargetRequest) returns (GetTargetResponse); rpc FindTarget(FindTargetRequest) returns (FindTargetResponse); rpc ListTargets(google.protobuf.Empty) returns (ListTargetsResponse); // CRUD operations for box rpc UpsertBox(UpsertBoxRequest) returns (UpsertBoxResponse); rpc DeleteBox(DeleteBoxRequest) returns (google.protobuf.Empty); rpc GetBox(GetBoxRequest) returns (GetBoxResponse); rpc ListBoxes(google.protobuf.Empty) returns (ListBoxesResponse); rpc FindBox(FindBoxRequest) returns (FindBoxResponse); // GetLogStream reads the log stream for a deployment. This will immediately // send a single LogEntry with the lines we have so far. If there are no // available lines this will NOT block and instead will return an error. // The client can choose to retry or not. rpc GetLogStream(GetLogStreamRequest) returns (stream LogBatch); // QueueJob queues a job for execution by a runner. This will return as // soon as the job is queued, it will not wait for execution. rpc QueueJob(QueueJobRequest) returns (QueueJobResponse); // CancelJob cancels a job. If the job is still queued this is a quick // and easy operation. If the job is already completed, then this does // nothing. If the job is assigned or running, then this will signal // the runner about the cancellation but it may take time. // // This RPC always returns immediately. You must use GetJob or GetJobStream // to wait on the status of the cancellation. rpc CancelJob(CancelJobRequest) returns (google.protobuf.Empty); // GetJob queries a job by ID. rpc GetJob(GetJobRequest) returns (Job); // INTERNAL: ListJobs lists all the jobs the server has processed. This // is not yet ready for public use. rpc _ListJobs(ListJobsRequest) returns (ListJobsResponse); // ValidateJob checks if a job appears valid. This will check the job // structure itself (i.e. missing fields) and can also check to ensure // the job is assignable to a runner. rpc ValidateJob(ValidateJobRequest) returns (ValidateJobResponse); // GetJobStream opens a job event stream for a running job. This can be // used to listen for terminal output and other events of a running job. // Multiple listeners can open a job stream. rpc GetJobStream(GetJobStreamRequest) returns (stream GetJobStreamResponse); // Clean out old jobs from the job database rpc PruneOldJobs(google.protobuf.Empty) returns (google.protobuf.Empty); // GetRunner gets information about a single runner. rpc GetRunner(GetRunnerRequest) returns (Runner); // BootstrapToken returns the initial token for the server. This can only // be requested once on first startup. After initial request this will // always return a PermissionDenied error. rpc BootstrapToken(google.protobuf.Empty) returns (NewTokenResponse); // Generate a new invite token that users can exchange for a login token. rpc GenerateInviteToken(InviteTokenRequest) returns (NewTokenResponse); // Generate a new login token that users can use to login directly. rpc GenerateLoginToken(google.protobuf.Empty) returns (NewTokenResponse); // Exchange a invite token for a login token. rpc ConvertInviteToken(ConvertInviteTokenRequest) returns (NewTokenResponse); //---------------------------------------------------------------------- // Runner endpoints. These are expected to be called only by a runner. // These are not meant to be public endpoints. //---------------------------------------------------------------------- // RunnerConfig is called to register a runner and receive the configuration // for the runner. The response is a stream so that the configuration can // be updated later. rpc RunnerConfig(stream RunnerConfigRequest) returns (stream RunnerConfigResponse); // RunnerJobStream is called by a runner to request a single job for // execution and update the status of that job. rpc RunnerJobStream(stream RunnerJobStreamRequest) returns (stream RunnerJobStreamResponse); } /******************************************************************** * Server Info ********************************************************************/ message GetVersionInfoResponse { VersionInfo info = 1; } message VersionInfo { ProtocolVersion api = 1; ProtocolVersion entrypoint = 2; // Full version string (semver-syntax). This may be hidden/blank for // security purposes so clients should gracefully handle blank values. string version = 3; message ProtocolVersion { uint32 current = 1; uint32 minimum = 2; } } /******************************************************************** * Basic Data Model ********************************************************************/ message Vagrantfile { // The Vagrantfile can be provided in a number of formats enum Format { JSON = 0; HCL = 1; RUBY = 2; } // Unfinalized Vagrantfile configuration. This content is // still able to be used for file merges. sdk.Args.Hash unfinalized = 1; // Finalized Vagrantfile configuration. This is the final // configuration which is not suitable for future merges. sdk.Args.Hash finalized = 2; // Raw contents of the file (not used for Ruby based Vagrantfile) bytes raw = 3; // Format of this Vagrantfile Format format = 4; // Original path of the Vagrantfile sdk.Args.Path path = 5; } // This is considered the core configuration and information for the // run. This correlates to a VAGRANT_HOME and contains information // around projects which utilize this basis as well as the configuration // for the basis message Basis { // Unique resource identifier (internal use) string resource_id = 1; // Name for this basis string name = 2; // Path to this basis string path = 3; // Projects within this basis repeated sdk.Ref.Project projects = 4; // Custom metadata sdk.Args.MetadataSet metadata = 5; // Serialized configuration of the basis (Vagrantfile) Vagrantfile configuration = 6; // TODO(spox): look back over these options and see if we // still care about them (i'm thinking no) // If true, then the `-remote` flag or the `vagrant build project/app` // syntax can be used with a remote runner. If this is false, then // this is not allowed. This is typically configured using the // `runner {}` block in the vagrant config. bool remote_enabled = 100; // Where data is sourced for remote operations. If this isn't set, then // there is no default data source and it will be an error if a job is // queued for this project without a data source set. This is usually // set using the `runner {}` block in the vagrant config. Job.DataSource data_source = 101; } message Project { // Unique resource identifier string resource_id = 1; // Name of this project string name = 2; // Path where this project lives string path = 3; // Targets associated with this project repeated sdk.Ref.Target targets = 4; // The basis which this project is within sdk.Ref.Basis basis = 5; // Custom metadata sdk.Args.MetadataSet metadata = 6; // Serialized configuration of the project (Vagrantfile) Vagrantfile configuration = 7; // TODO(spox): look back over these options and see if we // still care about them (i'm thinking no) // If true, then the `-remote` flag or the `vagrant build project/app` // syntax can be used with a remote runner. If this is false, then // this is not allowed. This is typically configured using the // `runner {}` block in the vagrant config. bool remote_enabled = 100; // Where data is sourced for remote operations. If this isn't set, then // there is no default data source and it will be an error if a job is // queued for this project without a data source set. This is usually // set using the `runner {}` block in the vagrant config. Job.DataSource data_source = 101; } message Box { // ID of the box string resource_id = 1; // This is the provider that this box is built for. string provider = 2; // The version of this box. string version = 3; // This is the directory on disk where this box exists. string directory = 4; // This is the metadata for the box. This is read from the "metadata.json" // file that all boxes require. google.protobuf.Struct metadata = 5; // This is the URL to the version info and other metadata for this // box. string metadata_url = 6; // The box name. This is the logical name used when adding the box. string name = 7; // Tracks the last automatic update for the box google.protobuf.Timestamp last_update = 8; } message Target { // Unique resource identifier string resource_id = 1; // Data directory for target specific files sdk.Args.DataDir.Target datadir = 2; // Name of the target string name = 3; // Project the target is associated sdk.Ref.Project project = 4; // State of the target Operation.PhysicalState state = 5; // Targets contained within this target repeated sdk.Ref.Target subtargets = 6; // Parent if this target is a subtarget sdk.Ref.Target parent = 7; // Public unique identifier for target string uuid = 8; // Custom metadata sdk.Args.MetadataSet metadata = 9; // Serialized configuration of the target (Vagrantfile) sdk.Args.ConfigData configuration = 10; // Specialized target information (from provider) google.protobuf.Any record = 11; // Provider name backing target string provider = 12; // Specialized target (machine) message Machine { // ID of machine as assigned by provider string id = 1; // Box information for guest Box box = 7; // User ID of machine creator string uid = 9; // State of the machine (Vagrant representation) sdk.Args.Target.Machine.State state = 10; } } /******************************************************************** * Shared Messages ********************************************************************/ // Ref contains shared messages used for references to other resources. // // Refs should be used when the full type shouldn't be embedded in the message. message Ref { // Component references a component. message Component { hashicorp.vagrant.Component.Type type = 1; string name = 2; } // Operation references an operation (build, deploy, etc.). This can reference // an operation in multiple ways so you must use the oneof to choose. message Operation { oneof target { string id = 1; TargetOperationSeq target_sequence = 2; ProjectOperationSeq project_sequence = 3; BasisOperationSeq basis_sequence = 4; } } // TargetOperationSeq references an operation by sequence number anchored // to a Target message TargetOperationSeq { sdk.Ref.Target target = 1; uint64 number = 2; } // MachineOperationSeq references an operation by sequence number anchored // to a Project message ProjectOperationSeq { sdk.Ref.Project project = 1; uint64 number = 2; } // BasisOperationSeq references an operation by sequence number anchored // to a Basis message BasisOperationSeq { sdk.Ref.Basis basis = 1; uint64 number = 2; } // Runner references a runner process which executes operations. This // can reference a runner by any of the more specific types, such as // by ID. If you want to constrain which runners can be targeted, // a different ref type should be used. message Runner { oneof target { RunnerAny any = 1; RunnerId id = 2; } } // RunenrId references a runner by ID. message RunnerId { string id = 1; } // RunnerAny will reference any runner. message RunnerAny {} // Vagrantfile references a Vagrantfile message Vagrantfile { string resource_id = 1; } } // Component represents metadata about a component. A component is the // generic name for a plugin type message Component { // type of the component Type type = 1; // name of the component string name = 2; string server_addr = 3; // Supported component types, the values here MUST match the enum values // in the Go sdk/component package exactly. A test in internal/server // validates this. enum Type { UNKNOWN = 0; COMMAND = 1; COMMUNICATOR = 2; GUEST = 3; HOST = 4; PROVIDER = 5; PROVISIONER = 6; SYNCEDFOLDER = 7; AUTHENTICATOR = 8; LOGPLATFORM = 9; LOGVIEWER = 10; MAPPER = 11; CONFIG = 12; PLUGININFO = 13; PUSH = 14; DOWNLOADER = 15; } } // Status represents the status of an async operation. message Status { // state is the state of this operation. State state = 1; // details may be non-empty to provide human-friendly information // about the current status. This may change between status updates // for the same state to provide updated details about the state. string details = 2; // error is set if the state == ERROR with the error that occurred. google.rpc.Status error = 3; // start_time is the time the operation was started. google.protobuf.Timestamp start_time = 4; // complete_time is the time the operation completed (success or fail). google.protobuf.Timestamp complete_time = 5; enum State { UNKNOWN = 0; RUNNING = 1; SUCCESS = 2; ERROR = 3; } } message StatusFilter { // Filters are ANDed together. repeated Filter filters = 1; message Filter { oneof filter { // state will match any status that has the given state. Status.State state = 2; } } } // Operation is a shared message type used to describe "operations" which are // executions of a build, deploy, etc. This just contains shared message types // used for fields. Each individual operation has their own message type // such as Deployment. message Operation { // PhysicalState is the state of any physical resources associated with // an operation. A physical resource for example is the actual container // that might be created alongside an operation. enum PhysicalState { UNKNOWN = 0; PENDING = 1; CREATED = 2; DESTROYED = 3; HALTED = 4; NOT_CREATED = 5; }; } // OperationOrder is a shared message type used for controlling the order // of results in queries for app operations such as build, deploys, etc. message OperationOrder { // Order for the results. Order order = 2; bool desc = 3; // Limit the number of results uint32 limit = 4; enum Order { UNSET = 0; START_TIME = 1; COMPLETE_TIME = 2; } } /******************************************************************** * Queueing ********************************************************************/ message QueueJobRequest { // The job to queue. See the Job message documentation for more details // on what to set. Job job = 1; // Set an expiration duration. If the job is not assigned and acked // in the given duration then the job will be automatically cancelled. string expires_in = 2; } message QueueJobResponse { // the job ID that was queued. This can be used with other RPC methods // to check on the status, cancel, etc. string job_id = 1; } message CancelJobRequest { // The job to cancel string job_id = 1; } message ValidateJobRequest { // The job to validate. Job job = 1; // If true, will NOT validate that the job is assignable. bool disable_assign = 2; } message ValidateJobResponse { // valid will be true if the job structure is valid. If it is invalid // validation_error will be set with a reason. bool valid = 1; google.rpc.Status validation_error = 2; // assignable will be true if the job is assignable at this point-in-time. // Assignable means that there are runners registered with the server that // claim to be able to service this job. Note that this is a point-in-time // result so it doesn't guarantee that a job will be serviced when queued. // Additionally, assignability doesn't imply anything about queue length, // so the job may still be queued for some time. // // This will always be false if "valid" is false since we don't check // assignability of invalid jobs. bool assignable = 3; } // A Job is a job that executes on a runner and is queued by QueueOperation. message Job { reserved 58 to 79; // future operation range // id of the job. This is generated on the server side when queued. If // you are queueing a job, this must be empty or unset. string id = 1; // The application to target for the operation. Some operations may allow // certain fields of this to be empty, so check with the operation // documentation to determine what needs to be set. Generally, project // must be set. oneof scope { sdk.Ref.Basis basis = 2; sdk.Ref.Project project = 3; sdk.Ref.Target target = 4; } // The runner that should execute this job. This is required. Ref.Runner target_runner = 5; // Labels are the labels to set for this operation. map labels = 6; // data_source determines where the data to operate on (such as the // application source code and Vagrant configuration) comes from. // If this is not set then QueueJob will populate this if a default // data source is configured for the target project. // // The overrides will set overrides of configs for the data source. This is // data source dependent but this allows for example setting the Git ref // without knowing the full data source. Invalid overrides will fail the // job. DataSource data_source = 7; map data_source_overrides = 8; // The operation to execute. See the message docs for details on the operation. oneof operation { Noop noop = 50; AuthOp auth = 51; DocsOp docs = 52; ValidateOp validate = 53; CommandOp command = 54; InitOp init = 55; InitBasisOp init_basis = 56; InitProjectOp init_project = 57; } //----------------------------------------------------------------- // Server-side fields - the fields below are all set by the server // and should not be set on the queueing request. //----------------------------------------------------------------- // state of the job State state = 100; // The runner that was assigned to execute this job. Note that the // runner may have been ephemeral and may no longer exist. Ref.RunnerId assigned_runner = 101; // The time when the job was queued. google.protobuf.Timestamp queue_time = 102; google.protobuf.Timestamp assign_time = 103; google.protobuf.Timestamp ack_time = 104; google.protobuf.Timestamp complete_time = 105; // error is set if state == ERROR google.rpc.Status error = 106; // result is set based on the operation specified. A nil result is possible // for some operations. Result result = 107; // cancel time is the time that cancellation of this job was requested. // If this is zero then this job was not cancelled. Note that this is the // cancellation _request_ time. The actual time a job ended is noted by // the complete_time field. google.protobuf.Timestamp cancel_time = 108; // expire time is the time when this job would expire. If this isn't set // then this is a non-expiring job. This will remain set even if the job // never expired because it was accepted and run. This field can be used // to detect that it was configured to expire. google.protobuf.Timestamp expire_time = 109; enum State { UNKNOWN = 0; QUEUED = 1; // queued and waiting for assignment WAITING = 2; // assigned to a runner, waiting for runner to ack RUNNING = 3; // runner acked and is executing ERROR = 4; // job failed SUCCESS = 5; // job succeeded } message Result { AuthResult auth = 1; DocsResult docs = 2; ValidateResult validate = 3; InitResult init = 4; CommandResult run = 5; InitBasisResult basis = 6; InitProjectResult project = 7; } message DataSource { oneof source { // local means the runner has access to the data locally and will // know what to do. This is primarily only useful if the target_runner // is a specific runner and should not be used by any runner unless your // runners are configured to have access to the proper data. Local local = 1; // git will check out the data from a Git repository. Git git = 2; } } message Local {} message Git { // url of the repository to clone. Local paths are not allowed. string url = 1; // a ref to checkout. If this isn't specified, then the default // ref that is cloned from the URL above will be used. string ref = 2; // path is a subdirectory within the checked out repository to // go into for the configuration. This must be a relative path // and may not contain ".." string path = 3; } // Noop operations do nothing. This is primarily used for testing. // This operation will still download the data from the data source. // A noop may be useful outside of testing to verify a runner is // executing properly or can access data properly. message Noop {} // ValidateOp validates various aspects of a configuration. message ValidateOp {} message ValidateResult {} // InitOp initializes a Vagrant configuration and returns information // about the runtime. message InitOp { } message InitResult { repeated Action actions = 1; repeated sdk.Command.CommandInfo commands = 2; repeated Hook hooks = 3; } message InitBasisOp { } message InitBasisResult { sdk.Ref.Basis basis = 1; } message InitProjectOp { } message InitProjectResult { sdk.Ref.Project project = 1; } message Action { string name = 1; string source = 2; } message Hook { string target_action_name = 1; Location location = 2; string action_name = 3; string source = 4; enum Location { BEFORE = 0; AFTER = 1; } } // CommandOp runs a command message CommandOp { // The scope this command was run within oneof scope { sdk.Ref.Target target = 1; sdk.Ref.Project project = 2; sdk.Ref.Basis basis = 3; } // Name of the command executed string command = 4; // id is the unique ID for this task string id = 5; // Status is the current status of the task Status status = 6; // State of any resources related to the task Operation.PhysicalState state = 7; // Component responsible for this task Component component = 8; // Any labels which were set for this task map labels = 9; // ID of the job that created this task string job_id = 10; // Map of cli arguments sdk.Command.Arguments cli_args = 11; Vagrantfile vagrantfile = 12; } message CommandResult { // Operation which was run Operation task = 1; // True if the task did not encounter any errors bool run_result = 2; // Provides any error information google.rpc.Status run_error = 3; // Exit code if applicable sint32 exit_code = 4; } // AuthOp is the configuration to authenticate any plugins. message AuthOp { // if true, auth will only be checked but not attempted. Currently // this must ALWAYS be true. Only authentication checking is supported. bool check_only = 1; // if set, only the component matching this reference will be authed. // If this component doesn't exist, an error will be returned. If this is // unset, all components wll be authed. Ref.Component component = 2; } message AuthResult { // results are the list of components that were checked repeated Result results = 1; message Result { // component that was checked Component component = 1; // result of the auth check. If the component didn't implement the // auth interface this will be set to true. You can check for interface // implementation using auth_supported. If auth is attempted, the auth // operation will recheck the status and this value will reflect the // check post-auth attempt. You can use this to verify if the auth // succeeded. bool check_result = 2; google.rpc.Status check_error = 3; // this is true if the component was authenticated using the Auth // callback. If false, then no attempt was made to authenticate. This // can be on purpose for example if "check_only" is set to true on // the op. bool auth_completed = 4; google.rpc.Status auth_error = 5; // auth supported is true if this component implemented the auth // interface. bool auth_supported = 6; } } message DocsOp { } message DocsResult { // results are the list of components that were checked repeated Result results = 1; message Result { // component that the docs are for Component component = 1; Documentation docs = 2; } } } message Documentation { string description = 1; string example = 2; string input = 3; string output = 4; map fields = 5; repeated Mapper mappers = 6; message Field { string name = 1; string synopsis = 2; string summary = 3; bool optional = 4; string env_var = 5; string type = 6; string default = 7; } message Mapper { string input = 1; string output = 2; string description = 3; } } message GetJobRequest { // ID of the job to request. string job_id = 1; } message ListJobsRequest {} message ListJobsResponse { repeated Job jobs = 1; } message GetJobStreamRequest { string job_id = 1; // Future: can add a timestamp here so that only output from after the // given timestamp is sent down. } message GetJobStreamResponse { oneof event { // Open is sent as confirmation that the job stream successfully opened. // This will be sent immediately by the server if the job ID is valid. // This is useful since other events such as terminal output may not // happen for a long time while the job is executing, queued, etc. // // This is ALWAYS sent. If the job is already completed, this will be // sent first followed immediately by a Complete. Open open = 1; // state is sent when there is a job state change event. State state = 2; // terminal output. On initial connection, the server may send buffered // historical terminal data so there isn't a race between queueing a job // and getting its first byte output. You can determine this based on the // flag on Terminal. Terminal terminal = 3; // an error regarding the stream itself, rather than the executing job. // For example, if you request a job stream for an invalid job ID, // this will be sent back. If this is sent, no further messages will // be sent and the stream is terminated. // // For errors in job execution, see "complete". Error error = 4; // job completion, no more events will follow this one. This can be // both success or failure, the event must be checked. Any errors // in complete are errors from the job execution itself. Complete complete = 5; } message Open {} message State { // previous and current are the previous and current states, respectively. Job.State previous = 1; Job.State current = 2; // The full updated job is also sent because additional fields may be // set depending on the state (such as the assigned runner, assignment // times, etc.) Job job = 3; // canceling is true if the job was requested to be canceled. bool canceling = 4; } message Terminal { repeated Event events = 1; // buffered if true signifies that the data being sent is from the // server buffer and is historical vs real-time since the stream was // opened. If this is true, all lines are buffered. We will never mix // buffered and non-buffered lines. bool buffered = 2; message Event { // timestamp of the event as seen by the runner. This might be // skewed from the server or the client but relative to all other // line output, it will be accurate. google.protobuf.Timestamp timestamp = 1; oneof event { Line line = 2; Status status = 3; NamedValues named_values = 4; Raw raw = 5; Table table = 6; StepGroup step_group = 7; Step step = 8; } message Status { string status = 1; string msg = 2; bool step = 3; } message Line { string msg = 1; string style = 2; bool disable_new_line = 3; string color = 4; } message Raw { bytes data = 1; bool stderr = 2; } message NamedValue { string name = 1; string value = 2; } message NamedValues { repeated NamedValue values = 1; } message TableEntry { string value = 1; string color = 2; } message TableRow { repeated TableEntry entries = 1; } message Table { repeated string headers = 1; repeated TableRow rows = 2; } message StepGroup { bool close = 1; } message Step { int32 id = 1; bool close = 2; string msg = 3; string status = 4; bytes output = 5; } } } message Error { google.rpc.Status error = 1; } message Complete { // error, if set, is an error that occurred as part of the job execution // and resulted in job termination. This is different than the "error" // event which is an error in the stream itself. google.rpc.Status error = 1; // Result will be set to the final result of the job execution, if any. Job.Result result = 2; } } /******************************************************************** * Runner ********************************************************************/ message Runner { // id is a unique ID generated by the runner. This should be a UUID or some // other guaranteed unique mechanism. This is not an auth mechanism, just // a way to associate an ID to a runner. string id = 1; // The runner will only be assigned jobs that directly target this // runner by ID. This is used by local runners to prevent external // jobs from being assigned to them. bool by_id_only = 2; // Components are the list of components that the runner supports. This // is used to match jobs to this runner. repeated Component components = 3; } message RunnerConfigRequest { oneof event { Open open = 1; } message Open { // Runner to register. See Runner for what fields can be set. Runner runner = 1; } } message RunnerConfigResponse { // config is any updated configuration for the runner. RunnerConfig config = 2; } message RunnerConfig { // The configuration for the runner. Any locally set runner config will // take priority in a conflict. This allows operators to setup runners // with specific configuration without fear that the server will override // them. repeated ConfigVar config_vars = 1; } message RunnerJobStreamRequest { oneof event { // request MUST BE the first message sent by a client. This is used to // signify that a runner is ready to accept a job. This is only ever // sent once. Once a job is complete, the client must terminate the // stream and open a new connection. Request request = 1; // ack is sent to accept a job assignment from the server. This // should be sent soon after the job is assigned to avoid the job being // reassigned and duplicated. Ack ack = 2; // complete is sent on job completion. This is only sent if there // were no errors, so this signals a successful completion. An erroneous // completion is signaled by sending an Error event. Complete complete = 3; // error is sent when there was an error with job execution (after // accept was sent). This signals that the job failed and it cannot // be retried. This terminates the job and no other events should be // sent. Error error = 4; // terminal output from the job. GetJobStreamResponse.Terminal terminal = 5; // heartbeat that the job is still running. Heartbeat heartbeat = 6; } message Request { string runner_id = 1; } message Ack {} message Complete { Job.Result result = 1; } message Error { google.rpc.Status error = 1; } message Heartbeat {} } message RunnerJobStreamResponse { oneof event { // assignment is when a job is assigned to this job stream. This // will happen ONLY in response to a "Request" message from the client. JobAssignment assignment = 1; // cancel is sent when a cancel request is made. JobCancel cancel = 2; } message JobAssignment { Job job = 1; } message JobCancel { bool force = 1; } } message GetRunnerRequest { // ID of the runner to request. string runner_id = 1; } /******************************************************************** * Projects & Machines ********************************************************************/ message UpsertBasisRequest { // Basis to upsert. See the message for what fields to set. Basis basis = 1; } message UpsertBasisResponse { Basis basis = 1; } message GetBasisRequest { sdk.Ref.Basis basis = 1; } message GetBasisResponse { Basis basis = 1; } message FindBasisRequest { Basis basis = 1; } message FindBasisResponse { Basis basis = 2; } message ListBasisResponse { repeated sdk.Ref.Basis basis = 1; } message UpsertProjectRequest { // Project to upsert. See the message for what fields to set. Project project = 1; } message UpsertProjectResponse { Project project = 1; } message GetProjectRequest { sdk.Ref.Project project = 1; } message GetProjectResponse { Project project = 1; } message FindProjectRequest { Project project = 1; } message FindProjectResponse { Project project = 2; } message ListProjectsResponse { repeated sdk.Ref.Project projects = 1; } message UpsertTargetRequest { // project to register the app against sdk.Ref.Project project = 1; Target target = 2; } message UpsertTargetResponse { Target target = 1; } message DeleteTargetRequest { sdk.Ref.Project project = 1; sdk.Ref.Target target = 2; } message GetTargetRequest { sdk.Ref.Project project = 1; sdk.Ref.Target target = 2; } message GetTargetResponse { Target target = 1; } message FindTargetRequest { Target target = 1; } message FindTargetResponse { Target target = 2; } message ListTargetsResponse { repeated sdk.Ref.Target targets = 1; } message UpsertBoxRequest { Box box = 1; } message UpsertBoxResponse { Box box = 1; } message DeleteBoxRequest { sdk.Ref.Box box = 1; } message GetBoxRequest { sdk.Ref.Box box = 2; } message GetBoxResponse { Box box = 1; } message ListBoxesResponse { repeated sdk.Ref.Box boxes = 1; } message FindBoxRequest { sdk.Ref.Box box = 2; } message FindBoxResponse { Box box = 1; } /******************************************************************** * Logs ********************************************************************/ message GetLogStreamRequest { oneof scope { sdk.Ref.Basis basis = 1; sdk.Ref.Project project = 2; sdk.Ref.Target target = 3; } // limit_backlog sets the maximum backlog lines to return on the initial // connection. This setting is per instance, not global. The maximum // backlog to expect is `n * limit_backlog` where n is the number of // instances. // // A negative value will not limit the backlog. // // A value of zero will default to a value of 50. int32 limit_backlog = 4; } message LogBatch { string deployment_id = 1; string instance_id = 2; repeated Entry lines = 3; message Entry { google.protobuf.Timestamp timestamp = 1; string line = 2; } } /******************************************************************** * Config ********************************************************************/ message ConfigVar { string name = 1; string value = 2; // scope is the scoping for this config variable. oneof scope { sdk.Ref.Basis basis = 3; sdk.Ref.Project project = 4; sdk.Ref.Target target = 5; // This specifies that the configuration variable is for runners only. // You can use more complex runner targeting via this ref. Ref.Runner runner = 6; } } message ConfigSetRequest { repeated ConfigVar variables = 1; } message ConfigSetResponse {} message ConfigGetRequest { // scope is the scoping for this config variable. oneof scope { sdk.Ref.Target target = 2; sdk.Ref.Project project = 3; sdk.Ref.Basis basis = 4; Ref.RunnerId runner = 5; } // Get all configuration entries under the given prefix. When empty, // returns all config variables. string prefix = 1; } message ConfigGetResponse { repeated ConfigVar variables = 1; } /******************************************************************** * Exec ********************************************************************/ message ExecStreamRequest { oneof event { Start start = 1; Input input = 2; WindowSize winch = 3; } message Start { // Deployment to exec into string deployment_id = 1; // Args including the command at args[0] to execute. repeated string args = 2; // Pty is set if we should allocate a PTY for this exec stream. PTY pty = 3; } message Input { bytes data = 1; } message PTY { bool enable = 1; // term is the TERM value to request on the remote side. This should be set. string term = 2; // window_size is the initial window size WindowSize window_size = 3; } message WindowSize { int32 rows = 1; int32 cols = 2; int32 width = 3; int32 height = 4; } } message ExecStreamResponse { oneof event { // Open is always sent first no matter what (unless there is an error // in which case the stream will exit). This should be used to validate // that the exec process started properly. Open open = 3; Output output = 1; Exit exit = 2; } message Open {} message Exit { int32 code = 1; } message Output { Channel channel = 1; bytes data = 2; enum Channel { UNKNOWN = 0; STDOUT = 1; STDERR = 2; } } } /******************************************************************** * Entrypoint ********************************************************************/ message EntrypointConfigRequest { // id of the deployment that this instance is a part of string deployment_id = 1; // instance_id is a unique ID generated by the running entrypoint. This is // not an auth mechanism, just a way to associate data with the correct instance. string instance_id = 2; } message EntrypointConfigResponse { EntrypointConfig config = 2; } message EntrypointConfig { // Exec are requested exec sessions for this instance. repeated Exec exec = 1; repeated ConfigVar env_vars = 2; // The URL service configuration. This might be nil. If this is nil, // then the URL service is disabled. URLService url_service = 3; message Exec { int64 index = 1; repeated string args = 2; ExecStreamRequest.PTY pty = 3; } message URLService { // address to the control server and the token for auth string control_addr = 1; string token = 2; // labels to register this instance under string labels = 3; } } // A batch of data for log streaming from the entrypoint. message EntrypointLogBatch { // instance_id is a unique ID generated by the running entrypoint. This is // not an auth mechanism, just a way to associate data with the correct instance. string instance_id = 1; // lines is the set of lines repeated LogBatch.Entry lines = 2; } message EntrypointExecRequest { oneof event { // open MUST BE the first message sent by a client. This will be used // by the server side to perform some initialization. If the first message // is not open the server will close the connection. Open open = 1; // exit should be sent as a final message type after the command exits. Exit exit = 2; // output contains stdout/stderr Output output = 3; // error indicates an error occurred. This will terminate the stream. Error error = 4; } message Open { string instance_id = 1; int64 index = 2; } message Exit { int32 code = 1; } message Output { Channel channel = 1; bytes data = 2; enum Channel { UNKNOWN = 0; STDOUT = 1; STDERR = 2; } } message Error { google.rpc.Status error = 1; } } message EntrypointExecResponse { oneof event { // input is raw stdin input from the client bytes input = 1; // winch is SIGWNCH information for window sizing ExecStreamRequest.WindowSize winch = 2; // opened is sent when the entrypoint session is successfully opened. // The value of this message is meaningless. The existence of the message // itself is a signal that the stream was opened properly. bool opened = 3; } } /******************************************************************** * Token ********************************************************************/ // The outer structure of the token that is directly Marshaled and // ASCII armored. message TokenTransport { // A Marshaled token, stored as bytes because we need to to validate // it with the given signature. bytes body = 1; // The signature of body for validation. bytes signature = 2; // The key used to generate the signature. string key_id = 3; // Any configuration style metadata that can be passed along with the token // without invalidating the token body itself. map metadata = 4; } // The authenticated Token information. This is used to authenticate requests. message Token { // The user that the token is fore. string user = 1; // A random id for the token. Also functions as a nonce when signing. bytes token_id = 2; // When the token is valid until. After the given date, the token will be rejected. // When this is not set, the token is valid forever. google.protobuf.Timestamp valid_until = 3; // Indicates whether or not this token can be used for to authenticate RPCs. bool login = 4; // Inidicates whether or not this token can be used as an invite. bool invite = 5; // Entrypoint if set indicates that this token is for entrypoint binary // usage only and specific restrictions are specified in this message. Entrypoint entrypoint = 6; message Entrypoint { // deployment id is the deployment to restrict this token to. string deployment_id = 1; } } // Represents a key used to sign tokens using HMAC message HMACKey { // The identifier of the key. string id = 1; // A randomly generated key used to sign tokens with bytes key = 2; } // Passed with GenerateInviteToken with the params on how the invite token should // be generate. message InviteTokenRequest { // How long the token should be valid until. The resulting token has a timestamp // encoded within it by adding the current time to this duration. string duration = 1; // If set, the token generated by this invite code is for the given entrypoint. Token.Entrypoint entrypoint = 2; } // Returned by any action that creates a token. message NewTokenResponse { // The new token which can be presented to whichever API expects it. string token = 1; } // Passed to ConvertInviteToken to create a new token that can be used to authenticate RPCs. message ConvertInviteTokenRequest { // A token previous returned by GenerateInviteToken. string token = 1; } /******************************************************************** * Snapshot/Restore ********************************************************************/ message CreateSnapshotResponse { oneof event { // Open is sent as the opening message with information about the // snapshot. This is always sent first (before any data). Open open = 1; // Chunk is a next chunk of data. You should continue to expect // data until an EOF is received on the stream. bytes chunk = 2; } // One day we may add information here. For now we are reserving this. message Open {} } message RestoreSnapshotRequest { oneof event { // Open MUST be sent as the first message and sent exactly once. // This sets the settings for the restore. Open open = 1; // Chunk is a chunk of restore data. The restore snapshot API will // continue reading data until an EOF is received (the write end is // closed). bytes chunk = 2; } message Open { // If true, the server will exit after the restore is staged. This will // SHUT DOWN the server and some external process you created is expected // to bring it back. The Vagrant server on its own WILL NOT automatically // restart. You should only set this if you have some operation to // automate restart such as running in Nomad or Kubernetes. bool exit = 1; } } // Snapshot is the encoding of the snapshot for all snapshot APIs. // The encoding is proto.Message delimited data. This is also the encoding // expected if the vagrant-restore.db file is copied manually from the // snapshot data. // // For snapshots, the Header message is always guaranteed first. After that, // it is NOT guaranteed that only data chunks are sent. It is only guaranteed // that the data chunks are over at EOF. Unknown messages can probably be // ignored. // // It is HIGHLY RECOMMENDED you do not modify snapshots, but these messages // are publicly exported so that you can try to inspect snapshots. message Snapshot { // Header is _always_ the first message encoded into a snapshot. If // this isn't present, the entire snapshot can be considered corrupt. message Header { // version is the version of Vagrant that generated this snapshot. VersionInfo version = 1; // format is the format of the remaining messages. This can be used // to determine what messages to expect following the header. Format format = 2; enum Format { UNKNOWN = 0; BOLT = 1; // Expect a series of BoltChunk messages } } // Trailer is sent as the final message encoded into a snapshot. Detecting // when the trailer is is dependent on the format. message Trailer { // checksum is the checksum of all the bytes up to but not including // this proto message. The checksum is for the raw uncompressed bytes. oneof checksum { string sha256 = 1; // SHA-256 checksum } } // BoltChunk is a single chunk of data for BoltDB if the snapshot format // is BOLT. A chunk will always contain items designated for a single bucket, // but a bucket may be repeated multiple time across chunks if there are // too many items in the bucket. // // The final BoltChunk will have trailer set to true. Immediaetly following // that chunk will be the Trailer message. message BoltChunk { // bucket is the name of the bucket. This may be empty. If this is empty, // then this chunk should be ignored. string bucket = 1; // items is a id/value mapping of all this chunk of items in this bucket map items = 2; // final is true if this is the last bolt chunk being written. bool final = 3; } }