[WIP] Micro Runtime (#947)
* Add Get() and GetOptions. * Removed watcher. Outline of client. YAML templates * Added default service and deployment templates and types * Added API tests and cleaned up errors. * Small refactoring. Template package is no more. * Ripped out existing code in preparation to small rework * Reshuffled the source code to make it organized better * Create service and deployment in kubernetes runtime * Major cleanup and refactoring of Kubernetes runtime * Service now handles low level K8s API calls across both K8s deployment an service API objects * Runtime has a task queue that serves for queueing runtime action requests * General refactoring * No need for Lock in k8s service * Added kubernetes runtime env var to default deployment * Enable running different versions of the same service * Can't delete services through labels * Proto cruft. Added runtime.CreateOptions implementation in proto * Removed proxy service from default env variables * Make service name mandatory param to Get method * Get Delete changes from https://github.com/micro/go-micro/pull/945 * Replaced template files with global variables * Validate service names before sending K8s API request * Refactored Kubernetes API client. Fixed typos. * Added client.Resource to make API resources more explicit in code
This commit is contained in:
parent
0af8be35bb
commit
97c1300f53
2
go.mod
2
go.mod
@ -32,9 +32,11 @@ require (
|
|||||||
github.com/mholt/certmagic v0.8.3
|
github.com/mholt/certmagic v0.8.3
|
||||||
github.com/micro/cli v0.2.0
|
github.com/micro/cli v0.2.0
|
||||||
github.com/micro/mdns v0.3.0
|
github.com/micro/mdns v0.3.0
|
||||||
|
github.com/miekg/dns v1.1.15
|
||||||
github.com/mitchellh/hashstructure v1.0.0
|
github.com/mitchellh/hashstructure v1.0.0
|
||||||
github.com/nats-io/nats.go v1.9.1
|
github.com/nats-io/nats.go v1.9.1
|
||||||
github.com/nlopes/slack v0.6.0
|
github.com/nlopes/slack v0.6.0
|
||||||
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
go.uber.org/zap v1.12.0 // indirect
|
go.uber.org/zap v1.12.0 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -283,6 +283,8 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo
|
|||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
||||||
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
|
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
|
||||||
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||||
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
@ -21,6 +21,7 @@ type runtime struct {
|
|||||||
// indicates if we're running
|
// indicates if we're running
|
||||||
running bool
|
running bool
|
||||||
// the service map
|
// the service map
|
||||||
|
// TODO: track different versions of the same service
|
||||||
services map[string]*service
|
services map[string]*service
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +176,56 @@ func (r *runtime) Create(s *Service, opts ...CreateOption) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns all instances of requested service
|
||||||
|
// If no service name is provided we return all the track services.
|
||||||
|
func (r *runtime) Get(name string, opts ...GetOption) ([]*Service, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, errors.New("missing service name")
|
||||||
|
}
|
||||||
|
|
||||||
|
gopts := GetOptions{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&gopts)
|
||||||
|
}
|
||||||
|
|
||||||
|
var services []*Service
|
||||||
|
// if we track the service check if the version is provided
|
||||||
|
if s, ok := r.services[name]; ok {
|
||||||
|
if len(gopts.Version) > 0 {
|
||||||
|
if s.Version == gopts.Version {
|
||||||
|
services = append(services, s.Service)
|
||||||
|
}
|
||||||
|
return services, nil
|
||||||
|
}
|
||||||
|
// no version has sbeen requested, just append the service
|
||||||
|
services = append(services, s.Service)
|
||||||
|
}
|
||||||
|
return services, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update attemps to update the service
|
||||||
|
func (r *runtime) Update(s *Service) error {
|
||||||
|
var opts []CreateOption
|
||||||
|
|
||||||
|
// check if the service already exists
|
||||||
|
r.RLock()
|
||||||
|
if service, ok := r.services[s.Name]; ok {
|
||||||
|
opts = append(opts, WithOutput(service.output))
|
||||||
|
}
|
||||||
|
r.RUnlock()
|
||||||
|
|
||||||
|
// delete the service
|
||||||
|
if err := r.Delete(s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new service
|
||||||
|
return r.Create(s, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
// Delete removes the service from the runtime and stops it
|
// Delete removes the service from the runtime and stops it
|
||||||
func (r *runtime) Delete(s *Service) error {
|
func (r *runtime) Delete(s *Service) error {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
@ -199,26 +250,6 @@ func (r *runtime) Delete(s *Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update attemps to update the service
|
|
||||||
func (r *runtime) Update(s *Service) error {
|
|
||||||
var opts []CreateOption
|
|
||||||
|
|
||||||
// check if the service already exists
|
|
||||||
r.RLock()
|
|
||||||
if service, ok := r.services[s.Name]; ok {
|
|
||||||
opts = append(opts, WithOutput(service.output))
|
|
||||||
}
|
|
||||||
r.RUnlock()
|
|
||||||
|
|
||||||
// delete the service
|
|
||||||
if err := r.Delete(s); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new service
|
|
||||||
return r.Create(s, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns a slice of all services tracked by the runtime
|
// List returns a slice of all services tracked by the runtime
|
||||||
func (r *runtime) List() ([]*Service, error) {
|
func (r *runtime) List() ([]*Service, error) {
|
||||||
var services []*Service
|
var services []*Service
|
||||||
|
169
runtime/kubernetes/client/api/api_test.go
Normal file
169
runtime/kubernetes/client/api/api_test.go
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testcase struct {
|
||||||
|
Token string
|
||||||
|
ReqFn func(opts *Options) *Request
|
||||||
|
Method string
|
||||||
|
URI string
|
||||||
|
Body interface{}
|
||||||
|
Header map[string]string
|
||||||
|
Assert func(req *http.Request) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type assertFn func(req *http.Request) bool
|
||||||
|
|
||||||
|
var tests = []testcase{
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Get().Resource("service")
|
||||||
|
},
|
||||||
|
Method: "GET",
|
||||||
|
URI: "/api/v1/namespaces/default/services/",
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Get().Resource("service").Name("foo")
|
||||||
|
},
|
||||||
|
Method: "GET",
|
||||||
|
URI: "/api/v1/namespaces/default/services/foo",
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Get().Resource("service").Namespace("test").Name("bar")
|
||||||
|
},
|
||||||
|
Method: "GET",
|
||||||
|
URI: "/api/v1/namespaces/test/services/bar",
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Get().Resource("deployment").Name("foo")
|
||||||
|
},
|
||||||
|
Method: "GET",
|
||||||
|
URI: "/apis/apps/v1/namespaces/default/deployments/foo",
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Get().Resource("deployment").Namespace("test").Name("foo")
|
||||||
|
},
|
||||||
|
Method: "GET",
|
||||||
|
URI: "/apis/apps/v1/namespaces/test/deployments/foo",
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Get().Resource("pod").Params(&Params{LabelSelector: map[string]string{"foo": "bar"}})
|
||||||
|
},
|
||||||
|
Method: "GET",
|
||||||
|
URI: "/api/v1/namespaces/default/pods/?labelSelector=foo%3Dbar",
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Post().Resource("service").Name("foo").Body(map[string]string{"foo": "bar"})
|
||||||
|
},
|
||||||
|
Method: "POST",
|
||||||
|
URI: "/api/v1/namespaces/default/services/foo",
|
||||||
|
Body: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Post().Resource("deployment").Namespace("test").Name("foo").Body(map[string]string{"foo": "bar"})
|
||||||
|
},
|
||||||
|
Method: "POST",
|
||||||
|
URI: "/apis/apps/v1/namespaces/test/deployments/foo",
|
||||||
|
Body: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Put().Resource("endpoint").Name("baz").Body(map[string]string{"bam": "bar"})
|
||||||
|
},
|
||||||
|
Method: "PUT",
|
||||||
|
URI: "/api/v1/namespaces/default/endpoints/baz",
|
||||||
|
Body: map[string]string{"bam": "bar"},
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Patch().Resource("endpoint").Name("baz").Body(map[string]string{"bam": "bar"})
|
||||||
|
},
|
||||||
|
Method: "PATCH",
|
||||||
|
URI: "/api/v1/namespaces/default/endpoints/baz",
|
||||||
|
Body: map[string]string{"bam": "bar"},
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Patch().Resource("endpoint").Name("baz").SetHeader("foo", "bar")
|
||||||
|
},
|
||||||
|
Method: "PATCH",
|
||||||
|
URI: "/api/v1/namespaces/default/endpoints/baz",
|
||||||
|
Header: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
testcase{
|
||||||
|
ReqFn: func(opts *Options) *Request {
|
||||||
|
return NewRequest(opts).Patch().Resource("deployment").Name("baz").SetHeader("foo", "bar")
|
||||||
|
},
|
||||||
|
Method: "PATCH",
|
||||||
|
URI: "/apis/apps/v1/namespaces/default/deployments/baz",
|
||||||
|
Header: map[string]string{"foo": "bar"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrappedHandler = func(test *testcase, t *testing.T) http.HandlerFunc {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
auth := r.Header.Get("Authorization")
|
||||||
|
if len(test.Token) > 0 && (len(auth) == 0 || auth != "Bearer "+test.Token) {
|
||||||
|
t.Errorf("test case token (%s) did not match expected token (%s)", "Bearer "+test.Token, auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(test.Method) > 0 && test.Method != r.Method {
|
||||||
|
t.Errorf("test case Method (%s) did not match expected Method (%s)", test.Method, r.Method)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(test.URI) > 0 && test.URI != r.URL.RequestURI() {
|
||||||
|
t.Errorf("test case URI (%s) did not match expected URI (%s)", test.URI, r.URL.RequestURI())
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.Body != nil {
|
||||||
|
var res map[string]string
|
||||||
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
if err := decoder.Decode(&res); err != nil {
|
||||||
|
t.Errorf("decoding body failed: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(res, test.Body) {
|
||||||
|
t.Error("body did not match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.Header != nil {
|
||||||
|
for k, v := range test.Header {
|
||||||
|
if r.Header.Get(k) != v {
|
||||||
|
t.Error("header did not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequest(t *testing.T) {
|
||||||
|
for _, test := range tests {
|
||||||
|
ts := httptest.NewServer(wrappedHandler(&test, t))
|
||||||
|
req := test.ReqFn(&Options{
|
||||||
|
Host: ts.URL,
|
||||||
|
Client: &http.Client{},
|
||||||
|
BearerToken: &test.Token,
|
||||||
|
Namespace: "default",
|
||||||
|
})
|
||||||
|
res := req.Do()
|
||||||
|
if res.Error() != nil {
|
||||||
|
t.Errorf("request failed with %v", res.Error())
|
||||||
|
}
|
||||||
|
ts.Close()
|
||||||
|
}
|
||||||
|
}
|
@ -3,12 +3,12 @@ package api
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/micro/go-micro/runtime/kubernetes/client/watch"
|
|
||||||
"github.com/micro/go-micro/util/log"
|
"github.com/micro/go-micro/util/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,7 +33,6 @@ type Request struct {
|
|||||||
type Params struct {
|
type Params struct {
|
||||||
LabelSelector map[string]string
|
LabelSelector map[string]string
|
||||||
Annotations map[string]string
|
Annotations map[string]string
|
||||||
Watch bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verb sets method
|
// verb sets method
|
||||||
@ -58,9 +57,8 @@ func (r *Request) Put() *Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Patch request
|
// Patch request
|
||||||
// https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#patch-operations
|
|
||||||
func (r *Request) Patch() *Request {
|
func (r *Request) Patch() *Request {
|
||||||
return r.verb("PATCH").SetHeader("Content-Type", "application/strategic-merge-patch+json")
|
return r.verb("PATCH")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete request
|
// Delete request
|
||||||
@ -87,15 +85,33 @@ func (r *Request) Name(s string) *Request {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body pass in a body to set, this is for POST, PUT
|
// Body pass in a body to set, this is for POST, PUT and PATCH requests
|
||||||
// and PATCH requests
|
|
||||||
func (r *Request) Body(in interface{}) *Request {
|
func (r *Request) Body(in interface{}) *Request {
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
|
// if we're not sending YAML request, we encode to JSON
|
||||||
|
if r.header.Get("Content-Type") != "application/yaml" {
|
||||||
if err := json.NewEncoder(b).Encode(&in); err != nil {
|
if err := json.NewEncoder(b).Encode(&in); err != nil {
|
||||||
r.err = err
|
r.err = err
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
log.Debugf("Patch body: %v", b)
|
log.Debugf("Request body: %v", b)
|
||||||
|
r.body = b
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// if application/yaml is set, we assume we get a raw bytes so we just copy over
|
||||||
|
body, ok := in.(io.Reader)
|
||||||
|
if !ok {
|
||||||
|
r.err = errors.New("invalid data")
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
// copy over data to the bytes buffer
|
||||||
|
if _, err := io.Copy(b, body); err != nil {
|
||||||
|
r.err = err
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Request body: %v", b)
|
||||||
r.body = b
|
r.body = b
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@ -120,12 +136,12 @@ func (r *Request) SetHeader(key, value string) *Request {
|
|||||||
func (r *Request) request() (*http.Request, error) {
|
func (r *Request) request() (*http.Request, error) {
|
||||||
var url string
|
var url string
|
||||||
switch r.resource {
|
switch r.resource {
|
||||||
case "pods":
|
case "pod", "service", "endpoint":
|
||||||
// /api/v1/namespaces/{namespace}/pods
|
// /api/v1/namespaces/{namespace}/pods
|
||||||
url = fmt.Sprintf("%s/api/v1/namespaces/%s/%s/", r.host, r.namespace, r.resource)
|
url = fmt.Sprintf("%s/api/v1/namespaces/%s/%ss/", r.host, r.namespace, r.resource)
|
||||||
case "deployments":
|
case "deployment":
|
||||||
// /apis/apps/v1/namespaces/{namespace}/deployments/{name}
|
// /apis/apps/v1/namespaces/{namespace}/deployments/{name}
|
||||||
url = fmt.Sprintf("%s/apis/apps/v1/namespaces/%s/%s/", r.host, r.namespace, r.resource)
|
url = fmt.Sprintf("%s/apis/apps/v1/namespaces/%s/%ss/", r.host, r.namespace, r.resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// append resourceName if it is present
|
// append resourceName if it is present
|
||||||
@ -179,24 +195,6 @@ func (r *Request) Do() *Response {
|
|||||||
return newResponse(res, err)
|
return newResponse(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch builds and triggers the request, but
|
|
||||||
// will watch instead of return an object
|
|
||||||
func (r *Request) Watch() (watch.Watch, error) {
|
|
||||||
if r.err != nil {
|
|
||||||
return nil, r.err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.params.Set("watch", "true")
|
|
||||||
|
|
||||||
req, err := r.request()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := watch.NewBodyWatcher(req, r.client)
|
|
||||||
return w, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options ...
|
// Options ...
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Host string
|
Host string
|
||||||
|
@ -11,9 +11,9 @@ import (
|
|||||||
|
|
||||||
// Errors ...
|
// Errors ...
|
||||||
var (
|
var (
|
||||||
ErrNotFound = errors.New("kubernetes: not found")
|
ErrNotFound = errors.New("kubernetes: resource not found")
|
||||||
ErrDecode = errors.New("kubernetes: error decoding")
|
ErrDecode = errors.New("kubernetes: error decoding")
|
||||||
ErrOther = errors.New("kubernetes: unknown error")
|
ErrUnknown = errors.New("kubernetes: unknown error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Status is an object that is returned when a request
|
// Status is an object that is returned when a request
|
||||||
@ -89,6 +89,7 @@ func newResponse(res *http.Response, err error) *Response {
|
|||||||
log.Log("kubernetes: request failed with body:")
|
log.Log("kubernetes: request failed with body:")
|
||||||
log.Log(string(b))
|
log.Log(string(b))
|
||||||
}
|
}
|
||||||
r.err = ErrOther
|
r.err = ErrUnknown
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// path to kubernetes service account token
|
||||||
serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
|
serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||||
// ErrReadNamespace is returned when the names could not be read from service account
|
// ErrReadNamespace is returned when the names could not be read from service account
|
||||||
ErrReadNamespace = errors.New("Could not read namespace from service account secret")
|
ErrReadNamespace = errors.New("Could not read namespace from service account secret")
|
||||||
@ -23,9 +25,7 @@ type client struct {
|
|||||||
opts *api.Options
|
opts *api.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClientInCluster should work similarily to the official api
|
// NewClientInCluster creates a Kubernetes client for use from within a k8s pod.
|
||||||
// NewInClient by setting up a client configuration for use within
|
|
||||||
// a k8s pod.
|
|
||||||
func NewClientInCluster() *client {
|
func NewClientInCluster() *client {
|
||||||
host := "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT")
|
host := "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT")
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ func NewClientInCluster() *client {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if s == nil || !s.IsDir() {
|
if s == nil || !s.IsDir() {
|
||||||
log.Fatal(errors.New("no k8s service account found"))
|
log.Fatal(errors.New("service account not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := ioutil.ReadFile(path.Join(serviceAccountPath, "token"))
|
token, err := ioutil.ReadFile(path.Join(serviceAccountPath, "token"))
|
||||||
@ -90,26 +90,72 @@ func detectNamespace() (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDeployment patches kubernetes deployment with metadata provided in body
|
// Create creates new API object
|
||||||
func (c *client) UpdateDeployment(name string, body interface{}) error {
|
func (c *client) Create(r *Resource) error {
|
||||||
|
b := new(bytes.Buffer)
|
||||||
|
if err := renderTemplate(r.Kind, b, r.Value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return api.NewRequest(c.opts).
|
return api.NewRequest(c.opts).
|
||||||
Patch().
|
Post().
|
||||||
Resource("deployments").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
Name(name).
|
Resource(r.Kind).
|
||||||
Body(body).
|
Body(b).
|
||||||
Do().
|
Do().
|
||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListDeployments lists all kubernetes deployments with given labels
|
// Get queries API objects and stores the result in r
|
||||||
func (c *client) ListDeployments(labels map[string]string) (*DeploymentList, error) {
|
func (c *client) Get(r *Resource, labels map[string]string) error {
|
||||||
var deployments DeploymentList
|
return api.NewRequest(c.opts).
|
||||||
err := api.NewRequest(c.opts).
|
|
||||||
Get().
|
Get().
|
||||||
Resource("deployments").
|
Resource(r.Kind).
|
||||||
Params(&api.Params{LabelSelector: labels}).
|
Params(&api.Params{LabelSelector: labels}).
|
||||||
Do().
|
Do().
|
||||||
Into(&deployments)
|
Into(r.Value)
|
||||||
|
}
|
||||||
return &deployments, err
|
|
||||||
|
// Update updates API object
|
||||||
|
func (c *client) Update(r *Resource) error {
|
||||||
|
req := api.NewRequest(c.opts).
|
||||||
|
Patch().
|
||||||
|
SetHeader("Content-Type", "application/strategic-merge-patch+json").
|
||||||
|
Resource(r.Kind).
|
||||||
|
Name(r.Name)
|
||||||
|
|
||||||
|
switch r.Kind {
|
||||||
|
case "service":
|
||||||
|
req.Body(r.Value.(*Service).Spec)
|
||||||
|
case "deployment":
|
||||||
|
req.Body(r.Value.(*Deployment).Spec)
|
||||||
|
default:
|
||||||
|
return errors.New("unsupported resource")
|
||||||
|
}
|
||||||
|
|
||||||
|
return req.Do().Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes API object
|
||||||
|
func (c *client) Delete(r *Resource) error {
|
||||||
|
return api.NewRequest(c.opts).
|
||||||
|
Delete().
|
||||||
|
Resource(r.Kind).
|
||||||
|
Name(r.Name).
|
||||||
|
Do().
|
||||||
|
Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// List lists API objects and stores the result in r
|
||||||
|
func (c *client) List(r *Resource) error {
|
||||||
|
labels := map[string]string{
|
||||||
|
"micro": "service",
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.NewRequest(c.opts).
|
||||||
|
Get().
|
||||||
|
Resource(r.Kind).
|
||||||
|
Params(&api.Params{LabelSelector: labels}).
|
||||||
|
Do().
|
||||||
|
Into(r.Value)
|
||||||
}
|
}
|
||||||
|
@ -1,43 +1,132 @@
|
|||||||
|
// Package client provides an implementation of a restricted subset of kubernetes API client
|
||||||
package client
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/micro/go-micro/util/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// https://github.com/kubernetes/apimachinery/blob/master/pkg/util/validation/validation.go#L134
|
||||||
|
dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultImage is default micro image
|
||||||
|
DefaultImage = "micro/micro"
|
||||||
|
// ServiceRegexp is used to validate service name
|
||||||
|
ServiceRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$")
|
||||||
|
)
|
||||||
|
|
||||||
// Kubernetes client
|
// Kubernetes client
|
||||||
type Kubernetes interface {
|
type Kubernetes interface {
|
||||||
// UpdateDeployment patches deployment annotations with new metadata
|
// Create creates new API resource
|
||||||
UpdateDeployment(string, interface{}) error
|
Create(*Resource) error
|
||||||
// ListDeployments lists all micro deployments
|
// Get queries API resrouces
|
||||||
ListDeployments(labels map[string]string) (*DeploymentList, error)
|
Get(*Resource, map[string]string) error
|
||||||
|
// Update patches existing API object
|
||||||
|
Update(*Resource) error
|
||||||
|
// Delete deletes API resource
|
||||||
|
Delete(*Resource) error
|
||||||
|
// List lists API resources
|
||||||
|
List(*Resource) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template is micro deployment template
|
// DefaultService returns default micro kubernetes service definition
|
||||||
type Template struct {
|
func DefaultService(name, version string) *Service {
|
||||||
Metadata *Metadata `json:"metadata,omitempty"`
|
Labels := map[string]string{
|
||||||
|
"name": name,
|
||||||
|
"version": version,
|
||||||
|
"micro": "service",
|
||||||
|
}
|
||||||
|
|
||||||
|
svcName := name
|
||||||
|
if len(version) > 0 {
|
||||||
|
// API service object name joins name and version over "-"
|
||||||
|
svcName = strings.Join([]string{name, version}, "-")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata := &Metadata{
|
||||||
|
Name: svcName,
|
||||||
|
Namespace: "default",
|
||||||
|
Version: version,
|
||||||
|
Labels: Labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
Spec := &ServiceSpec{
|
||||||
|
Type: "ClusterIP",
|
||||||
|
Selector: Labels,
|
||||||
|
Ports: []ServicePort{{
|
||||||
|
name + "-port", 9090, "",
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Service{
|
||||||
|
Metadata: Metadata,
|
||||||
|
Spec: Spec,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spec defines micro deployment spec
|
// DefaultService returns default micro kubernetes deployment definition
|
||||||
type Spec struct {
|
func DefaultDeployment(name, version string) *Deployment {
|
||||||
Template *Template `json:"template,omitempty"`
|
Labels := map[string]string{
|
||||||
}
|
"name": name,
|
||||||
|
"version": version,
|
||||||
|
"micro": "service",
|
||||||
|
}
|
||||||
|
|
||||||
// Metadata defines api request metadata
|
// API deployment object name joins name and version over "="
|
||||||
type Metadata struct {
|
depName := strings.Join([]string{name, version}, "-")
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
Labels map[string]string `json:"labels,omitempty"`
|
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeploymentList
|
Metadata := &Metadata{
|
||||||
type DeploymentList struct {
|
Name: depName,
|
||||||
Items []Deployment `json:"items"`
|
Namespace: "default",
|
||||||
}
|
Version: version,
|
||||||
|
Labels: Labels,
|
||||||
|
}
|
||||||
|
|
||||||
// Deployment is Kubernetes deployment
|
// TODO: we need to figure out this version stuff
|
||||||
type Deployment struct {
|
// might be worth adding Build to runtime.Service
|
||||||
Metadata *Metadata `json:"metadata"`
|
buildTime, err := strconv.ParseInt(version, 10, 64)
|
||||||
Status *Status `json:"status"`
|
if err == nil {
|
||||||
}
|
buildUnixTimeUTC := time.Unix(buildTime, 0)
|
||||||
|
Metadata.Annotations = map[string]string{
|
||||||
|
"build": buildUnixTimeUTC.Format(time.RFC3339),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Debugf("Runtime could not parse build: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Status is Kubernetes deployment status
|
// TODO: change the image name here
|
||||||
type Status struct {
|
Spec := &DeploymentSpec{
|
||||||
Replicas int `json:"replicas"`
|
Replicas: 1,
|
||||||
AvailableReplicas int `json:"availablereplicas"`
|
Selector: &LabelSelector{
|
||||||
|
MatchLabels: Labels,
|
||||||
|
},
|
||||||
|
Template: &Template{
|
||||||
|
Metadata: Metadata,
|
||||||
|
PodSpec: &PodSpec{
|
||||||
|
Containers: []Container{{
|
||||||
|
Name: name,
|
||||||
|
Image: DefaultImage,
|
||||||
|
Env: []EnvVar{},
|
||||||
|
Command: []string{"go", "run", "main.go"},
|
||||||
|
Ports: []ContainerPort{{
|
||||||
|
Name: name + "-port",
|
||||||
|
ContainerPort: 8080,
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Deployment{
|
||||||
|
Metadata: Metadata,
|
||||||
|
Spec: Spec,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
93
runtime/kubernetes/client/templates.go
Normal file
93
runtime/kubernetes/client/templates.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
var templates = map[string]string{
|
||||||
|
"deployments": deploymentTmpl,
|
||||||
|
"services": serviceTmpl,
|
||||||
|
}
|
||||||
|
|
||||||
|
var deploymentTmpl = `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Metadata.Name }}"
|
||||||
|
namespace: "{{ .Metadata.Namespace }}"
|
||||||
|
labels:
|
||||||
|
{{- with .Metadata.Labels }}
|
||||||
|
{{- range $key, $value := . }}
|
||||||
|
{{ $key }}: "{{ $value }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Spec.Replicas }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- with .Spec.Selector.MatchLabels }}
|
||||||
|
{{- range $key, $value := . }}
|
||||||
|
{{ $key }}: "{{ $value }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- with .Spec.Template.Metadata.Labels }}
|
||||||
|
{{- range $key, $value := . }}
|
||||||
|
{{ $key }}: "{{ $value }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
{{- with .Spec.Template.PodSpec.Containers }}
|
||||||
|
{{- range . }}
|
||||||
|
- name: {{ .Name }}
|
||||||
|
env:
|
||||||
|
{{- with .Env }}
|
||||||
|
{{- range . }}
|
||||||
|
- name: "{{ .Name }}"
|
||||||
|
value: "{{ .Value }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
command:
|
||||||
|
{{- range .Command }}
|
||||||
|
- {{.}}
|
||||||
|
{{- end }}
|
||||||
|
image: {{ .Image }}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
{{- with .Ports }}
|
||||||
|
{{- range . }}
|
||||||
|
- containerPort: {{ .ContainerPort }}
|
||||||
|
name: {{ .Name }}
|
||||||
|
{{- end}}
|
||||||
|
{{- end}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end}}
|
||||||
|
`
|
||||||
|
|
||||||
|
var serviceTmpl = `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Metadata.Name }}"
|
||||||
|
namespace: "{{ .Metadata.Namespace }}"
|
||||||
|
labels:
|
||||||
|
{{- with .Metadata.Labels }}
|
||||||
|
{{- range $key, $value := . }}
|
||||||
|
{{ $key }}: "{{ $value }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
{{- with .Spec.Selector }}
|
||||||
|
{{- range $key, $value := . }}
|
||||||
|
{{ $key }}: "{{ $value }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
{{- with .Spec.Ports }}
|
||||||
|
{{- range . }}
|
||||||
|
- name: "{{ .Name }}"
|
||||||
|
port: {{ .Port }}
|
||||||
|
protocol: {{ .Protocol }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
`
|
125
runtime/kubernetes/client/types.go
Normal file
125
runtime/kubernetes/client/types.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
// Resource is API resource
|
||||||
|
type Resource struct {
|
||||||
|
Name string
|
||||||
|
Kind string
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata defines api object metadata
|
||||||
|
type Metadata struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServicePort configures service ports
|
||||||
|
type ServicePort struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceSpec provides service configuration
|
||||||
|
type ServiceSpec struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Selector map[string]string `json:"selector,omitempty"`
|
||||||
|
Ports []ServicePort `json:"ports,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerIngress struct {
|
||||||
|
IP string `json:"ip,omitempty"`
|
||||||
|
Hostname string `json:"hostname,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
Ingress []LoadBalancerIngress `json:"ingress,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceStatus
|
||||||
|
type ServiceStatus struct {
|
||||||
|
LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service is kubernetes service
|
||||||
|
type Service struct {
|
||||||
|
Metadata *Metadata `json:"metadata"`
|
||||||
|
Spec *ServiceSpec `json:"spec,omitempty"`
|
||||||
|
Status *ServiceStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceList
|
||||||
|
type ServiceList struct {
|
||||||
|
Items []Service `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerPort
|
||||||
|
type ContainerPort struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
HostPort int `json:"hostPort,omitempty"`
|
||||||
|
ContainerPort int `json:"containerPort"`
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnvVar is environment variable
|
||||||
|
type EnvVar struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container defined container runtime values
|
||||||
|
type Container struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
Env []EnvVar `json:"env,omitempty"`
|
||||||
|
Command []string `json:"command,omitempty"`
|
||||||
|
Ports []ContainerPort `json:"ports,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodSpec
|
||||||
|
type PodSpec struct {
|
||||||
|
Containers []Container `json:"containers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template is micro deployment template
|
||||||
|
type Template struct {
|
||||||
|
Metadata *Metadata `json:"metadata,omitempty"`
|
||||||
|
PodSpec *PodSpec `json:"spec,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabelSelector is a label query over a set of resources
|
||||||
|
// NOTE: we do not support MatchExpressions at the moment
|
||||||
|
type LabelSelector struct {
|
||||||
|
MatchLabels map[string]string `json:"matchLabels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentSpec defines micro deployment spec
|
||||||
|
type DeploymentSpec struct {
|
||||||
|
Replicas int `json:"replicas,omitempty"`
|
||||||
|
Selector *LabelSelector `json:"selector"`
|
||||||
|
Template *Template `json:"template,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentStatus is returned when querying deployment
|
||||||
|
type DeploymentStatus struct {
|
||||||
|
Replicas int `json:"replicas,omitempty"`
|
||||||
|
UpdatedReplicas int `json:"updatedReplicas,omitempty"`
|
||||||
|
ReadyReplicas int `json:"readyReplicas,omitempty"`
|
||||||
|
AvailableReplicas int `json:"availableReplicas,omitempty"`
|
||||||
|
UnavailableReplicas int `json:"unavailableReplicas,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deployment is Kubernetes deployment
|
||||||
|
type Deployment struct {
|
||||||
|
Metadata *Metadata `json:"metadata"`
|
||||||
|
Spec *DeploymentSpec `json:"spec,omitempty"`
|
||||||
|
Status *DeploymentStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentList
|
||||||
|
type DeploymentList struct {
|
||||||
|
Items []Deployment `json:"items"`
|
||||||
|
}
|
@ -5,9 +5,22 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// renderTemplateFile renders template file in path into writer w with supplied data
|
||||||
|
func renderTemplate(text string, w io.Writer, data interface{}) error {
|
||||||
|
t := template.Must(template.New("kubernetes").Parse(text))
|
||||||
|
|
||||||
|
if err := t.Execute(w, data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// COPIED FROM
|
// COPIED FROM
|
||||||
// https://github.com/kubernetes/kubernetes/blob/7a725418af4661067b56506faabc2d44c6d7703a/pkg/util/crypto/crypto.go
|
// https://github.com/kubernetes/kubernetes/blob/7a725418af4661067b56506faabc2d44c6d7703a/pkg/util/crypto/crypto.go
|
||||||
|
|
||||||
|
25
runtime/kubernetes/client/utils_test.go
Normal file
25
runtime/kubernetes/client/utils_test.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTemplates(t *testing.T) {
|
||||||
|
name := "foo"
|
||||||
|
version := "1.2.3"
|
||||||
|
|
||||||
|
// Render default service
|
||||||
|
s := DefaultService(name, version)
|
||||||
|
bs := new(bytes.Buffer)
|
||||||
|
if err := renderTemplate(serviceTmpl, bs, s); err != nil {
|
||||||
|
t.Errorf("Failed to render kubernetes service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render default deployment
|
||||||
|
d := DefaultDeployment(name, version)
|
||||||
|
bd := new(bytes.Buffer)
|
||||||
|
if err := renderTemplate(deploymentTmpl, bd, d); err != nil {
|
||||||
|
t.Errorf("Failed to render kubernetes deployment: %v", err)
|
||||||
|
}
|
||||||
|
}
|
@ -1,74 +0,0 @@
|
|||||||
package watch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// bodyWatcher scans the body of a request for chunks
|
|
||||||
type bodyWatcher struct {
|
|
||||||
results chan Event
|
|
||||||
stop chan struct{}
|
|
||||||
res *http.Response
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
// Changes returns the results channel
|
|
||||||
func (wr *bodyWatcher) ResultChan() <-chan Event {
|
|
||||||
return wr.results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop cancels the request
|
|
||||||
func (wr *bodyWatcher) Stop() {
|
|
||||||
select {
|
|
||||||
case <-wr.stop:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
close(wr.stop)
|
|
||||||
close(wr.results)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wr *bodyWatcher) stream() {
|
|
||||||
reader := bufio.NewReader(wr.res.Body)
|
|
||||||
|
|
||||||
// stop the watcher
|
|
||||||
defer wr.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
// read a line
|
|
||||||
b, err := reader.ReadBytes('\n')
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the event
|
|
||||||
var event Event
|
|
||||||
if err := json.Unmarshal(b, &event); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wr.results <- event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBodyWatcher creates a k8s body watcher for a given http request
|
|
||||||
func NewBodyWatcher(req *http.Request, client *http.Client) (Watch, error) {
|
|
||||||
stop := make(chan struct{})
|
|
||||||
req.Cancel = stop
|
|
||||||
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
wr := &bodyWatcher{
|
|
||||||
results: make(chan Event),
|
|
||||||
stop: stop,
|
|
||||||
req: req,
|
|
||||||
res: res,
|
|
||||||
}
|
|
||||||
|
|
||||||
go wr.stream()
|
|
||||||
return wr, nil
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package watch
|
|
||||||
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
// Watch ...
|
|
||||||
type Watch interface {
|
|
||||||
Stop()
|
|
||||||
ResultChan() <-chan Event
|
|
||||||
}
|
|
||||||
|
|
||||||
// EventType defines the possible types of events.
|
|
||||||
type EventType string
|
|
||||||
|
|
||||||
// EventTypes used
|
|
||||||
const (
|
|
||||||
Added EventType = "ADDED"
|
|
||||||
Modified EventType = "MODIFIED"
|
|
||||||
Deleted EventType = "DELETED"
|
|
||||||
Error EventType = "ERROR"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Event represents a single event to a watched resource.
|
|
||||||
type Event struct {
|
|
||||||
Type EventType `json:"type"`
|
|
||||||
Object json.RawMessage `json:"object"`
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package watch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var actions = []string{
|
|
||||||
`{"type": "create", "object":{"foo": "bar"}}`,
|
|
||||||
`{"type": "delete", INVALID}`,
|
|
||||||
`{"type": "update", "object":{"foo": {"foo": "bar"}}}`,
|
|
||||||
`{"type": "delete", "object":null}`,
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBodyWatcher(t *testing.T) {
|
|
||||||
// set up server with handler to flush strings from ch.
|
|
||||||
ch := make(chan string)
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
flusher, ok := w.(http.Flusher)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("expected ResponseWriter to be a flusher")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(w, "\n")
|
|
||||||
flusher.Flush()
|
|
||||||
|
|
||||||
for v := range ch {
|
|
||||||
fmt.Fprintf(w, "%s\n", v)
|
|
||||||
flusher.Flush()
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", ts.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create new request: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup body watcher
|
|
||||||
w, err := NewBodyWatcher(req, http.DefaultClient)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create new BodyWatcher %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// send action strings in, and expect result back
|
|
||||||
ch <- actions[0]
|
|
||||||
if r := <-w.ResultChan(); r.Type != "create" {
|
|
||||||
t.Fatalf("expected result to be create")
|
|
||||||
}
|
|
||||||
|
|
||||||
ch <- actions[1] // should be ignored as its invalid json
|
|
||||||
ch <- actions[2]
|
|
||||||
if r := <-w.ResultChan(); r.Type != "update" {
|
|
||||||
t.Fatalf("expected result to be update")
|
|
||||||
}
|
|
||||||
|
|
||||||
ch <- actions[3]
|
|
||||||
if r := <-w.ResultChan(); r.Type != "delete" {
|
|
||||||
t.Fatalf("expected result to be delete")
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop should clean up all channels.
|
|
||||||
w.Stop()
|
|
||||||
close(ch)
|
|
||||||
}
|
|
@ -14,18 +14,31 @@ import (
|
|||||||
"github.com/micro/go-micro/util/log"
|
"github.com/micro/go-micro/util/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// action to take on runtime service
|
||||||
|
type action int
|
||||||
|
|
||||||
|
const (
|
||||||
|
start action = iota
|
||||||
|
update
|
||||||
|
stop
|
||||||
|
)
|
||||||
|
|
||||||
|
// task is queued into runtime queue
|
||||||
|
type task struct {
|
||||||
|
action action
|
||||||
|
service *service
|
||||||
|
}
|
||||||
|
|
||||||
type kubernetes struct {
|
type kubernetes struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
// options configure runtime
|
// options configure runtime
|
||||||
options runtime.Options
|
options runtime.Options
|
||||||
// indicates if we're running
|
// indicates if we're running
|
||||||
running bool
|
running bool
|
||||||
// used to start new services
|
// task queue for kubernetes services
|
||||||
start chan *runtime.Service
|
queue chan *task
|
||||||
// used to stop the runtime
|
// used to stop the runtime
|
||||||
closed chan bool
|
closed chan bool
|
||||||
// service tracks deployed services
|
|
||||||
services map[string]*runtime.Service
|
|
||||||
// client is kubernetes client
|
// client is kubernetes client
|
||||||
client client.Kubernetes
|
client client.Kubernetes
|
||||||
}
|
}
|
||||||
@ -46,8 +59,7 @@ func NewRuntime(opts ...runtime.Option) runtime.Runtime {
|
|||||||
return &kubernetes{
|
return &kubernetes{
|
||||||
options: options,
|
options: options,
|
||||||
closed: make(chan bool),
|
closed: make(chan bool),
|
||||||
start: make(chan *runtime.Service, 128),
|
queue: make(chan *task, 128),
|
||||||
services: make(map[string]*runtime.Service),
|
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,33 +76,109 @@ func (k *kubernetes) Init(opts ...runtime.Option) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a service
|
// Creates a service
|
||||||
func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) error {
|
func (k *kubernetes) Create(s *runtime.Service, opts ...runtime.CreateOption) error {
|
||||||
k.Lock()
|
k.Lock()
|
||||||
defer k.Unlock()
|
defer k.Unlock()
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// * create service
|
|
||||||
// * create deployment
|
|
||||||
|
|
||||||
// NOTE: our services have micro- prefix
|
|
||||||
muName := strings.Split(s.Name, ".")
|
|
||||||
s.Name = "micro-" + muName[len(muName)-1]
|
|
||||||
|
|
||||||
// NOTE: we are tracking this in memory for now
|
|
||||||
if _, ok := k.services[s.Name]; ok {
|
|
||||||
return errors.New("service already registered")
|
|
||||||
}
|
|
||||||
|
|
||||||
var options runtime.CreateOptions
|
var options runtime.CreateOptions
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&options)
|
o(&options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// save service
|
svcName := s.Name
|
||||||
k.services[s.Name] = s
|
if len(s.Version) > 0 {
|
||||||
|
svcName = strings.Join([]string{s.Name, s.Version}, "-")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !client.ServiceRegexp.MatchString(svcName) {
|
||||||
|
return fmt.Errorf("invalid service name: %s", svcName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new kubernetes micro service
|
||||||
|
service := newService(s, options)
|
||||||
|
|
||||||
|
log.Debugf("Runtime queueing service %s for start action", service.Name)
|
||||||
|
|
||||||
// push into start queue
|
// push into start queue
|
||||||
k.start <- k.services[s.Name]
|
k.queue <- &task{
|
||||||
|
action: start,
|
||||||
|
service: service,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns all instances of given service
|
||||||
|
func (k *kubernetes) Get(name string, opts ...runtime.GetOption) ([]*runtime.Service, error) {
|
||||||
|
k.Lock()
|
||||||
|
defer k.Unlock()
|
||||||
|
|
||||||
|
// if no name has been passed in, return error
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, errors.New("missing service name")
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the default label
|
||||||
|
labels := map[string]string{
|
||||||
|
"micro": "service",
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
var options runtime.GetOptions
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add version to labels if a version has been supplied
|
||||||
|
if len(options.Version) > 0 {
|
||||||
|
labels["version"] = options.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Runtime querying service %s", name)
|
||||||
|
|
||||||
|
serviceList := new(client.ServiceList)
|
||||||
|
r := &client.Resource{
|
||||||
|
Kind: "service",
|
||||||
|
Value: serviceList,
|
||||||
|
}
|
||||||
|
if err := k.client.Get(r, labels); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
services := make([]*runtime.Service, 0, len(serviceList.Items))
|
||||||
|
for _, kservice := range serviceList.Items {
|
||||||
|
service := &runtime.Service{
|
||||||
|
Name: kservice.Metadata.Name,
|
||||||
|
Version: kservice.Metadata.Version,
|
||||||
|
}
|
||||||
|
services = append(services, service)
|
||||||
|
}
|
||||||
|
|
||||||
|
return services, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the service in place
|
||||||
|
func (k *kubernetes) Update(s *runtime.Service) error {
|
||||||
|
// parse version into human readable timestamp
|
||||||
|
updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
unixTimeUTC := time.Unix(updateTimeStamp, 0)
|
||||||
|
|
||||||
|
// create new kubernetes micro service
|
||||||
|
service := newService(s, runtime.CreateOptions{})
|
||||||
|
|
||||||
|
// update build time annotation
|
||||||
|
service.kdeploy.Spec.Template.Metadata.Annotations["build"] = unixTimeUTC.Format(time.RFC3339)
|
||||||
|
|
||||||
|
log.Debugf("Runtime queueing service %s for update action", service.Name)
|
||||||
|
|
||||||
|
// queue service for removal
|
||||||
|
k.queue <- &task{
|
||||||
|
action: update,
|
||||||
|
service: service,
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -100,61 +188,37 @@ func (k *kubernetes) Delete(s *runtime.Service) error {
|
|||||||
k.Lock()
|
k.Lock()
|
||||||
defer k.Unlock()
|
defer k.Unlock()
|
||||||
|
|
||||||
// TODO:
|
// create new kubernetes micro service
|
||||||
// * delete service
|
service := newService(s, runtime.CreateOptions{})
|
||||||
// * delete dpeloyment
|
|
||||||
|
|
||||||
// NOTE: we are tracking this in memory for now
|
log.Debugf("Runtime queueing service %s for delete action", service.Name)
|
||||||
if s, ok := k.services[s.Name]; ok {
|
|
||||||
delete(k.services, s.Name)
|
// queue service for removal
|
||||||
return nil
|
k.queue <- &task{
|
||||||
|
action: stop,
|
||||||
|
service: service,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the service in place
|
|
||||||
func (k *kubernetes) Update(s *runtime.Service) error {
|
|
||||||
type body struct {
|
|
||||||
Spec *client.Spec `json:"spec"`
|
|
||||||
}
|
|
||||||
// parse version into human readable timestamp
|
|
||||||
updateTimeStamp, err := strconv.ParseInt(s.Version, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
unixTimeUTC := time.Unix(updateTimeStamp, 0)
|
|
||||||
// metada which we will PATCH deployment with
|
|
||||||
reqBody := body{
|
|
||||||
Spec: &client.Spec{
|
|
||||||
Template: &client.Template{
|
|
||||||
Metadata: &client.Metadata{
|
|
||||||
Annotations: map[string]string{
|
|
||||||
"build": unixTimeUTC.Format(time.RFC3339),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return k.client.UpdateDeployment(s.Name, reqBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
// List the managed services
|
// List the managed services
|
||||||
func (k *kubernetes) List() ([]*runtime.Service, error) {
|
func (k *kubernetes) List() ([]*runtime.Service, error) {
|
||||||
labels := map[string]string{
|
serviceList := new(client.ServiceList)
|
||||||
"micro": "service",
|
r := &client.Resource{
|
||||||
|
Kind: "service",
|
||||||
|
Value: serviceList,
|
||||||
}
|
}
|
||||||
// list all micro core deployments
|
|
||||||
deployments, err := k.client.ListDeployments(labels)
|
if err := k.client.List(r); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Runtime found %d micro deployments with labels %v", len(deployments.Items), labels)
|
log.Debugf("Runtime found %d micro services", len(serviceList.Items))
|
||||||
|
|
||||||
services := make([]*runtime.Service, 0, len(deployments.Items))
|
services := make([]*runtime.Service, 0, len(serviceList.Items))
|
||||||
|
|
||||||
for _, service := range deployments.Items {
|
for _, service := range serviceList.Items {
|
||||||
buildTime, err := time.Parse(time.RFC3339, service.Metadata.Annotations["build"])
|
buildTime, err := time.Parse(time.RFC3339, service.Metadata.Annotations["build"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("Runtime error parsing build time for %s: %v", service.Metadata.Name, err)
|
log.Debugf("Runtime error parsing build time for %s: %v", service.Metadata.Name, err)
|
||||||
@ -179,23 +243,31 @@ func (k *kubernetes) run(events <-chan runtime.Event) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
// check running services
|
// TODO: figure out what to do here
|
||||||
services, err := k.List()
|
// - do we even need the ticker for k8s services?
|
||||||
if err != nil {
|
case task := <-k.queue:
|
||||||
log.Debugf("Runtime failed listing running services: %v", err)
|
switch task.action {
|
||||||
|
case start:
|
||||||
|
log.Debugf("Runtime starting new service: %s", task.service.Name)
|
||||||
|
if err := task.service.Start(k.client); err != nil {
|
||||||
|
log.Debugf("Runtime failed to start service %s: %v", task.service.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO: for now we just log the running services
|
case stop:
|
||||||
// * make sure all core deployments exist
|
log.Debugf("Runtime stopping service: %s", task.service.Name)
|
||||||
// * make sure all core services are exposed
|
if err := task.service.Stop(k.client); err != nil {
|
||||||
for _, service := range services {
|
log.Debugf("Runtime failed to stop service %s: %v", task.service.Name, err)
|
||||||
log.Debugf("Runtime found running service: %v", service)
|
continue
|
||||||
|
}
|
||||||
|
case update:
|
||||||
|
log.Debugf("Runtime updating service: %s", task.service.Name)
|
||||||
|
if err := task.service.Update(k.client); err != nil {
|
||||||
|
log.Debugf("Runtime failed to update service %s: %v", task.service.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Debugf("Runtime received unknown action for service: %s", task.service.Name)
|
||||||
}
|
}
|
||||||
case service := <-k.start:
|
|
||||||
// TODO: this is a noop for now
|
|
||||||
// * create a deployment
|
|
||||||
// * expose a service
|
|
||||||
log.Debugf("Runtime starting service: %s", service.Name)
|
|
||||||
case event := <-events:
|
case event := <-events:
|
||||||
// NOTE: we only handle Update events for now
|
// NOTE: we only handle Update events for now
|
||||||
log.Debugf("Runtime received notification event: %v", event)
|
log.Debugf("Runtime received notification event: %v", event)
|
||||||
@ -207,50 +279,23 @@ func (k *kubernetes) run(events <-chan runtime.Event) {
|
|||||||
log.Debugf("Runtime error parsing update build time: %v", err)
|
log.Debugf("Runtime error parsing update build time: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
buildTime := time.Unix(updateTimeStamp, 0)
|
unixTimeUTC := time.Unix(updateTimeStamp, 0)
|
||||||
processEvent := func(event runtime.Event, service *runtime.Service) error {
|
|
||||||
buildTimeStamp, err := strconv.ParseInt(service.Version, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
muBuild := time.Unix(buildTimeStamp, 0)
|
|
||||||
if buildTime.After(muBuild) {
|
|
||||||
version := fmt.Sprintf("%d", buildTime.Unix())
|
|
||||||
muService := &runtime.Service{
|
|
||||||
Name: service.Name,
|
|
||||||
Source: service.Source,
|
|
||||||
Path: service.Path,
|
|
||||||
Exec: service.Exec,
|
|
||||||
Version: version,
|
|
||||||
}
|
|
||||||
if err := k.Update(muService); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
service.Version = version
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
k.Lock()
|
|
||||||
if len(event.Service) > 0 {
|
if len(event.Service) > 0 {
|
||||||
service, ok := k.services[event.Service]
|
s := &runtime.Service{
|
||||||
if !ok {
|
Name: event.Service,
|
||||||
log.Debugf("Runtime unknown service: %s", event.Service)
|
Version: event.Version,
|
||||||
k.Unlock()
|
}
|
||||||
|
// create new kubernetes micro service
|
||||||
|
service := newService(s, runtime.CreateOptions{})
|
||||||
|
// update build time annotation
|
||||||
|
service.kdeploy.Spec.Template.Metadata.Annotations["build"] = unixTimeUTC.Format(time.RFC3339)
|
||||||
|
|
||||||
|
log.Debugf("Runtime updating service: %s", service.Name)
|
||||||
|
if err := service.Update(k.client); err != nil {
|
||||||
|
log.Debugf("Runtime failed to update service %s: %v", service.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := processEvent(event, service); err != nil {
|
|
||||||
log.Debugf("Runtime error updating service %s: %v", event.Service, err)
|
|
||||||
}
|
}
|
||||||
k.Unlock()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// if blank service was received we update all services
|
|
||||||
for _, service := range k.services {
|
|
||||||
if err := processEvent(event, service); err != nil {
|
|
||||||
log.Debugf("Runtime error updating service %s: %v", service.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
k.Unlock()
|
|
||||||
}
|
}
|
||||||
case <-k.closed:
|
case <-k.closed:
|
||||||
log.Debugf("Runtime stopped")
|
log.Debugf("Runtime stopped")
|
||||||
|
106
runtime/kubernetes/service.go
Normal file
106
runtime/kubernetes/service.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/micro/go-micro/runtime"
|
||||||
|
"github.com/micro/go-micro/runtime/kubernetes/client"
|
||||||
|
"github.com/micro/go-micro/util/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
// service to manage
|
||||||
|
*runtime.Service
|
||||||
|
// Kubernetes service
|
||||||
|
kservice *client.Service
|
||||||
|
// Kubernetes deployment
|
||||||
|
kdeploy *client.Deployment
|
||||||
|
}
|
||||||
|
|
||||||
|
func newService(s *runtime.Service, c runtime.CreateOptions) *service {
|
||||||
|
kservice := client.DefaultService(s.Name, s.Version)
|
||||||
|
kdeploy := client.DefaultDeployment(s.Name, s.Version)
|
||||||
|
|
||||||
|
env := make([]client.EnvVar, 0, len(c.Env))
|
||||||
|
for _, evar := range c.Env {
|
||||||
|
evarPair := strings.Split(evar, "=")
|
||||||
|
env = append(env, client.EnvVar{Name: evarPair[0], Value: evarPair[1]})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should we append instead of overriding?
|
||||||
|
// if environment has been supplied update deployment
|
||||||
|
if len(env) > 0 {
|
||||||
|
kdeploy.Spec.Template.PodSpec.Containers[0].Env = env
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Command has been supplied override the default command
|
||||||
|
if len(c.Command) > 0 {
|
||||||
|
kdeploy.Spec.Template.PodSpec.Containers[0].Command = c.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
return &service{
|
||||||
|
Service: s,
|
||||||
|
kservice: kservice,
|
||||||
|
kdeploy: kdeploy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deploymentResource(d *client.Deployment) *client.Resource {
|
||||||
|
return &client.Resource{
|
||||||
|
Name: d.Metadata.Name,
|
||||||
|
Kind: "deployment",
|
||||||
|
Value: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serviceResource(s *client.Service) *client.Resource {
|
||||||
|
return &client.Resource{
|
||||||
|
Name: s.Metadata.Name,
|
||||||
|
Kind: "service",
|
||||||
|
Value: s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start starts the Kubernetes service. It creates new kubernetes deployment and service API objects
|
||||||
|
func (s *service) Start(k client.Kubernetes) error {
|
||||||
|
// create deployment first; if we fail, we dont create service
|
||||||
|
if err := k.Create(deploymentResource(s.kdeploy)); err != nil {
|
||||||
|
log.Debugf("Runtime failed to create deployment: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// create service now that the deployment has been created
|
||||||
|
if err := k.Create(serviceResource(s.kservice)); err != nil {
|
||||||
|
log.Debugf("Runtime failed to create service: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Stop(k client.Kubernetes) error {
|
||||||
|
// first attempt to delete service
|
||||||
|
if err := k.Delete(serviceResource(s.kservice)); err != nil {
|
||||||
|
log.Debugf("Runtime failed to delete service: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// delete deployment once the service has been deleted
|
||||||
|
if err := k.Delete(deploymentResource(s.kdeploy)); err != nil {
|
||||||
|
log.Debugf("Runtime failed to delete deployment: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Update(k client.Kubernetes) error {
|
||||||
|
if err := k.Update(deploymentResource(s.kdeploy)); err != nil {
|
||||||
|
log.Debugf("Runtime failed to update deployment: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := k.Update(serviceResource(s.kservice)); err != nil {
|
||||||
|
log.Debugf("Runtime failed to update service: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -54,3 +54,18 @@ func WithOutput(out io.Writer) CreateOption {
|
|||||||
o.Output = out
|
o.Output = out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetOption func(o *GetOptions)
|
||||||
|
|
||||||
|
// GetOptions queries runtime services
|
||||||
|
type GetOptions struct {
|
||||||
|
// Version queries services with given version
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithVersion confifgures service version
|
||||||
|
func WithVersion(version string) GetOption {
|
||||||
|
return func(o *GetOptions) {
|
||||||
|
o.Version = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,17 +12,19 @@ var (
|
|||||||
type Runtime interface {
|
type Runtime interface {
|
||||||
// Init initializes runtime
|
// Init initializes runtime
|
||||||
Init(...Option) error
|
Init(...Option) error
|
||||||
// Registers a service
|
// Create registers a service
|
||||||
Create(*Service, ...CreateOption) error
|
Create(*Service, ...CreateOption) error
|
||||||
// Remove a service
|
// Get returns service or fails with error
|
||||||
Delete(*Service) error
|
Get(string, ...GetOption) ([]*Service, error)
|
||||||
// Update the service in place
|
// Update the service in place
|
||||||
Update(*Service) error
|
Update(*Service) error
|
||||||
|
// Remove a service
|
||||||
|
Delete(*Service) error
|
||||||
// List the managed services
|
// List the managed services
|
||||||
List() ([]*Service, error)
|
List() ([]*Service, error)
|
||||||
// starts the runtime
|
// Start starts the runtime
|
||||||
Start() error
|
Start() error
|
||||||
// Shutdown the runtime
|
// Stop shuts down the runtime
|
||||||
Stop() error
|
Stop() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +32,48 @@ func toService(s *pb.Service) *runtime.Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toCreateOptions(opts *pb.CreateOptions) []runtime.CreateOption {
|
||||||
|
options := []runtime.CreateOption{}
|
||||||
|
// command options
|
||||||
|
l := len(opts.Command)
|
||||||
|
if l == 1 {
|
||||||
|
options = append(options, runtime.WithCommand(opts.Command[0]))
|
||||||
|
}
|
||||||
|
if l > 1 {
|
||||||
|
options = append(options, runtime.WithCommand(opts.Command[0], opts.Command[1:]...))
|
||||||
|
}
|
||||||
|
// env options
|
||||||
|
if len(opts.Env) > 0 {
|
||||||
|
options = append(options, runtime.WithEnv(opts.Env))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: output options
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
func toGetOptions(opts *pb.GetOptions) []runtime.GetOption {
|
||||||
|
options := []runtime.GetOption{}
|
||||||
|
// version options
|
||||||
|
if len(opts.Version) > 0 {
|
||||||
|
options = append(options, runtime.WithVersion(opts.Version))
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error {
|
func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error {
|
||||||
if req.Service == nil {
|
if req.Service == nil {
|
||||||
return errors.BadRequest("go.micro.runtime", "blank service")
|
return errors.BadRequest("go.micro.runtime", "blank service")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add opts
|
var options []runtime.CreateOption
|
||||||
|
if req.Options != nil {
|
||||||
|
options = toCreateOptions(req.Options)
|
||||||
|
}
|
||||||
|
|
||||||
service := toService(req.Service)
|
service := toService(req.Service)
|
||||||
err := r.Runtime.Create(service)
|
err := r.Runtime.Create(service, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.InternalServerError("go.micro.runtime", err.Error())
|
return errors.InternalServerError("go.micro.runtime", err.Error())
|
||||||
}
|
}
|
||||||
@ -47,6 +81,28 @@ func (r *Runtime) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.Cre
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) Get(ctx context.Context, req *pb.GetRequest, rsp *pb.GetResponse) error {
|
||||||
|
if len(req.Name) == 0 {
|
||||||
|
return errors.BadRequest("go.micro.runtime", "blank service")
|
||||||
|
}
|
||||||
|
|
||||||
|
var options []runtime.GetOption
|
||||||
|
if req.Options != nil {
|
||||||
|
options = toGetOptions(req.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
services, err := r.Runtime.Get(req.Name, options...)
|
||||||
|
if err != nil {
|
||||||
|
return errors.InternalServerError("go.micro.runtime", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, service := range services {
|
||||||
|
rsp.Services = append(rsp.Services, toProto(service))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Runtime) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error {
|
func (r *Runtime) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error {
|
||||||
if req.Service == nil {
|
if req.Service == nil {
|
||||||
return errors.BadRequest("go.micro.runtime", "blank service")
|
return errors.BadRequest("go.micro.runtime", "blank service")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||||
// source: micro/go-micro/runtime/service/proto/runtime.proto
|
// source: runtime.proto
|
||||||
|
|
||||||
package go_micro_runtime
|
package go_micro_runtime
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ var _ server.Option
|
|||||||
|
|
||||||
type RuntimeService interface {
|
type RuntimeService interface {
|
||||||
Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error)
|
Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error)
|
||||||
|
Get(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error)
|
||||||
Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error)
|
Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error)
|
||||||
Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error)
|
Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error)
|
||||||
List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error)
|
List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error)
|
||||||
@ -68,6 +69,16 @@ func (c *runtimeService) Create(ctx context.Context, in *CreateRequest, opts ...
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *runtimeService) Get(ctx context.Context, in *GetRequest, opts ...client.CallOption) (*GetResponse, error) {
|
||||||
|
req := c.c.NewRequest(c.name, "Runtime.Get", in)
|
||||||
|
out := new(GetResponse)
|
||||||
|
err := c.c.Call(ctx, req, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *runtimeService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) {
|
func (c *runtimeService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) {
|
||||||
req := c.c.NewRequest(c.name, "Runtime.Delete", in)
|
req := c.c.NewRequest(c.name, "Runtime.Delete", in)
|
||||||
out := new(DeleteResponse)
|
out := new(DeleteResponse)
|
||||||
@ -102,6 +113,7 @@ func (c *runtimeService) List(ctx context.Context, in *ListRequest, opts ...clie
|
|||||||
|
|
||||||
type RuntimeHandler interface {
|
type RuntimeHandler interface {
|
||||||
Create(context.Context, *CreateRequest, *CreateResponse) error
|
Create(context.Context, *CreateRequest, *CreateResponse) error
|
||||||
|
Get(context.Context, *GetRequest, *GetResponse) error
|
||||||
Delete(context.Context, *DeleteRequest, *DeleteResponse) error
|
Delete(context.Context, *DeleteRequest, *DeleteResponse) error
|
||||||
Update(context.Context, *UpdateRequest, *UpdateResponse) error
|
Update(context.Context, *UpdateRequest, *UpdateResponse) error
|
||||||
List(context.Context, *ListRequest, *ListResponse) error
|
List(context.Context, *ListRequest, *ListResponse) error
|
||||||
@ -110,6 +122,7 @@ type RuntimeHandler interface {
|
|||||||
func RegisterRuntimeHandler(s server.Server, hdlr RuntimeHandler, opts ...server.HandlerOption) error {
|
func RegisterRuntimeHandler(s server.Server, hdlr RuntimeHandler, opts ...server.HandlerOption) error {
|
||||||
type runtime interface {
|
type runtime interface {
|
||||||
Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error
|
Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error
|
||||||
|
Get(ctx context.Context, in *GetRequest, out *GetResponse) error
|
||||||
Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error
|
Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error
|
||||||
Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error
|
Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error
|
||||||
List(ctx context.Context, in *ListRequest, out *ListResponse) error
|
List(ctx context.Context, in *ListRequest, out *ListResponse) error
|
||||||
@ -129,6 +142,10 @@ func (h *runtimeHandler) Create(ctx context.Context, in *CreateRequest, out *Cre
|
|||||||
return h.RuntimeHandler.Create(ctx, in, out)
|
return h.RuntimeHandler.Create(ctx, in, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *runtimeHandler) Get(ctx context.Context, in *GetRequest, out *GetResponse) error {
|
||||||
|
return h.RuntimeHandler.Get(ctx, in, out)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *runtimeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error {
|
func (h *runtimeHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error {
|
||||||
return h.RuntimeHandler.Delete(ctx, in, out)
|
return h.RuntimeHandler.Delete(ctx, in, out)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: micro/go-micro/runtime/service/proto/runtime.proto
|
// source: runtime.proto
|
||||||
|
|
||||||
package go_micro_runtime
|
package go_micro_runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
|
||||||
fmt "fmt"
|
fmt "fmt"
|
||||||
proto "github.com/golang/protobuf/proto"
|
proto "github.com/golang/protobuf/proto"
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
math "math"
|
math "math"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +40,7 @@ func (m *Service) Reset() { *m = Service{} }
|
|||||||
func (m *Service) String() string { return proto.CompactTextString(m) }
|
func (m *Service) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Service) ProtoMessage() {}
|
func (*Service) ProtoMessage() {}
|
||||||
func (*Service) Descriptor() ([]byte, []int) {
|
func (*Service) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{0}
|
return fileDescriptor_86e2dd377c869464, []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Service) XXX_Unmarshal(b []byte) error {
|
func (m *Service) XXX_Unmarshal(b []byte) error {
|
||||||
@ -98,9 +96,9 @@ func (m *Service) GetExec() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options struct {
|
type CreateOptions struct {
|
||||||
// command to pass in
|
// command to pass in
|
||||||
Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"`
|
Command []string `protobuf:"bytes,1,rep,name=command,proto3" json:"command,omitempty"`
|
||||||
// environment to pass in
|
// environment to pass in
|
||||||
Env []string `protobuf:"bytes,2,rep,name=env,proto3" json:"env,omitempty"`
|
Env []string `protobuf:"bytes,2,rep,name=env,proto3" json:"env,omitempty"`
|
||||||
// output to send to
|
// output to send to
|
||||||
@ -110,46 +108,46 @@ type Options struct {
|
|||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Options) Reset() { *m = Options{} }
|
func (m *CreateOptions) Reset() { *m = CreateOptions{} }
|
||||||
func (m *Options) String() string { return proto.CompactTextString(m) }
|
func (m *CreateOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Options) ProtoMessage() {}
|
func (*CreateOptions) ProtoMessage() {}
|
||||||
func (*Options) Descriptor() ([]byte, []int) {
|
func (*CreateOptions) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{1}
|
return fileDescriptor_86e2dd377c869464, []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Options) XXX_Unmarshal(b []byte) error {
|
func (m *CreateOptions) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Options.Unmarshal(m, b)
|
return xxx_messageInfo_CreateOptions.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *CreateOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Options.Marshal(b, m, deterministic)
|
return xxx_messageInfo_CreateOptions.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (m *Options) XXX_Merge(src proto.Message) {
|
func (m *CreateOptions) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Options.Merge(m, src)
|
xxx_messageInfo_CreateOptions.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Options) XXX_Size() int {
|
func (m *CreateOptions) XXX_Size() int {
|
||||||
return xxx_messageInfo_Options.Size(m)
|
return xxx_messageInfo_CreateOptions.Size(m)
|
||||||
}
|
}
|
||||||
func (m *Options) XXX_DiscardUnknown() {
|
func (m *CreateOptions) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_Options.DiscardUnknown(m)
|
xxx_messageInfo_CreateOptions.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_Options proto.InternalMessageInfo
|
var xxx_messageInfo_CreateOptions proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *Options) GetCommand() string {
|
func (m *CreateOptions) GetCommand() []string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Command
|
return m.Command
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Options) GetEnv() []string {
|
func (m *CreateOptions) GetEnv() []string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Env
|
return m.Env
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Options) GetOutput() string {
|
func (m *CreateOptions) GetOutput() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Output
|
return m.Output
|
||||||
}
|
}
|
||||||
@ -158,7 +156,7 @@ func (m *Options) GetOutput() string {
|
|||||||
|
|
||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
||||||
Options *Options `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"`
|
Options *CreateOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
@ -168,7 +166,7 @@ func (m *CreateRequest) Reset() { *m = CreateRequest{} }
|
|||||||
func (m *CreateRequest) String() string { return proto.CompactTextString(m) }
|
func (m *CreateRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*CreateRequest) ProtoMessage() {}
|
func (*CreateRequest) ProtoMessage() {}
|
||||||
func (*CreateRequest) Descriptor() ([]byte, []int) {
|
func (*CreateRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{2}
|
return fileDescriptor_86e2dd377c869464, []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CreateRequest) XXX_Unmarshal(b []byte) error {
|
func (m *CreateRequest) XXX_Unmarshal(b []byte) error {
|
||||||
@ -196,7 +194,7 @@ func (m *CreateRequest) GetService() *Service {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CreateRequest) GetOptions() *Options {
|
func (m *CreateRequest) GetOptions() *CreateOptions {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Options
|
return m.Options
|
||||||
}
|
}
|
||||||
@ -213,7 +211,7 @@ func (m *CreateResponse) Reset() { *m = CreateResponse{} }
|
|||||||
func (m *CreateResponse) String() string { return proto.CompactTextString(m) }
|
func (m *CreateResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*CreateResponse) ProtoMessage() {}
|
func (*CreateResponse) ProtoMessage() {}
|
||||||
func (*CreateResponse) Descriptor() ([]byte, []int) {
|
func (*CreateResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{3}
|
return fileDescriptor_86e2dd377c869464, []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CreateResponse) XXX_Unmarshal(b []byte) error {
|
func (m *CreateResponse) XXX_Unmarshal(b []byte) error {
|
||||||
@ -234,6 +232,132 @@ func (m *CreateResponse) XXX_DiscardUnknown() {
|
|||||||
|
|
||||||
var xxx_messageInfo_CreateResponse proto.InternalMessageInfo
|
var xxx_messageInfo_CreateResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
type GetOptions struct {
|
||||||
|
// version of the service
|
||||||
|
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetOptions) Reset() { *m = GetOptions{} }
|
||||||
|
func (m *GetOptions) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*GetOptions) ProtoMessage() {}
|
||||||
|
func (*GetOptions) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_86e2dd377c869464, []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetOptions) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_GetOptions.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *GetOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_GetOptions.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *GetOptions) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_GetOptions.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *GetOptions) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_GetOptions.Size(m)
|
||||||
|
}
|
||||||
|
func (m *GetOptions) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_GetOptions.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_GetOptions proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *GetOptions) GetVersion() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Version
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetRequest struct {
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
Options *GetOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetRequest) Reset() { *m = GetRequest{} }
|
||||||
|
func (m *GetRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*GetRequest) ProtoMessage() {}
|
||||||
|
func (*GetRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_86e2dd377c869464, []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetRequest) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_GetRequest.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *GetRequest) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_GetRequest.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *GetRequest) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_GetRequest.Size(m)
|
||||||
|
}
|
||||||
|
func (m *GetRequest) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_GetRequest.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_GetRequest proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *GetRequest) GetName() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetRequest) GetOptions() *GetOptions {
|
||||||
|
if m != nil {
|
||||||
|
return m.Options
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetResponse struct {
|
||||||
|
Services []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetResponse) Reset() { *m = GetResponse{} }
|
||||||
|
func (m *GetResponse) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*GetResponse) ProtoMessage() {}
|
||||||
|
func (*GetResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_86e2dd377c869464, []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *GetResponse) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_GetResponse.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *GetResponse) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_GetResponse.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *GetResponse) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_GetResponse.Size(m)
|
||||||
|
}
|
||||||
|
func (m *GetResponse) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_GetResponse.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_GetResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *GetResponse) GetServices() []*Service {
|
||||||
|
if m != nil {
|
||||||
|
return m.Services
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteRequest struct {
|
type DeleteRequest struct {
|
||||||
Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
@ -245,7 +369,7 @@ func (m *DeleteRequest) Reset() { *m = DeleteRequest{} }
|
|||||||
func (m *DeleteRequest) String() string { return proto.CompactTextString(m) }
|
func (m *DeleteRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*DeleteRequest) ProtoMessage() {}
|
func (*DeleteRequest) ProtoMessage() {}
|
||||||
func (*DeleteRequest) Descriptor() ([]byte, []int) {
|
func (*DeleteRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{4}
|
return fileDescriptor_86e2dd377c869464, []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DeleteRequest) XXX_Unmarshal(b []byte) error {
|
func (m *DeleteRequest) XXX_Unmarshal(b []byte) error {
|
||||||
@ -283,7 +407,7 @@ func (m *DeleteResponse) Reset() { *m = DeleteResponse{} }
|
|||||||
func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
|
func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*DeleteResponse) ProtoMessage() {}
|
func (*DeleteResponse) ProtoMessage() {}
|
||||||
func (*DeleteResponse) Descriptor() ([]byte, []int) {
|
func (*DeleteResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{5}
|
return fileDescriptor_86e2dd377c869464, []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
|
func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
|
||||||
@ -315,7 +439,7 @@ func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
|
|||||||
func (m *UpdateRequest) String() string { return proto.CompactTextString(m) }
|
func (m *UpdateRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UpdateRequest) ProtoMessage() {}
|
func (*UpdateRequest) ProtoMessage() {}
|
||||||
func (*UpdateRequest) Descriptor() ([]byte, []int) {
|
func (*UpdateRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{6}
|
return fileDescriptor_86e2dd377c869464, []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UpdateRequest) XXX_Unmarshal(b []byte) error {
|
func (m *UpdateRequest) XXX_Unmarshal(b []byte) error {
|
||||||
@ -353,7 +477,7 @@ func (m *UpdateResponse) Reset() { *m = UpdateResponse{} }
|
|||||||
func (m *UpdateResponse) String() string { return proto.CompactTextString(m) }
|
func (m *UpdateResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UpdateResponse) ProtoMessage() {}
|
func (*UpdateResponse) ProtoMessage() {}
|
||||||
func (*UpdateResponse) Descriptor() ([]byte, []int) {
|
func (*UpdateResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{7}
|
return fileDescriptor_86e2dd377c869464, []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UpdateResponse) XXX_Unmarshal(b []byte) error {
|
func (m *UpdateResponse) XXX_Unmarshal(b []byte) error {
|
||||||
@ -384,7 +508,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} }
|
|||||||
func (m *ListRequest) String() string { return proto.CompactTextString(m) }
|
func (m *ListRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListRequest) ProtoMessage() {}
|
func (*ListRequest) ProtoMessage() {}
|
||||||
func (*ListRequest) Descriptor() ([]byte, []int) {
|
func (*ListRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{8}
|
return fileDescriptor_86e2dd377c869464, []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ListRequest) XXX_Unmarshal(b []byte) error {
|
func (m *ListRequest) XXX_Unmarshal(b []byte) error {
|
||||||
@ -416,7 +540,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} }
|
|||||||
func (m *ListResponse) String() string { return proto.CompactTextString(m) }
|
func (m *ListResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListResponse) ProtoMessage() {}
|
func (*ListResponse) ProtoMessage() {}
|
||||||
func (*ListResponse) Descriptor() ([]byte, []int) {
|
func (*ListResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_4bc91a8efec81434, []int{9}
|
return fileDescriptor_86e2dd377c869464, []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ListResponse) XXX_Unmarshal(b []byte) error {
|
func (m *ListResponse) XXX_Unmarshal(b []byte) error {
|
||||||
@ -446,9 +570,12 @@ func (m *ListResponse) GetServices() []*Service {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*Service)(nil), "go.micro.runtime.Service")
|
proto.RegisterType((*Service)(nil), "go.micro.runtime.Service")
|
||||||
proto.RegisterType((*Options)(nil), "go.micro.runtime.Options")
|
proto.RegisterType((*CreateOptions)(nil), "go.micro.runtime.CreateOptions")
|
||||||
proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest")
|
proto.RegisterType((*CreateRequest)(nil), "go.micro.runtime.CreateRequest")
|
||||||
proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse")
|
proto.RegisterType((*CreateResponse)(nil), "go.micro.runtime.CreateResponse")
|
||||||
|
proto.RegisterType((*GetOptions)(nil), "go.micro.runtime.GetOptions")
|
||||||
|
proto.RegisterType((*GetRequest)(nil), "go.micro.runtime.GetRequest")
|
||||||
|
proto.RegisterType((*GetResponse)(nil), "go.micro.runtime.GetResponse")
|
||||||
proto.RegisterType((*DeleteRequest)(nil), "go.micro.runtime.DeleteRequest")
|
proto.RegisterType((*DeleteRequest)(nil), "go.micro.runtime.DeleteRequest")
|
||||||
proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse")
|
proto.RegisterType((*DeleteResponse)(nil), "go.micro.runtime.DeleteResponse")
|
||||||
proto.RegisterType((*UpdateRequest)(nil), "go.micro.runtime.UpdateRequest")
|
proto.RegisterType((*UpdateRequest)(nil), "go.micro.runtime.UpdateRequest")
|
||||||
@ -457,205 +584,35 @@ func init() {
|
|||||||
proto.RegisterType((*ListResponse)(nil), "go.micro.runtime.ListResponse")
|
proto.RegisterType((*ListResponse)(nil), "go.micro.runtime.ListResponse")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() { proto.RegisterFile("runtime.proto", fileDescriptor_86e2dd377c869464) }
|
||||||
proto.RegisterFile("micro/go-micro/runtime/service/proto/runtime.proto", fileDescriptor_4bc91a8efec81434)
|
|
||||||
}
|
var fileDescriptor_86e2dd377c869464 = []byte{
|
||||||
|
// 425 bytes of a gzipped FileDescriptorProto
|
||||||
var fileDescriptor_4bc91a8efec81434 = []byte{
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xc9, 0xcb, 0xd3, 0x40,
|
||||||
// 379 bytes of a gzipped FileDescriptorProto
|
0x14, 0xff, 0xda, 0xd4, 0x44, 0x5f, 0x8c, 0x94, 0x39, 0xc8, 0x58, 0x5c, 0xca, 0x1c, 0xc4, 0x53,
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xcb, 0x4e, 0xc2, 0x40,
|
0x0e, 0x2d, 0x0a, 0x9e, 0x8d, 0xf4, 0x62, 0x11, 0x52, 0x04, 0xaf, 0x31, 0x7d, 0x68, 0xc0, 0x64,
|
||||||
0x14, 0x86, 0x81, 0x22, 0x95, 0x83, 0x18, 0x32, 0x0b, 0x33, 0x92, 0xa8, 0x4d, 0x57, 0x6c, 0x2c,
|
0x62, 0x66, 0x52, 0xbd, 0x79, 0xf2, 0xff, 0x96, 0xd9, 0xba, 0xa4, 0x93, 0xef, 0xd2, 0xdb, 0xbc,
|
||||||
0x09, 0xc4, 0x27, 0x10, 0xe3, 0x46, 0x62, 0x52, 0xe3, 0x03, 0xd4, 0x72, 0x82, 0x4d, 0x6c, 0xa7,
|
0xa5, 0xbf, 0xf7, 0x5b, 0x4a, 0x20, 0xe9, 0xfa, 0x46, 0x56, 0x35, 0xa6, 0x6d, 0xc7, 0x25, 0x27,
|
||||||
0xce, 0x4c, 0x51, 0x9f, 0xce, 0x57, 0x33, 0x73, 0x43, 0x81, 0xe2, 0x86, 0xdd, 0xb9, 0x7e, 0xff,
|
0xf3, 0xef, 0x3c, 0xad, 0xab, 0xb2, 0xe3, 0xa9, 0xed, 0xb3, 0xdf, 0x10, 0xed, 0xb0, 0x3b, 0x54,
|
||||||
0x99, 0xbf, 0x29, 0x4c, 0xf2, 0x2c, 0xe5, 0x6c, 0xbc, 0x64, 0xd7, 0x26, 0xe0, 0x55, 0x21, 0xb3,
|
0x25, 0x12, 0x02, 0xb3, 0xa6, 0xa8, 0x91, 0x4e, 0x96, 0x93, 0x37, 0x8f, 0x72, 0xfd, 0x26, 0x14,
|
||||||
0x1c, 0xc7, 0x02, 0xf9, 0x2a, 0x4b, 0x71, 0x5c, 0x72, 0x26, 0xd7, 0xd5, 0x48, 0x67, 0x64, 0xb0,
|
0xa2, 0x03, 0x76, 0xa2, 0xe2, 0x0d, 0x9d, 0xea, 0xb6, 0x2b, 0xc9, 0x53, 0x08, 0x05, 0xef, 0xbb,
|
||||||
0x64, 0x91, 0x9e, 0x8e, 0x6c, 0x3d, 0xfc, 0x00, 0xff, 0xc9, 0x2c, 0x10, 0x02, 0xed, 0x22, 0xc9,
|
0x12, 0x69, 0xa0, 0x07, 0xb6, 0x52, 0x28, 0x6d, 0x21, 0x7f, 0xd0, 0x99, 0x41, 0x51, 0x6f, 0xd5,
|
||||||
0x91, 0x36, 0x83, 0xe6, 0xa8, 0x1b, 0xeb, 0x98, 0x50, 0xf0, 0x57, 0xc8, 0x45, 0xc6, 0x0a, 0xda,
|
0xc3, 0x3f, 0x58, 0xd2, 0x07, 0xa6, 0xa7, 0xde, 0x6c, 0x07, 0xc9, 0x87, 0x0e, 0x0b, 0x89, 0x9f,
|
||||||
0xd2, 0x65, 0x97, 0x92, 0x33, 0xe8, 0x08, 0x56, 0xf1, 0x14, 0xa9, 0xa7, 0x1b, 0x36, 0x53, 0x94,
|
0x5b, 0x59, 0xf1, 0x46, 0xa8, 0x53, 0x25, 0xaf, 0xeb, 0xa2, 0xd9, 0xd3, 0xc9, 0x32, 0x50, 0xa7,
|
||||||
0x32, 0x91, 0xaf, 0xb4, 0x6d, 0x28, 0x2a, 0x56, 0x35, 0xfc, 0xc4, 0x94, 0x1e, 0x99, 0x9a, 0x8a,
|
0x6c, 0x49, 0xe6, 0x10, 0x60, 0x73, 0xa0, 0x53, 0xdd, 0x55, 0x4f, 0x75, 0x9c, 0xf7, 0xb2, 0xed,
|
||||||
0xc3, 0x39, 0xf8, 0x8f, 0xa5, 0xcc, 0x58, 0x21, 0x94, 0x48, 0xca, 0xf2, 0x3c, 0x29, 0x16, 0x56,
|
0xa5, 0x3b, 0x6e, 0x2a, 0xf6, 0xd7, 0x81, 0xe6, 0xf8, 0xab, 0x47, 0x21, 0xc9, 0x1a, 0x22, 0x61,
|
||||||
0xdb, 0xa5, 0x64, 0x00, 0x1e, 0x16, 0x2b, 0xda, 0x0a, 0xbc, 0x51, 0x37, 0x56, 0xa1, 0x92, 0x65,
|
0xe4, 0x69, 0x59, 0xf1, 0xea, 0x59, 0x3a, 0xb4, 0x20, 0xb5, 0xfa, 0x73, 0xb7, 0x49, 0xde, 0x43,
|
||||||
0x95, 0x2c, 0x2b, 0xe9, 0x64, 0x4d, 0x16, 0x7e, 0x41, 0xff, 0x96, 0x63, 0x22, 0x31, 0xc6, 0xf7,
|
0xc4, 0x0d, 0x29, 0x2d, 0x3a, 0x5e, 0xbd, 0xba, 0xfe, 0xd1, 0x05, 0xf7, 0xdc, 0xed, 0xb3, 0x39,
|
||||||
0x0a, 0x85, 0x24, 0x53, 0xf0, 0xad, 0x13, 0x1a, 0xda, 0x9b, 0x9c, 0x47, 0xdb, 0x8f, 0x8f, 0xec,
|
0x3c, 0x71, 0x04, 0x44, 0xcb, 0x1b, 0x81, 0xec, 0x35, 0xc0, 0x06, 0xe5, 0x99, 0x48, 0xbf, 0x9f,
|
||||||
0xcb, 0x63, 0x37, 0xa9, 0x96, 0x98, 0x39, 0x4a, 0x3f, 0xb7, 0x76, 0xc9, 0x5e, 0x1d, 0xbb, 0xc9,
|
0xec, 0xab, 0xde, 0x73, 0xbc, 0x7d, 0x59, 0xbc, 0x1b, 0xd2, 0x7a, 0x7e, 0x4d, 0xeb, 0x74, 0xea,
|
||||||
0x70, 0x00, 0xa7, 0x4e, 0x5a, 0x94, 0xac, 0x10, 0x18, 0xce, 0xa0, 0x3f, 0xc3, 0x37, 0x3c, 0xec,
|
0xc4, 0x29, 0x83, 0x58, 0x23, 0x1b, 0x42, 0xe4, 0x2d, 0x3c, 0xb4, 0x42, 0x85, 0x36, 0xfa, 0x5e,
|
||||||
0x18, 0xc5, 0x75, 0x94, 0x5f, 0xee, 0x73, 0xb9, 0x48, 0x0e, 0xe7, 0x3a, 0x8a, 0xe5, 0xf6, 0xa1,
|
0x4f, 0x8e, 0xab, 0x2c, 0x83, 0x24, 0xc3, 0x9f, 0x78, 0x9b, 0xb5, 0xca, 0x1f, 0x87, 0x62, 0xfd,
|
||||||
0xf7, 0x90, 0x09, 0x69, 0xa9, 0xe1, 0x1d, 0x9c, 0x98, 0xd4, 0xb4, 0xc9, 0x0d, 0x1c, 0xdb, 0x5d,
|
0xc9, 0x20, 0xf9, 0xd2, 0xee, 0x8b, 0xdb, 0x71, 0x1d, 0x8a, 0xc5, 0x4d, 0x20, 0xfe, 0x54, 0x09,
|
||||||
0x41, 0x9b, 0x81, 0xf7, 0xbf, 0xcc, 0x7a, 0x74, 0xf2, 0xdd, 0x02, 0x3f, 0x36, 0x5d, 0x32, 0x87,
|
0x67, 0x28, 0xfb, 0x08, 0x8f, 0x4d, 0x79, 0x93, 0x0b, 0xab, 0x7f, 0x01, 0x44, 0xb9, 0x99, 0x92,
|
||||||
0x8e, 0xf1, 0x88, 0x5c, 0xed, 0xae, 0x6e, 0x7c, 0xb8, 0x61, 0xb0, 0x7f, 0xc0, 0x9e, 0xdb, 0x50,
|
0x2d, 0x84, 0x26, 0x6b, 0x32, 0xfa, 0xff, 0xb0, 0xd7, 0x17, 0xcb, 0xf1, 0x05, 0x4b, 0xf7, 0x8e,
|
||||||
0x38, 0x63, 0x4d, 0x1d, 0x6e, 0xc3, 0xfa, 0x3a, 0xdc, 0x96, 0xab, 0x1a, 0x67, 0x1c, 0xa9, 0xc3,
|
0x64, 0x10, 0x6c, 0x50, 0x12, 0x7f, 0xa8, 0x0e, 0xe8, 0xc5, 0xc8, 0xf4, 0x88, 0xb2, 0x85, 0xd0,
|
||||||
0x6d, 0x38, 0x5e, 0x87, 0xdb, 0x32, 0xb3, 0x41, 0xee, 0xa1, 0xad, 0xfc, 0x23, 0x17, 0xbb, 0xb3,
|
0x18, 0xec, 0x23, 0x75, 0x11, 0xa0, 0x8f, 0xd4, 0x20, 0x1b, 0x0d, 0x67, 0x7c, 0xf5, 0xc1, 0x5d,
|
||||||
0x7f, 0x6c, 0x1e, 0x5e, 0xee, 0x6b, 0x3b, 0xd0, 0x4b, 0x47, 0xff, 0xb5, 0xd3, 0x9f, 0x00, 0x00,
|
0xe4, 0xe6, 0x83, 0x1b, 0x44, 0x72, 0x47, 0x36, 0x30, 0x53, 0x29, 0x10, 0x8f, 0x8c, 0xb3, 0xb0,
|
||||||
0x00, 0xff, 0xff, 0x69, 0x49, 0x0f, 0xe1, 0xeb, 0x03, 0x00, 0x00,
|
0x16, 0x2f, 0xc7, 0xc6, 0x0e, 0xe8, 0x5b, 0xa8, 0xbf, 0x67, 0xeb, 0xff, 0x01, 0x00, 0x00, 0xff,
|
||||||
}
|
0xff, 0x19, 0x21, 0xd3, 0xfb, 0xe0, 0x04, 0x00, 0x00,
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ context.Context
|
|
||||||
var _ grpc.ClientConn
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
const _ = grpc.SupportPackageIsVersion4
|
|
||||||
|
|
||||||
// RuntimeClient is the client API for Runtime service.
|
|
||||||
//
|
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
|
||||||
type RuntimeClient interface {
|
|
||||||
Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error)
|
|
||||||
Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
|
||||||
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error)
|
|
||||||
List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type runtimeClient struct {
|
|
||||||
cc *grpc.ClientConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRuntimeClient(cc *grpc.ClientConn) RuntimeClient {
|
|
||||||
return &runtimeClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *runtimeClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) {
|
|
||||||
out := new(CreateResponse)
|
|
||||||
err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Create", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *runtimeClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
|
|
||||||
out := new(DeleteResponse)
|
|
||||||
err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Delete", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *runtimeClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) {
|
|
||||||
out := new(UpdateResponse)
|
|
||||||
err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/Update", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *runtimeClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) {
|
|
||||||
out := new(ListResponse)
|
|
||||||
err := c.cc.Invoke(ctx, "/go.micro.runtime.Runtime/List", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RuntimeServer is the server API for Runtime service.
|
|
||||||
type RuntimeServer interface {
|
|
||||||
Create(context.Context, *CreateRequest) (*CreateResponse, error)
|
|
||||||
Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
|
|
||||||
Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
|
|
||||||
List(context.Context, *ListRequest) (*ListResponse, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterRuntimeServer(s *grpc.Server, srv RuntimeServer) {
|
|
||||||
s.RegisterService(&_Runtime_serviceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Runtime_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(CreateRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(RuntimeServer).Create(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/go.micro.runtime.Runtime/Create",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(RuntimeServer).Create(ctx, req.(*CreateRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Runtime_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(DeleteRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(RuntimeServer).Delete(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/go.micro.runtime.Runtime/Delete",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(RuntimeServer).Delete(ctx, req.(*DeleteRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Runtime_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(UpdateRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(RuntimeServer).Update(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/go.micro.runtime.Runtime/Update",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(RuntimeServer).Update(ctx, req.(*UpdateRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Runtime_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(ListRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(RuntimeServer).List(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/go.micro.runtime.Runtime/List",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(RuntimeServer).List(ctx, req.(*ListRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _Runtime_serviceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "go.micro.runtime.Runtime",
|
|
||||||
HandlerType: (*RuntimeServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{
|
|
||||||
{
|
|
||||||
MethodName: "Create",
|
|
||||||
Handler: _Runtime_Create_Handler,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MethodName: "Delete",
|
|
||||||
Handler: _Runtime_Delete_Handler,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MethodName: "Update",
|
|
||||||
Handler: _Runtime_Update_Handler,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MethodName: "List",
|
|
||||||
Handler: _Runtime_List_Handler,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Streams: []grpc.StreamDesc{},
|
|
||||||
Metadata: "micro/go-micro/runtime/service/proto/runtime.proto",
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ package go.micro.runtime;
|
|||||||
|
|
||||||
service Runtime {
|
service Runtime {
|
||||||
rpc Create(CreateRequest) returns (CreateResponse) {};
|
rpc Create(CreateRequest) returns (CreateResponse) {};
|
||||||
|
rpc Get(GetRequest) returns (GetResponse) {};
|
||||||
rpc Delete(DeleteRequest) returns (DeleteResponse) {};
|
rpc Delete(DeleteRequest) returns (DeleteResponse) {};
|
||||||
rpc Update(UpdateRequest) returns (UpdateResponse) {};
|
rpc Update(UpdateRequest) returns (UpdateResponse) {};
|
||||||
rpc List(ListRequest) returns (ListResponse) {};
|
rpc List(ListRequest) returns (ListResponse) {};
|
||||||
@ -22,9 +23,9 @@ message Service {
|
|||||||
string exec = 5;
|
string exec = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Options {
|
message CreateOptions {
|
||||||
// command to pass in
|
// command to pass in
|
||||||
string command = 1;
|
repeated string command = 1;
|
||||||
// environment to pass in
|
// environment to pass in
|
||||||
repeated string env = 2;
|
repeated string env = 2;
|
||||||
// output to send to
|
// output to send to
|
||||||
@ -33,11 +34,25 @@ message Options {
|
|||||||
|
|
||||||
message CreateRequest {
|
message CreateRequest {
|
||||||
Service service = 1;
|
Service service = 1;
|
||||||
Options options = 2;
|
CreateOptions options = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateResponse {}
|
message CreateResponse {}
|
||||||
|
|
||||||
|
message GetOptions {
|
||||||
|
// version of the service
|
||||||
|
string version = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetRequest {
|
||||||
|
string name = 1;
|
||||||
|
GetOptions options = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetResponse {
|
||||||
|
repeated Service services = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message DeleteRequest {
|
message DeleteRequest {
|
||||||
Service service = 1;
|
Service service = 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user