provide CaseSensitive option to ignore case of keys or not (#258)

* provide CaseSensitive option to ignore case of keys or not

* provide CaseSensitive option to ignore case of keys or not
diff --git a/server/datasource/etcd/kv/kv_dao.go b/server/datasource/etcd/kv/kv_dao.go
index 93cfc39..6296e08 100644
--- a/server/datasource/etcd/kv/kv_dao.go
+++ b/server/datasource/etcd/kv/kv_dao.go
@@ -186,7 +186,8 @@
 		datasource.WithExactLabels(),
 		datasource.WithLabels(opts.Labels),
 		datasource.WithLabelFormat(opts.LabelFormat),
-		datasource.WithKey(key))
+		datasource.WithKey(key),
+		datasource.WithCaseSensitive())
 	if err != nil {
 		openlog.Error("check kv exist: " + err.Error())
 		return false, err
@@ -485,7 +486,10 @@
 	default:
 		value = strings.ReplaceAll(opts.Key, ".", "\\.")
 	}
-	value = "(?i)^" + value + "$"
+	value = "^" + value + "$"
+	if !opts.CaseSensitive {
+		value = "(?i)" + value
+	}
 	regex, err := regexp.Compile(value)
 	if err != nil {
 		openlog.Error("invalid wildcard expr: " + value + ", error: " + err.Error())
diff --git a/server/datasource/options.go b/server/datasource/options.go
index 086dd01..2e311f5 100644
--- a/server/datasource/options.go
+++ b/server/datasource/options.go
@@ -70,7 +70,8 @@
 	// Offset the offset of the response, start at 0
 	Offset int64
 	// Limit the page size of the response, dot not paging if limit=0
-	Limit int64
+	Limit         int64
+	CaseSensitive bool
 }
 
 // WriteOption is functional option to create, update and delete kv
@@ -86,6 +87,13 @@
 	}
 }
 
+// WithCaseSensitive tell model service whether to match case of letters or not.
+func WithCaseSensitive() FindOption {
+	return func(o *FindOptions) {
+		o.CaseSensitive = true
+	}
+}
+
 // WithExactLabels tell model service to return only one kv matches the labels
 func WithExactLabels() FindOption {
 	return func(o *FindOptions) {
diff --git a/server/service/kv/kv_svc_test.go b/server/service/kv/kv_svc_test.go
index 7401d8d..471c016 100644
--- a/server/service/kv/kv_svc_test.go
+++ b/server/service/kv/kv_svc_test.go
@@ -148,6 +148,23 @@
 		assert.EqualError(t, err,
 			config.NewError(config.ErrRecordAlreadyExists, datasource.ErrKVAlreadyExists.Error()).Error())
 	})
+	t.Run("create the kv with uppercase, expected: create successfully", func(t *testing.T) {
+		result, err := kvsvc.Create(context.TODO(), &model.KVDoc{
+			Key:    "TIMEOUT",
+			Value:  "2s",
+			Status: common.StatusEnabled,
+			Labels: map[string]string{
+				"app":     "mall",
+				"service": "utCart",
+			},
+			Domain:  domain,
+			Project: project,
+		})
+		assert.Nil(t, err)
+		assert.NotEmpty(t, result.ID)
+		assert.Equal(t, "TIMEOUT", result.Key)
+		assert.Equal(t, "2s", result.Value)
+	})
 	t.Run("list the kv", func(t *testing.T) {
 		res, err := kvsvc.List(context.TODO(), project, domain,
 			datasource.WithKey("wildcard(time*1)"))