func TestAsyncCreateError(t *testing.T) { ch := make(chan struct{}) storage := SimpleRESTStorage{ injectedFunction: func(obj runtime.Object) (runtime.Object, error) { <-ch return nil, apierrs.NewAlreadyExists("foo", "bar") }, } selfLinker := &setTestSelfLinker{ t: t, name: "bar", expectedSet: "/prefix/version/foo/bar", } handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version", selfLinker) handler.(*defaultAPIServer).group.handler.asyncOpWait = 0 server := httptest.NewServer(handler) defer server.Close() simple := &Simple{Other: "bar"} data, _ := codec.Encode(simple) status := expectApiStatus(t, "POST", fmt.Sprintf("%s/prefix/version/foo", server.URL), data, http.StatusAccepted) if status.Status != api.StatusWorking || status.Details == nil || status.Details.ID == "" { t.Errorf("Unexpected status %#v", status) } otherStatus := expectApiStatus(t, "GET", fmt.Sprintf("%s/prefix/version/operations/%s", server.URL, status.Details.ID), []byte{}, http.StatusAccepted) if !reflect.DeepEqual(status, otherStatus) { t.Errorf("Expected %#v, Got %#v", status, otherStatus) } ch <- struct{}{} time.Sleep(time.Millisecond) finalStatus := expectApiStatus(t, "GET", fmt.Sprintf("%s/prefix/version/operations/%s?after=1", server.URL, status.Details.ID), []byte{}, http.StatusOK) expectedErr := apierrs.NewAlreadyExists("foo", "bar") expectedStatus := &api.Status{ Status: api.StatusFailure, Code: http.StatusConflict, Reason: "AlreadyExists", Message: expectedErr.Error(), Details: &api.StatusDetails{ Kind: "foo", ID: "bar", }, } if !reflect.DeepEqual(expectedStatus, finalStatus) { t.Errorf("Expected %#v, Got %#v", expectedStatus, finalStatus) if finalStatus.Details != nil { t.Logf("Details %#v, Got %#v", *expectedStatus.Details, *finalStatus.Details) } } if !selfLinker.called { t.Errorf("Never set self link") } }
// CreateController creates a new ReplicationController. func (r *Registry) CreateController(controller api.ReplicationController) error { err := r.CreateObj(makeControllerKey(controller.ID), controller) if tools.IsEtcdNodeExist(err) { return errors.NewAlreadyExists("replicationController", controller.ID) } return err }
// CreateService creates a new Service. func (r *Registry) CreateService(svc api.Service) error { err := r.CreateObj(makeServiceKey(svc.ID), svc) if tools.IsEtcdNodeExist(err) { return errors.NewAlreadyExists("service", svc.ID) } return err }
func TestErrorsToAPIStatus(t *testing.T) { cases := map[error]api.Status{ errors.NewAlreadyExists("foo", "bar"): { Status: api.StatusFailure, Code: http.StatusConflict, Reason: "AlreadyExists", Message: "foo \"bar\" already exists", Details: &api.StatusDetails{ Kind: "foo", ID: "bar", }, }, errors.NewConflict("foo", "bar", stderrs.New("failure")): { Status: api.StatusFailure, Code: http.StatusConflict, Reason: "Conflict", Message: "foo \"bar\" cannot be updated: failure", Details: &api.StatusDetails{ Kind: "foo", ID: "bar", }, }, } for k, v := range cases { actual := errToAPIStatus(k) if !reflect.DeepEqual(actual, &v) { t.Errorf("%s: Expected %#v, Got %#v", k, v, actual) } } }
// CreateImage creates a new image func (r *Etcd) CreateImage(image *api.Image) error { err := r.CreateObj(makeImageKey(image.ID), image) if tools.IsEtcdNodeExist(err) { return apierrors.NewAlreadyExists("image", image.ID) } return err }
func TestCheckGeneratedNameError(t *testing.T) { expect := errors.NewNotFound("foo", "bar") if err := CheckGeneratedNameError(Services, expect, &api.Pod{}); err != expect { t.Errorf("NotFoundError should be ignored: %v", err) } expect = errors.NewAlreadyExists("foo", "bar") if err := CheckGeneratedNameError(Services, expect, &api.Pod{}); err != expect { t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err) } expect = errors.NewAlreadyExists("foo", "bar") if err := CheckGeneratedNameError(Services, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) { t.Errorf("expected try again later error: %v", err) } }
func (m *VirtualStorage) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { if err := rest.BeforeCreate(m.CreateStrategy, ctx, obj); err != nil { return nil, err } role := obj.(*authorizationapi.Role) policy, err := m.EnsurePolicy(ctx) if err != nil { return nil, err } if _, exists := policy.Roles[role.Name]; exists { return nil, kapierrors.NewAlreadyExists("Role", role.Name) } role.ResourceVersion = policy.ResourceVersion policy.Roles[role.Name] = role policy.LastModified = util.Now() if err := m.PolicyStorage.UpdatePolicy(ctx, policy); err != nil { return nil, err } return role, nil }
// CreateBuild creates a new Build. func (r *EtcdRegistry) CreateBuild(build *api.Build) error { err := r.CreateObj(makeBuildKey(build.ID), build) if tools.IsEtcdNodeExist(err) { return errors.NewAlreadyExists("build", build.ID) } return err }
// CreateBuildConfig creates a new BuildConfig. func (r *EtcdRegistry) CreateBuildConfig(config *api.BuildConfig) error { err := r.CreateObj(makeBuildConfigKey(config.ID), config) if tools.IsEtcdNodeExist(err) { return errors.NewAlreadyExists("buildConfig", config.ID) } return err }
// InterpretCreateError converts a generic etcd error on a create // operation into the appropriate API error. func InterpretCreateError(err error, kind, name string) error { switch { case tools.IsEtcdNodeExist(err): return errors.NewAlreadyExists(kind, name) default: return err } }
// CreateImageRepository registers the given ImageRepository. func (r *Etcd) CreateImageRepository(repo *api.ImageRepository) error { err := r.CreateObj(makeImageRepositoryKey(repo.ID), repo) if err != nil && tools.IsEtcdNodeExist(err) { return apierrors.NewAlreadyExists("imageRepository", repo.ID) } return err }
func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { if err := rest.BeforeCreate(projectrequestregistry.Strategy, ctx, obj); err != nil { return nil, err } projectRequest := obj.(*projectapi.ProjectRequest) if _, err := r.openshiftClient.Projects().Get(projectRequest.Name); err == nil { return nil, kapierror.NewAlreadyExists("project", projectRequest.Name) } projectName := projectRequest.Name projectAdmin := "" if userInfo, exists := kapi.UserFrom(ctx); exists { projectAdmin = userInfo.GetName() } template, err := r.getTemplate() if err != nil { return nil, err } for i := range template.Parameters { switch template.Parameters[i].Name { case ProjectAdminUserParam: template.Parameters[i].Value = projectAdmin case ProjectDescriptionParam: template.Parameters[i].Value = projectRequest.Description case ProjectDisplayNameParam: template.Parameters[i].Value = projectRequest.DisplayName case ProjectNameParam: template.Parameters[i].Value = projectName } } list, err := r.openshiftClient.TemplateConfigs(kapi.NamespaceDefault).Create(template) if err != nil { return nil, err } if err := utilerrors.NewAggregate(runtime.DecodeList(list.Objects, kapi.Scheme)); err != nil { return nil, err } bulk := configcmd.Bulk{ Mapper: latest.RESTMapper, Typer: kapi.Scheme, RESTClientFactory: func(mapping *meta.RESTMapping) (resource.RESTClient, error) { return r.openshiftClient, nil }, } if err := utilerrors.NewAggregate(bulk.Create(&kapi.List{Items: list.Objects}, projectName)); err != nil { return nil, err } return r.openshiftClient.Projects().Get(projectName) }
// InterpretCreateError converts a generic etcd error on a create // operation into the appropriate API error. func InterpretCreateError(err error, kind, name string) error { switch { case tools.IsEtcdNodeExist(err): return errors.NewAlreadyExists(kind, name) case errors.IsAPIStatusError(err): return err default: return errors.NewInternalError(err) } }
// transformResponse converts an API response into a structured API object. func (r *Request) transformResponse(resp *http.Response, req *http.Request) ([]byte, bool, error) { defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, false, err } // Did the server give us a status response? isStatusResponse := false var status api.Status if err := r.codec.DecodeInto(body, &status); err == nil && status.Status != "" { isStatusResponse = true } switch { case resp.StatusCode == http.StatusSwitchingProtocols: // no-op, we've been upgraded case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent: if !isStatusResponse { var err error = &UnexpectedStatusError{ Request: req, Response: resp, Body: string(body), } // TODO: handle other error classes we know about switch resp.StatusCode { case http.StatusConflict: if req.Method == "POST" { err = errors.NewAlreadyExists(r.resource, r.resourceName) } else { err = errors.NewConflict(r.resource, r.resourceName, err) } case http.StatusNotFound: err = errors.NewNotFound(r.resource, r.resourceName) case http.StatusBadRequest: err = errors.NewBadRequest(err.Error()) } return nil, false, err } return nil, false, errors.FromObject(&status) } // If the server gave us a status back, look at what it was. if isStatusResponse && status.Status != api.StatusSuccess { // "Working" requests need to be handled specially. // "Failed" requests are clearly just an error and it makes sense to return them as such. return nil, false, errors.FromObject(&status) } created := resp.StatusCode == http.StatusCreated return body, created, err }
func TestErroredConflictedCreateServices(t *testing.T) { servicesSetup() te.CreateRCError = kerrors.NewAlreadyExists("thing", "name") sd, err := adapter.CreateServices(services) assert.Len(t, sd, 0) pmxErr, ok := err.(*pmxadapter.Error) if assert.Error(t, pmxErr) && assert.True(t, ok) { assert.Equal(t, te.CreateRCError.Error(), pmxErr.Message) assert.Equal(t, http.StatusConflict, pmxErr.Code) } }
func (t *Tester) TestCreateGeneratesNameReturnsServerTimeout(valid runtime.Object) { objectMeta, err := api.ObjectMetaFor(valid) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, valid) } objectMeta.GenerateName = "test-" t.withStorageError(errors.NewAlreadyExists("kind", "thing"), func() { _, err := t.storage.(rest.Creater).Create(api.NewDefaultContext(), valid) if err == nil || !errors.IsServerTimeout(err) { t.Fatalf("Unexpected error: %v", err) } }) }
// TestHandle_unrelatedPodAlreadyExists ensures that attempts to create a // deployer pod, when a pod with the same name but missing annotations results // a transition to failed. func TestHandle_unrelatedPodAlreadyExists(t *testing.T) { var updatedDeployment *kapi.ReplicationController config := deploytest.OkDeploymentConfig(1) deployment, _ := deployutil.MakeDeployment(config, kapi.Codec) deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusNew) otherPod := unrelatedPod(deployment) controller := &DeploymentController{ decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) { return deployutil.DecodeDeploymentConfig(deployment, api.Codec) }, deploymentClient: &deploymentClientImpl{ updateDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { updatedDeployment = deployment return updatedDeployment, nil }, }, podClient: &podClientImpl{ getPodFunc: func(namespace, name string) (*kapi.Pod, error) { return otherPod, nil }, createPodFunc: func(namespace string, pod *kapi.Pod) (*kapi.Pod, error) { return nil, kerrors.NewAlreadyExists("Pod", pod.Name) }, }, makeContainer: func(strategy *deployapi.DeploymentStrategy) (*kapi.Container, error) { return okContainer(), nil }, recorder: &record.FakeRecorder{}, } err := controller.Handle(deployment) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, exists := updatedDeployment.Annotations[deployapi.DeploymentPodAnnotation]; exists { t.Fatalf("deployment updated with pod name annotation") } if e, a := deployapi.DeploymentFailedUnrelatedDeploymentExists, deployment.Annotations[deployapi.DeploymentStatusReasonAnnotation]; e != a { t.Errorf("expected reason annotation %s, got %s", e, a) } if e, a := deployapi.DeploymentStatusFailed, deployutil.DeploymentStatusFor(updatedDeployment); e != a { t.Errorf("expected deployment status %s, got %s", e, a) } }
func (m *FakeNodeHandler) Create(node *api.Node) (*api.Node, error) { defer func() { m.RequestCount++ }() for _, n := range m.Existing { if n.Name == node.Name { return nil, apierrors.NewAlreadyExists("Minion", node.Name) } } if m.CreateHook == nil || m.CreateHook(m, node) { nodeCopy := *node m.CreatedNodes = append(m.CreatedNodes, &nodeCopy) return node, nil } else { return nil, errors.New("Create error.") } }
func TestDelayReturnsError(t *testing.T) { storage := SimpleRESTStorage{ injectedFunction: func(obj runtime.Object) (runtime.Object, error) { return nil, apierrs.NewAlreadyExists("foo", "bar") }, } handler := handle(map[string]RESTStorage{"foo": &storage}) server := httptest.NewServer(handler) defer server.Close() status := expectApiStatus(t, "DELETE", fmt.Sprintf("%s/api/version/foo/bar", server.URL), nil, http.StatusConflict) if status.Status != api.StatusFailure || status.Message == "" || status.Details == nil || status.Reason != api.StatusReasonAlreadyExists { t.Errorf("Unexpected status %#v", status) } }
func TestAsyncDelayReturnsError(t *testing.T) { storage := SimpleRESTStorage{ injectedFunction: func(obj runtime.Object) (runtime.Object, error) { return nil, apierrs.NewAlreadyExists("foo", "bar") }, } handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix/version") handler.(*defaultAPIServer).group.handler.asyncOpWait = time.Millisecond / 2 server := httptest.NewServer(handler) status := expectApiStatus(t, "DELETE", fmt.Sprintf("%s/prefix/version/foo/bar", server.URL), nil, http.StatusConflict) if status.Status != api.StatusFailure || status.Message == "" || status.Details == nil || status.Reason != api.StatusReasonAlreadyExists { t.Errorf("Unexpected status %#v", status) } }
// TestHandle_deployerPodAlreadyExists ensures that attempts to create a // deployer pod which was already created don't result in an error // (effectively skipping the handling as redundant). func TestHandle_deployerPodAlreadyExists(t *testing.T) { var updatedDeployment *kapi.ReplicationController config := deploytest.OkDeploymentConfig(1) deployment, _ := deployutil.MakeDeployment(config, kapi.Codec) deployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusNew) deployerPod := relatedPod(deployment) controller := &DeploymentController{ decodeConfig: func(deployment *kapi.ReplicationController) (*deployapi.DeploymentConfig, error) { return deployutil.DecodeDeploymentConfig(deployment, api.Codec) }, deploymentClient: &deploymentClientImpl{ updateDeploymentFunc: func(namespace string, deployment *kapi.ReplicationController) (*kapi.ReplicationController, error) { updatedDeployment = deployment return updatedDeployment, nil }, }, podClient: &podClientImpl{ getPodFunc: func(namespace, name string) (*kapi.Pod, error) { return deployerPod, nil }, createPodFunc: func(namespace string, pod *kapi.Pod) (*kapi.Pod, error) { return nil, kerrors.NewAlreadyExists("Pod", pod.Name) }, }, makeContainer: func(strategy *deployapi.DeploymentStrategy) (*kapi.Container, error) { return okContainer(), nil }, recorder: &record.FakeRecorder{}, } err := controller.Handle(deployment) if err != nil { t.Fatalf("unexpected error: %v", err) } if updatedDeployment.Annotations[deployapi.DeploymentPodAnnotation] != deployerPod.Name { t.Fatalf("deployment not updated with pod name annotation") } if updatedDeployment.Annotations[deployapi.DeploymentStatusAnnotation] != string(deployapi.DeploymentStatusPending) { t.Fatalf("deployment status not updated to pending") } }
// CreateClusterPolicyBinding creates a new policyBinding. func (r *ClusterPolicyBindingRegistry) CreateClusterPolicyBinding(ctx kapi.Context, policyBinding *authorizationapi.ClusterPolicyBinding) error { if r.Err != nil { return r.Err } namespace := kapi.NamespaceValue(ctx) if len(namespace) != 0 { return errors.New("invalid request. Namespace parameter disallowed.") } if existing, _ := r.GetClusterPolicyBinding(ctx, policyBinding.Name); existing != nil { return kapierrors.NewAlreadyExists("ClusterPolicyBinding", policyBinding.Name) } addClusterPolicyBinding(r.ClusterPolicyBindings, *policyBinding) return nil }
// TestAdmissionNamespaceExistsUnknownToHandler func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) { namespace := "test" mockClient := &testclient.Fake{ Err: errors.NewAlreadyExists("namespaces", namespace), } store := cache.NewStore(cache.MetaNamespaceKeyFunc) handler := &provision{ client: mockClient, store: store, } pod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", namespace, "pods", "", admission.Create, nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler") } }
func (m *VirtualStorage) createRoleBinding(ctx kapi.Context, obj runtime.Object, allowEscalation bool) (*authorizationapi.RoleBinding, error) { if err := rest.BeforeCreate(m.CreateStrategy, ctx, obj); err != nil { return nil, err } roleBinding := obj.(*authorizationapi.RoleBinding) if err := m.validateReferentialIntegrity(ctx, roleBinding); err != nil { return nil, err } if !allowEscalation { if err := m.confirmNoEscalation(ctx, roleBinding); err != nil { return nil, err } } policyBinding, err := m.getPolicyBindingForPolicy(ctx, roleBinding.RoleRef.Namespace, allowEscalation) if err != nil { return nil, err } _, exists := policyBinding.RoleBindings[roleBinding.Name] if exists { return nil, kapierrors.NewAlreadyExists("RoleBinding", roleBinding.Name) } roleBinding.ResourceVersion = policyBinding.ResourceVersion policyBinding.RoleBindings[roleBinding.Name] = roleBinding policyBinding.LastModified = util.Now() if err := m.BindingRegistry.UpdatePolicyBinding(ctx, policyBinding); err != nil { return nil, err } return roleBinding, nil }
func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { if err := rest.BeforeCreate(projectrequestregistry.Strategy, ctx, obj); err != nil { return nil, err } projectRequest := obj.(*projectapi.ProjectRequest) if _, err := r.openshiftClient.Projects().Get(projectRequest.Name); err == nil { return nil, kapierror.NewAlreadyExists("project", projectRequest.Name) } projectName := projectRequest.Name projectAdmin := "" if userInfo, exists := kapi.UserFrom(ctx); exists { projectAdmin = userInfo.GetName() } template, err := r.getTemplate() if err != nil { return nil, err } for i := range template.Parameters { switch template.Parameters[i].Name { case ProjectAdminUserParam: template.Parameters[i].Value = projectAdmin case ProjectDescriptionParam: template.Parameters[i].Value = projectRequest.Description case ProjectDisplayNameParam: template.Parameters[i].Value = projectRequest.DisplayName case ProjectNameParam: template.Parameters[i].Value = projectName } } list, err := r.openshiftClient.TemplateConfigs(kapi.NamespaceDefault).Create(template) if err != nil { return nil, err } if err := utilerrors.NewAggregate(runtime.DecodeList(list.Objects, kapi.Scheme)); err != nil { return nil, kapierror.NewInternalError(err) } // one of the items in this list should be the project. We are going to locate it, remove it from the list, create it separately var projectFromTemplate *projectapi.Project objectsToCreate := &kapi.List{} for i := range list.Objects { if templateProject, ok := list.Objects[i].(*projectapi.Project); ok { projectFromTemplate = templateProject if len(list.Objects) > (i + 1) { objectsToCreate.Items = append(objectsToCreate.Items, list.Objects[i+1:]...) } break } objectsToCreate.Items = append(objectsToCreate.Items, list.Objects[i]) } if projectFromTemplate == nil { return nil, kapierror.NewInternalError(fmt.Errorf("the project template (%s/%s) is not correctly configured: must contain a project resource", r.templateNamespace, r.templateName)) } // we split out project creation separately so that in a case of racers for the same project, only one will win and create the rest of their template objects if _, err := r.openshiftClient.Projects().Create(projectFromTemplate); err != nil { return nil, err } bulk := configcmd.Bulk{ Mapper: latest.RESTMapper, Typer: kapi.Scheme, RESTClientFactory: func(mapping *meta.RESTMapping) (resource.RESTClient, error) { return r.openshiftClient, nil }, } if err := utilerrors.NewAggregate(bulk.Create(objectsToCreate, projectName)); err != nil { return nil, kapierror.NewInternalError(err) } return r.openshiftClient.Projects().Get(projectName) }
func (s *REST) createOrUpdate(ctx kapi.Context, obj runtime.Object, forceCreate bool) (runtime.Object, bool, error) { mapping := obj.(*api.UserIdentityMapping) identity, identityErr, oldUser, oldUserErr, oldMapping, oldMappingErr := s.getRelatedObjects(ctx, mapping.Name) // Ensure we didn't get any errors other than NotFound errors if !(oldMappingErr == nil || kerrs.IsNotFound(oldMappingErr)) { return nil, false, oldMappingErr } if !(identityErr == nil || kerrs.IsNotFound(identityErr)) { return nil, false, identityErr } if !(oldUserErr == nil || kerrs.IsNotFound(oldUserErr)) { return nil, false, oldUserErr } // If we expect to be creating, fail if the mapping already existed if forceCreate && oldMappingErr == nil { return nil, false, kerrs.NewAlreadyExists("UserIdentityMapping", oldMapping.Name) } // Allow update to create if missing creating := forceCreate || kerrs.IsNotFound(oldMappingErr) if creating { // Pre-create checks with no access to oldMapping if err := rest.BeforeCreate(Strategy, ctx, mapping); err != nil { return nil, false, err } // Ensure resource version is not specified if len(mapping.ResourceVersion) > 0 { return nil, false, kerrs.NewNotFound("UserIdentityMapping", mapping.Name) } } else { // Pre-update checks with access to oldMapping if err := rest.BeforeUpdate(Strategy, ctx, mapping, oldMapping); err != nil { return nil, false, err } // Ensure resource versions match if len(mapping.ResourceVersion) > 0 && mapping.ResourceVersion != oldMapping.ResourceVersion { return nil, false, kerrs.NewConflict("UserIdentityMapping", mapping.Name, fmt.Errorf("the resource was updated to %s", oldMapping.ResourceVersion)) } // If we're "updating" to the user we're already pointing to, we're already done if mapping.User.Name == oldMapping.User.Name { return oldMapping, false, nil } } // Validate identity if kerrs.IsNotFound(identityErr) { errs := fielderrors.ValidationErrorList([]error{ fielderrors.NewFieldInvalid("identity.name", mapping.Identity.Name, "referenced identity does not exist"), }) return nil, false, kerrs.NewInvalid("UserIdentityMapping", mapping.Name, errs) } // Get new user newUser, err := s.userRegistry.GetUser(ctx, mapping.User.Name) if kerrs.IsNotFound(err) { errs := fielderrors.ValidationErrorList([]error{ fielderrors.NewFieldInvalid("user.name", mapping.User.Name, "referenced user does not exist"), }) return nil, false, kerrs.NewInvalid("UserIdentityMapping", mapping.Name, errs) } if err != nil { return nil, false, err } // Update the new user to point at the identity. If this fails, Update is re-entrant if addIdentityToUser(identity, newUser) { if _, err := s.userRegistry.UpdateUser(ctx, newUser); err != nil { return nil, false, err } } // Update the identity to point at the new user. If this fails. Update is re-entrant if setIdentityUser(identity, newUser) { if updatedIdentity, err := s.identityRegistry.UpdateIdentity(ctx, identity); err != nil { return nil, false, err } else { identity = updatedIdentity } } // At this point, the mapping for the identity has been updated to the new user // Everything past this point is cleanup // Update the old user to no longer point at the identity. // If this fails, log the error, but continue, because Update is no longer re-entrant if oldUser != nil && removeIdentityFromUser(identity, oldUser) { if _, err := s.userRegistry.UpdateUser(ctx, oldUser); err != nil { util.HandleError(fmt.Errorf("error removing identity reference %s from user %s: %v", identity.Name, oldUser.Name, err)) } } updatedMapping, err := mappingFor(newUser, identity) return updatedMapping, creating, err }
func (*errExistsPodManager) CreatePod(namespace string, pod *kapi.Pod) (*kapi.Pod, error) { return &kapi.Pod{}, kerrors.NewAlreadyExists("kind", "name") }