func TestStatusBackoffOnConflict(t *testing.T) { now := nowFn() nowFn = func() unversioned.Time { return now } touched := unversioned.Time{Time: now.Add(-time.Minute)} p := &fakePlugin{} c := testclient.NewSimpleFake(&(errors.NewConflict(kapi.Resource("Route"), "route1", nil).ErrStatus)) admitter := NewStatusAdmitter(p, c, "test") err := admitter.HandleRoute(watch.Added, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ { Host: "route2.test.local", RouterName: "test", Conditions: []routeapi.RouteIngressCondition{ { Type: routeapi.RouteAdmitted, Status: kapi.ConditionFalse, LastTransitionTime: &touched, }, }, }, }, }, }) checkResult(t, err, c, admitter, "route1.test.local", now, nil, 0, 0) }
// TestHandle_configAlreadyDeployed ensures that an attempt to create a // deployment for an updated config for which the deployment was already // created results in a no-op. func TestHandle_configAlreadyDeployed(t *testing.T) { deploymentConfig := deploytest.OkDeploymentConfig(0) controller := &DeploymentConfigController{ makeDeployment: func(config *deployapi.DeploymentConfig) (*kapi.ReplicationController, error) { return deployutil.MakeDeployment(config, api.Codec) }, deploymentClient: &deploymentClientImpl{ createDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected call to to create deployment: %v", deployment) return nil, nil }, listDeploymentsForConfigFunc: func(namespace, configName string) (*kapi.ReplicationControllerList, error) { existingDeployments := []kapi.ReplicationController{} deployment, _ := deployutil.MakeDeployment(deploymentConfig, kapi.Codec) existingDeployments = append(existingDeployments, *deployment) return &kapi.ReplicationControllerList{Items: existingDeployments}, nil }, updateDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected update call with deployment %v", deployment) return nil, nil }, }, osClient: testclient.NewSimpleFake(deploymentConfig), } err := controller.Handle(deploymentConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } }
// TestOriginQuotaAdmissionIsErrorQuotaExceeded verifies that if a resource exceeds allowed usage, the // admission will return error we can recognize. func TestOriginQuotaAdmissionIsErrorQuotaExceeded(t *testing.T) { resourceQuota := &kapi.ResourceQuota{ ObjectMeta: kapi.ObjectMeta{Name: "quota", Namespace: "test", ResourceVersion: "124"}, Status: kapi.ResourceQuotaStatus{ Hard: kapi.ResourceList{ imageapi.ResourceImageStreams: resource.MustParse("0"), }, Used: kapi.ResourceList{ imageapi.ResourceImageStreams: resource.MustParse("0"), }, }, } kubeClient := kfake.NewSimpleClientset(resourceQuota) osClient := testclient.NewSimpleFake(&imageapi.ImageStream{}) plugin := NewOriginResourceQuota(kubeClient).(*originQuotaAdmission) plugin.SetOriginQuotaRegistry(quota.NewOriginQuotaRegistry(osClient)) if err := plugin.Validate(); err != nil { t.Fatalf("unexpected error: %v", err) } newIS := &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Namespace: "test", Name: "is", }, } err := plugin.Admit(admission.NewAttributesRecord(newIS, nil, imageapi.Kind("ImageStream").WithVersion("version"), newIS.Namespace, newIS.Name, kapi.Resource("imageStreams").WithVersion("version"), "", admission.Create, nil)) if err == nil { t.Fatalf("Expected an error exceeding quota") } if !quotautil.IsErrorQuotaExceeded(err) { t.Fatalf("Expected error %q to be matched by IsErrorQuotaExceeded()", err.Error()) } }
func buildRouteClient(routes []*routeapi.Route) saOAuthClientAdapter { objects := []runtime.Object{} for _, route := range routes { objects = append(objects, route) } return saOAuthClientAdapter{routeClient: ostestclient.NewSimpleFake(objects...)} }
func TestImagePruneNamespaced(t *testing.T) { kFake := fake.NewSimpleClientset() osFake := testclient.NewSimpleFake() opts := &PruneImagesOptions{ Namespace: "foo", OSClient: osFake, KClient: kFake, Out: ioutil.Discard, } if err := opts.Run(); err != nil { t.Errorf("Unexpected error: %v", err) } if len(osFake.Actions()) == 0 || len(kFake.Actions()) == 0 { t.Errorf("Missing get images actions") } for _, a := range osFake.Actions() { // images are non-namespaced if a.GetResource().Resource == "images" { continue } if a.GetNamespace() != "foo" { t.Errorf("Unexpected namespace while pruning %s: %s", a.GetResource(), a.GetNamespace()) } } for _, a := range kFake.Actions() { if a.GetNamespace() != "foo" { t.Errorf("Unexpected namespace while pruning %s: %s", a.GetResource(), a.GetNamespace()) } } }
// mockREST mocks a DeploymentLog REST func mockREST(version, desired int, endStatus api.DeploymentStatus) *REST { // Fake deploymentConfig config := deploytest.OkDeploymentConfig(version) fakeDn := testclient.NewSimpleFake(config) fakeDn.PrependReactor("get", "deploymentconfigs", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, config, nil }) // Fake deployments fakeDeployments := makeDeploymentList(version) fakeRn := ktestclient.NewSimpleFake(fakeDeployments) fakeRn.PrependReactor("get", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { return true, &fakeDeployments.Items[desired-1], nil }) // Fake watcher for deployments fakeWatch := watch.NewFake() fakeRn.PrependWatchReactor("replicationcontrollers", ktestclient.DefaultWatchReactor(fakeWatch, nil)) // Everything is fake connectionInfo := &kclient.HTTPKubeletClient{Config: &kclient.KubeletConfig{EnableHttps: true, Port: 12345}, Client: &http.Client{}} obj := &fakeDeployments.Items[desired-1] obj.Annotations[api.DeploymentStatusAnnotation] = string(endStatus) go fakeWatch.Add(obj) return &REST{ ConfigGetter: fakeDn, DeploymentGetter: fakeRn, PodGetter: &deployerPodGetter{}, ConnectionInfo: connectionInfo, Timeout: defaultTimeout, } }
// TestHandle_fatalError ensures that in internal (not API) failure to make a // deployment from an updated config results in a fatal error. func TestHandle_fatalError(t *testing.T) { configController := &DeploymentConfigController{ makeDeployment: func(config *deployapi.DeploymentConfig) (*kapi.ReplicationController, error) { return nil, fmt.Errorf("couldn't make deployment") }, deploymentClient: &deploymentClientImpl{ createDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected call to create") return nil, kerrors.NewInternalError(fmt.Errorf("test error")) }, listDeploymentsForConfigFunc: func(namespace, configName string) (*kapi.ReplicationControllerList, error) { return &kapi.ReplicationControllerList{}, nil }, updateDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected update call with deployment %v", deployment) return nil, nil }, }, osClient: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(1)), } err := configController.Handle(deploytest.OkDeploymentConfig(1)) if err == nil { t.Fatalf("expected error") } if _, isFatal := err.(fatalError); !isFatal { t.Fatalf("expected a fatal error, got: %v", err) } }
// TestHandle_initialOk ensures that an initial config (version 0) doesn't result // in a new deployment. func TestHandle_initialOk(t *testing.T) { controller := &DeploymentConfigController{ makeDeployment: func(config *deployapi.DeploymentConfig) (*kapi.ReplicationController, error) { return deployutil.MakeDeployment(config, api.Codec) }, deploymentClient: &deploymentClientImpl{ createDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected call with deployment %v", deployment) return nil, nil }, listDeploymentsForConfigFunc: func(namespace, configName string) (*kapi.ReplicationControllerList, error) { return &kapi.ReplicationControllerList{}, nil }, updateDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected update call with deployment %v", deployment) return nil, nil }, }, osClient: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(0)), } err := controller.Handle(deploytest.OkDeploymentConfig(0)) if err != nil { t.Fatalf("unexpected error: %v", err) } }
func TestDeploymentPruneNamespaced(t *testing.T) { kFake := ktestclient.NewSimpleFake() osFake := testclient.NewSimpleFake() opts := &PruneDeploymentsOptions{ Namespace: "foo", OSClient: osFake, KClient: kFake, Out: ioutil.Discard, } if err := opts.Run(); err != nil { t.Errorf("Unexpected error: %v", err) } if len(osFake.Actions()) == 0 || len(kFake.Actions()) == 0 { t.Errorf("Missing get deployments actions") } for _, a := range osFake.Actions() { if a.GetNamespace() != "foo" { t.Errorf("Unexpected namespace while pruning %s: %s", a.GetResource(), a.GetNamespace()) } } for _, a := range kFake.Actions() { if a.GetNamespace() != "foo" { t.Errorf("Unexpected namespace while pruning %s: %s", a.GetResource(), a.GetNamespace()) } } }
func TestStatusRecordRejection(t *testing.T) { now := nowFn() nowFn = func() unversioned.Time { return now } p := &fakePlugin{} c := testclient.NewSimpleFake(&routeapi.Route{}) admitter := NewStatusAdmitter(p, c, "test") admitter.RecordRouteRejection(&routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, }, "Failed", "generic error") if len(c.Actions()) != 1 { t.Fatalf("unexpected actions: %#v", c.Actions()) } action := c.Actions()[0] if action.GetVerb() != "update" || action.GetResource() != "routes" || action.GetSubresource() != "status" { t.Fatalf("unexpected action: %#v", action) } obj := c.Actions()[0].(ktestclient.UpdateAction).GetObject().(*routeapi.Route) if len(obj.Status.Ingress) != 1 || obj.Status.Ingress[0].Host != "route1.test.local" { t.Fatalf("expected route reset: %#v", obj) } condition := obj.Status.Ingress[0].Conditions[0] if condition.LastTransitionTime == nil || *condition.LastTransitionTime != now || condition.Status != kapi.ConditionFalse || condition.Reason != "Failed" || condition.Message != "generic error" { t.Fatalf("unexpected condition: %#v", condition) } if v, ok := admitter.expected.Peek(types.UID("uid1")); !ok || !reflect.DeepEqual(v, now.Time) { t.Fatalf("expected empty time: %#v", v) } }
func TestStatusNoOp(t *testing.T) { now := unversioned.Now() touched := unversioned.Time{Time: now.Add(-time.Minute)} p := &fakePlugin{} c := testclient.NewSimpleFake() admitter := NewStatusAdmitter(p, c, "test") err := admitter.HandleRoute(watch.Added, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ { Host: "route1.test.local", RouterName: "test", Conditions: []routeapi.RouteIngressCondition{ { Type: routeapi.RouteAdmitted, Status: kapi.ConditionTrue, LastTransitionTime: &touched, }, }, }, }, }, }) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(c.Actions()) > 0 { t.Fatalf("unexpected actions: %#v", c.Actions()) } }
func TestStatusBackoffOnConflict(t *testing.T) { now := nowFn() nowFn = func() unversioned.Time { return now } touched := unversioned.Time{Time: now.Add(-time.Minute)} p := &fakePlugin{} c := testclient.NewSimpleFake(&routeapi.Route{ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}}) c.PrependReactor("update", "routes", func(action core.Action) (handled bool, ret runtime.Object, err error) { if action.GetSubresource() != "status" { return false, nil, nil } return true, nil, errors.NewConflict(kapi.Resource("Route"), "route1", nil) }) admitter := NewStatusAdmitter(p, c, "test") err := admitter.HandleRoute(watch.Added, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ { Host: "route2.test.local", RouterName: "test", Conditions: []routeapi.RouteIngressCondition{ { Type: routeapi.RouteAdmitted, Status: kapi.ConditionFalse, LastTransitionTime: &touched, }, }, }, }, }, }) checkResult(t, err, c, admitter, "route1.test.local", now, nil, 0, 0) }
// TestHandle_nonfatalLookupError ensures that an API failure to look up the // existing deployment for an updated config results in a nonfatal error. func TestHandle_nonfatalLookupError(t *testing.T) { configController := &DeploymentConfigController{ makeDeployment: func(config *deployapi.DeploymentConfig) (*kapi.ReplicationController, error) { return deployutil.MakeDeployment(config, api.Codec) }, deploymentClient: &deploymentClientImpl{ createDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected call with deployment %v", deployment) return nil, nil }, listDeploymentsForConfigFunc: func(namespace, configName string) (*kapi.ReplicationControllerList, error) { return nil, kerrors.NewInternalError(fmt.Errorf("fatal test error")) }, updateDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { t.Fatalf("unexpected update call with deployment %v", deployment) return nil, nil }, }, osClient: testclient.NewSimpleFake(), } err := configController.Handle(deploytest.OkDeploymentConfig(1)) if err == nil { t.Fatalf("expected error") } if _, isFatal := err.(fatalError); isFatal { t.Fatalf("expected a retryable error, got a fatal error: %v", err) } }
// fakeMasterConfig creates a new fake master config with an empty kubelet config and dummy storage. func fakeMasterConfig() *MasterConfig { informerFactory := shared.NewInformerFactory(testclient.NewSimpleFake(), otestclient.NewSimpleFake(), shared.DefaultListerWatcherOverrides{}, 1*time.Second) return &MasterConfig{ KubeletClientConfig: &kubeletclient.KubeletClientConfig{}, RESTOptionsGetter: restoptions.NewSimpleGetter(&storagebackend.Config{ServerList: []string{"localhost"}}), Informers: informerFactory, ClusterQuotaMappingController: clusterquotamapping.NewClusterQuotaMappingController(informerFactory.Namespaces(), informerFactory.ClusterResourceQuotas()), } }
func TestGetRepositoryBuildConfigs(t *testing.T) { tests := []struct { name string bcs []runtime.Object searchFor string shouldContain []string shouldNotContain []string }{ { name: "find a named build config", bcs: []runtime.Object{bc("bc1", ""), bc("bc2", ""), bc("bc3", "")}, searchFor: "bc2", shouldContain: []string{"bc2"}, shouldNotContain: []string{"bc1", "bc3"}, }, { name: "find no match", bcs: []runtime.Object{bc("bc1", ""), bc("bc2", "")}, searchFor: "bc3", shouldContain: []string{}, shouldNotContain: []string{"bc1", "bc2"}, }, { name: "multiple matches", bcs: []runtime.Object{bc("bc1", ""), bc("bc2", ""), bc("bc3", "bc2")}, searchFor: "bc2", shouldContain: []string{"bc2", "bc3"}, shouldNotContain: []string{"bc1"}, }, { name: "match on annotation", bcs: []runtime.Object{bc("bc1", "a1"), bc("bc2", ""), bc("bc3", "")}, searchFor: "a1", shouldContain: []string{"bc1"}, shouldNotContain: []string{"bc2", "bc3"}, }, } for _, test := range tests { client := testclient.NewSimpleFake(test.bcs...) output := &bytes.Buffer{} GetRepositoryBuildConfigs(client, test.searchFor, output) for _, c := range test.shouldContain { if !strings.Contains(output.String(), c) { t.Errorf("%s: output should contain %q. Output: %q", test.name, c, output.String()) } } for _, c := range test.shouldNotContain { if strings.Contains(output.String(), c) { t.Errorf("%s: output should not contain %q. Output: %q", test.name, c, output.String()) } } } }
func TestMaxProjectByRequester(t *testing.T) { tests := []struct { userLabels map[string]string expectUnlimited bool expectedLimit int }{ { userLabels: map[string]string{"platinum": "yes"}, expectUnlimited: true, }, { userLabels: map[string]string{"gold": "yes"}, expectedLimit: 10, }, { userLabels: map[string]string{"silver": "yes", "bronze": "yes"}, expectedLimit: 3, }, { userLabels: map[string]string{"unknown": "yes"}, expectedLimit: 1, }, } for _, tc := range tests { reqLimit, err := NewProjectRequestLimit(multiLevelConfig()) if err != nil { t.Fatalf("Unexpected error: %v", err) } user := fakeUser("testuser", tc.userLabels) client := testclient.NewSimpleFake(user) reqLimit.(oadmission.WantsOpenshiftClient).SetOpenshiftClient(client) maxProjects, hasLimit, err := reqLimit.(*projectRequestLimit).maxProjectsByRequester("testuser") if err != nil { t.Errorf("Unexpected error: %v", err) } if tc.expectUnlimited { if hasLimit { t.Errorf("Expected no limit, but got limit for labels %v", tc.userLabels) } continue } if !tc.expectUnlimited && !hasLimit { t.Errorf("Did not expect unlimited for labels %v", tc.userLabels) continue } if maxProjects != tc.expectedLimit { t.Errorf("Did not get expected limit for labels %v. Got: %d. Expected: %d", tc.userLabels, maxProjects, tc.expectedLimit) } } }
func TestStatusFightBetweenReplicas(t *testing.T) { p := &fakePlugin{} // the initial pre-population now1 := unversioned.Now() nowFn = func() unversioned.Time { return now1 } c1 := testclient.NewSimpleFake(&routeapi.Route{}) admitter1 := NewStatusAdmitter(p, c1, "test") err := admitter1.HandleRoute(watch.Added, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, Status: routeapi.RouteStatus{}, }) outObj1 := checkResult(t, err, c1, admitter1, "route1.test.local", now1, &now1.Time, 0, 0) // the new deployment's replica now2 := unversioned.Time{Time: now1.Time.Add(time.Minute)} nowFn = func() unversioned.Time { return now2 } c2 := testclient.NewSimpleFake(&routeapi.Route{}) admitter2 := NewStatusAdmitter(p, c2, "test") outObj1.Spec.Host = "route1.test-new.local" err = admitter2.HandleRoute(watch.Added, outObj1) outObj2 := checkResult(t, err, c2, admitter2, "route1.test-new.local", now2, &now2.Time, 0, 0) now3 := unversioned.Time{Time: now1.Time.Add(time.Minute)} nowFn = func() unversioned.Time { return now3 } outObj2.Spec.Host = "route1.test.local" err = admitter1.HandleRoute(watch.Modified, outObj2) if err != nil { t.Fatalf("unexpected error: %v", err) } // expect the last HandleRoute not to have performed any actions if len(c1.Actions()) != 1 { t.Fatalf("unexpected actions: %#v", c1.Actions()) } }
func makePass(t *testing.T, host string, admitter *StatusAdmitter, srcObj *routeapi.Route, expectUpdate bool, conflict bool) *routeapi.Route { // initialize a new client var c *testclient.Fake if conflict { c = testclient.NewSimpleFake(&(errors.NewConflict(kapi.Resource("Route"), "route1", nil).ErrStatus)) } else { c = testclient.NewSimpleFake(&routeapi.Route{}) } admitter.client = c inputObjRaw, err := kapi.Scheme.DeepCopy(srcObj) if err != nil { t.Fatalf("unexpected error: %v", err) } inputObj := inputObjRaw.(*routeapi.Route) inputObj.Spec.Host = host err = admitter.HandleRoute(watch.Modified, inputObj) if expectUpdate { now := nowFn() var nowTime *time.Time if !conflict { nowTime = &now.Time } return checkResult(t, err, c, admitter, inputObj.Spec.Host, now, nowTime, 0, 0) } else { if err != nil { t.Fatalf("unexpected error: %v", err) } // expect the last HandleRoute not to have performed any actions if len(c.Actions()) != 0 { t.Fatalf("unexpected actions: %#v", c) } return nil } }
// fakeMasterConfig creates a new fake master config with an empty kubelet config and dummy storage. func fakeMasterConfig() *MasterConfig { etcdHelper := etcdstorage.NewEtcdStorage(nil, api.Codecs.LegacyCodec(), "", false, genericapiserveroptions.DefaultDeserializationCacheSize) informerFactory := shared.NewInformerFactory(testclient.NewSimpleFake(), otestclient.NewSimpleFake(), shared.DefaultListerWatcherOverrides{}, 1*time.Second) return &MasterConfig{ KubeletClientConfig: &kubeletclient.KubeletClientConfig{}, RESTOptionsGetter: restoptions.NewSimpleGetter(etcdHelper), EtcdHelper: etcdHelper, Informers: informerFactory, ClusterQuotaMappingController: clusterquotamapping.NewClusterQuotaMappingController(informerFactory.Namespaces(), informerFactory.ClusterResourceQuotas()), } }
func TestRunTag_AddAccrossNamespaces(t *testing.T) { streams := testData() client := testclient.NewSimpleFake(streams[2], streams[0]) client.PrependReactor("create", "imagestreamtags", func(action ktc.Action) (handled bool, ret runtime.Object, err error) { return true, nil, kapierrors.NewMethodNotSupported(imageapi.Resource("imagestreamtags"), "create") }) client.PrependReactor("update", "imagestreamtags", func(action ktc.Action) (handled bool, ret runtime.Object, err error) { return true, nil, kapierrors.NewMethodNotSupported(imageapi.Resource("imagestreamtags"), "update") }) test := struct { opts *TagOptions expectedActions []testAction expectedErr error }{ opts: &TagOptions{ out: os.Stdout, osClient: client, ref: imageapi.DockerImageReference{ Namespace: "openshift", Name: "ruby", Tag: "latest", }, namespace: "myproject2", sourceKind: "ImageStreamTag", destNamespace: []string{"yourproject"}, destNameAndTag: []string{"rails:tip"}, }, expectedActions: []testAction{ {verb: "update", resource: "imagestreamtags"}, {verb: "create", resource: "imagestreamtags"}, {verb: "get", resource: "imagestreams"}, {verb: "update", resource: "imagestreams"}, }, expectedErr: nil, } if err := test.opts.RunTag(); err != test.expectedErr { t.Fatalf("error mismatch: expected %v, got %v", test.expectedErr, err) } got := client.Actions() if len(test.expectedActions) != len(got) { t.Fatalf("action length mismatch: expectedc %d, got %d", len(test.expectedActions), len(got)) } for i, action := range test.expectedActions { if !got[i].Matches(action.verb, action.resource) { t.Errorf("action mismatch: expected %s %s, got %s %s", action.verb, action.resource, got[i].GetVerb(), got[i].GetResource()) } } }
func TestStatusRecordRejectionConflict(t *testing.T) { now := nowFn() nowFn = func() unversioned.Time { return now } touched := unversioned.Time{Time: now.Add(-time.Minute)} p := &fakePlugin{} c := testclient.NewSimpleFake(&routeapi.Route{ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}}) c.PrependReactor("update", "routes", func(action core.Action) (handled bool, ret runtime.Object, err error) { if action.GetSubresource() != "status" { return false, nil, nil } return true, nil, errors.NewConflict(kapi.Resource("Route"), "route1", nil) }) admitter := NewStatusAdmitter(p, c, "test") admitter.RecordRouteRejection(&routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ { Host: "route2.test.local", RouterName: "test", Conditions: []routeapi.RouteIngressCondition{ { Type: routeapi.RouteAdmitted, Status: kapi.ConditionFalse, LastTransitionTime: &touched, }, }, }, }, }, }, "Failed", "generic error") if len(c.Actions()) != 1 { t.Fatalf("unexpected actions: %#v", c.Actions()) } action := c.Actions()[0] if action.GetVerb() != "update" || action.GetResource().Resource != "routes" || action.GetSubresource() != "status" { t.Fatalf("unexpected action: %#v", action) } obj := c.Actions()[0].(core.UpdateAction).GetObject().(*routeapi.Route) if len(obj.Status.Ingress) != 1 || obj.Status.Ingress[0].Host != "route1.test.local" { t.Fatalf("expected route reset: %#v", obj) } condition := obj.Status.Ingress[0].Conditions[0] if condition.LastTransitionTime == nil || *condition.LastTransitionTime != now || condition.Status != kapi.ConditionFalse || condition.Reason != "Failed" || condition.Message != "generic error" { t.Fatalf("unexpected condition: %#v", condition) } if v, ok := admitter.expected.Peek(types.UID("uid1")); ok { t.Fatalf("expected empty time: %#v", v) } }
func TestStatusBackoffOnConflict(t *testing.T) { now := unversioned.Now() nowFn = func() unversioned.Time { return now } touched := unversioned.Time{Time: now.Add(-time.Minute)} p := &fakePlugin{} c := testclient.NewSimpleFake(&(errors.NewConflict(kapi.Resource("Route"), "route1", nil).(*errors.StatusError).ErrStatus)) admitter := NewStatusAdmitter(p, c, "test") err := admitter.HandleRoute(watch.Added, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{Name: "route1", Namespace: "default", UID: types.UID("uid1")}, Spec: routeapi.RouteSpec{Host: "route1.test.local"}, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ { Host: "route2.test.local", RouterName: "test", Conditions: []routeapi.RouteIngressCondition{ { Type: routeapi.RouteAdmitted, Status: kapi.ConditionFalse, LastTransitionTime: &touched, }, }, }, }, }, }) if len(c.Actions()) != 1 { t.Fatalf("unexpected actions: %#v", c.Actions()) } action := c.Actions()[0] if action.GetVerb() != "update" || action.GetResource() != "routes" || action.GetSubresource() != "status" { t.Fatalf("unexpected action: %#v", action) } obj := c.Actions()[0].(ktestclient.UpdateAction).GetObject().(*routeapi.Route) if len(obj.Status.Ingress) != 1 && obj.Status.Ingress[0].Host != "route1.test.local" { t.Fatalf("expected route reset: %#v", obj) } condition := obj.Status.Ingress[0].Conditions[0] if condition.LastTransitionTime == nil || *condition.LastTransitionTime != now || condition.Status != kapi.ConditionTrue || condition.Reason != "" { t.Fatalf("unexpected condition: %#v", condition) } if err == nil { t.Fatalf("unexpected non-error: %#v", admitter.expected) } if v, ok := admitter.expected.Peek(types.UID("uid1")); !ok || !reflect.DeepEqual(v, time.Time{}) { t.Fatalf("expected empty time: %#v", v) } }
func TestRunTag_DeleteOld(t *testing.T) { streams := testData() client := testclient.NewSimpleFake(streams[1]) client.PrependReactor("delete", "imagestreamtags", func(action ktc.Action) (handled bool, ret runtime.Object, err error) { return true, nil, kapierrors.NewForbidden(imageapi.Resource("imagestreamtags"), "rails:tip", fmt.Errorf("dne")) }) client.PrependReactor("get", "imagestreams", func(action ktc.Action) (handled bool, ret runtime.Object, err error) { return true, testData()[1], nil }) client.PrependReactor("update", "imagestreams", func(action ktc.Action) (handled bool, ret runtime.Object, err error) { return true, nil, nil }) test := struct { opts *TagOptions expectedActions []testAction expectedErr error }{ opts: &TagOptions{ out: os.Stdout, osClient: client, deleteTag: true, destNamespace: []string{"yourproject"}, destNameAndTag: []string{"rails:tip"}, }, expectedActions: []testAction{ {verb: "delete", resource: "imagestreamtags"}, {verb: "get", resource: "imagestreams"}, {verb: "update", resource: "imagestreams"}, }, expectedErr: nil, } if err := test.opts.RunTag(); err != test.expectedErr { t.Fatalf("error mismatch: expected %v, got %v", test.expectedErr, err) } got := client.Actions() if len(test.expectedActions) != len(got) { t.Fatalf("action length mismatch: expectedc %d, got %d", len(test.expectedActions), len(got)) } for i, action := range test.expectedActions { if !got[i].Matches(action.verb, action.resource) { t.Errorf("action mismatch: expected %s %s, got %s %s", action.verb, action.resource, got[i].GetVerb(), got[i].GetResource()) } } }
// creates mock implemenation of STI builder, instrumenting different parts of a process to return errors func makeStiBuilder( errPushImage error, getStrategyErr error, buildError error, validationErrors []validation.ValidationError) S2IBuilder { return *newS2IBuilder( testDockerClient{ errPushImage: errPushImage, }, "/docker.socket", testclient.NewSimpleFake().Builds(""), makeBuild(), testStiBuilderFactory{getStrategyErr: getStrategyErr, buildError: buildError}, testStiConfigValidator{errors: validationErrors}, ) }
// newTestS2IBuilder creates a mock implementation of S2IBuilder, instrumenting // different parts to return specific errors according to config. func newTestS2IBuilder(config testS2IBuilderConfig) *S2IBuilder { return newS2IBuilder( &FakeDocker{ errPushImage: config.errPushImage, }, "/docker.socket", testclient.NewSimpleFake().Builds(""), makeBuild(), git.NewRepository(), testStiBuilderFactory{ getStrategyErr: config.getStrategyErr, buildError: config.buildError, }, runtimeConfigValidator{}, ) }
func newTestPruner() (*LDAPGroupPruner, *testclient.Fake) { tc := testclient.NewSimpleFake() tc.PrependReactor("delete", "groups", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, nil, nil }) return &LDAPGroupPruner{ GroupLister: newTestLister(), GroupDetector: newTestGroupDetector(), GroupNameMapper: newTestGroupNameMapper(), GroupClient: tc.Groups(), Host: newTestHost(), Out: ioutil.Discard, Err: ioutil.Discard, }, tc }
func newTestSyncer() (*LDAPGroupSyncer, *testclient.Fake) { tc := testclient.NewSimpleFake() tc.PrependReactor("create", "groups", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { createAction := action.(ktestclient.CreateAction) return true, createAction.GetObject(), nil }) tc.PrependReactor("update", "groups", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { updateAction := action.(ktestclient.UpdateAction) return true, updateAction.GetObject(), nil }) testGroupLister := TestGroupLister{ GroupUIDs: []string{Group1UID, Group2UID, Group3UID}, } testGroupMemberExtractor := TestGroupMemberExtractor{ MemberMapping: map[string][]*ldap.Entry{ Group1UID: Group1Members, Group2UID: Group2Members, Group3UID: Group3Members, }, } testUserNameMapper := TestUserNameMapper{ NameAttributes: []string{UserNameAttribute}, } testGroupNameMapper := TestGroupNameMapper{ NameMapping: map[string]string{ Group1UID: "os" + Group1UID, Group2UID: "os" + Group2UID, Group3UID: "os" + Group3UID, }, } testHost := "test.host:port" return &LDAPGroupSyncer{ GroupLister: &testGroupLister, GroupMemberExtractor: &testGroupMemberExtractor, UserNameMapper: &testUserNameMapper, GroupNameMapper: &testGroupNameMapper, GroupClient: tc.Groups(), Host: testHost, Out: ioutil.Discard, Err: ioutil.Discard, }, tc }
func TestRunTag_AddNew(t *testing.T) { client := testclient.NewSimpleFake( &imageapi.ImageStreamTag{ ObjectMeta: api.ObjectMeta{Name: "rails:tip", Namespace: "yourproject", ResourceVersion: "10", CreationTimestamp: unversioned.Now()}, }, ) test := struct { opts *TagOptions expectedActions []testAction expectedErr error }{ opts: &TagOptions{ out: os.Stdout, osClient: client, ref: imageapi.DockerImageReference{ Namespace: "openshift", Name: "ruby", Tag: "2.0", }, sourceKind: "ImageStreamTag", destNamespace: []string{"yourproject"}, destNameAndTag: []string{"rails:tip"}, }, expectedActions: []testAction{ {verb: "update", resource: "imagestreamtags"}, }, expectedErr: nil, } if err := test.opts.RunTag(); err != test.expectedErr { t.Fatalf("error mismatch: expected %v, got %v", test.expectedErr, err) } got := client.Actions() if len(test.expectedActions) != len(got) { t.Fatalf("action length mismatch: expectedc %d, got %d", len(test.expectedActions), len(got)) } for i, action := range test.expectedActions { if !got[i].Matches(action.verb, action.resource) { t.Errorf("action mismatch: expected %s %s, got %s %s", action.verb, action.resource, got[i].GetVerb(), got[i].GetResource()) } } }
// TestRequestProjectRun ensures that Run command calls the right actions. func TestRequestProjectRun(t *testing.T) { client := testclient.NewSimpleFake() buf := &bytes.Buffer{} test := struct { opts *NewProjectOptions expectedActions []testAction expectedErr error }{ opts: &NewProjectOptions{ Out: buf, Server: "127.0.0.1", Client: client, Name: "oc", ProjectName: "yourproject", }, expectedActions: []testAction{ {verb: "list", resource: "newprojects"}, {verb: "create", resource: "newprojects"}, }, expectedErr: nil, } expectedOutput := fmt.Sprintf(requestProjectSwitchProjectOutput, test.opts.Name, test.opts.ProjectName, test.opts.Server) if err := test.opts.Run(); err != test.expectedErr { t.Fatalf("error mismatch: expected %v, got %v", test.expectedErr, err) } if buf.String() != expectedOutput { t.Fatalf("error mismatch output: expected %v, got %v", expectedOutput, buf) } got := client.Actions() if len(test.expectedActions) != len(got) { t.Fatalf("action length mismatch: expected %d, got %d", len(test.expectedActions), len(got)) } for i, action := range test.expectedActions { if !got[i].Matches(action.verb, action.resource) { t.Errorf("action mismatch: expected %s %s, got %s %s", action.verb, action.resource, got[i].GetVerb(), got[i].GetResource()) } } }
func makePass(t *testing.T, host string, admitter *StatusAdmitter, srcObj *routeapi.Route, expectUpdate bool, conflict bool) *routeapi.Route { // initialize a new client c := testclient.NewSimpleFake(srcObj) if conflict { c.PrependReactor("update", "routes", func(action core.Action) (handled bool, ret runtime.Object, err error) { if action.GetSubresource() != "status" { return false, nil, nil } return true, nil, errors.NewConflict(kapi.Resource("Route"), "route1", nil) }) } admitter.client = c inputObjRaw, err := kapi.Scheme.DeepCopy(srcObj) if err != nil { t.Fatalf("unexpected error: %v", err) } inputObj := inputObjRaw.(*routeapi.Route) inputObj.Spec.Host = host err = admitter.HandleRoute(watch.Modified, inputObj) if expectUpdate { now := nowFn() var nowTime *time.Time if !conflict { nowTime = &now.Time } return checkResult(t, err, c, admitter, inputObj.Spec.Host, now, nowTime, 0, 0) } else { if err != nil { t.Fatalf("unexpected error: %v", err) } // expect the last HandleRoute not to have performed any actions if len(c.Actions()) != 0 { t.Fatalf("unexpected actions: %#v", c) } return nil } }