Skip to content

Commit

Permalink
Migrate replication controllers to generic etcd
Browse files Browse the repository at this point in the history
  • Loading branch information
bprashanth committed Mar 24, 2015
1 parent 8065fb5 commit ef66016
Show file tree
Hide file tree
Showing 10 changed files with 821 additions and 648 deletions.
40 changes: 40 additions & 0 deletions pkg/api/rest/resttest/resttest.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd"
)

type Tester struct {
Expand Down Expand Up @@ -197,6 +199,44 @@ func (t *Tester) TestCreateRejectsNamespace(valid runtime.Object) {
}
}

func (t *Tester) TestDeleteInvokesValidation(invalid ...runtime.Object) {
for i, obj := range invalid {
objectMeta, err := api.ObjectMetaFor(obj)
if err != nil {
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj)
}
ctx := api.NewDefaultContext()
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil)
if !errors.IsInvalid(err) {
t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err)
}
}
}

func (t *Tester) TestDelete(createFn func() runtime.Object, wasGracefulFn func() bool, invalid ...runtime.Object) {
t.TestDeleteNonExist(createFn)
t.TestDeleteNoGraceful(createFn, wasGracefulFn)
t.TestDeleteInvokesValidation(invalid...)
// TODO: Test delete namespace mismatch rejection
// once #5684 is fixed.
}

func (t *Tester) TestDeleteNonExist(createFn func() runtime.Object) {
existing := createFn()
objectMeta, err := api.ObjectMetaFor(existing)
if err != nil {
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing)
}
context := api.NewDefaultContext()

t.withStorageError(&etcd.EtcdError{ErrorCode: tools.EtcdErrorCodeNotFound}, func() {
_, err := t.storage.(rest.GracefulDeleter).Delete(context, objectMeta.Name, nil)
if err == nil || !errors.IsNotFound(err) {
t.Fatalf("Unexpected error: %v", err)
}
})
}

func (t *Tester) TestDeleteGraceful(createFn func() runtime.Object, expectedGrace int64, wasGracefulFn func() bool) {
t.TestDeleteGracefulHasDefault(createFn(), expectedGrace, wasGracefulFn)
t.TestDeleteGracefulUsesZeroOnNil(createFn(), 0)
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/replication_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type RealPodControl struct {
}

// Time period of main replication controller sync loop
const DefaultSyncPeriod = 10 * time.Second
const DefaultSyncPeriod = 5 * time.Second

func (r RealPodControl) createReplica(namespace string, controller api.ReplicationController) {
desiredLabels := make(labels.Set)
Expand Down
6 changes: 4 additions & 2 deletions pkg/master/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/controller"
controlleretcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/controller/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/endpoint"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/event"
Expand Down Expand Up @@ -384,14 +384,16 @@ func (m *Master) init(c *Config) {
podStorage = podStorage.WithPodStatus(podCache)
}

controllerStorage := controlleretcd.NewREST(c.EtcdHelper)

// TODO: Factor out the core API registration
m.storage = map[string]rest.Storage{
"pods": podStorage,
"pods/status": podStatusStorage,
"pods/binding": bindingStorage,
"bindings": bindingStorage,

"replicationControllers": controller.NewStorage(registry, podRegistry),
"replicationControllers": controllerStorage,
"services": service.NewStorage(m.serviceRegistry, c.Cloud, m.nodeRegistry, m.portalNet, c.ClusterName),
"endpoints": endpoint.NewStorage(m.endpointRegistry),
"minions": nodeStorage,
Expand Down
76 changes: 76 additions & 0 deletions pkg/registry/controller/etcd/etcd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package etcd

import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/controller"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
)

// rest implements a RESTStorage for replication controllers against etcd
type REST struct {
*etcdgeneric.Etcd
}

// controllerPrefix is the location for controllers in etcd, only exposed
// for testing
var controllerPrefix = "/registry/controllers"

// NewREST returns a RESTStorage object that will work against replication controllers.
func NewREST(h tools.EtcdHelper) *REST {
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.ReplicationController{} },

// NewListFunc returns an object capable of storing results of an etcd list.
NewListFunc: func() runtime.Object { return &api.ReplicationControllerList{} },
// Produces a path that etcd understands, to the root of the resource
// by combining the namespace in the context with the given prefix
KeyRootFunc: func(ctx api.Context) string {
return etcdgeneric.NamespaceKeyRootFunc(ctx, controllerPrefix)
},
// Produces a path that etcd understands, to the resource by combining
// the namespace in the context with the given prefix
KeyFunc: func(ctx api.Context, name string) (string, error) {
return etcdgeneric.NamespaceKeyFunc(ctx, controllerPrefix, name)
},
// Retrieve the name field of a replication controller
ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*api.ReplicationController).Name, nil
},
// Used to match objects based on labels/fields for list and watch
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return controller.MatchController(label, field)
},
EndpointName: "replicationControllers",

// Used to validate controller creation
CreateStrategy: controller.Strategy,

// Used to validate controller updates
UpdateStrategy: controller.Strategy,

Helper: h,
}

return &REST{store}
}
Loading

0 comments on commit ef66016

Please sign in to comment.