You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2021/12/31 08:25:25 UTC

[servicecomb-service-center] branch master updated: [feat] add role sync func and ut when db is etcd (#1198)

This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new a983b51  [feat] add role sync func and ut when db is etcd (#1198)
a983b51 is described below

commit a983b51d56a99760ad41087a3e0ad86814485cf8
Author: robotljw <79...@qq.com>
AuthorDate: Fri Dec 31 16:25:18 2021 +0800

    [feat] add role sync func and ut when db is etcd (#1198)
---
 datasource/common.go            |   1 +
 datasource/etcd/account_test.go |  16 +++--
 datasource/etcd/role.go         |  51 ++++++++++++++--
 datasource/etcd/role_test.go    | 129 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 185 insertions(+), 12 deletions(-)

diff --git a/datasource/common.go b/datasource/common.go
index 90d28cd..f783594 100644
--- a/datasource/common.go
+++ b/datasource/common.go
@@ -33,6 +33,7 @@ const (
 	Provider              = "p"
 
 	ResourceAccount = "account"
+	ResourceRole    = "role"
 )
 
 // WrapErrResponse is temp func here to wait finish to refact the discosvc pkg
diff --git a/datasource/etcd/account_test.go b/datasource/etcd/account_test.go
index 58a36ae..47a3771 100644
--- a/datasource/etcd/account_test.go
+++ b/datasource/etcd/account_test.go
@@ -55,13 +55,15 @@ func TestSyncAccount(t *testing.T) {
 				_, err = rbac.Instance().DeleteAccount(context.Background(), []string{a1.Name})
 				assert.NoError(t, err)
 				listTaskReq := model.ListTaskRequest{
-					Domain:  "",
-					Project: "",
+					Domain:       "",
+					Project:      "",
+					ResourceType: datasource.ResourceAccount,
 				}
 				tasks, err := task.List(context.Background(), &listTaskReq)
 				assert.NoError(t, err)
 				assert.Equal(t, 2, len(tasks))
-				task.Delete(context.Background(), tasks...)
+				err = task.Delete(context.Background(), tasks...)
+				assert.NoError(t, err)
 				tombstoneListReq := model.ListTombstoneRequest{
 					ResourceType: datasource.ResourceAccount,
 				}
@@ -105,13 +107,15 @@ func TestSyncAccount(t *testing.T) {
 				_, err = rbac.Instance().DeleteAccount(context.Background(), []string{a2.Name, a3.Name})
 				assert.NoError(t, err)
 				listTaskReq := model.ListTaskRequest{
-					Domain:  "",
-					Project: "",
+					Domain:       "",
+					Project:      "",
+					ResourceType: datasource.ResourceAccount,
 				}
 				tasks, err := task.List(context.Background(), &listTaskReq)
 				assert.NoError(t, err)
 				assert.Equal(t, 6, len(tasks))
-				task.Delete(context.Background(), tasks...)
+				err = task.Delete(context.Background(), tasks...)
+				assert.NoError(t, err)
 				tombstoneListReq := model.ListTombstoneRequest{
 					ResourceType: datasource.ResourceAccount,
 				}
diff --git a/datasource/etcd/role.go b/datasource/etcd/role.go
index f1a1092..9e117d9 100644
--- a/datasource/etcd/role.go
+++ b/datasource/etcd/role.go
@@ -24,13 +24,16 @@ import (
 	"strconv"
 	"time"
 
+	rbacmodel "github.com/go-chassis/cari/rbac"
+	"github.com/go-chassis/cari/sync"
+	"github.com/little-cui/etcdadpt"
+
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/datasource/etcd/path"
 	"github.com/apache/servicecomb-service-center/datasource/rbac"
 	"github.com/apache/servicecomb-service-center/pkg/etcdsync"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	rbacmodel "github.com/go-chassis/cari/rbac"
-	"github.com/little-cui/etcdadpt"
 )
 
 func (rm *RbacDAO) CreateRole(ctx context.Context, r *rbacmodel.Role) error {
@@ -61,7 +64,18 @@ func (rm *RbacDAO) CreateRole(ctx context.Context, r *rbacmodel.Role) error {
 		log.Error("role info is invalid", err)
 		return err
 	}
-	err = etcdadpt.PutBytes(ctx, key, value)
+	opts := []etcdadpt.OpOptions{
+		etcdadpt.OpPut(etcdadpt.WithStrKey(key), etcdadpt.WithValue(value)),
+	}
+	if datasource.EnableSync {
+		taskOpt, err := GenTaskOpts("", "", sync.CreateAction, datasource.ResourceRole, r)
+		if err != nil {
+			log.Error("", err)
+			return err
+		}
+		opts = append(opts, taskOpt)
+	}
+	err = etcdadpt.Txn(ctx, opts)
 	if err != nil {
 		log.Error("can not save account info", err)
 		return err
@@ -117,11 +131,25 @@ func (rm *RbacDAO) DeleteRole(ctx context.Context, name string) (bool, error) {
 	if exists {
 		return false, rbac.ErrRoleBindingExist
 	}
-	del, err := etcdadpt.Delete(ctx, path.GenerateRBACRoleKey(name))
+	opts := []etcdadpt.OpOptions{etcdadpt.OpDel(etcdadpt.WithStrKey(path.GenerateRBACRoleKey(name)))}
+	if datasource.EnableSync {
+		taskOpt, err := GenTaskOpts("", "", sync.DeleteAction, datasource.ResourceRole, name)
+		if err != nil {
+			log.Error("", err)
+			return false, err
+		}
+		tombstoneOpt, err := GenTombstoneOpts("", "", datasource.ResourceRole, name)
+		if err != nil {
+			log.Error("", err)
+			return false, err
+		}
+		opts = append(opts, taskOpt, tombstoneOpt)
+	}
+	err = etcdadpt.Txn(ctx, opts)
 	if err != nil {
 		return false, err
 	}
-	return del, nil
+	return true, nil
 }
 func RoleBindingExists(ctx context.Context, role string) (bool, error) {
 	_, total, err := etcdadpt.List(ctx, path.GenRoleAccountPrefixIdxKey(role))
@@ -138,5 +166,16 @@ func (rm *RbacDAO) UpdateRole(ctx context.Context, name string, role *rbacmodel.
 		log.Error("role info is invalid", err)
 		return err
 	}
-	return etcdadpt.PutBytes(ctx, path.GenerateRBACRoleKey(name), value)
+	opts := []etcdadpt.OpOptions{
+		etcdadpt.OpPut(etcdadpt.WithStrKey(path.GenerateRBACRoleKey(name)), etcdadpt.WithValue(value)),
+	}
+	if datasource.EnableSync {
+		taskOpt, err := GenTaskOpts("", "", sync.UpdateAction, datasource.ResourceRole, role)
+		if err != nil {
+			log.Error("", err)
+			return err
+		}
+		opts = append(opts, taskOpt)
+	}
+	return etcdadpt.Txn(ctx, opts)
 }
diff --git a/datasource/etcd/role_test.go b/datasource/etcd/role_test.go
new file mode 100644
index 0000000..0a447c5
--- /dev/null
+++ b/datasource/etcd/role_test.go
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package etcd_test
+
+import (
+	"context"
+	"strconv"
+	"testing"
+
+	rbacmodel "github.com/go-chassis/cari/rbac"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/datasource/rbac"
+	"github.com/apache/servicecomb-service-center/eventbase/model"
+	"github.com/apache/servicecomb-service-center/eventbase/service/task"
+	"github.com/apache/servicecomb-service-center/eventbase/service/tombstone"
+	_ "github.com/apache/servicecomb-service-center/test"
+)
+
+func TestSyncRole(t *testing.T) {
+
+	datasource.EnableSync = true
+
+	t.Run("create role", func(t *testing.T) {
+		t.Run("creating a role and delete it will create two tasks and a tombstone should pass", func(t *testing.T) {
+			r1 := rbacmodel.Role{
+				ID:    "create-11111",
+				Name:  "create-role",
+				Perms: nil,
+			}
+			err := rbac.Instance().CreateRole(context.Background(), &r1)
+			assert.NoError(t, err)
+			r, err := rbac.Instance().GetRole(context.Background(), "create-role")
+			assert.NoError(t, err)
+			assert.Equal(t, r1, *r)
+			dt, _ := strconv.Atoi(r.CreateTime)
+			assert.Less(t, 0, dt)
+			assert.Equal(t, r.CreateTime, r.UpdateTime)
+			_, err = rbac.Instance().DeleteRole(context.Background(), r1.Name)
+			assert.NoError(t, err)
+			listTaskReq := model.ListTaskRequest{
+				Domain:       "",
+				Project:      "",
+				ResourceType: datasource.ResourceRole,
+			}
+			tasks, err := task.List(context.Background(), &listTaskReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 2, len(tasks))
+			err = task.Delete(context.Background(), tasks...)
+			assert.NoError(t, err)
+			tombstoneListReq := model.ListTombstoneRequest{
+				ResourceType: datasource.ResourceRole,
+			}
+			tombstones, err := tombstone.List(context.Background(), &tombstoneListReq)
+			assert.NoError(t, err)
+			assert.Equal(t, 1, len(tombstones))
+			err = tombstone.Delete(context.Background(), tombstones...)
+			assert.NoError(t, err)
+		})
+	})
+
+	t.Run("update role", func(t *testing.T) {
+		t.Run("create two roles ,then update them, finally delete them, will create six tasks and two tombstones should pass",
+			func(t *testing.T) {
+				r2 := rbacmodel.Role{
+					ID:    "update-22222",
+					Name:  "update-role-22222",
+					Perms: nil,
+				}
+				r3 := rbacmodel.Role{
+					ID:    "update-33333",
+					Name:  "update-role-33333",
+					Perms: nil,
+				}
+				err := rbac.Instance().CreateRole(context.Background(), &r2)
+				assert.NoError(t, err)
+				err = rbac.Instance().CreateRole(context.Background(), &r3)
+				assert.NoError(t, err)
+				r2.ID = "update-22222-33333"
+				err = rbac.Instance().UpdateRole(context.Background(), "update-role-22222", &r2)
+				assert.NoError(t, err)
+				r3.ID = "update-33333-44444"
+				err = rbac.Instance().UpdateRole(context.Background(), "update-role-33333", &r3)
+				assert.NoError(t, err)
+				_, err = rbac.Instance().DeleteRole(context.Background(), r2.Name)
+				assert.NoError(t, err)
+				_, err = rbac.Instance().DeleteRole(context.Background(), r3.Name)
+				assert.NoError(t, err)
+				listTaskReq := model.ListTaskRequest{
+					Domain:       "",
+					Project:      "",
+					ResourceType: datasource.ResourceRole,
+				}
+				tasks, err := task.List(context.Background(), &listTaskReq)
+				assert.NoError(t, err)
+				assert.Equal(t, 6, len(tasks))
+				err = task.Delete(context.Background(), tasks...)
+				assert.NoError(t, err)
+				tombstoneListReq := model.ListTombstoneRequest{
+					ResourceType: datasource.ResourceRole,
+				}
+				tombstones, err := tombstone.List(context.Background(), &tombstoneListReq)
+				assert.NoError(t, err)
+				assert.Equal(t, 2, len(tombstones))
+				err = tombstone.Delete(context.Background(), tombstones...)
+				assert.NoError(t, err)
+
+			})
+	})
+
+	datasource.EnableSync = false
+
+}