port minion registry to generic etcd

This commit is contained in:
Masahiro Sano
2015-03-13 23:49:38 +09:00
parent 2ad3af246a
commit c49af0b7cb
9 changed files with 538 additions and 602 deletions

View File

@@ -17,7 +17,6 @@ limitations under the License.
package minion
import (
"errors"
"fmt"
"net"
"net/http"
@@ -25,135 +24,79 @@ import (
"strconv"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
)
// REST adapts minion into apiserver's RESTStorage model.
type REST struct {
registry Registry
connection client.ConnectionInfoGetter
// nodeStrategy implements behavior for nodes
type nodeStrategy struct {
runtime.ObjectTyper
api.NameGenerator
}
// NewStorage returns a new rest.Storage implementation for minion.
func NewStorage(m Registry, connection client.ConnectionInfoGetter) *REST {
return &REST{
registry: m,
connection: connection,
}
// Nodes is the default logic that applies when creating and updating Node
// objects.
var Strategy = nodeStrategy{api.Scheme, api.SimpleNameGenerator}
// NamespaceScoped is false for nodes.
func (nodeStrategy) NamespaceScoped() bool {
return false
}
var ErrDoesNotExist = errors.New("The requested resource does not exist.")
// Create satisfies the RESTStorage interface.
func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) {
minion, ok := obj.(*api.Node)
if !ok {
return nil, fmt.Errorf("not a minion: %#v", obj)
}
if err := rest.BeforeCreate(rest.Nodes, ctx, obj); err != nil {
return nil, err
}
if err := rs.registry.CreateMinion(ctx, minion); err != nil {
err = rest.CheckGeneratedNameError(rest.Nodes, err, minion)
return nil, err
}
return minion, nil
// AllowCreateOnUpdate is false for nodes.
func (nodeStrategy) AllowCreateOnUpdate() bool {
return false
}
// Delete satisfies the RESTStorage interface.
func (rs *REST) Delete(ctx api.Context, id string) (runtime.Object, error) {
minion, err := rs.registry.GetMinion(ctx, id)
if minion == nil {
return nil, ErrDoesNotExist
}
if err != nil {
return nil, err
}
return &api.Status{Status: api.StatusSuccess}, rs.registry.DeleteMinion(ctx, id)
// ResetBeforeCreate clears fields that are not allowed to be set by end users on creation.
func (nodeStrategy) ResetBeforeCreate(obj runtime.Object) {
_ = obj.(*api.Node)
// Nodes allow *all* fields, including status, to be set.
}
// Get satisfies the RESTStorage interface.
func (rs *REST) Get(ctx api.Context, id string) (runtime.Object, error) {
minion, err := rs.registry.GetMinion(ctx, id)
if err != nil {
return minion, err
}
if minion == nil {
return nil, ErrDoesNotExist
}
return minion, err
// Validate validates a new node.
func (nodeStrategy) Validate(obj runtime.Object) fielderrors.ValidationErrorList {
node := obj.(*api.Node)
return validation.ValidateMinion(node)
}
// List satisfies the RESTStorage interface.
func (rs *REST) List(ctx api.Context, label labels.Selector, field fields.Selector) (runtime.Object, error) {
return rs.registry.ListMinions(ctx)
// ValidateUpdate is the default update validation for an end user.
func (nodeStrategy) ValidateUpdate(obj, old runtime.Object) fielderrors.ValidationErrorList {
return validation.ValidateMinionUpdate(old.(*api.Node), obj.(*api.Node))
}
func (rs *REST) New() runtime.Object {
return &api.Node{}
// ResourceGetter is an interface for retrieving resources by ResourceLocation.
type ResourceGetter interface {
Get(api.Context, string) (runtime.Object, error)
}
func (*REST) NewList() runtime.Object {
return &api.NodeList{}
// MatchNode returns a generic matcher for a given label and field selector.
func MatchNode(label labels.Selector, field fields.Selector) generic.Matcher {
return generic.MatcherFunc(func(obj runtime.Object) (bool, error) {
nodeObj, ok := obj.(*api.Node)
if !ok {
return false, fmt.Errorf("not a node")
}
// TODO: Add support for filtering based on field, once NodeStatus is defined.
return label.Matches(labels.Set(nodeObj.Labels)), nil
})
}
// Update satisfies the RESTStorage interface.
func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
minion, ok := obj.(*api.Node)
if !ok {
return nil, false, fmt.Errorf("not a minion: %#v", obj)
}
// This is hacky, but minions don't really have a namespace, but kubectl currently automatically
// stuffs one in there. Fix it here temporarily until we fix kubectl
if minion.Namespace == api.NamespaceDefault {
minion.Namespace = api.NamespaceNone
}
// Clear out the self link, if specified, since it's not in the registry either.
minion.SelfLink = ""
oldMinion, err := rs.registry.GetMinion(ctx, minion.Name)
if err != nil {
return nil, false, err
}
if errs := validation.ValidateMinionUpdate(oldMinion, minion); len(errs) > 0 {
return nil, false, kerrors.NewInvalid("minion", minion.Name, errs)
}
if err := rs.registry.UpdateMinion(ctx, minion); err != nil {
return nil, false, err
}
out, err := rs.registry.GetMinion(ctx, minion.Name)
return out, false, err
}
// Watch returns Minions events via a watch.Interface.
// It implements rest.Watcher.
func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return rs.registry.WatchMinions(ctx, label, field, resourceVersion)
}
// Implement Redirector.
var _ = rest.Redirector(&REST{})
// ResourceLocation returns a URL to which one can send traffic for the specified minion.
func (rs *REST) ResourceLocation(ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
minion, err := rs.registry.GetMinion(ctx, id)
// ResourceLocation returns a URL to which one can send traffic for the specified node.
func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
nodeObj, err := getter.Get(ctx, id)
if err != nil {
return nil, nil, err
}
host := minion.Name
node := nodeObj.(*api.Node)
host := node.Name
scheme, port, transport, err := rs.connection.GetConnectionInfo(host)
scheme, port, transport, err := connection.GetConnectionInfo(host)
if err != nil {
return nil, nil, err
}