func (c *FakeImageStreamSecrets) Secrets(name string, options kapi.ListOptions) (*kapi.SecretList, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("imagestreams/secrets", c.Namespace, name), &kapi.SecretList{}) if obj == nil { return nil, err } return obj.(*kapi.SecretList), err }
func (c *FakeAppliedClusterResourceQuotas) Get(name string) (*quotaapi.AppliedClusterResourceQuota, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("appliedclusterresourcequotas", c.Namespace, name), "aapi.AppliedClusterResourceQuota{}) if obj == nil { return nil, err } return obj.(*quotaapi.AppliedClusterResourceQuota), err }
func (c *FakeEgressNetworkPolicy) Get(name string) (*sdnapi.EgressNetworkPolicy, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("egressnetworkpolicies", c.Namespace, name), &sdnapi.EgressNetworkPolicy{}) if obj == nil { return nil, err } return obj.(*sdnapi.EgressNetworkPolicy), err }
func (c *FakeImageStreams) Get(name string) (*imageapi.ImageStream, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("imagestreams", c.Namespace, name), &imageapi.ImageStream{}) if obj == nil { return nil, err } return obj.(*imageapi.ImageStream), err }
func (c *FakeImageStreamTags) Get(name, tag string) (*imageapi.ImageStreamTag, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("imagestreamtags", c.Namespace, imageapi.JoinImageStreamTag(name, tag)), &imageapi.ImageStreamTag{}) if obj == nil { return nil, err } return obj.(*imageapi.ImageStreamTag), err }
func (c *FakeRoleBindings) Get(name string) (*authorizationapi.RoleBinding, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("rolebindings", c.Namespace, name), &authorizationapi.RoleBinding{}) if obj == nil { return nil, err } return obj.(*authorizationapi.RoleBinding), err }
func (c *FakeDeploymentConfigs) GetScale(name string) (*extensions.Scale, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("deploymentconfigs/scale", c.Namespace, name), &extensions.Scale{}) if obj == nil { return nil, err } return obj.(*extensions.Scale), err }
func (c *FakePolicies) Get(name string) (*authorizationapi.Policy, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("policies", c.Namespace, name), &authorizationapi.Policy{}) if obj == nil { return nil, err } return obj.(*authorizationapi.Policy), err }
func (c *FakeBuilds) Get(name string) (*buildapi.Build, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("builds", c.Namespace, name), &buildapi.Build{}) if obj == nil { return nil, err } return obj.(*buildapi.Build), err }
func (c *FakeDeploymentConfigs) Get(name string) (*deployapi.DeploymentConfig, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("deploymentconfigs", c.Namespace, name), &deployapi.DeploymentConfig{}) if obj == nil { return nil, err } return obj.(*deployapi.DeploymentConfig), err }
func (c *FakeBackingServiceInstances) Get(name string) (*backingserviceinstanceapi.BackingServiceInstance, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("backingserviceinstances", c.Namespace, name), &backingserviceinstanceapi.BackingServiceInstance{}) if obj == nil { return nil, err } return obj.(*backingserviceinstanceapi.BackingServiceInstance), err }
func (c *FakeRoutes) Get(name string) (*routeapi.Route, error) { obj, err := c.Fake.Invokes(ktestclient.NewGetAction("routes", c.Namespace, name), &routeapi.Route{}) if obj == nil { return nil, err } return obj.(*routeapi.Route), err }
func (c *fakeRc) Get(name string) (*api.ReplicationController, error) { action := testclient.NewGetAction("replicationcontrollers", "", name) if len(c.responses) == 0 { return nil, fmt.Errorf("Unexpected Action: %s", action) } c.Fake.Invokes(action, nil) result := c.responses[0] c.responses = c.responses[1:] return result.controller, result.err }
func (c *FakeImageStreamImages) Get(repo, imageID string) (*imageapi.ImageStreamImage, error) { name := fmt.Sprintf("%s@%s", repo, imageID) obj, err := c.Fake.Invokes(ktestclient.NewGetAction("imagestreamimages", c.Namespace, name), &imageapi.ImageStreamImage{}) if obj == nil { return nil, err } return obj.(*imageapi.ImageStreamImage), err }
func TestStop(t *testing.T) { notfound := func() runtime.Object { return &(kerrors.NewNotFound(kapi.Resource("DeploymentConfig"), "config").ErrStatus) } pause := func(d *deployapi.DeploymentConfig) *deployapi.DeploymentConfig { d.Spec.Paused = true return d } fakeDC := map[string]*deployapi.DeploymentConfig{ "simple-stop": deploytest.OkDeploymentConfig(1), "legacy-simple-stop": deploytest.OkDeploymentConfig(1), "multi-stop": deploytest.OkDeploymentConfig(5), "legacy-multi-stop": deploytest.OkDeploymentConfig(5), "no-deployments": deploytest.OkDeploymentConfig(5), "legacy-no-deployments": deploytest.OkDeploymentConfig(5), } tests := []struct { testName string namespace string name string oc *testclient.Fake kc *ktestclient.Fake expected []ktestclient.Action kexpected []ktestclient.Action err bool }{ { testName: "simple stop", namespace: "default", name: "config", oc: testclient.NewSimpleFake(fakeDC["simple-stop"]), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewUpdateAction("deploymentconfigs", "default", pause(fakeDC["simple-stop"])), ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), }, err: false, }, { testName: "legacy simple stop", namespace: "default", name: "config", oc: testclient.NewSimpleFake(fakeDC["legacy-simple-stop"]), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewUpdateAction("deploymentconfigs", "default", nil), ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), }, err: false, }, { testName: "stop multiple controllers", namespace: "default", name: "config", oc: testclient.NewSimpleFake(fakeDC["multi-stop"]), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1, 2, 3, 4, 5)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewUpdateAction("deploymentconfigs", "default", pause(fakeDC["multi-stop"])), ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-2"), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-3"), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-4"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-5"), }, err: false, }, { testName: "legacy stop multiple controllers", namespace: "default", name: "config", oc: testclient.NewSimpleFake(fakeDC["legacy-multi-stop"]), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1, 2, 3, 4, 5)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewUpdateAction("deploymentconfigs", "default", nil), ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-2"), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-3"), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-4"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-5"), }, err: false, }, { testName: "no config, some deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(notfound()), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", kapi.ListOptions{}), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), }, err: false, }, { testName: "no config, no deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(notfound()), kc: ktestclient.NewSimpleFake(&kapi.ReplicationControllerList{}), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), }, err: true, }, { testName: "config, no deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(fakeDC["no-deployments"]), kc: ktestclient.NewSimpleFake(&kapi.ReplicationControllerList{}), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewUpdateAction("deploymentconfigs", "default", pause(fakeDC["no-deployments"])), ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), }, err: false, }, { testName: "legacy config, no deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(fakeDC["legacy-no-deployments"]), kc: ktestclient.NewSimpleFake(&kapi.ReplicationControllerList{}), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewUpdateAction("deploymentconfigs", "default", nil), ktestclient.NewGetAction("deploymentconfigs", "default", "config"), ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", kapi.ListOptions{}), }, err: false, }, } for _, test := range tests { reaper := &DeploymentConfigReaper{oc: test.oc, kc: test.kc, pollInterval: time.Millisecond, timeout: time.Millisecond} err := reaper.Stop(test.namespace, test.name, 1*time.Second, nil) if !test.err && err != nil { t.Errorf("%s: unexpected error: %v", test.testName, err) } if test.err && err == nil { t.Errorf("%s: expected an error", test.testName) } if len(test.oc.Actions()) != len(test.expected) { t.Fatalf("%s: unexpected actions: %v, expected %v", test.testName, test.oc.Actions(), test.expected) } for j, actualAction := range test.oc.Actions() { e, a := test.expected[j], actualAction switch a.(type) { case ktestclient.UpdateAction: if e.GetVerb() != a.GetVerb() || e.GetNamespace() != a.GetNamespace() || e.GetResource() != a.GetResource() || e.GetSubresource() != a.GetSubresource() { t.Errorf("%s: unexpected action[%d]: %s, expected %s", test.testName, j, a, e) } default: if !reflect.DeepEqual(actualAction, test.expected[j]) { t.Errorf("%s: unexpected action: got:\n%#+v\nexpected:\n%#+v", test.testName, actualAction, test.expected[j]) } } } if len(test.kc.Actions()) != len(test.kexpected) { t.Fatalf("%s: unexpected actions: %v, expected %v", test.testName, test.kc.Actions(), test.kexpected) } for j, actualAction := range test.kc.Actions() { e, a := test.kexpected[j], actualAction if e.GetVerb() != a.GetVerb() || e.GetNamespace() != a.GetNamespace() || e.GetResource() != a.GetResource() || e.GetSubresource() != a.GetSubresource() { t.Errorf("%s: unexpected action[%d]: %s, expected %s", test.testName, j, a, e) } switch a.(type) { case ktestclient.GetAction, ktestclient.DeleteAction: if !reflect.DeepEqual(e, a) { t.Errorf("%s: unexpected action[%d]: %s, expected %s", test.testName, j, a, e) } } } } }
func TestStop(t *testing.T) { notfound := func() runtime.Object { return &(kerrors.NewNotFound("DeploymentConfig", "config").(*kerrors.StatusError).ErrStatus) } tests := []struct { testName string namespace string name string oc *testclient.Fake kc *ktestclient.Fake expected []ktestclient.Action kexpected []ktestclient.Action output string err bool }{ { testName: "simple stop", namespace: "default", name: "config", oc: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(1)), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1)), expected: []ktestclient.Action{ ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), }, output: "config stopped", err: false, }, { testName: "stop multiple controllers", namespace: "default", name: "config", oc: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(5)), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1, 2, 3, 4, 5)), expected: []ktestclient.Action{ ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-2"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-2"), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-3"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-3"), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-4"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-4"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewGetAction("replicationcontrollers", "", "config-5"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-5"), }, output: "config stopped", err: false, }, { testName: "no config, some deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(notfound()), kc: ktestclient.NewSimpleFake(mkdeploymentlist(1)), expected: []ktestclient.Action{ ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewListAction("replicationcontrollers", "", nil, nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "", nil), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), ktestclient.NewDeleteAction("replicationcontrollers", "", "config-1"), }, output: "config stopped", err: false, }, { testName: "no config, no deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(notfound()), kc: ktestclient.NewSimpleFake(&kapi.ReplicationControllerList{}), expected: []ktestclient.Action{ ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", nil, nil), }, output: "", err: true, }, { testName: "config, no deployments", namespace: "default", name: "config", oc: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(5)), kc: ktestclient.NewSimpleFake(&kapi.ReplicationControllerList{}), expected: []ktestclient.Action{ ktestclient.NewDeleteAction("deploymentconfigs", "default", "config"), }, kexpected: []ktestclient.Action{ ktestclient.NewListAction("replicationcontrollers", "default", nil, nil), }, output: "config stopped", err: false, }, } for _, test := range tests { reaper := &DeploymentConfigReaper{oc: test.oc, kc: test.kc, pollInterval: time.Millisecond, timeout: time.Millisecond} out, err := reaper.Stop(test.namespace, test.name, 1*time.Second, nil) if !test.err && err != nil { t.Errorf("%s: unexpected error: %v", test.testName, err) } if test.err && err == nil { t.Errorf("%s: expected an error", test.testName) } if len(test.oc.Actions()) != len(test.expected) { t.Fatalf("%s: unexpected actions: %v, expected %v", test.testName, test.oc.Actions, test.expected) } for j, actualAction := range test.oc.Actions() { if !reflect.DeepEqual(actualAction, test.expected[j]) { t.Errorf("%s: unexpected action: %s, expected %s", test.testName, actualAction, test.expected[j]) } } if len(test.kc.Actions()) != len(test.kexpected) { t.Fatalf("%s: unexpected actions: %v, expected %v", test.testName, test.kc.Actions(), test.kexpected) } for j, actualAction := range test.kc.Actions() { e, a := test.kexpected[j], actualAction if e.GetVerb() != a.GetVerb() || e.GetNamespace() != a.GetNamespace() || e.GetResource() != a.GetResource() || e.GetSubresource() != a.GetSubresource() { t.Errorf("%s: unexpected action[%d]: %s, expected %s", test.testName, j, a, e) } switch a.(type) { case ktestclient.GetAction, ktestclient.DeleteAction: if !reflect.DeepEqual(e, a) { t.Errorf("%s: unexpected action[%d]: %s, expected %s", test.testName, j, a, e) } } } if out != test.output { t.Errorf("%s: unexpected output %q, expected %q", test.testName, out, test.output) } } }
func TestScale(t *testing.T) { tests := []struct { testName string namespace string name string count uint preconditions *kubectl.ScalePrecondition retry, waitForReplicas *kubectl.RetryParams oc *testclient.Fake kc *ktestclient.Fake expected []ktestclient.Action kexpected []ktestclient.Action expectedErr error }{ { testName: "simple scale", namespace: "default", name: "foo", count: uint(3), oc: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(1)), kc: ktestclient.NewSimpleFake(mkDeploymentList(1)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "foo"), }, kexpected: []ktestclient.Action{ ktestclient.NewGetAction("replicationcontrollers", "default", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "default", nil), }, expectedErr: nil, }, { testName: "wait for replicas", namespace: "default", name: "foo", count: uint(3), waitForReplicas: &kubectl.RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond}, oc: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(1)), kc: ktestclient.NewSimpleFake(mkDeploymentList(1)), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "foo"), }, kexpected: []ktestclient.Action{ ktestclient.NewGetAction("replicationcontrollers", "default", "config-1"), ktestclient.NewUpdateAction("replicationcontrollers", "default", nil), ktestclient.NewGetAction("replicationcontrollers", "default", "config-1"), ktestclient.NewGetAction("replicationcontrollers", "", "config-1"), }, expectedErr: nil, }, { testName: "no deployment - dc scale", namespace: "default", name: "foo", count: uint(3), oc: testclient.NewSimpleFake(deploytest.OkDeploymentConfig(1)), kc: ktestclient.NewSimpleFake(), expected: []ktestclient.Action{ ktestclient.NewGetAction("deploymentconfigs", "default", "foo"), ktestclient.NewGetAction("deploymentconfigs", "default", "foo"), ktestclient.NewUpdateAction("deploymentconfigs", "default", nil), }, kexpected: []ktestclient.Action{ ktestclient.NewGetAction("replicationcontrollers", "default", "config-1"), }, expectedErr: nil, }, } for _, test := range tests { scaler := NewDeploymentConfigScaler(test.oc, test.kc) got := scaler.Scale(test.namespace, test.name, test.count, test.preconditions, test.retry, test.waitForReplicas) if got != test.expectedErr { t.Errorf("%s: error mismatch: expected %v, got %v", test.testName, test.expectedErr, got) } if len(test.oc.Actions()) != len(test.expected) { t.Fatalf("%s: unexpected OpenShift actions amount: %d, expected %d", test.testName, len(test.oc.Actions()), len(test.expected)) } for j, actualAction := range test.oc.Actions() { e, a := test.expected[j], actualAction if e.GetVerb() != a.GetVerb() || e.GetNamespace() != a.GetNamespace() || e.GetResource() != a.GetResource() || e.GetSubresource() != a.GetSubresource() { t.Errorf("%s: unexpected OpenShift action[%d]: %s, expected %s", test.testName, j, a, e) } } if len(test.kc.Actions()) != len(test.kexpected) { t.Fatalf("%s: unexpected Kubernetes actions amount: %d, expected %d", test.testName, len(test.kc.Actions()), len(test.kexpected)) } for j, actualAction := range test.kc.Actions() { e, a := test.kexpected[j], actualAction if e.GetVerb() != a.GetVerb() || e.GetNamespace() != a.GetNamespace() || e.GetResource() != a.GetResource() || e.GetSubresource() != a.GetSubresource() { t.Errorf("%s: unexpected Kubernetes action[%d]: %s, expected %s", test.testName, j, a, e) } } } }
func TestStop(t *testing.T) { notFound := func() runtime.Object { return &(kerrors.NewNotFound(buildapi.Resource("BuildConfig"), configName).(*kerrors.StatusError).ErrStatus) } tests := map[string]struct { oc *testclient.Fake expected []ktestclient.Action err bool }{ "simple stop": { oc: newBuildListFake(makeBuildConfig(0, false)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewUpdateAction("buildconfigs", "default", makeBuildConfig(0, true)), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewDeleteAction("buildconfigs", "default", configName), }, err: false, }, "multiple builds": { oc: newBuildListFake(makeBuildConfig(4, false), makeBuildList(4)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewUpdateAction("buildconfigs", "default", makeBuildConfig(4, true)), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewDeleteAction("builds", "default", "build-1"), ktestclient.NewDeleteAction("builds", "default", "build-3"), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewDeleteAction("builds", "default", "build-2"), ktestclient.NewDeleteAction("builds", "default", "build-4"), ktestclient.NewDeleteAction("buildconfigs", "default", configName), }, err: false, }, "no config, some builds": { oc: newBuildListFake(makeBuildList(2)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewDeleteAction("builds", "default", "build-1"), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewDeleteAction("builds", "default", "build-2"), }, err: false, }, "no config, no builds": { oc: testclient.NewSimpleFake(notFound()), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), }, err: true, }, "config, no builds": { oc: testclient.NewSimpleFake(makeBuildConfig(0, false)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewUpdateAction("buildconfigs", "default", makeBuildConfig(0, true)), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewDeleteAction("buildconfigs", "default", configName), }, err: false, }, } for testName, test := range tests { reaper := &BuildConfigReaper{oc: test.oc, pollInterval: time.Millisecond, timeout: time.Millisecond} err := reaper.Stop("default", configName, 1*time.Second, nil) if !test.err && err != nil { t.Errorf("%s: unexpected error: %v", testName, err) } if test.err && err == nil { t.Errorf("%s: expected an error", testName) } if len(test.oc.Actions()) != len(test.expected) { t.Fatalf("%s: unexpected actions: %v, expected %v", testName, test.oc.Actions(), test.expected) } for j, actualAction := range test.oc.Actions() { if !actionsAreEqual(actualAction, test.expected[j]) { t.Errorf("%s: unexpected action: %v, expected %v", testName, actualAction, test.expected[j]) } } } }
func TestGetClient(t *testing.T) { testCases := []struct { name string clientName string kubeClient *ktestclient.Fake expectedDelegation bool expectedErr string expectedClient *oauthapi.OAuthClient expectedActions []ktestclient.Action }{ { name: "delegate", clientName: "not:serviceaccount", kubeClient: ktestclient.NewSimpleFake(), expectedDelegation: true, expectedActions: []ktestclient.Action{}, }, { name: "missing sa", clientName: "system:serviceaccount:ns-01:missing-sa", kubeClient: ktestclient.NewSimpleFake(), expectedErr: `ServiceAccount "missing-sa" not found`, expectedActions: []ktestclient.Action{ktestclient.NewGetAction("serviceaccounts", "ns-01", "missing-sa")}, }, { name: "sa no redirects", clientName: "system:serviceaccount:ns-01:default", kubeClient: ktestclient.NewSimpleFake( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{}, }, }), expectedErr: `system:serviceaccount:ns-01:default has no redirectURIs; set serviceaccounts.openshift.io/oauth-redirecturi.<some-value>`, expectedActions: []ktestclient.Action{ktestclient.NewGetAction("serviceaccounts", "ns-01", "default")}, }, { name: "sa no tokens", clientName: "system:serviceaccount:ns-01:default", kubeClient: ktestclient.NewSimpleFake( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{OAuthRedirectURISecretAnnotationPrefix + "one": "anywhere"}, }, }), expectedErr: `system:serviceaccount:ns-01:default has no tokens`, expectedActions: []ktestclient.Action{ ktestclient.NewGetAction("serviceaccounts", "ns-01", "default"), ktestclient.NewListAction("secrets", "ns-01", kapi.ListOptions{}), }, }, { name: "good SA", clientName: "system:serviceaccount:ns-01:default", kubeClient: ktestclient.NewSimpleFake( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{OAuthRedirectURISecretAnnotationPrefix + "one": "anywhere"}, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"anywhere"}, }, expectedActions: []ktestclient.Action{ ktestclient.NewGetAction("serviceaccounts", "ns-01", "default"), ktestclient.NewListAction("secrets", "ns-01", kapi.ListOptions{}), }, }, } for _, tc := range testCases { delegate := &fakeDelegate{} getter := NewServiceAccountOAuthClientGetter(tc.kubeClient, tc.kubeClient, delegate) client, err := getter.GetClient(kapi.NewContext(), tc.clientName) switch { case len(tc.expectedErr) == 0 && err == nil: case len(tc.expectedErr) == 0 && err != nil, len(tc.expectedErr) > 0 && err == nil, len(tc.expectedErr) > 0 && err != nil && !strings.Contains(err.Error(), tc.expectedErr): t.Errorf("%s: expected %v, got %v", tc.name, tc.expectedErr, err) continue } if tc.expectedDelegation != delegate.called { t.Errorf("%s: expected %v, got %v", tc.name, tc.expectedDelegation, delegate.called) continue } if !kapi.Semantic.DeepEqual(tc.expectedClient, client) { t.Errorf("%s: expected %v, got %v", tc.name, tc.expectedClient, client) continue } if !reflect.DeepEqual(tc.expectedActions, tc.kubeClient.Actions()) { t.Errorf("%s: expected %v, got %v", tc.name, tc.expectedActions, tc.kubeClient.Actions()) continue } } }
func TestDockercfgDeletion(t *testing.T) { testcases := map[string]struct { ClientObjects []runtime.Object DeletedSecret *api.Secret ExpectedActions []testclient.Action }{ "deleted dockercfg secret without serviceaccount": { DeletedSecret: createdDockercfgSecret(), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", "default", "default"), testclient.NewDeleteAction("secrets", "default", "token-secret-1"), }, }, "deleted dockercfg secret with serviceaccount with reference": { ClientObjects: []runtime.Object{serviceAccount(addTokenSecretReference(tokenSecretReferences()), imagePullSecretReferences()), createdDockercfgSecret()}, DeletedSecret: createdDockercfgSecret(), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", "default", "default"), testclient.NewUpdateAction("serviceaccounts", "default", serviceAccount(tokenSecretReferences(), emptyImagePullSecretReferences())), testclient.NewDeleteAction("secrets", "default", "token-secret-1"), }, }, "deleted dockercfg secret with serviceaccount without reference": { ClientObjects: []runtime.Object{serviceAccount(addTokenSecretReference(tokenSecretReferences()), imagePullSecretReferences()), createdDockercfgSecret()}, DeletedSecret: createdDockercfgSecret(), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", "default", "default"), testclient.NewUpdateAction("serviceaccounts", "default", serviceAccount(tokenSecretReferences(), emptyImagePullSecretReferences())), testclient.NewDeleteAction("secrets", "default", "token-secret-1"), }, }, } for k, tc := range testcases { // Re-seed to reset name generation rand.Seed(1) client := testclient.NewSimpleFake(tc.ClientObjects...) controller := NewDockercfgDeletedController(client, DockercfgDeletedControllerOptions{}) if tc.DeletedSecret != nil { controller.secretDeleted(tc.DeletedSecret) } for i, action := range client.Actions() { if len(tc.ExpectedActions) < i+1 { t.Errorf("%s: %d unexpected actions: %+v", k, len(client.Actions())-len(tc.ExpectedActions), client.Actions()[i:]) break } expectedAction := tc.ExpectedActions[i] if !reflect.DeepEqual(expectedAction, action) { t.Errorf("%s: Expected %v, got %v", k, expectedAction, action) continue } } if len(tc.ExpectedActions) > len(client.Actions()) { t.Errorf("%s: %d additional expected actions:%+v", k, len(tc.ExpectedActions)-len(client.Actions()), tc.ExpectedActions[len(client.Actions()):]) } } }
func TestGetClient(t *testing.T) { testCases := []struct { name string clientName string kubeClient *fake.Clientset osClient *ostestclient.Fake expectedDelegation bool expectedErr string expectedClient *oauthapi.OAuthClient expectedKubeActions []core.Action expectedOSActions []ktestclient.Action }{ { name: "delegate", clientName: "not:serviceaccount", kubeClient: fake.NewSimpleClientset(), osClient: ostestclient.NewSimpleFake(), expectedDelegation: true, expectedKubeActions: []core.Action{}, expectedOSActions: []ktestclient.Action{}, }, { name: "missing sa", clientName: "system:serviceaccount:ns-01:missing-sa", kubeClient: fake.NewSimpleClientset(), osClient: ostestclient.NewSimpleFake(), expectedErr: `ServiceAccount "missing-sa" not found`, expectedKubeActions: []core.Action{core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "missing-sa")}, expectedOSActions: []ktestclient.Action{}, }, { name: "sa no redirects", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{}, }, }), osClient: ostestclient.NewSimpleFake(), expectedErr: `system:serviceaccount:ns-01:default has no redirectURIs; set serviceaccounts.openshift.io/oauth-redirecturi.<some-value>`, expectedKubeActions: []core.Action{core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default")}, expectedOSActions: []ktestclient.Action{}, }, { name: "sa no tokens", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{OAuthRedirectModelAnnotationURIPrefix + "one": "http://anywhere"}, }, }), osClient: ostestclient.NewSimpleFake(), expectedErr: `system:serviceaccount:ns-01:default has no tokens`, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{}, }, { name: "good SA", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{OAuthRedirectModelAnnotationURIPrefix + "one": "http://anywhere"}, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake(), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"http://anywhere"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{}, }, { name: "good SA with valid, simple route redirects", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{ OAuthRedirectModelAnnotationURIPrefix + "one": "http://anywhere", OAuthRedirectModelAnnotationReferencePrefix + "1": buildRedirectObjectReferenceString(routeKind, "route1", ""), }, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake( &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route1", UID: types.UID("route1"), }, Spec: routeapi.RouteSpec{ Path: "/defaultpath", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "example1.com", Conditions: buildValidRouteIngressCondition()}, }, }, }, ), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"http://anywhere", "https://example1.com/defaultpath"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{ ktestclient.NewGetAction("routes", "ns-01", "route1"), }, }, { name: "good SA with invalid route redirects", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{ OAuthRedirectModelAnnotationURIPrefix + "one": "http://anywhere", OAuthRedirectModelAnnotationReferencePrefix + "1": buildRedirectObjectReferenceString(routeKind, "route1", "wronggroup"), OAuthRedirectModelAnnotationReferencePrefix + "2": buildRedirectObjectReferenceString("wrongkind", "route1", ""), }, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake( &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route1", UID: types.UID("route1"), }, Spec: routeapi.RouteSpec{ Path: "/defaultpath", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "example1.com", Conditions: buildValidRouteIngressCondition()}, {Host: "example2.com", Conditions: buildValidRouteIngressCondition()}, {Host: "example3.com", Conditions: buildValidRouteIngressCondition()}, }, }, }, ), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"http://anywhere"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{}, }, { name: "good SA with a route that don't have a host", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{ OAuthRedirectModelAnnotationURIPrefix + "one": "http://anywhere", OAuthRedirectModelAnnotationReferencePrefix + "1": buildRedirectObjectReferenceString(routeKind, "route1", ""), }, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake( &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route1", UID: types.UID("route1"), }, Spec: routeapi.RouteSpec{ Path: "/defaultpath", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "", Conditions: buildValidRouteIngressCondition()}, }, }, }, ), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"http://anywhere"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{ ktestclient.NewGetAction("routes", "ns-01", "route1"), }, }, { name: "good SA with routes that don't have hosts, some of which are empty or duplicates", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{ OAuthRedirectModelAnnotationURIPrefix + "one": "http://anywhere", OAuthRedirectModelAnnotationReferencePrefix + "1": buildRedirectObjectReferenceString(routeKind, "route1", ""), OAuthRedirectModelAnnotationReferencePrefix + "2": buildRedirectObjectReferenceString(routeKind, "route2", ""), OAuthRedirectModelAnnotationReferencePrefix + "3": buildRedirectObjectReferenceString(routeKind, "missingroute", ""), }, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake( &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route1", UID: types.UID("route1"), }, Spec: routeapi.RouteSpec{ Path: "/defaultpath", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "", Conditions: buildValidRouteIngressCondition()}, {Host: "a.com", Conditions: buildValidRouteIngressCondition()}, {Host: ""}, {Host: "a.com", Conditions: buildValidRouteIngressCondition()}, {Host: "b.com", Conditions: buildValidRouteIngressCondition()}, }, }, }, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route2", UID: types.UID("route2"), }, Spec: routeapi.RouteSpec{ Path: "/path2", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "a.com", Conditions: buildValidRouteIngressCondition()}, {Host: "", Conditions: buildValidRouteIngressCondition()}, {Host: "b.com", Conditions: buildValidRouteIngressCondition()}, {Host: "b.com"}, {Host: ""}, }, }, }, ), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"http://anywhere", "https://a.com/defaultpath", "https://a.com/path2", "https://b.com/defaultpath", "https://b.com/path2"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{ ktestclient.NewListAction("routes", "ns-01", kapi.ListOptions{}), }, }, { name: "host overrides route data", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{ OAuthRedirectModelAnnotationReferencePrefix + "1": buildRedirectObjectReferenceString(routeKind, "route1", ""), OAuthRedirectModelAnnotationURIPrefix + "1": "//redhat.com", OAuthRedirectModelAnnotationReferencePrefix + "2": buildRedirectObjectReferenceString(routeKind, "route2", ""), OAuthRedirectModelAnnotationURIPrefix + "2": "//google.com", }, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake( &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route1", UID: types.UID("route1"), }, Spec: routeapi.RouteSpec{ Path: "/defaultpath", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: ""}, }, }, }, &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route2", UID: types.UID("route2"), }, Spec: routeapi.RouteSpec{ Path: "/otherpath", TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "ignored.com", Conditions: buildValidRouteIngressCondition()}, {Host: "alsoignored.com", Conditions: buildValidRouteIngressCondition()}, }, }, }, ), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"https://google.com/otherpath", "https://redhat.com/defaultpath"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{ ktestclient.NewListAction("routes", "ns-01", kapi.ListOptions{}), }, }, { name: "good SA with valid, route redirects using the same route twice", clientName: "system:serviceaccount:ns-01:default", kubeClient: fake.NewSimpleClientset( &kapi.ServiceAccount{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", UID: types.UID("any"), Annotations: map[string]string{ OAuthRedirectModelAnnotationURIPrefix + "1": "/awesomepath", OAuthRedirectModelAnnotationReferencePrefix + "1": buildRedirectObjectReferenceString(routeKind, "route1", ""), OAuthRedirectModelAnnotationURIPrefix + "2": "//:8000", OAuthRedirectModelAnnotationReferencePrefix + "2": buildRedirectObjectReferenceString(routeKind, "route1", ""), }, }, }, &kapi.Secret{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "default", Annotations: map[string]string{ kapi.ServiceAccountNameKey: "default", kapi.ServiceAccountUIDKey: "any", }, }, Type: kapi.SecretTypeServiceAccountToken, Data: map[string][]byte{kapi.ServiceAccountTokenKey: []byte("foo")}, }), osClient: ostestclient.NewSimpleFake( &routeapi.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "ns-01", Name: "route1", UID: types.UID("route1"), }, Spec: routeapi.RouteSpec{ TLS: &routeapi.TLSConfig{}, }, Status: routeapi.RouteStatus{ Ingress: []routeapi.RouteIngress{ {Host: "woot.com", Conditions: buildValidRouteIngressCondition()}, }, }, }, ), expectedClient: &oauthapi.OAuthClient{ ObjectMeta: kapi.ObjectMeta{Name: "system:serviceaccount:ns-01:default"}, ScopeRestrictions: getScopeRestrictionsFor("ns-01", "default"), AdditionalSecrets: []string{"foo"}, RedirectURIs: []string{"https://woot.com/awesomepath", "https://woot.com:8000"}, GrantMethod: oauthapi.GrantHandlerPrompt, }, expectedKubeActions: []core.Action{ core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, "ns-01", "default"), core.NewListAction(unversioned.GroupVersionResource{Resource: "secrets"}, "ns-01", kapi.ListOptions{}), }, expectedOSActions: []ktestclient.Action{ ktestclient.NewGetAction("routes", "ns-01", "route1"), }, }, } for _, tc := range testCases { delegate := &fakeDelegate{} getter := NewServiceAccountOAuthClientGetter(tc.kubeClient.Core(), tc.kubeClient.Core(), tc.osClient, delegate, oauthapi.GrantHandlerPrompt) client, err := getter.GetClient(kapi.NewContext(), tc.clientName) switch { case len(tc.expectedErr) == 0 && err == nil: case len(tc.expectedErr) == 0 && err != nil, len(tc.expectedErr) > 0 && err == nil, len(tc.expectedErr) > 0 && err != nil && !strings.Contains(err.Error(), tc.expectedErr): t.Errorf("%s: expected %#v, got %#v", tc.name, tc.expectedErr, err) continue } if tc.expectedDelegation != delegate.called { t.Errorf("%s: expected %#v, got %#v", tc.name, tc.expectedDelegation, delegate.called) continue } if !kapi.Semantic.DeepEqual(tc.expectedClient, client) { t.Errorf("%s: expected %#v, got %#v", tc.name, tc.expectedClient, client) continue } if !reflect.DeepEqual(tc.expectedKubeActions, tc.kubeClient.Actions()) { t.Errorf("%s: expected %#v, got %#v", tc.name, tc.expectedKubeActions, tc.kubeClient.Actions()) continue } if !reflect.DeepEqual(tc.expectedOSActions, tc.osClient.Actions()) { t.Errorf("%s: expected %#v, got %#v", tc.name, tc.expectedOSActions, tc.osClient.Actions()) continue } } }
func TestTokenCreation(t *testing.T) { testcases := map[string]struct { ClientObjects []runtime.Object SecretsSyncPending bool ServiceAccountsSyncPending bool ExistingServiceAccount *api.ServiceAccount ExistingSecrets []*api.Secret AddedServiceAccount *api.ServiceAccount UpdatedServiceAccount *api.ServiceAccount DeletedServiceAccount *api.ServiceAccount AddedSecret *api.Secret UpdatedSecret *api.Secret DeletedSecret *api.Secret ExpectedActions []testclient.Action }{ "new serviceaccount with no secrets": { ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, AddedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), }, }, "new serviceaccount with no secrets with unsynced secret store": { ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, SecretsSyncPending: true, AddedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), }, }, "new serviceaccount with missing secrets": { ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, AddedServiceAccount: serviceAccount(missingSecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(missingSecretReferences()))), }, }, "new serviceaccount with missing secrets with unsynced secret store": { ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, SecretsSyncPending: true, AddedServiceAccount: serviceAccount(missingSecretReferences()), ExpectedActions: []testclient.Action{}, }, "new serviceaccount with non-token secrets": { ClientObjects: []runtime.Object{serviceAccount(regularSecretReferences()), createdTokenSecret(), opaqueSecret()}, AddedServiceAccount: serviceAccount(regularSecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(regularSecretReferences()))), }, }, "new serviceaccount with token secrets": { ClientObjects: []runtime.Object{serviceAccount(tokenSecretReferences()), serviceAccountTokenSecret()}, ExistingSecrets: []*api.Secret{serviceAccountTokenSecret()}, AddedServiceAccount: serviceAccount(tokenSecretReferences()), ExpectedActions: []testclient.Action{}, }, "new serviceaccount with no secrets with resource conflict": { ClientObjects: []runtime.Object{updatedServiceAccount(emptySecretReferences()), createdTokenSecret()}, AddedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), }, }, "updated serviceaccount with no secrets": { ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, UpdatedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), }, }, "updated serviceaccount with no secrets with unsynced secret store": { ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, SecretsSyncPending: true, UpdatedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), }, }, "updated serviceaccount with missing secrets": { ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, UpdatedServiceAccount: serviceAccount(missingSecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(missingSecretReferences()))), }, }, "updated serviceaccount with missing secrets with unsynced secret store": { ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, SecretsSyncPending: true, UpdatedServiceAccount: serviceAccount(missingSecretReferences()), ExpectedActions: []testclient.Action{}, }, "updated serviceaccount with non-token secrets": { ClientObjects: []runtime.Object{serviceAccount(regularSecretReferences()), createdTokenSecret(), opaqueSecret()}, UpdatedServiceAccount: serviceAccount(regularSecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewCreateAction("secrets", api.NamespaceDefault, createdTokenSecret()), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(addTokenSecretReference(regularSecretReferences()))), }, }, "updated serviceaccount with token secrets": { ExistingSecrets: []*api.Secret{serviceAccountTokenSecret()}, UpdatedServiceAccount: serviceAccount(tokenSecretReferences()), ExpectedActions: []testclient.Action{}, }, "updated serviceaccount with no secrets with resource conflict": { ClientObjects: []runtime.Object{updatedServiceAccount(emptySecretReferences()), createdTokenSecret()}, UpdatedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), }, }, "deleted serviceaccount with no secrets": { DeletedServiceAccount: serviceAccount(emptySecretReferences()), ExpectedActions: []testclient.Action{}, }, "deleted serviceaccount with missing secrets": { DeletedServiceAccount: serviceAccount(missingSecretReferences()), ExpectedActions: []testclient.Action{}, }, "deleted serviceaccount with non-token secrets": { ClientObjects: []runtime.Object{opaqueSecret()}, DeletedServiceAccount: serviceAccount(regularSecretReferences()), ExpectedActions: []testclient.Action{}, }, "deleted serviceaccount with token secrets": { ClientObjects: []runtime.Object{serviceAccountTokenSecret()}, ExistingSecrets: []*api.Secret{serviceAccountTokenSecret()}, DeletedServiceAccount: serviceAccount(tokenSecretReferences()), ExpectedActions: []testclient.Action{ testclient.NewDeleteAction("secrets", api.NamespaceDefault, "token-secret-1"), }, }, "added secret without serviceaccount": { ClientObjects: []runtime.Object{serviceAccountTokenSecret()}, AddedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewDeleteAction("secrets", api.NamespaceDefault, "token-secret-1"), }, }, "added secret with serviceaccount": { ExistingServiceAccount: serviceAccount(tokenSecretReferences()), AddedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{}, }, "added token secret without token data": { ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutTokenData()}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), AddedSecret: serviceAccountTokenSecretWithoutTokenData(), ExpectedActions: []testclient.Action{ testclient.NewUpdateAction("secrets", api.NamespaceDefault, serviceAccountTokenSecret()), }, }, "added token secret without ca data": { ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutCAData()}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), AddedSecret: serviceAccountTokenSecretWithoutCAData(), ExpectedActions: []testclient.Action{ testclient.NewUpdateAction("secrets", api.NamespaceDefault, serviceAccountTokenSecret()), }, }, "added token secret with mismatched ca data": { ClientObjects: []runtime.Object{serviceAccountTokenSecretWithCAData([]byte("mismatched"))}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), AddedSecret: serviceAccountTokenSecretWithCAData([]byte("mismatched")), ExpectedActions: []testclient.Action{ testclient.NewUpdateAction("secrets", api.NamespaceDefault, serviceAccountTokenSecret()), }, }, "updated secret without serviceaccount": { ClientObjects: []runtime.Object{serviceAccountTokenSecret()}, UpdatedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewDeleteAction("secrets", api.NamespaceDefault, "token-secret-1"), }, }, "updated secret with serviceaccount": { ExistingServiceAccount: serviceAccount(tokenSecretReferences()), UpdatedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{}, }, "updated token secret without token data": { ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutTokenData()}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), UpdatedSecret: serviceAccountTokenSecretWithoutTokenData(), ExpectedActions: []testclient.Action{ testclient.NewUpdateAction("secrets", api.NamespaceDefault, serviceAccountTokenSecret()), }, }, "updated token secret without ca data": { ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutCAData()}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), UpdatedSecret: serviceAccountTokenSecretWithoutCAData(), ExpectedActions: []testclient.Action{ testclient.NewUpdateAction("secrets", api.NamespaceDefault, serviceAccountTokenSecret()), }, }, "updated token secret with mismatched ca data": { ClientObjects: []runtime.Object{serviceAccountTokenSecretWithCAData([]byte("mismatched"))}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), UpdatedSecret: serviceAccountTokenSecretWithCAData([]byte("mismatched")), ExpectedActions: []testclient.Action{ testclient.NewUpdateAction("secrets", api.NamespaceDefault, serviceAccountTokenSecret()), }, }, "deleted secret without serviceaccount": { DeletedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{}, }, "deleted secret with serviceaccount with reference": { ClientObjects: []runtime.Object{serviceAccount(tokenSecretReferences())}, ExistingServiceAccount: serviceAccount(tokenSecretReferences()), DeletedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{ testclient.NewGetAction("serviceaccounts", api.NamespaceDefault, "default"), testclient.NewUpdateAction("serviceaccounts", api.NamespaceDefault, serviceAccount(emptySecretReferences())), }, }, "deleted secret with serviceaccount without reference": { ExistingServiceAccount: serviceAccount(emptySecretReferences()), DeletedSecret: serviceAccountTokenSecret(), ExpectedActions: []testclient.Action{}, }, } for k, tc := range testcases { // Re-seed to reset name generation utilrand.Seed(1) generator := &testGenerator{Token: "ABC"} client := testclient.NewSimpleFake(tc.ClientObjects...) controller := NewTokensController(client, TokensControllerOptions{TokenGenerator: generator, RootCA: []byte("CA Data")}) // Tell the token controller whether its stores have been synced controller.serviceAccountsSynced = func() bool { return !tc.ServiceAccountsSyncPending } controller.secretsSynced = func() bool { return !tc.SecretsSyncPending } if tc.ExistingServiceAccount != nil { controller.serviceAccounts.Add(tc.ExistingServiceAccount) } for _, s := range tc.ExistingSecrets { controller.secrets.Add(s) } if tc.AddedServiceAccount != nil { controller.serviceAccountAdded(tc.AddedServiceAccount) } if tc.UpdatedServiceAccount != nil { controller.serviceAccountUpdated(nil, tc.UpdatedServiceAccount) } if tc.DeletedServiceAccount != nil { controller.serviceAccountDeleted(tc.DeletedServiceAccount) } if tc.AddedSecret != nil { controller.secretAdded(tc.AddedSecret) } if tc.UpdatedSecret != nil { controller.secretUpdated(nil, tc.UpdatedSecret) } if tc.DeletedSecret != nil { controller.secretDeleted(tc.DeletedSecret) } actions := client.Actions() for i, action := range actions { if len(tc.ExpectedActions) < i+1 { t.Errorf("%s: %d unexpected actions: %+v", k, len(actions)-len(tc.ExpectedActions), actions[i:]) break } expectedAction := tc.ExpectedActions[i] if !reflect.DeepEqual(expectedAction, action) { t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, expectedAction, action) continue } } if len(tc.ExpectedActions) > len(actions) { t.Errorf("%s: %d additional expected actions:%+v", k, len(tc.ExpectedActions)-len(actions), tc.ExpectedActions[len(actions):]) } } }
func TestSimpleStop(t *testing.T) { tests := []struct { fake *reaperFake kind unversioned.GroupKind actions []testclient.Action expectError bool test string }{ { fake: &reaperFake{ Fake: &testclient.Fake{}, }, kind: api.Kind("Pod"), actions: []testclient.Action{ testclient.NewGetAction("pods", api.NamespaceDefault, "foo"), testclient.NewDeleteAction("pods", api.NamespaceDefault, "foo"), }, expectError: false, test: "stop pod succeeds", }, { fake: &reaperFake{ Fake: &testclient.Fake{}, }, kind: api.Kind("Service"), actions: []testclient.Action{ testclient.NewGetAction("services", api.NamespaceDefault, "foo"), testclient.NewDeleteAction("services", api.NamespaceDefault, "foo"), }, expectError: false, test: "stop service succeeds", }, { fake: &reaperFake{ Fake: &testclient.Fake{}, noSuchPod: true, }, kind: api.Kind("Pod"), actions: []testclient.Action{}, expectError: true, test: "stop pod fails, no pod", }, { fake: &reaperFake{ Fake: &testclient.Fake{}, noDeleteService: true, }, kind: api.Kind("Service"), actions: []testclient.Action{ testclient.NewGetAction("services", api.NamespaceDefault, "foo"), }, expectError: true, test: "stop service fails, can't delete", }, } for _, test := range tests { fake := test.fake reaper, err := ReaperFor(test.kind, fake) if err != nil { t.Errorf("unexpected error: %v (%s)", err, test.test) } err = reaper.Stop("default", "foo", 0, nil) if err != nil && !test.expectError { t.Errorf("unexpected error: %v (%s)", err, test.test) } if err == nil { if test.expectError { t.Errorf("unexpected non-error: %v (%s)", err, test.test) } } actions := fake.Actions() if len(test.actions) != len(actions) { t.Errorf("unexpected actions: %v; expected %v (%s)", actions, test.actions, test.test) } for i, action := range actions { testAction := test.actions[i] if action != testAction { t.Errorf("unexpected action: %#v; expected %v (%s)", action, testAction, test.test) } } } }
func TestStop(t *testing.T) { notFound := func() runtime.Object { return &(kerrors.NewNotFound(buildapi.Resource("BuildConfig"), configName).ErrStatus) } tests := map[string]struct { targetBC string oc *testclient.Fake expected []ktestclient.Action err bool }{ "simple stop": { targetBC: configName, oc: newBuildListFake(makeBuildConfig(configName, 0, false)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), // Since there are no builds associated with this build config, do not expect an update ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewDeleteAction("buildconfigs", "default", configName), }, err: false, }, "multiple builds": { targetBC: configName, oc: newBuildListFake(makeBuildConfig(configName, 4, false), makeBuildList(configName, 4)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewGetAction("buildconfigs", "default", configName), // Second GET to enable conflict retry logic ktestclient.NewUpdateAction("buildconfigs", "default", makeBuildConfig(configName, 4, true)), // Because this bc has builds, it is paused ktestclient.NewDeleteAction("builds", "default", "build-1"), ktestclient.NewDeleteAction("builds", "default", "build-2"), ktestclient.NewDeleteAction("builds", "default", "build-3"), ktestclient.NewDeleteAction("builds", "default", "build-4"), ktestclient.NewDeleteAction("buildconfigs", "default", configName), }, err: false, }, "long name builds": { targetBC: longConfigNameA, oc: newBuildListFake(makeBuildConfig(longConfigNameA, 4, false), makeBuildList(longConfigNameA, 4), makeBuildList(longConfigNameB, 4)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", longConfigNameA), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(longConfigNameA)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(longConfigNameA)}), ktestclient.NewGetAction("buildconfigs", "default", longConfigNameA), // Second GET to enable conflict retry logic ktestclient.NewUpdateAction("buildconfigs", "default", makeBuildConfig(longConfigNameA, 4, true)), // Because this bc has builds, it is paused ktestclient.NewDeleteAction("builds", "default", "build-1"), ktestclient.NewDeleteAction("builds", "default", "build-2"), ktestclient.NewDeleteAction("builds", "default", "build-3"), ktestclient.NewDeleteAction("builds", "default", "build-4"), ktestclient.NewDeleteAction("buildconfigs", "default", longConfigNameA), }, err: false, }, "no config, no or some builds": { targetBC: configName, oc: testclient.NewSimpleFake(notFound(), makeBuildList(configName, 2)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), }, err: true, }, "config, no builds": { targetBC: configName, oc: testclient.NewSimpleFake(makeBuildConfig(configName, 0, false)), expected: []ktestclient.Action{ ktestclient.NewGetAction("buildconfigs", "default", configName), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelector(configName)}), ktestclient.NewListAction("builds", "default", kapi.ListOptions{LabelSelector: buildutil.BuildConfigSelectorDeprecated(configName)}), ktestclient.NewDeleteAction("buildconfigs", "default", configName), }, err: false, }, } for testName, test := range tests { reaper := &BuildConfigReaper{oc: test.oc, pollInterval: time.Millisecond, timeout: time.Millisecond} err := reaper.Stop("default", test.targetBC, 1*time.Second, nil) if !test.err && err != nil { t.Errorf("%s: unexpected error: %v", testName, err) } if test.err && err == nil { t.Errorf("%s: expected an error", testName) } if len(test.oc.Actions()) != len(test.expected) { t.Fatalf("%s: unexpected actions: %v, expected %v", testName, test.oc.Actions(), test.expected) } for j, actualAction := range test.oc.Actions() { if !actionsAreEqual(actualAction, test.expected[j]) { t.Errorf("%s: unexpected action: %v, expected %v", testName, actualAction, test.expected[j]) } } } }