Ejemplo n.º 1
0
func TestCounter(t *testing.T) {
	db := modeltesthelper.NewMongoDB(t)
	defer db.Close()

	if err := delCounters(); err != nil {
		t.Fatalf("delCounters()=%s", err)
	}

	counters := []*models.Counter{{
		ID:        bson.NewObjectId(),
		Namespace: "foo",
		Type:      "member_instaces",
		Current:   10,
	}, {
		ID:        bson.NewObjectId(),
		Namespace: "foo",
		Type:      "member_stacks",
		Current:   1,
	}, {
		ID:        bson.NewObjectId(),
		Namespace: "bar",
		Type:      "member_instances",
		Current:   2,
	}, {
		ID:        bson.NewObjectId(),
		Namespace: "bar",
		Type:      "member_stacks",
		Current:   5,
	}}

	sort.Sort(models.Counters(counters))

	if err := modelhelper.CreateCounters(counters...); err != nil {
		t.Fatalf("CreateCounters()=%s", err)
	}

	c, err := allCounters()
	if err != nil {
		t.Fatalf("counters()=%s", err)
	}

	if !reflect.DeepEqual(counters, c) {
		t.Fatalf("got %+v, want %+v", c, counters)
	}

	decCases := []struct {
		n    int
		want int
	}{
		{7, 3}, // i=0
		{1, 0}, // i=1
		{2, 0}, // i=2
		{3, 2}, // i=3
	}

	for i, cas := range decCases {
		c := counters[i]

		err := modelhelper.DecrementOrCreateCounter(c.Namespace, c.Type, cas.n)
		if err != nil {
			t.Errorf("%d (%s): DecrementOrCreateCounter()=%s", i, c.ID.Hex(), err)
			continue
		}

		got, err := modelhelper.CounterByID(c.ID)
		if err != nil {
			t.Errorf("%d (%s): CounterByID()=%d", i, c.ID.Hex(), err)
			continue
		}

		if got.Current != cas.want {
			t.Errorf("%d (%s): got %d, want %d", i, c.ID.Hex(), got.Current, cas.want)
		}
	}

	newCases := []struct {
		namespace string
		typ       string
		n         int
	}{
		{"qux", "member_stacks", 1},    // i=0
		{"qux", "member_instances", 3}, // i=0
	}

	for i, cas := range newCases {
		err := modelhelper.DecrementOrCreateCounter(cas.namespace, cas.typ, cas.n)
		if err != nil {
			t.Errorf("%d: DecrementOrCreateCounter()=%s", i, err)
		}
	}

	c, err = modelhelper.CountersByNamespace("qux")
	if err != nil {
		t.Fatalf("CountersByNamespace()=%s", err)
	}

	if len(c) != 2 {
		t.Fatalf("got len(c)=%d, want len(c)=2", len(c))
	}
}
Ejemplo n.º 2
0
// Detach implements the Database interface.
func (db *mongoDatabase) Detach(opts *DetachOptions) error {
	const detachReason = "Stack destroy requested."

	if err := opts.Valid(); err != nil {
		return err
	}

	// 1) Detach stack from user. Failure is critical, as upon return
	//    a user would not be able to create new stack.

	detachStack := modelhelper.Selector{
		"targetName": "JStackTemplate",
		"targetId":   opts.Stack.BaseStackId,
		"sourceName": "JAccount",
		"sourceId":   opts.Stack.OriginId,
		"as":         "user",
	}

	err := modelhelper.DeleteRelationships(detachStack)
	if err != nil && err != mgo.ErrNotFound {
		return err
	}

	// 2) Set stack to "destroying" state.
	id := opts.Stack.Id.Hex()

	err = modelhelper.SetStackState(id, detachReason, stackstate.Destroying)
	if err != nil && err != mgo.ErrNotFound {
		// Stack state update failure is not critical, as jComputeStack
		// is going to be removed either way at the end of destroy op.
		opts.Log.Error("unable to set stack state to %q", stackstate.Destroying)
	}

	// 3) Update counters.

	err = modelhelper.DecrementOrCreateCounter(opts.Stack.Group, modelhelper.CounterStacks, 1)
	if err != nil {
		// Counter update is not crucial, nevertheless we log an error
		// if updating failed for whatever reason.
		opts.Log.Error("failure updating %q counter", modelhelper.CounterStacks)
	}

	err = modelhelper.DecrementOrCreateCounter(opts.Stack.Group, modelhelper.CounterInstances, len(opts.Stack.Machines))
	if err != nil {
		// Counter update is not crucial, nevertheless we log an error
		// if updating failed for whatever reason.
		opts.Log.Error("failure updating %q counter", modelhelper.CounterInstances)
	}

	// 4) Detach machines from user.

	detachMachines := bson.M{
		"$set": bson.M{
			"status.state": "Terminated",
			"users":        []interface{}{},
		},
	}

	err = modelhelper.UpdateMachines(detachMachines, opts.Stack.Machines...)
	if err != nil && err != mgo.ErrNotFound {
		// Detaching users from machines error is not critical, as the jMachine
		// documents are going to be deleted at the end of destroy operation.
		// Nevertheless we log error in case a troubleshooting would be needed.
		opts.Log.Error("detaching users from machines failed: %s", err)
	}

	return nil
}