micro/runtime/kubernetes/client/kubernetes.go
Milos Gajdos 97c1300f53 [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
2019-11-15 13:41:40 +00:00

133 lines
2.9 KiB
Go

// Package client provides an implementation of a restricted subset of kubernetes API 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
type Kubernetes interface {
// Create creates new API resource
Create(*Resource) error
// Get queries API resrouces
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
}
// DefaultService returns default micro kubernetes service definition
func DefaultService(name, version string) *Service {
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,
}
}
// DefaultService returns default micro kubernetes deployment definition
func DefaultDeployment(name, version string) *Deployment {
Labels := map[string]string{
"name": name,
"version": version,
"micro": "service",
}
// API deployment object name joins name and version over "="
depName := strings.Join([]string{name, version}, "-")
Metadata := &Metadata{
Name: depName,
Namespace: "default",
Version: version,
Labels: Labels,
}
// TODO: we need to figure out this version stuff
// might be worth adding Build to runtime.Service
buildTime, err := strconv.ParseInt(version, 10, 64)
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)
}
// TODO: change the image name here
Spec := &DeploymentSpec{
Replicas: 1,
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,
}
}