Ejemplo n.º 1
0
func TestUpdateImageStreamOK(t *testing.T) {
	fakeEtcdClient, helper := newHelper(t)
	fakeEtcdClient.Data["/imagestreams/default/bar"] = tools.EtcdResponseWithError{
		R: &etcd.Response{
			Node: &etcd.Node{
				Value: runtime.EncodeOrDie(latest.Codec, &api.ImageStream{
					ObjectMeta: kapi.ObjectMeta{Name: "bar", Namespace: "default"},
				}),
				ModifiedIndex: 2,
			},
		},
	}
	storage, _ := NewREST(helper, noDefaultRegistry, &fakeSubjectAccessReviewRegistry{})

	ctx := kapi.WithUser(kapi.NewDefaultContext(), &fakeUser{})
	obj, created, err := storage.Update(ctx, &api.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: "bar", ResourceVersion: "1"}})
	if !errors.IsConflict(err) {
		t.Fatalf("unexpected non-error: %v", err)
	}
	obj, created, err = storage.Update(ctx, &api.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: "bar", ResourceVersion: "2"}})
	if err != nil || created {
		t.Fatalf("Unexpected non-nil error: %#v", err)
	}
	stream, ok := obj.(*api.ImageStream)
	if !ok {
		t.Errorf("Expected image stream, got %#v", obj)
	}
	if stream.Name != "bar" {
		t.Errorf("Unexpected stream returned: %#v", stream)
	}
}
Ejemplo n.º 2
0
func TestEtcdControllerValidatesUpdate(t *testing.T) {
	ctx := api.NewDefaultContext()
	storage, _ := newStorage(t)

	updateController, err := createController(storage, validController, t)
	if err != nil {
		t.Errorf("Failed to create controller, cannot proceed with test.")
	}

	updaters := []func(rc api.ReplicationController) (runtime.Object, bool, error){
		func(rc api.ReplicationController) (runtime.Object, bool, error) {
			rc.UID = "newUID"
			return storage.Update(ctx, &rc)
		},
		func(rc api.ReplicationController) (runtime.Object, bool, error) {
			rc.Name = ""
			return storage.Update(ctx, &rc)
		},
		func(rc api.ReplicationController) (runtime.Object, bool, error) {
			rc.Spec.Selector = map[string]string{}
			return storage.Update(ctx, &rc)
		},
	}
	for _, u := range updaters {
		c, updated, err := u(updateController)
		if c != nil || updated {
			t.Errorf("Expected nil object and not created")
		}
		if !errors.IsInvalid(err) && !errors.IsBadRequest(err) {
			t.Errorf("Expected invalid or bad request error, got %v of type %T", err, err)
		}
	}
}
Ejemplo n.º 3
0
func TestGenerationNumber(t *testing.T) {
	storage, _ := newStorage(t)
	modifiedSno := validController
	modifiedSno.Generation = 100
	modifiedSno.Status.ObservedGeneration = 10
	ctx := api.NewDefaultContext()
	rc, err := createController(storage, modifiedSno, t)
	ctrl, err := storage.Get(ctx, rc.Name)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	controller, _ := ctrl.(*api.ReplicationController)

	// Generation initialization
	if controller.Generation != 1 && controller.Status.ObservedGeneration != 0 {
		t.Fatalf("Unexpected generation number %v, status generation %v", controller.Generation, controller.Status.ObservedGeneration)
	}

	// Updates to spec should increment the generation number
	controller.Spec.Replicas += 1
	storage.Update(ctx, controller)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	ctrl, err = storage.Get(ctx, rc.Name)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	controller, _ = ctrl.(*api.ReplicationController)
	if controller.Generation != 2 || controller.Status.ObservedGeneration != 0 {
		t.Fatalf("Unexpected generation, spec: %v, status: %v", controller.Generation, controller.Status.ObservedGeneration)
	}

	// Updates to status should not increment either spec or status generation numbers
	controller.Status.Replicas += 1
	storage.Update(ctx, controller)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	ctrl, err = storage.Get(ctx, rc.Name)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	controller, _ = ctrl.(*api.ReplicationController)
	if controller.Generation != 2 || controller.Status.ObservedGeneration != 0 {
		t.Fatalf("Unexpected generation number, spec: %v, status: %v", controller.Generation, controller.Status.ObservedGeneration)
	}
}
Ejemplo n.º 4
0
func TestEtcdUpdateEndpoints(t *testing.T) {
	ctx := api.NewDefaultContext()
	storage, fakeClient := newStorage(t)
	endpoints := validChangedEndpoints()

	key, _ := storage.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewEndpoints()), 0)

	_, _, err := storage.Update(ctx, endpoints)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	response, err := fakeClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("Unexpected error %v", err)
	}
	var endpointsOut api.Endpoints
	err = latest.Codec.DecodeInto([]byte(response.Node.Value), &endpointsOut)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	endpoints.ObjectMeta.ResourceVersion = endpointsOut.ObjectMeta.ResourceVersion
	if !api.Semantic.DeepEqual(endpoints, &endpointsOut) {
		t.Errorf("Unexpected endpoints: %#v, expected %#v", &endpointsOut, endpoints)
	}
}
Ejemplo n.º 5
0
func TestEtcdUpdateEndpoints(t *testing.T) {
	ctx := api.NewContext()
	storage, fakeClient := newStorage(t)
	node := validChangedNode()

	key, _ := storage.KeyFunc(ctx, node.Name)
	key = etcdtest.AddPrefix(key)
	fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewNode()), 0)

	_, _, err := storage.Update(ctx, node)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	response, err := fakeClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("Unexpected error %v", err)
	}
	var nodeOut api.Node
	err = latest.Codec.DecodeInto([]byte(response.Node.Value), &nodeOut)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	node.ObjectMeta.ResourceVersion = nodeOut.ObjectMeta.ResourceVersion
	if !api.Semantic.DeepEqual(node, &nodeOut) {
		t.Errorf("Unexpected node: %#v, expected %#v", &nodeOut, node)
	}
}
Ejemplo n.º 6
0
func TestEtcdUpdateNotScheduled(t *testing.T) {
	storage, _, _, server := newStorage(t)
	defer server.Terminate(t)
	defer storage.Store.DestroyFunc()
	ctx := api.NewDefaultContext()

	key, _ := storage.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	if _, err := storage.Create(ctx, validNewPod()); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	podIn := validChangedPod()
	_, _, err := storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(podIn, api.Scheme))
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}
	obj, err := storage.Get(ctx, validNewPod().ObjectMeta.Name)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	podOut := obj.(*api.Pod)
	// validChangedPod only changes the Labels, so were checking the update was valid
	if !api.Semantic.DeepEqual(podIn.Labels, podOut.Labels) {
		t.Errorf("objects differ: %v", diff.ObjectDiff(podOut, podIn))
	}
}
Ejemplo n.º 7
0
func TestUpdateWithConflictingNamespace(t *testing.T) {
	fakeEtcdClient, etcdStorage := newEtcdStorage(t)
	storage := NewStorage(etcdStorage, nil).Pod
	ctx := api.NewDefaultContext()
	key, _ := storage.Etcd.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
		R: &etcd.Response{
			Node: &etcd.Node{
				Value: runtime.EncodeOrDie(latest.Codec, &api.Pod{
					ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "default"},
					Spec:       api.PodSpec{NodeName: "machine"},
				}),
				ModifiedIndex: 1,
			},
		},
	}

	pod := validChangedPod()
	pod.Namespace = "not-default"

	obj, created, err := storage.Update(api.NewDefaultContext(), pod)
	if obj != nil || created {
		t.Error("Expected a nil channel, but we got a value or created")
	}
	if err == nil {
		t.Errorf("Expected an error, but we didn't get one")
	} else if strings.Index(err.Error(), "the namespace of the provided object does not match the namespace sent on the request") == -1 {
		t.Errorf("Expected 'Pod.Namespace does not match the provided context' error, got '%v'", err.Error())
	}
}
Ejemplo n.º 8
0
func TestUpdateImageStreamConflictingNamespace(t *testing.T) {
	fakeEtcdClient, helper := newHelper(t)
	fakeEtcdClient.Data["/imagestreams/legal-name/bar"] = tools.EtcdResponseWithError{
		R: &etcd.Response{
			Node: &etcd.Node{
				Value: runtime.EncodeOrDie(latest.Codec, &api.ImageStream{
					ObjectMeta: kapi.ObjectMeta{Name: "bar", Namespace: "default"},
				}),
				ModifiedIndex: 2,
			},
		},
	}
	storage, _ := NewREST(helper, noDefaultRegistry, &fakeSubjectAccessReviewRegistry{})

	ctx := kapi.WithUser(kapi.WithNamespace(kapi.NewContext(), "legal-name"), &fakeUser{})
	obj, created, err := storage.Update(ctx, &api.ImageStream{
		ObjectMeta: kapi.ObjectMeta{Name: "bar", Namespace: "some-value", ResourceVersion: "2"},
	})

	if obj != nil || created {
		t.Error("Expected a nil obj, but we got a value")
	}

	checkExpectedNamespaceError(t, err)
}
Ejemplo n.º 9
0
func TestStrategyPrepareMethods(t *testing.T) {
	_, helper := newHelper(t)
	storage, _ := NewREST(helper, testDefaultRegistry, &fakeSubjectAccessReviewRegistry{})
	stream := validNewStream()
	strategy := fakeStrategy{imagestream.NewStrategy(testDefaultRegistry, &fakeSubjectAccessReviewRegistry{})}

	storage.store.CreateStrategy = strategy
	storage.store.UpdateStrategy = strategy

	ctx := kapi.WithUser(kapi.NewDefaultContext(), &fakeUser{})
	obj, err := storage.Create(ctx, stream)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	updatedStream := obj.(*api.ImageStream)
	if updatedStream.Annotations["test"] != "PrepareForCreate" {
		t.Errorf("Expected PrepareForCreate annotation")
	}

	obj, _, err = storage.Update(ctx, updatedStream)
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	updatedStream = obj.(*api.ImageStream)
	if updatedStream.Annotations["test"] != "PrepareForUpdate" {
		t.Errorf("Expected PrepareForUpdate annotation")
	}
}
Ejemplo n.º 10
0
func TestEtcdUpdatePersistentVolumes(t *testing.T) {
	ctx := api.NewContext()
	storage, _, fakeClient, _ := newStorage(t)
	persistentVolume := validChangedPersistentVolume()

	key, _ := storage.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("foo")), 0)

	_, _, err := storage.Update(ctx, persistentVolume)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	response, err := fakeClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("Unexpected error %v", err)
	}
	var persistentVolumeOut api.PersistentVolume
	err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	persistentVolume.ObjectMeta.ResourceVersion = persistentVolumeOut.ObjectMeta.ResourceVersion
	if !api.Semantic.DeepEqual(persistentVolume, &persistentVolumeOut) {
		t.Errorf("Unexpected persistentVolume: %#v, expected %#v", &persistentVolumeOut, persistentVolume)
	}
}
Ejemplo n.º 11
0
func TestUpdate(t *testing.T) {
	storage, _, si, destroyFunc := newStorage(t)
	defer destroyFunc()

	ctx := api.WithNamespace(api.NewContext(), "test")
	key := "/controllers/test/foo"
	if err := si.Create(ctx, key, &validController, nil, 0); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	replicas := int32(12)
	update := extensions.Scale{
		ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"},
		Spec: extensions.ScaleSpec{
			Replicas: replicas,
		},
	}

	if _, _, err := storage.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	updated := obj.(*extensions.Scale)
	if updated.Spec.Replicas != replicas {
		t.Errorf("wrong replicas count expected: %d got: %d", replicas, updated.Spec.Replicas)
	}
}
Ejemplo n.º 12
0
func TestUpdate(t *testing.T) {
	storage, fakeClient := newStorage(t)

	ctx := api.WithNamespace(api.NewContext(), "test")
	key := etcdtest.AddPrefix("/controllers/test/foo")
	if _, err := fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), &validController), 0); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	replicas := 12
	update := extensions.Scale{
		ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"},
		Spec: extensions.ScaleSpec{
			Replicas: replicas,
		},
	}

	if _, _, err := storage.Update(ctx, &update); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	response, err := fakeClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	var controller api.ReplicationController
	testapi.Extensions.Codec().DecodeInto([]byte(response.Node.Value), &controller)
	if controller.Spec.Replicas != replicas {
		t.Errorf("wrong replicas count expected: %d got: %d", replicas, controller.Spec.Replicas)
	}
}
Ejemplo n.º 13
0
func TestUpdate(t *testing.T) {
	storage, server, si := newStorage(t)
	defer server.Terminate(t)

	ctx := api.WithNamespace(api.NewContext(), "test")
	key := etcdtest.AddPrefix("/controllers/test/foo")
	if err := si.Set(ctx, key, &validController, nil, 0); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	replicas := 12
	update := extensions.Scale{
		ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"},
		Spec: extensions.ScaleSpec{
			Replicas: replicas,
		},
	}

	if _, _, err := storage.Update(ctx, &update); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	obj, err := storage.Get(ctx, "foo")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	updated := obj.(*extensions.Scale)
	if updated.Spec.Replicas != replicas {
		t.Errorf("wrong replicas count expected: %d got: %d", replicas, updated.Spec.Replicas)
	}
}
Ejemplo n.º 14
0
func TestUpdateRegistryErrorSaving(t *testing.T) {
	fakeEtcdClient, helper := newHelper(t)
	fakeEtcdClient.Err = fmt.Errorf("foo")
	storage, _ := NewREST(helper, noDefaultRegistry, &fakeSubjectAccessReviewRegistry{})

	_, created, err := storage.Update(kapi.NewDefaultContext(), &api.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: "bar"}})
	if err != fakeEtcdClient.Err || created {
		t.Fatalf("Unexpected non-nil error: %#v", err)
	}
}
Ejemplo n.º 15
0
func TestUpdateImageStreamMissingID(t *testing.T) {
	_, helper := newHelper(t)
	storage, _ := NewREST(helper, noDefaultRegistry, &fakeSubjectAccessReviewRegistry{})

	obj, created, err := storage.Update(kapi.NewDefaultContext(), &api.ImageStream{})
	if obj != nil || created {
		t.Fatalf("Expected nil, got %v", obj)
	}
	if strings.Index(err.Error(), "Name parameter required") == -1 {
		t.Errorf("Expected 'Name parameter required' error, got %v", err)
	}
}
Ejemplo n.º 16
0
func TestEtcdControllerValidatesNamespaceOnUpdate(t *testing.T) {
	storage, _ := newStorage(t)
	ns := "newnamespace"

	// The update should fail if the namespace on the controller is set to something
	// other than the namespace on the given context, even if the namespace on the
	// controller is valid.
	updateController, err := createController(storage, validController, t)

	newNamespaceController := validController
	newNamespaceController.Namespace = ns
	_, err = createController(storage, newNamespaceController, t)

	c, updated, err := storage.Update(api.WithNamespace(api.NewContext(), ns), &updateController)
	if c != nil || updated {
		t.Errorf("Expected nil object and not created")
	}
	// TODO: Be more paranoid about the type of error and make sure it has the substring
	// "namespace" in it, once #5684 is fixed. Ideally this would be a NewBadRequest.
	if err == nil {
		t.Errorf("Expected an error, but we didn't get one")
	}
}
Ejemplo n.º 17
0
func TestEtcdUpdateNotScheduled(t *testing.T) {
	storage, _, _, fakeClient := newStorage(t)
	ctx := api.NewDefaultContext()
	fakeClient.TestIndex = true

	key, _ := storage.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), validNewPod()), 1)

	podIn := validChangedPod()
	_, _, err := storage.Update(ctx, podIn)
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}
	response, err := fakeClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}
	podOut := &api.Pod{}
	testapi.Default.Codec().DecodeInto([]byte(response.Node.Value), podOut)
	if !api.Semantic.DeepEqual(podOut, podIn) {
		t.Errorf("objects differ: %v", util.ObjectDiff(podOut, podIn))
	}
}
Ejemplo n.º 18
0
func TestEtcdUpdateController(t *testing.T) {
	ctx := api.NewDefaultContext()
	storage, fakeClient := newStorage(t)
	key, _ := makeControllerKey(ctx, validController.Name)
	key = etcdtest.AddPrefix(key)

	// set a key, then retrieve the current resource version and try updating it
	resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &validController), 0)
	update := validController
	update.ResourceVersion = strconv.FormatUint(resp.Node.ModifiedIndex, 10)
	update.Spec.Replicas = validController.Spec.Replicas + 1
	_, created, err := storage.Update(ctx, &update)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	if created {
		t.Errorf("expected an update but created flag was returned")
	}
	ctrl, err := storage.Get(ctx, validController.Name)
	updatedController, _ := ctrl.(*api.ReplicationController)
	if updatedController.Spec.Replicas != validController.Spec.Replicas+1 {
		t.Errorf("Unexpected controller: %#v", ctrl)
	}
}
Ejemplo n.º 19
0
func TestUpdate(t *testing.T) {
	fakeEtcdClient, etcdStorage := newEtcdStorage(t)
	storage := NewStorage(etcdStorage).Scale

	key := etcdtest.AddPrefix("/controllers/test/foo")
	fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
		R: &etcd.Response{
			Node: &etcd.Node{
				Value:         runtime.EncodeOrDie(latest.Codec, &validController),
				ModifiedIndex: 1,
			},
		},
	}
	replicas := 12
	update := expapi.Scale{
		ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"},
		Spec: expapi.ScaleSpec{
			Replicas: replicas,
		},
	}

	_, _, err := storage.Update(api.WithNamespace(api.NewContext(), "test"), &update)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}
	response, err := fakeEtcdClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	var controller api.ReplicationController
	latest.Codec.DecodeInto([]byte(response.Node.Value), &controller)
	if controller.Spec.Replicas != replicas {
		t.Errorf("wrong replicas count expected: %d got: %d", replicas, controller.Spec.Replicas)
	}
}
Ejemplo n.º 20
0
func TestEtcdUpdateScheduled(t *testing.T) {
	storage, _, _, server := newStorage(t)
	defer server.Terminate(t)
	defer storage.Store.DestroyFunc()
	ctx := api.NewDefaultContext()

	key, _ := storage.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	err := storage.Storage.Create(ctx, key, &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "foo",
			Namespace: api.NamespaceDefault,
		},
		Spec: api.PodSpec{
			NodeName: "machine",
			Containers: []api.Container{
				{
					Name:            "foobar",
					Image:           "foo:v1",
					SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(),
				},
			},
			SecurityContext: &api.PodSecurityContext{},
		},
	}, nil, 1)
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	grace := int64(30)
	podIn := api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name: "foo",
			Labels: map[string]string{
				"foo": "bar",
			},
		},
		Spec: api.PodSpec{
			NodeName: "machine",
			Containers: []api.Container{{
				Name:                   "foobar",
				Image:                  "foo:v2",
				ImagePullPolicy:        api.PullIfNotPresent,
				TerminationMessagePath: api.TerminationMessagePathDefault,
				SecurityContext:        securitycontext.ValidSecurityContextWithContainerDefaults(),
			}},
			RestartPolicy: api.RestartPolicyAlways,
			DNSPolicy:     api.DNSClusterFirst,

			TerminationGracePeriodSeconds: &grace,
			SecurityContext:               &api.PodSecurityContext{},
		},
	}
	_, _, err = storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme))
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	obj, err := storage.Get(ctx, "foo")
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}
	podOut := obj.(*api.Pod)
	// Check to verify the Spec and Label updates match from change above.  Those are the fields changed.
	if !api.Semantic.DeepEqual(podOut.Spec, podIn.Spec) || !api.Semantic.DeepEqual(podOut.Labels, podIn.Labels) {
		t.Errorf("objects differ: %v", diff.ObjectDiff(podOut, podIn))
	}

}
Ejemplo n.º 21
0
func TestUpdateResetsMetadata(t *testing.T) {
	testCases := []struct {
		image    *api.Image
		existing *api.Image
		expect   func(*api.Image) bool
	}{
		// manifest changes are ignored
		{
			expect: func(image *api.Image) bool {
				if image.Labels["a"] != "b" {
					t.Errorf("unexpected labels: %s", image.Labels)
					return false
				}
				if image.DockerImageManifest != "" {
					t.Errorf("unexpected manifest: %s", image.DockerImageManifest)
					return false
				}
				if image.DockerImageMetadata.ID != "foo" {
					t.Errorf("unexpected docker image: %#v", image.DockerImageMetadata)
					return false
				}
				if image.DockerImageReference != "openshift/ruby-19-centos-2" {
					t.Errorf("image reference changed: %s", image.DockerImageReference)
					return false
				}
				if image.DockerImageMetadata.Size != 0 {
					t.Errorf("image had size %d", image.DockerImageMetadata.Size)
					return false
				}
				if len(image.DockerImageLayers) != 1 && image.DockerImageLayers[0].Size != 10 {
					t.Errorf("unexpected layers: %#v", image.DockerImageLayers)
					return false
				}
				return true
			},
			existing: &api.Image{
				ObjectMeta:           kapi.ObjectMeta{Name: "foo", ResourceVersion: "1"},
				DockerImageReference: "openshift/ruby-19-centos-2",
				DockerImageLayers:    []api.ImageLayer{{Name: "test", Size: 10}},
				DockerImageMetadata:  api.DockerImage{ID: "foo"},
			},
			image: &api.Image{
				ObjectMeta:           kapi.ObjectMeta{Name: "foo", ResourceVersion: "1", Labels: map[string]string{"a": "b"}},
				DockerImageReference: "openshift/ruby-19-centos",
				DockerImageManifest:  etcdManifest,
			},
		},
		// existing manifest is preserved, and unpacked
		{
			expect: func(image *api.Image) bool {
				if image.DockerImageManifest != etcdManifest {
					t.Errorf("unexpected manifest: %s", image.DockerImageManifest)
					return false
				}
				if image.DockerImageMetadata.ID != "fe50ac14986497fa6b5d2cc24feb4a561d01767bc64413752c0988cb70b0b8b9" {
					t.Errorf("unexpected docker image: %#v", image.DockerImageMetadata)
					return false
				}
				if image.DockerImageReference != "openshift/ruby-19-centos-2" {
					t.Errorf("image reference changed: %s", image.DockerImageReference)
					return false
				}
				if image.DockerImageMetadata.Size != 28643712 {
					t.Errorf("image had size %d", image.DockerImageMetadata.Size)
					return false
				}
				if len(image.DockerImageLayers) != 4 || image.DockerImageLayers[0].Name != "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" || image.DockerImageLayers[0].Size != 15141568 {
					t.Errorf("unexpected layers: %#v", image.DockerImageLayers)
					return false
				}
				return true
			},
			existing: &api.Image{
				ObjectMeta:           kapi.ObjectMeta{Name: "foo", ResourceVersion: "1"},
				DockerImageReference: "openshift/ruby-19-centos-2",
				DockerImageLayers:    []api.ImageLayer{},
				DockerImageManifest:  etcdManifest,
			},
			image: &api.Image{
				ObjectMeta:           kapi.ObjectMeta{Name: "foo", ResourceVersion: "1"},
				DockerImageReference: "openshift/ruby-19-centos",
				DockerImageMetadata:  api.DockerImage{ID: "foo"},
			},
		},
	}

	for i, test := range testCases {
		fakeEtcdClient, helper := newHelper(t)
		storage := NewREST(helper)

		fakeEtcdClient.Data[etcdtest.AddPrefix("/images/foo")] = tools.EtcdResponseWithError{
			R: &etcd.Response{
				Node: &etcd.Node{
					Value:         runtime.EncodeOrDie(latest.Codec, test.existing),
					CreatedIndex:  1,
					ModifiedIndex: 1,
				},
			},
		}

		obj, _, err := storage.Update(kapi.NewDefaultContext(), test.image)
		if err != nil {
			t.Errorf("%d: Unexpected non-nil error: %#v", i, err)
			continue
		}
		if obj == nil {
			t.Errorf("%d: Expected nil obj, got %v", i, obj)
			continue
		}
		image, ok := obj.(*api.Image)
		if !ok {
			t.Errorf("%d: Expected image type, got: %#v", i, obj)
			continue
		}
		if test.expect != nil && !test.expect(image) {
			t.Errorf("%d: Unexpected image: %#v", i, obj)
		}
	}
}
Ejemplo n.º 22
0
func TestEtcdUpdateScheduled(t *testing.T) {
	storage, _, _, fakeClient := newStorage(t)
	ctx := api.NewDefaultContext()
	fakeClient.TestIndex = true

	key, _ := storage.KeyFunc(ctx, "foo")
	key = etcdtest.AddPrefix(key)
	fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "foo",
			Namespace: api.NamespaceDefault,
		},
		Spec: api.PodSpec{
			NodeName: "machine",
			Containers: []api.Container{
				{
					Name:            "foobar",
					Image:           "foo:v1",
					SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(),
				},
			},
			SecurityContext: &api.PodSecurityContext{},
		},
	}), 1)

	grace := int64(30)
	podIn := api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:            "foo",
			ResourceVersion: "1",
			Labels: map[string]string{
				"foo": "bar",
			},
		},
		Spec: api.PodSpec{
			NodeName: "machine",
			Containers: []api.Container{{
				Name:                   "foobar",
				Image:                  "foo:v2",
				ImagePullPolicy:        api.PullIfNotPresent,
				TerminationMessagePath: api.TerminationMessagePathDefault,
				SecurityContext:        securitycontext.ValidSecurityContextWithContainerDefaults(),
			}},
			RestartPolicy: api.RestartPolicyAlways,
			DNSPolicy:     api.DNSClusterFirst,

			TerminationGracePeriodSeconds: &grace,
			SecurityContext:               &api.PodSecurityContext{},
		},
	}
	_, _, err := storage.Update(ctx, &podIn)
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}
	response, err := fakeClient.Get(key, false, false)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}
	var podOut api.Pod
	testapi.Default.Codec().DecodeInto([]byte(response.Node.Value), &podOut)
	if !api.Semantic.DeepEqual(podOut, podIn) {
		t.Errorf("expected: %#v, got: %#v", podOut, podIn)
	}

}
Ejemplo n.º 23
0
func TestUpdateImageStreamTags(t *testing.T) {
	fakeEtcdClient, helper := newHelper(t)
	fakeEtcdClient.Data[etcdtest.AddPrefix("/imagestreams/default/test")] = tools.EtcdResponseWithError{
		R: &etcd.Response{
			Node: &etcd.Node{
				Value: runtime.EncodeOrDie(latest.Codec, &api.ImageStream{
					ObjectMeta: kapi.ObjectMeta{Name: "test", Namespace: "default"},
					Spec: api.ImageStreamSpec{
						Tags: map[string]api.TagReference{
							"another": {
								From: &kapi.ObjectReference{
									Kind: "ImageStreamTag",
									Name: "test:another",
								},
							},
							api.DefaultImageTag: {
								From: &kapi.ObjectReference{
									Kind: "ImageStreamTag",
									Name: "test:latest",
								},
							},
						},
					},
					Status: api.ImageStreamStatus{
						DockerImageRepository: "registry.default.local/default/test",
						Tags: map[string]api.TagEventList{
							api.DefaultImageTag: {
								Items: []api.TagEvent{
									{
										DockerImageReference: "registry.default.local/default/test@sha256:381151ac5b7f775e8371e489f3479b84a4c004c90ceddb2ad80b6877215a892f",
										Image:                "sha256:381151ac5b7f775e8371e489f3479b84a4c004c90ceddb2ad80b6877215a892f",
									},
								},
							},
						},
					},
				}),
				ModifiedIndex: 1,
			},
		},
	}

	_, _, storage := NewREST(helper, noDefaultRegistry, &fakeSubjectAccessReviewRegistry{})

	stream := &api.ImageStream{
		ObjectMeta: kapi.ObjectMeta{
			Namespace:       "default",
			Name:            "test",
			ResourceVersion: "1",
		},
		Spec: api.ImageStreamSpec{
			Tags: map[string]api.TagReference{
				"another": {
					From: &kapi.ObjectReference{
						Kind: "ImageStreamTag",
						Name: "test:another",
					},
				},
				api.DefaultImageTag: {
					From: &kapi.ObjectReference{
						Kind: "ImageStreamTag",
						Name: "test:latest",
					},
				},
			},
		},
		Status: api.ImageStreamStatus{
			DockerImageRepository: "registry.default.local/default/test",
			Tags: map[string]api.TagEventList{
				api.DefaultImageTag: {
					Items: []api.TagEvent{
						{
							DockerImageReference: "registry.default.local/default/test@sha256:381151ac5b7f775e8371e489f3479b84a4c004c90ceddb2ad80b6877215a892f",
							Image:                "sha256:381151ac5b7f775e8371e489f3479b84a4c004c90ceddb2ad80b6877215a892f",
						},
					},
				},
			},
		},
	}

	delete(stream.Spec.Tags, api.DefaultImageTag)
	delete(stream.Status.Tags, api.DefaultImageTag)

	ctx := kapi.WithUser(kapi.NewDefaultContext(), &fakeUser{})

	obj, created, err := storage.Update(ctx, stream)
	if err != nil {
		t.Fatalf("Unexpected non-nil error: %#v", err)
	}
	if created {
		t.Fatal("Unexpected stream creation")
	}
	updated, ok := obj.(*api.ImageStream)
	if !ok {
		t.Errorf("Expected image stream, got %#v", obj)
	}
	if _, ok := updated.Spec.Tags[api.DefaultImageTag]; ok {
		t.Errorf("Expected deleted spec tag: %s", api.DefaultImageTag)
	}
	if _, ok := updated.Status.Tags[api.DefaultImageTag]; ok {
		t.Errorf("Expected deleted status tag: %s", api.DefaultImageTag)
	}
}
Ejemplo n.º 24
0
func TestUpdateImageStreamSpecTagsFromSet(t *testing.T) {
	tests := map[string]struct {
		otherNamespace string
		sarExpected    bool
		sarAllowed     bool
	}{
		"same namespace (blank), no sar": {
			otherNamespace: "",
			sarExpected:    false,
		},
		"same namespace (set), no sar": {
			otherNamespace: "default",
			sarExpected:    false,
		},
		"different namespace, sar allowed": {
			otherNamespace: "otherns",
			sarExpected:    true,
			sarAllowed:     true,
		},
		"different namespace, sar denied": {
			otherNamespace: "otherns",
			sarExpected:    true,
			sarAllowed:     false,
		},
	}
	for name, test := range tests {
		fakeEtcdClient, helper := newHelper(t)
		sarRegistry := &fakeSubjectAccessReviewRegistry{
			allow: test.sarAllowed,
		}
		storage, _ := NewREST(helper, noDefaultRegistry, sarRegistry)

		fakeEtcdClient.Data["/imagestreams/default/foo"] = tools.EtcdResponseWithError{
			R: &etcd.Response{
				Node: &etcd.Node{
					Value: runtime.EncodeOrDie(latest.Codec, &api.ImageStream{
						ObjectMeta: kapi.ObjectMeta{Name: "foo", Namespace: "default"},
					}),
					ModifiedIndex: 1,
				},
			},
		}

		otherNamespace := test.otherNamespace
		if len(otherNamespace) == 0 {
			otherNamespace = "default"
		}
		fakeEtcdClient.Data[fmt.Sprintf("/imagestreams/%s/other", otherNamespace)] = tools.EtcdResponseWithError{
			R: &etcd.Response{
				Node: &etcd.Node{
					Value: runtime.EncodeOrDie(latest.Codec, &api.ImageStream{
						ObjectMeta: kapi.ObjectMeta{Name: "other", Namespace: otherNamespace},
						Status: api.ImageStreamStatus{
							Tags: map[string]api.TagEventList{
								"latest": {
									Items: []api.TagEvent{
										{
											DockerImageReference: fmt.Sprintf("%s/other:latest", otherNamespace),
										},
									},
								},
							},
						},
					}),
					ModifiedIndex: 1,
				},
			},
		}

		stream := &api.ImageStream{
			ObjectMeta: kapi.ObjectMeta{Name: "foo", ResourceVersion: "1"},
			Spec: api.ImageStreamSpec{
				Tags: map[string]api.TagReference{
					"other": {
						From: &kapi.ObjectReference{
							Kind:      "ImageStreamTag",
							Namespace: test.otherNamespace,
							Name:      "other:latest",
						},
					},
				},
			},
		}
		ctx := kapi.WithUser(kapi.NewDefaultContext(), &fakeUser{})
		_, _, err := storage.Update(ctx, stream)
		if test.sarExpected {
			if sarRegistry.request == nil {
				t.Errorf("%s: expected sar request", name)
				continue
			}
			if e, a := test.sarAllowed, err == nil; e != a {
				t.Errorf("%s: expected sarAllowed=%t, got error %t: %v", name, e, a, err)
				continue
			}

			continue
		}

		// sar not expected
		if err != nil {
			t.Fatalf("%s: unexpected error: %v", name, err)
		}

		actual := &api.ImageStream{}
		if err := helper.Get("/imagestreams/default/foo", actual, false); err != nil {
			t.Fatalf("%s: unexpected extraction error: %v", name, err)
		}
		if e, a := fmt.Sprintf("%s/other:latest", otherNamespace), actual.Status.Tags["other"].Items[0].DockerImageReference; e != a {
			t.Errorf("%s: dockerImageReference: expected %q, got %q", name, e, a)
		}
	}
}