1
0
mirror of https://github.com/go-micro/go-micro.git synced 2025-06-18 22:17:44 +02:00

[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:
Milos Gajdos
2019-11-15 13:41:40 +00:00
committed by Asim Aslam
parent 0af8be35bb
commit 97c1300f53
23 changed files with 1284 additions and 646 deletions

View File

@ -1,6 +1,7 @@
package client
import (
"bytes"
"crypto/tls"
"errors"
"io/ioutil"
@ -13,6 +14,7 @@ import (
)
var (
// path to kubernetes service account token
serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
// ErrReadNamespace is returned when the names could not be read from service account
ErrReadNamespace = errors.New("Could not read namespace from service account secret")
@ -23,9 +25,7 @@ type client struct {
opts *api.Options
}
// NewClientInCluster should work similarily to the official api
// NewInClient by setting up a client configuration for use within
// a k8s pod.
// NewClientInCluster creates a Kubernetes client for use from within a k8s pod.
func NewClientInCluster() *client {
host := "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT")
@ -34,7 +34,7 @@ func NewClientInCluster() *client {
log.Fatal(err)
}
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"))
@ -90,26 +90,72 @@ func detectNamespace() (string, error) {
}
}
// UpdateDeployment patches kubernetes deployment with metadata provided in body
func (c *client) UpdateDeployment(name string, body interface{}) error {
// Create creates new API object
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).
Patch().
Resource("deployments").
Name(name).
Body(body).
Post().
SetHeader("Content-Type", "application/yaml").
Resource(r.Kind).
Body(b).
Do().
Error()
}
// ListDeployments lists all kubernetes deployments with given labels
func (c *client) ListDeployments(labels map[string]string) (*DeploymentList, error) {
var deployments DeploymentList
err := api.NewRequest(c.opts).
// Get queries API objects and stores the result in r
func (c *client) Get(r *Resource, labels map[string]string) error {
return api.NewRequest(c.opts).
Get().
Resource("deployments").
Resource(r.Kind).
Params(&api.Params{LabelSelector: labels}).
Do().
Into(&deployments)
return &deployments, err
Into(r.Value)
}
// 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)
}