-
Notifications
You must be signed in to change notification settings - Fork 551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define the Galley API #122
Changes from all commits
2edf887
002bf31
92df06f
9767050
e78028a
73527c0
aaca5ee
7297a29
34927ca
16f13e8
fdd5db3
6853e76
112c7cd
e69e266
69c7618
4d671ad
308f87b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
// Copyright 2017 Istio Authors | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
syntax = "proto3"; | ||
|
||
package istio.galley.v1; | ||
|
||
import "google/api/annotations.proto"; | ||
import "google/protobuf/struct.proto"; | ||
import "google/rpc/status.proto"; | ||
|
||
// Galley follows | ||
// the Kubenertes API server delegation and resource model. | ||
// /apiGroup/version/objecttype/{namespace}/objectname | ||
// | ||
// It generalizes the concept of namespace to an arbitrary grouping. | ||
// | ||
// /apiGroup/objecttype/version/{objectGroup}/objectname | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consistent with camel case |
||
// | ||
// apiGroup = /core/ | ||
// apiGroup = /vendor1/ | ||
service Galley { | ||
// Get a single object. | ||
rpc GetObject(GetObjectRequest) returns (ConfigObject) { | ||
option (google.api.http) = { | ||
get: "/{key.api_group}/{key.object_type}/{key.object_type_version}/{key.object_group}/{key.name}" | ||
}; | ||
}; | ||
|
||
// Get a list of objects. | ||
// Other arguments like query.object_group, query.name are optional | ||
// This lets the caller list all objects of a type, or all objects of a type | ||
// that is within an object group. | ||
rpc ListObjects(ListObjectsRequest) returns (ListObjectsResponse) { | ||
option (google.api.http) = { | ||
// meta.object_group can be specified as a query parameter | ||
get: "/{query.api_group}/{query.object_type}/{query.object_type_version}" | ||
additional_bindings: { | ||
get: "/{query.api_group}/{query.object_type}/{query.object_type_version}/{query.object_group}" | ||
}; | ||
}; | ||
}; | ||
|
||
// Get a list of object types. | ||
// Lists all object types or all object types | ||
// within an api group. | ||
rpc ListObjectTypes(ListObjectTypesRequest) returns (ListObjectTypesResponse) { | ||
option (google.api.http) = { | ||
get: "/{meta.api_group}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
additional_bindings: { | ||
get: "/" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I commented previously, grpc-gateway can't compile with this spec (see grpc-ecosystem/grpc-gateway#414). Consider removing this additional binding for the time being. |
||
}; | ||
}; | ||
}; | ||
|
||
// Create an object. This may result in configuration validation errors. | ||
// Referential integrity should be maximally enforced, except where not possible or desirable. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what this line means. Could you elaborate more? |
||
rpc CreateObject(UpdateObjectRequest) returns (UpdateObjectResponse) { | ||
option (google.api.http) = { | ||
post: "/{key.api_group}/{key.object_type}/{key.object_type_version}/{key.object_group}" | ||
body: "source_data" | ||
}; | ||
}; | ||
|
||
// Update a single object. May return validation errors. | ||
rpc UpdateObject(UpdateObjectRequest) returns (UpdateObjectResponse) { | ||
option (google.api.http) = { | ||
put: "/{key.api_group}/{key.object_type}/{key.object_type_version}/{key.object_group}/{key.name}" | ||
body: "source_data" | ||
}; | ||
}; | ||
|
||
// Delete a single object. May return validation errors. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it's possible that Delete will fail due to consistency constraints. That's always difficult for the user. The errors we return will need to include the steps needed to be able to delete. |
||
rpc DeleteObject(DeleteObjectRequest) returns (DeleteObjectResponse) { | ||
option (google.api.http) = { | ||
delete: "/{meta.api_group}/{meta.object_type}/{meta.object_type_version}/{meta.object_group}/{meta.name}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
}; | ||
}; | ||
}; | ||
|
||
|
||
// DeleteObjectResponse is returned when an attempt is made to delete an object | ||
// from the store. | ||
message DeleteObjectResponse{ | ||
// result of the operation | ||
// if status == INVALID_ARGUMENT | ||
// check errors for details. | ||
google.rpc.Status status = 1; | ||
|
||
repeated ValidationError validation_errors = 2; | ||
} | ||
|
||
// UpdateObjectResponse is returned when an attempt is made to update the store. | ||
// ADD or UPDATE operations. | ||
message UpdateObjectResponse { | ||
// result of the operation | ||
// if status == INVALID_ARGUMENT | ||
// check errors for details. | ||
google.rpc.Status status = 1; | ||
|
||
// state of the object after the change. | ||
ConfigObject object = 2; | ||
|
||
// errors if st | ||
repeated ValidationError validation_errors = 3; | ||
} | ||
|
||
message ValidationError { | ||
// The key of the object where error was detected. | ||
// This may not be the object that introduced the error. | ||
string key = 1; | ||
// The primary field that was in error, if available. | ||
string field = 2; | ||
// The line number on which error occurred, if available. | ||
int32 line_number = 3; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the config object has no information about the original source ( |
||
// Textual error message. | ||
string error = 4; | ||
} | ||
|
||
message ListObjectTypesRequest { | ||
// meta is the metadata associated with the root where listing begins. | ||
Meta query = 1; | ||
|
||
// paged result, set to empty on first page. | ||
string page_token = 2; | ||
|
||
// If non zero, response should have at most these number of entries. | ||
int32 max_page_size = 3; | ||
} | ||
|
||
message ListObjectsRequest { | ||
// meta is the metadata associated with the root where listing begins. | ||
Meta query = 1; | ||
|
||
// paged result, set to empty on first page. | ||
string page_token = 2; | ||
|
||
// If non zero, response should have at most these number of entries. | ||
int32 max_page_size = 3; | ||
} | ||
|
||
message UpdateObjectRequest { | ||
// key associated with the requested object. | ||
Meta key = 1; | ||
|
||
// oneof source_data or data | ||
|
||
// source_data is the data as it was specified in json / yaml format. | ||
google.protobuf.Struct source_data = 2; | ||
|
||
// data is the binary encoded protobuf data | ||
// For example: | ||
// If `source_data` contains an expressions in text form | ||
// `data` may contain a parsed AST | ||
bytes data = 3; | ||
} | ||
|
||
message GetObjectRequest { | ||
// key associated with the object to fetch. | ||
Meta key = 1; | ||
} | ||
|
||
message DeleteObjectRequest { | ||
// key associated with the requested object. | ||
Meta key = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any validation that the meta.version, meta.revision, etc. matches the current state before deletion? |
||
} | ||
|
||
// ConfigObject is the concrete representation of a resource. | ||
message ConfigObject { | ||
// meta is the metadata associated with the object. | ||
Meta meta = 1; | ||
|
||
// source_data is the data as it was specified in json / yaml format. | ||
google.protobuf.Struct source_data = 2; | ||
|
||
// data is the binary encoded protobuf data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment here and on ObjectRequest.data probably should match. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
// For example: | ||
// If `source_data` contains an expressions in text form | ||
// `data` may contain a parsed AST | ||
bytes data = 3; | ||
} | ||
|
||
message ListObjectTypesResponse { | ||
// meta is the metadata associated with this list. | ||
Meta meta = 1; | ||
|
||
// list of objects returned. | ||
repeated Meta object_types = 2; | ||
|
||
// If next_page_token is not empty, this is a paged result. | ||
// use this value in the next request. | ||
string next_page_token = 3; | ||
} | ||
|
||
message ListObjectsResponse { | ||
// meta is the metadata associated with this list. | ||
Meta meta = 1; | ||
|
||
// list of objects returned. | ||
repeated ConfigObject objects = 2; | ||
|
||
// If next_page_token is not empty, this is a paged result. | ||
// use this value in the next request. | ||
string next_page_token = 3; | ||
} | ||
|
||
|
||
// Meta is the metadata associated with an object. | ||
message Meta { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want a payload_type enum as suggested yesterday in our conversation with Daniel? |
||
// api_group is the top level delegation and extension point. | ||
string api_group = 1; | ||
|
||
// object_type is the type of an object. | ||
// It corresponds to a behavior being configured. | ||
// route-rule, metrics, logs, ... | ||
string object_type = 2; | ||
|
||
// every object type is independently versioned. | ||
string object_type_version = 3; | ||
|
||
// object_group is an arbitrary hierarchical grouping of resources. | ||
// For Mixer configuration object_group == mesh, svc:svc1, svc:svc2 ... | ||
// For Proxy it can be mesh, destination. | ||
string object_group = 4; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the comment above seems to suggest that string could have a format (e.g., svc:svc1, etc.) that indicates the grouping. |
||
|
||
// name of the object. | ||
string name = 5; | ||
|
||
// uuid assigned to the object. Only used when a new object is created | ||
// in the same place as before. | ||
string uuid = 6; | ||
|
||
// revision of the repository, the last time ConfigObject was updated. | ||
int64 revision = 7; | ||
|
||
// labels associated with the object. | ||
map<string, string> labels = 8; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// Copyright 2017 Istio Authors | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
syntax = "proto3"; | ||
|
||
package istio.galley.v1; | ||
|
||
import "google/rpc/status.proto"; | ||
import "google/api/annotations.proto"; | ||
|
||
import "service.proto"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: import line should specify the path from the root. i.e. |
||
|
||
// ValidatorAndTransformer service validates objects before they are committed to storage. | ||
// Galley maintains a map of object_types to validators. A single validator may validate many types. | ||
// For example MixerValidator service should validate all Mixer resources. | ||
service ValidatorAndTransformer { | ||
// Validate the resource and convert it to typed proto if applicable | ||
// if Object.source_data is specified, it should be converted | ||
// to the appropriate proto representation. | ||
// Every attempt should be made to do a deep validation. | ||
// If full validation requires referential integrity checks, this service should use the | ||
// GalleyWatch Service to maintain current view of configuration. | ||
// | ||
// For example a Mixer rule consists of a selector expression and a named handler amongst other things. | ||
// Mixer validator should check | ||
// 1. expression syntax is valid | ||
// 2. expression uses known attributes | ||
// 3. Rule refers to a known handler | ||
// 4. Any other semantic check that is required for full validation. | ||
// | ||
// It should convert untyped proto into typed proto and return binary encoding of it in Object.data. | ||
// | ||
// On validation failure, it should return a validation error with text. | ||
rpc ValidateAndTransform(ValidationRequest) returns (ValidationResponse) { | ||
option (google.api.http) = { | ||
post: "/resources/v1:validate" | ||
body: "*" | ||
}; | ||
}; | ||
}; | ||
|
||
// Validation repesents individual change to be validated. | ||
message Validation { | ||
oneof validation_union { | ||
// This object should be validated and converted to binary encoded proto. | ||
ConfigObject object = 1; | ||
|
||
// If this object was deleted. | ||
// In this case Validator should check referential integrity. | ||
// Only metadata about the object being deleted is sent. | ||
Meta deleted = 2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And deny deletion if it could result in loss of referential integrity? |
||
} | ||
} | ||
|
||
message ValidationRequest { | ||
// Supports multiple ordered changes to be validated together. | ||
// When a large config is pushed into Galley, batching | ||
// validation requests is an optimization. | ||
repeated Validation validations = 1; | ||
// Objects should be validated against this revision of the repository. | ||
// If the validator or the object is agnostic to repository versions, this can be ignored. | ||
// This is useful for referential integrity checking. | ||
int64 validation_revision = 3; | ||
} | ||
|
||
message ValidationResponse { | ||
// result of the operation | ||
// if status == INVALID_ARGUMENT | ||
// check errors for details. | ||
google.rpc.Status status = 1; | ||
|
||
// state of the object after the change. | ||
ConfigObject object = 2; | ||
|
||
// errors if status = INVALID_ARGUMENT | ||
repeated ValidationError validation_errors = 3; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the Galley design seems to abandon the k8s approach:
A granular resource oriented API based on the Kubernetes resource model was considered here. However it does not provide the required CI/CD experience therefore this document proposes a hierarchical resource API.
Can this be clarified?