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")
	}
}
Example #2
0
// 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
}
Example #3
0
// 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
}
Example #4
0
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)
		}
	}
}
Example #5
0
// 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
}
Example #8
0
// 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
}
Example #9
0
// 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
}
Example #10
0
// 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
	}
}
Example #11
0
// 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)
}
Example #13
0
// 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)
		}
	})
}
Example #17
0
// 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)
	}
}
Example #18
0
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.")
	}
}
Example #19
0
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)
	}
}
Example #20
0
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)
	}
}
Example #21
0
// 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
}
Example #23
0
// 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")
	}
}
Example #24
0
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
}
Example #25
0
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)
}
Example #26
0
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
}
Example #27
0
func (*errExistsPodManager) CreatePod(namespace string, pod *kapi.Pod) (*kapi.Pod, error) {
	return &kapi.Pod{}, kerrors.NewAlreadyExists("kind", "name")
}