syntax = "proto3"; package entity; option go_package = "github.com/grafana/grafana/pkg/services/store/entity"; import "pkg/infra/grn/grn.proto"; // The canonical entity/document data -- this represents the raw bytes and storage level metadata message Entity { // Globally unique ID set by the system. This can not be set explicitly string guid = 1; // The resourceVersion -- it will change whenever anythign on the object is saved string version = 2; // Entity identifier -- tenant_id, kind, uid grn.GRN GRN = 3; // group version of the entity string group_version = 23; // k8s key value string key = 22; // The folder UID string folder = 4; // Raw meta from k8s bytes meta = 5; // Raw bytes of the storage entity. The kind will determine what is a valid payload bytes body = 6; // k8s style status (ignored for now) bytes status = 7; // the friendly name of the entity string name = 8; // Content Length int64 size = 9; // MD5 digest of the body string ETag = 10; // Time in epoch milliseconds that the entity was created int64 created_at = 11; // Who created the entity string created_by = 12; // Time in epoch milliseconds that the entity was updated int64 updated_at = 13; // Who updated the entity string updated_by = 14; // External location info EntityOriginInfo origin = 15; // human-readable description of the entity string description = 16; // URL safe version of the name. It will be unique within the folder string slug = 17; // Commit message (optional) string message = 18; // Key value pairs. Tags are are represented as keys with empty values map labels = 19; // Optional field values. The schema will define and document possible values for a given kind map fields = 20; // When errors exist repeated EntityErrorInfo errors = 21; } // This stores additional metadata for items entities that were synced from external systmes message EntityOriginInfo { // identify the external source (plugin, git instance, etc) string source = 1; // Key in the upstream system (git hash, file path, etc) string key = 2; // Time in epoch milliseconds that the entity was last synced with an external system (provisioning/git) int64 time = 3; } // Report error while working with entitys // NOTE: real systems at scale will contain errors. message EntityErrorInfo { // Match an error code registry? int64 code = 1; // Simple error display string message = 2; // Details encoded in JSON bytes details_json = 3; } //----------------------------------------------- // Get request/response //----------------------------------------------- message ReadEntityRequest { // Entity identifier grn.GRN GRN = 1; string key = 7; // Fetch an explicit version (default is latest) string version = 2; // Include the full meta bytes bool with_meta = 3; // Include the full body bytes bool with_body = 4; // Include the status bytes (ignored for now) bool with_status = 5; // Include derived summary metadata bool with_summary = 6; } //------------------------------------------------------ // Make many read requests at once (by Kind+ID+version) //------------------------------------------------------ message BatchReadEntityRequest { repeated ReadEntityRequest batch = 1; } message BatchReadEntityResponse { repeated Entity results = 1; } //----------------------------------------------- // Write request/response //----------------------------------------------- message WriteEntityRequest { // Entity details Entity entity = 1; // Used for optimistic locking. If missing, the previous version will be replaced regardless string previous_version = 2; } // This operation is useful when syncing a resource from external sources // that have more accurate metadata information (git, or an archive). // This process can bypass the forced checks that message AdminWriteEntityRequest { // Entity details Entity entity = 1; // Used for optimistic locking. If missing, the previous version will be replaced regardless // This may not be used along with an explicit version in the request string previous_version = 2; // Request that all previous versions are removed from the history // This will make sense for systems that manage history explicitly externallay bool clear_history = 3; } message WriteEntityResponse { // Error info -- if exists, the save did not happen EntityErrorInfo error = 1; // Entity details Entity entity = 2; // Status code Status status = 3; // Status enumeration enum Status { ERROR = 0; CREATED = 1; UPDATED = 2; UNCHANGED = 3; } } //----------------------------------------------- // Create request/response //----------------------------------------------- message CreateEntityRequest { // Entity details Entity entity = 1; } message CreateEntityResponse { // Error info -- if exists, the save did not happen EntityErrorInfo error = 1; // Entity details Entity entity = 2; // Status code Status status = 3; // Status enumeration enum Status { ERROR = 0; CREATED = 1; } } //----------------------------------------------- // Update request/response //----------------------------------------------- message UpdateEntityRequest { // Entity details Entity entity = 1; // Used for optimistic locking. If missing, the previous version will be replaced regardless string previous_version = 2; } message UpdateEntityResponse { // Error info -- if exists, the save did not happen EntityErrorInfo error = 1; // Entity details Entity entity = 2; // Status code Status status = 3; // Status enumeration enum Status { ERROR = 0; UPDATED = 1; UNCHANGED = 2; } } //----------------------------------------------- // Delete request/response //----------------------------------------------- message DeleteEntityRequest { // Entity identifier grn.GRN GRN = 1; string key = 3; // Used for optimistic locking. If missing, the current version will be deleted regardless string previous_version = 2; } message DeleteEntityResponse { // Error info -- if exists, the delete did not happen EntityErrorInfo error = 1; // Entity details Entity entity = 2; // Status code Status status = 3; // Status enumeration enum Status { ERROR = 0; DELETED = 1; NOTFOUND = 2; } } //----------------------------------------------- // History request/response //----------------------------------------------- message EntityHistoryRequest { // Entity identifier grn.GRN GRN = 1; // Maximum number of items to return int64 limit = 3; // Starting from the requested page string next_page_token = 5; } message EntityHistoryResponse { // Entity identifier grn.GRN GRN = 1; // Entity metadata without the raw bytes repeated Entity versions = 2; // More results exist... pass this in the next request string next_page_token = 3; } //----------------------------------------------- // List request/response //----------------------------------------------- message EntityListRequest { // Starting from the requested page (other query parameters must match!) string next_page_token = 1; // Maximum number of items to return int64 limit = 2; // Free text query string -- mileage may vary :) string query = 3; // limit to a specific kind (empty is all) repeated string kind = 4; // limit to a specific key repeated string key = 11; // Limit results to items in a specific folder string folder = 5; // Must match all labels map labels = 6; // Sorting instructions `field ASC/DESC` repeated string sort = 7; // Return the full body in each payload bool with_body = 8; // Return the full body in each payload bool with_labels = 9; // Return the full body in each payload bool with_fields = 10; } message ReferenceRequest { // Starting from the requested page (other query parameters must match!) string next_page_token = 1; // Maximum number of items to return int64 limit = 2; // Free text query string -- mileage may vary :) string kind = 3; // Free text query string -- mileage may vary :) string uid = 4; } message EntityListResponse { repeated Entity results = 1; // More results exist... pass this in the next request string next_page_token = 2; } //----------------------------------------------- // Watch request/response //----------------------------------------------- message EntityWatchRequest { // Timestamp of last changes. Empty will default to int64 since = 1; // Watch sppecific entities repeated grn.GRN GRN = 2; // limit to a specific kind (empty is all) repeated string kind = 3; // Limit results to items in a specific folder string folder = 4; // Must match all labels map labels = 5; // Return the full body in each payload bool with_body = 6; // Return the full body in each payload bool with_labels = 7; // Return the full body in each payload bool with_fields = 8; } message EntityWatchResponse { // Timestamp the event was sent int64 timestamp = 1; // List of entities with the same action repeated Entity entity = 2; // Action code Action action = 3; // Status enumeration enum Action { UNKNOWN = 0; UPDATED = 1; DELETED = 2; } } message EntitySummary { string UID = 1; string kind = 2; string name = 3; string description = 4; // Key value pairs. Tags are are represented as keys with empty values map labels = 5; // Parent folder UID string folder = 6; // URL safe version of the name. It will be unique within the folder string slug = 7; // When errors exist EntityErrorInfo error = 8; // Optional field values. The schema will define and document possible values for a given kind map fields = 9; // eg: panels within dashboard repeated EntitySummary nested = 10; // Optional references to external things repeated EntityExternalReference references = 11; } message EntityExternalReference { // Category of dependency // eg: datasource, plugin, runtime string family = 1; // datasource > prometheus|influx|... // plugin > panel | datasource // runtime > transformer string type = 2; // datasource > UID // plugin > plugin identifier // runtime > name lookup string identifier = 3; } //----------------------------------------------- // Storage interface //----------------------------------------------- // The entity store provides a basic CRUD (+watch eventually) interface for generic entitys service EntityStore { rpc Read(ReadEntityRequest) returns (Entity); rpc BatchRead(BatchReadEntityRequest) returns (BatchReadEntityResponse); rpc Write(WriteEntityRequest) returns (WriteEntityResponse); rpc Create(CreateEntityRequest) returns (CreateEntityResponse); rpc Update(UpdateEntityRequest) returns (UpdateEntityResponse); rpc Delete(DeleteEntityRequest) returns (DeleteEntityResponse); rpc History(EntityHistoryRequest) returns (EntityHistoryResponse); rpc List(EntityListRequest) returns (EntityListResponse); rpc Watch(EntityWatchRequest) returns (stream EntityWatchResponse); // TEMPORARY... while we split this into a new service (see below) rpc AdminWrite(AdminWriteEntityRequest) returns (WriteEntityResponse); } // The admin service extends the basic entity store interface, but provides // more explicit control that can support bulk operations like efficient git sync service EntityStoreAdmin { rpc AdminWrite(AdminWriteEntityRequest) returns (WriteEntityResponse); }