mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-15 22:20:51 +00:00
Add name generation and normalize common create flows
Adds `ObjectMeta.GenerateName`, an optional string field that defines name generation behavior if a Name is not provided. Adds `pkg/api/rest`, which defines the default Kubernetes API pattern for creation (and will cover update as well). Will allow registries and REST objects to be merged by moving logic on api out of those places. Add `pkg/api/rest/resttest`, which will be the test suite that verifies a RESTStorage object follows the Kubernetes API conventions and begin reducing our duplicated tests.
This commit is contained in:
@@ -21,12 +21,12 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"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/apiserver"
|
||||
rc "github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
@@ -55,23 +55,14 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a replication controller: %#v", obj)
|
||||
}
|
||||
if !api.ValidNamespace(ctx, &controller.ObjectMeta) {
|
||||
return nil, errors.NewConflict("controller", controller.Namespace, fmt.Errorf("Controller.Namespace does not match the provided context"))
|
||||
}
|
||||
|
||||
if len(controller.Name) == 0 {
|
||||
controller.Name = string(util.NewUUID())
|
||||
if err := rest.BeforeCreate(rest.ReplicationControllers, ctx, obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
|
||||
return nil, errors.NewInvalid("replicationController", controller.Name, errs)
|
||||
}
|
||||
|
||||
api.FillObjectMetaSystemFields(ctx, &controller.ObjectMeta)
|
||||
|
||||
return apiserver.MakeAsync(func() (runtime.Object, error) {
|
||||
err := rs.registry.CreateController(ctx, controller)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err := rs.registry.CreateController(ctx, controller); err != nil {
|
||||
return apiserver.RESTResult{}, err
|
||||
}
|
||||
return rs.registry.GetController(ctx, controller.Name)
|
||||
}), nil
|
||||
|
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
|
||||
@@ -106,6 +107,7 @@ func TestListControllerList(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove, this is sufficiently covered by other tests
|
||||
func TestControllerDecode(t *testing.T) {
|
||||
mockRegistry := registrytest.ControllerRegistry{}
|
||||
storage := REST{
|
||||
@@ -140,6 +142,7 @@ func TestControllerDecode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this is sufficiently covered by other tetss
|
||||
func TestControllerParsing(t *testing.T) {
|
||||
expectedController := api.ReplicationController{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@@ -228,6 +231,7 @@ var validPodTemplate = api.PodTemplate{
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: remove, this is sufficiently covered by other tests
|
||||
func TestCreateController(t *testing.T) {
|
||||
mockRegistry := registrytest.ControllerRegistry{}
|
||||
mockPodRegistry := registrytest.PodRegistry{
|
||||
@@ -274,6 +278,7 @@ func TestCreateController(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove, covered by TestCreate
|
||||
func TestControllerStorageValidatesCreate(t *testing.T) {
|
||||
mockRegistry := registrytest.ControllerRegistry{}
|
||||
storage := REST{
|
||||
@@ -376,6 +381,32 @@ func TestFillCurrentState(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove, covered by TestCreate
|
||||
func TestCreateControllerWithGeneratedName(t *testing.T) {
|
||||
storage := NewREST(®istrytest.ControllerRegistry{}, nil)
|
||||
controller := &api.ReplicationController{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Namespace: api.NamespaceDefault,
|
||||
GenerateName: "rc-",
|
||||
},
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
Replicas: 2,
|
||||
Selector: map[string]string{"a": "b"},
|
||||
Template: &validPodTemplate.Spec,
|
||||
},
|
||||
}
|
||||
|
||||
ctx := api.NewDefaultContext()
|
||||
_, err := storage.Create(ctx, controller)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if controller.Name == "rc-" || !strings.HasPrefix(controller.Name, "rc-") {
|
||||
t.Errorf("unexpected name: %#v", controller)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove, covered by TestCreate
|
||||
func TestCreateControllerWithConflictingNamespace(t *testing.T) {
|
||||
storage := REST{}
|
||||
controller := &api.ReplicationController{
|
||||
@@ -389,7 +420,7 @@ func TestCreateControllerWithConflictingNamespace(t *testing.T) {
|
||||
}
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error, but we didn't get one")
|
||||
} else if strings.Index(err.Error(), "Controller.Namespace does not match the provided context") == -1 {
|
||||
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
|
||||
t.Errorf("Expected 'Controller.Namespace does not match the provided context' error, got '%v'", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -411,3 +442,25 @@ func TestUpdateControllerWithConflictingNamespace(t *testing.T) {
|
||||
t.Errorf("Expected 'Controller.Namespace does not match the provided context' error, got '%v'", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
test := resttest.New(t, NewREST(®istrytest.ControllerRegistry{}, nil))
|
||||
test.TestCreate(
|
||||
// valid
|
||||
&api.ReplicationController{
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
Replicas: 2,
|
||||
Selector: map[string]string{"a": "b"},
|
||||
Template: &validPodTemplate.Spec,
|
||||
},
|
||||
},
|
||||
// invalid
|
||||
&api.ReplicationController{
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
Replicas: 2,
|
||||
Selector: map[string]string{},
|
||||
Template: &validPodTemplate.Spec,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user