You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apisix.apache.org by kv...@apache.org on 2020/08/17 13:02:20 UTC

[apisix-control-plane] branch master updated: feat: add mem struct transform and store (#11)

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

kvn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-control-plane.git


The following commit(s) were added to refs/heads/master by this push:
     new b7489fa  feat: add mem struct transform and store (#11)
b7489fa is described below

commit b7489fac9e2ba9181a6efe2327fbf18ef91361ea
Author: kv <gx...@163.com>
AuthorDate: Mon Aug 17 21:02:10 2020 +0800

    feat: add mem struct transform and store (#11)
---
 doc/yaml_struct.md     |   5 +-
 go.mod                 |   1 +
 go.sum                 |   8 ++++
 pkg/mem/gateway.go     |  39 ++++++++++++++++
 pkg/mem/model.go       |  64 ++++++++++++++++++--------
 pkg/mem/plugin.go      |  39 ++++++++++++++++
 pkg/mem/route.go       |  39 ++++++++++++++++
 pkg/mem/store.go       | 121 +++++++++++++++++++++++++++++++++++++++++++++++++
 pkg/mem/upstream.go    |  39 ++++++++++++++++
 pkg/yml/destination.go |  38 ++++++++++++++++
 pkg/yml/gateway.go     |  53 ++++++++++++++++++++++
 pkg/yml/model.go       |  71 ++++++++++++++---------------
 pkg/yml/plugin.go      |  26 +++++++++++
 pkg/yml/rule.go        |  36 +++++++++++++++
 pkg/yml/trans_test.go  |   9 ++--
 15 files changed, 524 insertions(+), 64 deletions(-)

diff --git a/doc/yaml_struct.md b/doc/yaml_struct.md
index 5e46d01..e4588aa 100644
--- a/doc/yaml_struct.md
+++ b/doc/yaml_struct.md
@@ -220,8 +220,9 @@ http:
        exact: "json"
      age:
        Greater: 18
-  - uri:
-      prefix: "/"
+  - uris:
+    - prefix: "/"
+
 -------------------
 
 kind: destinations
diff --git a/go.mod b/go.mod
index ea95110..2f8dc5c 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.13
 
 require (
 	github.com/ghodss/yaml v1.0.0
+	github.com/hashicorp/go-memdb v1.2.1
 	github.com/onsi/ginkgo v1.14.0
 	github.com/onsi/gomega v1.10.1
 	github.com/xeipuuv/gojsonschema v1.2.0
diff --git a/go.sum b/go.sum
index 774ba0a..4602519 100644
--- a/go.sum
+++ b/go.sum
@@ -15,6 +15,14 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/hashicorp/go-immutable-radix v1.2.0 h1:l6UW37iCXwZkZoAbEYnptSHVE/cQ5bOTPYG5W3vf9+8=
+github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-memdb v1.2.1 h1:wI9btDjYUOJJHTCnRlAG/TkRyD/ij7meJMrLK9X31Cc=
+github.com/hashicorp/go-memdb v1.2.1/go.mod h1:OSvLJ662Jim8hMM+gWGyhktyWk2xPCnWMc7DWIqtkGA=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
diff --git a/pkg/mem/gateway.go b/pkg/mem/gateway.go
new file mode 100644
index 0000000..aad72e6
--- /dev/null
+++ b/pkg/mem/gateway.go
@@ -0,0 +1,39 @@
+/*
+ * 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 mem
+
+type GatewayDB struct {
+	Gateways []*Gateway
+}
+
+// insert Gateway to memDB
+func (db *GatewayDB) Insert() error {
+	txn := DB.Txn(true)
+	defer txn.Abort()
+	for _, r := range db.Gateways {
+		if err := txn.Insert(GatewayTable, r); err != nil {
+			return err
+		}
+	}
+	txn.Commit()
+	return nil
+}
+
+func (g *Gateway) Diff(t MemModel) bool {
+	return true
+}
diff --git a/pkg/mem/model.go b/pkg/mem/model.go
index b68c5e4..93fcc4e 100644
--- a/pkg/mem/model.go
+++ b/pkg/mem/model.go
@@ -17,24 +17,29 @@
 
 package mem
 
+type MemModel interface {
+	Diff(m MemModel) bool
+}
+
 type Route struct {
-	ID              *string   `json:"id,omitempty" yml:"id,omitempty"`
-	Group           *string   `json:"group,omitempty" yml:"group,omitempty"`
-	FullName        *string   `json:"full_name,omitempty" yml:"full_name,omitempty"`
-	ResourceVersion *string   `json:"resource_version,omitempty" yml:"resource_version,omitempty"`
-	Host            *string   `json:"host,omitempty" yml:"host,omitempty"`
-	Path            *string   `json:"path,omitempty" yml:"path,omitempty"`
-	Name            *string   `json:"name,omitempty" yml:"name,omitempty"`
-	Methods         []*string `json:"methods,omitempty" yml:"methods,omitempty"`
-	ServiceId       *string   `json:"service_id,omitempty" yml:"service_id,omitempty"`
-	ServiceName     *string   `json:"service_name,omitempty" yml:"service_name,omitempty"`
-	UpstreamId      *string   `json:"upstream_id,omitempty" yml:"upstream_id,omitempty"`
-	UpstreamName    *string   `json:"upstream_name,omitempty" yml:"upstream_name,omitempty"`
-	Plugins         []*Plugin `json:"plugins,omitempty" yml:"plugins,omitempty"`
+	ID           *string                  `json:"id,omitempty" yml:"id,omitempty"`
+	Kind         *string                  `json:"kind"`
+	FullName     *string                  `json:"full_name,omitempty" yml:"full_name,omitempty"`
+	Hosts        []*string                `json:"hosts,omitempty" yml:"hosts,omitempty"`
+	Match        []map[string]interface{} `json:"paths,omitempty" yml:"paths,omitempty"`
+	Name         *string                  `json:"name,omitempty" yml:"name,omitempty"`
+	Methods      []*string                `json:"methods,omitempty" yml:"methods,omitempty"`
+	ServiceId    *string                  `json:"service_id,omitempty" yml:"service_id,omitempty"`
+	ServiceName  *string                  `json:"service_name,omitempty" yml:"service_name,omitempty"`
+	UpstreamId   *string                  `json:"upstream_id,omitempty" yml:"upstream_id,omitempty"`
+	UpstreamName *string                  `json:"upstream_name,omitempty" yml:"upstream_name,omitempty"`
+	Plugins      []*Plugin                `json:"plugins,omitempty" yml:"plugins,omitempty"`
 }
 
 type Upstream struct {
 	ID              *string `json:"id,omitempty" yml:"id,omitempty"`
+	Kind            *string `json:"kind"`
+	Host            *string `json:"host"`
 	FullName        *string `json:"full_name,omitempty" yml:"full_name,omitempty"`
 	Group           *string `json:"group,omitempty" yml:"group,omitempty"`
 	ResourceVersion *string `json:"resource_version,omitempty" yml:"resource_version,omitempty"`
@@ -43,6 +48,7 @@ type Upstream struct {
 	HashOn          *string `json:"hash_on,omitemtpy" yml:"hash_on,omitempty"`
 	Key             *string `json:"key,omitempty" yml:"key,omitempty"`
 	Nodes           []*Node `json:"nodes,omitempty" yml:"nodes,omitempty"`
+	Weight          int64   `json:"weight"`
 	FromKind        *string `json:"from_kind,omitempty" yml:"from_kind,omitempty"`
 }
 
@@ -53,14 +59,32 @@ type Node struct {
 }
 
 type Plugin struct {
-	ID       *string        `json:"id,omitempty"`
-	Selector Selector       `json:"selector"`
-	Sort     []PluginSchema `json:"sort"`
+	ID       *string           `json:"id,omitempty"`
+	Kind     *string           `json:"kind"`
+	Selector map[string]string `json:"selector"`
+	Sets     []*PluginSet      `json:"sets"`
+}
+
+type PluginSet struct {
+	Name *string                `json:"name"`
+	Conf map[string]interface{} `json:"conf"`
 }
 
-type Selector map[string]string
+type Gateway struct {
+	ID       *string   `json:"id,omitempty"`
+	FullName *string   `json:"full_name,omitempty" yml:"full_name,omitempty"`
+	Kind     *string   `json:"kind"`
+	Name     *string   `json:"name"`
+	Servers  []*Server `json:"servers"`
+}
+
+type Server struct {
+	Port  *Port    `json:"port,omitempty"`
+	Hosts []string `json:"host,omitempty"`
+}
 
-type PluginSchema struct {
-	Name string      `json:"name"`
-	Conf interface{} `json:"conf"`
+type Port struct {
+	Number   int    `json:"number"`
+	Name     string `json:"name"`
+	Protocol string `json:"protocol"`
 }
diff --git a/pkg/mem/plugin.go b/pkg/mem/plugin.go
new file mode 100644
index 0000000..253d586
--- /dev/null
+++ b/pkg/mem/plugin.go
@@ -0,0 +1,39 @@
+/*
+ * 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 mem
+
+type PluginDB struct {
+	Plugins []*Plugin
+}
+
+// insert Plugin to memDB
+func (db *PluginDB) Insert() error {
+	txn := DB.Txn(true)
+	defer txn.Abort()
+	for _, r := range db.Plugins {
+		if err := txn.Insert(PluginTable, r); err != nil {
+			return err
+		}
+	}
+	txn.Commit()
+	return nil
+}
+
+func (g *Plugin) Diff(t MemModel) bool {
+	return true
+}
diff --git a/pkg/mem/route.go b/pkg/mem/route.go
new file mode 100644
index 0000000..5d94446
--- /dev/null
+++ b/pkg/mem/route.go
@@ -0,0 +1,39 @@
+/*
+ * 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 mem
+
+type RouteDB struct {
+	Routes []*Route
+}
+
+// InsertRoute insert route to memDB
+func (db *RouteDB) Insert() error {
+	txn := DB.Txn(true)
+	defer txn.Abort()
+	for _, r := range db.Routes {
+		if err := txn.Insert(RouteTable, r); err != nil {
+			return err
+		}
+	}
+	txn.Commit()
+	return nil
+}
+
+func (g *Route) Diff(t MemModel) bool {
+	return true
+}
diff --git a/pkg/mem/store.go b/pkg/mem/store.go
new file mode 100644
index 0000000..0760217
--- /dev/null
+++ b/pkg/mem/store.go
@@ -0,0 +1,121 @@
+/*
+ * 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 mem
+
+import "github.com/hashicorp/go-memdb"
+
+var DB *memdb.MemDB
+
+const (
+	GatewayTable  = "Gateway"
+	RouteTable    = "Route"
+	UpstreamTable = "Upstream"
+	PluginTable   = "Plugin"
+)
+
+func init() {
+	if db, err := NewDB(); err != nil {
+		panic(err)
+	} else {
+		DB = db
+	}
+}
+
+func NewDB() (*memdb.MemDB, error) {
+	var schema = &memdb.DBSchema{
+		Tables: map[string]*memdb.TableSchema{
+			GatewayTable:  gatewaySchema,
+			RouteTable:    routeSchema,
+			UpstreamTable: upstreamSchema,
+			PluginTable:   pluginSchema,
+		},
+	}
+	if memDB, err := memdb.NewMemDB(schema); err != nil {
+		return nil, err
+	} else {
+		return memDB, nil
+	}
+}
+
+var gatewaySchema = &memdb.TableSchema{
+	Name: GatewayTable,
+	Indexes: map[string]*memdb.IndexSchema{
+		"id": {
+			Name:    "id",
+			Unique:  true,
+			Indexer: &memdb.StringFieldIndex{Field: "FullName"},
+		},
+		"name": {
+			Name:         "name",
+			Unique:       true,
+			Indexer:      &memdb.StringFieldIndex{Field: "Name"},
+			AllowMissing: true,
+		},
+	},
+}
+
+var routeSchema = &memdb.TableSchema{
+	Name: RouteTable,
+	Indexes: map[string]*memdb.IndexSchema{
+		"id": {
+			Name:    "id",
+			Unique:  true,
+			Indexer: &memdb.StringFieldIndex{Field: "FullName"},
+		},
+		"name": {
+			Name:         "name",
+			Unique:       true,
+			Indexer:      &memdb.StringFieldIndex{Field: "Name"},
+			AllowMissing: true,
+		},
+	},
+}
+
+var upstreamSchema = &memdb.TableSchema{
+	Name: UpstreamTable,
+	Indexes: map[string]*memdb.IndexSchema{
+		"id": {
+			Name:    "id",
+			Unique:  true,
+			Indexer: &memdb.StringFieldIndex{Field: "FullName"},
+		},
+		"name": {
+			Name:         "name",
+			Unique:       true,
+			Indexer:      &memdb.StringFieldIndex{Field: "Name"},
+			AllowMissing: true,
+		},
+	},
+}
+
+var pluginSchema = &memdb.TableSchema{
+	Name: PluginTable,
+	Indexes: map[string]*memdb.IndexSchema{
+		"id": {
+			Name:    "id",
+			Unique:  true,
+			Indexer: &memdb.StringFieldIndex{Field: "FullName"},
+		},
+		"name": {
+			Name:         "name",
+			Unique:       true,
+			Indexer:      &memdb.StringFieldIndex{Field: "Name"},
+			AllowMissing: true,
+		},
+	},
+}
diff --git a/pkg/mem/upstream.go b/pkg/mem/upstream.go
new file mode 100644
index 0000000..327e8b1
--- /dev/null
+++ b/pkg/mem/upstream.go
@@ -0,0 +1,39 @@
+/*
+ * 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 mem
+
+type UpstreamDB struct {
+	Upstreams []*Upstream
+}
+
+// insert Upstream to memDB
+func (db *UpstreamDB) Insert() error {
+	txn := DB.Txn(true)
+	defer txn.Abort()
+	for _, r := range db.Upstreams {
+		if err := txn.Insert(UpstreamTable, r); err != nil {
+			return err
+		}
+	}
+	txn.Commit()
+	return nil
+}
+
+func (g *Upstream) Diff(t MemModel) bool {
+	return true
+}
diff --git a/pkg/yml/destination.go b/pkg/yml/destination.go
new file mode 100644
index 0000000..8f51ec0
--- /dev/null
+++ b/pkg/yml/destination.go
@@ -0,0 +1,38 @@
+/*
+ * 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 yml
+
+import "github.com/apache/apisix-control-plane/pkg/mem"
+
+func (d *Destination) ToMem() []mem.MemModel {
+	result := make([]mem.MemModel, 0)
+	for _, s := range d.Subsets {
+		fullName := *d.Kind + seprator + *d.Name + seprator + *s.Name
+		group := *d.Kind + seprator + *d.Name
+		upstream := &mem.Upstream{
+			Kind:     d.Kind,
+			Name:     d.Name,
+			FullName: &fullName,
+			Host:     d.Host,
+			Group:    &group,
+			Weight:   s.Weight,
+		}
+		result = append(result, upstream)
+	}
+	return result
+}
diff --git a/pkg/yml/gateway.go b/pkg/yml/gateway.go
new file mode 100644
index 0000000..f724efa
--- /dev/null
+++ b/pkg/yml/gateway.go
@@ -0,0 +1,53 @@
+/*
+ * 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 yml
+
+import "github.com/apache/apisix-control-plane/pkg/mem"
+
+func (g *Gateway) ToMem() []mem.MemModel {
+	result := make([]mem.MemModel, 0)
+	fullName := *g.Kind + seprator + *g.Name
+	servers := make([]*mem.Server, 0)
+	for _, e := range g.Servers {
+		server := e.ToMem()
+		servers = append(servers, server)
+	}
+	gateway := &mem.Gateway{
+		FullName: &fullName,
+		Kind:     g.Kind,
+		Name:     g.Name,
+		Servers:  servers,
+	}
+	result = append(result, gateway)
+	return result
+}
+
+func (s *Server) ToMem() *mem.Server {
+	return &mem.Server{
+		Port:  s.Port.ToMem(),
+		Hosts: s.Hosts,
+	}
+}
+
+func (p *Port) ToMem() *mem.Port {
+	return &mem.Port{
+		Number:   p.Number,
+		Name:     p.Name,
+		Protocol: p.Protocol,
+	}
+}
diff --git a/pkg/yml/model.go b/pkg/yml/model.go
index 1920b35..432de7a 100644
--- a/pkg/yml/model.go
+++ b/pkg/yml/model.go
@@ -17,14 +17,18 @@
 
 package yml
 
+import "github.com/apache/apisix-control-plane/pkg/mem"
+
+const seprator = ":"
+
 type YmlModel interface {
-	ToMem() string
+	ToMem() []mem.MemModel
 }
 
 type Gateway struct {
-	Kind    *string  `json:"kind"`
-	Name    *string  `json:"name"`
-	Servers []Server `json:"servers"`
+	Kind    *string   `json:"kind"`
+	Name    *string   `json:"name"`
+	Servers []*Server `json:"servers"`
 }
 
 type Server struct {
@@ -38,16 +42,12 @@ type Port struct {
 	Protocol string `json:"protocol"`
 }
 
-func (g *Gateway) ToMem() string {
-	return "gateway"
-}
-
 type Rule struct {
-	Kind     string   `json:"kind"`
-	Name     string   `json:"name"`
-	Hosts    []string `json:"hosts"`
-	Gateways []string `json:"gateways"`
-	HTTP     []HTTP   `json:"http"`
+	Kind     *string   `json:"kind"`
+	Name     *string   `json:"name"`
+	Hosts    []*string `json:"hosts"`
+	Gateways []*string `json:"gateways"`
+	HTTP     []*HTTP   `json:"http"`
 }
 type RouteDestination struct {
 	Port   int64  `json:"port"`
@@ -64,45 +64,42 @@ type Headers map[string]interface{}
 
 type Match struct {
 	Headers Headers `json:"headers"`
+	Uris    []*Uri  `json:"uris"`
 }
-type HTTP struct {
-	Route []Route `json:"route"`
-	Label Label   `json:"label"`
-	Match []Match `json:"match,omitempty"`
+
+type Uri struct {
+	Prefix  *string `json:"prefix,omitempty"`
+	Exact   *string `json:"exact,omitempty"`
+	Regular *string `json:"regular,omitempty"`
 }
 
-func (r *Rule) ToMem() string {
-	return "Rule"
+type HTTP struct {
+	Route []*Route                 `json:"route"`
+	Label *Label                   `json:"label"`
+	Match []map[string]interface{} `json:"match,omitempty"`
 }
 
 type Destination struct {
-	Kind    string   `json:"kind"`
-	Name    string   `json:"name"`
-	Host    string   `json:"host"`
-	Subsets []Subset `json:"subsets"`
+	Kind    *string   `json:"kind"`
+	Name    *string   `json:"name"`
+	Host    *string   `json:"host"`
+	Subsets []*Subset `json:"subsets"`
 }
 
 type Subset struct {
-	Name     string            `json:"name"`
-	Ips      []string          `json:"ips,omitempty"`
+	Name     *string           `json:"name"`
+	Ips      []*string         `json:"ips,omitempty"`
 	Selector map[string]string `json:"selector,omitempty"`
-}
-
-func (g *Destination) ToMem() string {
-	return "destination"
+	Weight   int64             `json:"weight"`
 }
 
 type Plugin struct {
-	Kind     string            `yaml:"kind"`
+	Kind     *string           `yaml:"kind"`
 	Selector map[string]string `yaml:"selector"`
-	Sets     []Set             `yaml:"sets"`
+	Sets     []*PluginSet      `yaml:"sets"`
 }
 
-type Set struct {
-	Name string                 `yaml:"name"`
+type PluginSet struct {
+	Name *string                `yaml:"name"`
 	Conf map[string]interface{} `yaml:"conf,omitempty"`
 }
-
-func (g *Plugin) ToMem() string {
-	return "plugin"
-}
diff --git a/pkg/yml/plugin.go b/pkg/yml/plugin.go
new file mode 100644
index 0000000..129de0d
--- /dev/null
+++ b/pkg/yml/plugin.go
@@ -0,0 +1,26 @@
+package yml
+
+import "github.com/apache/apisix-control-plane/pkg/mem"
+
+func (p *Plugin) ToMem() []mem.MemModel {
+	result := make([]mem.MemModel, 0)
+	plugins := make([]*mem.PluginSet, 0)
+	for _, s := range p.Sets {
+		plugin := s.ToMem()
+		plugins = append(plugins, plugin)
+	}
+	plugin := &mem.Plugin{
+		Kind:     p.Kind,
+		Selector: p.Selector,
+		Sets:     plugins,
+	}
+	result = append(result, plugin)
+	return result
+}
+
+func (s *PluginSet) ToMem() *mem.PluginSet {
+	return &mem.PluginSet{
+		Name: s.Name,
+		Conf: s.Conf,
+	}
+}
diff --git a/pkg/yml/rule.go b/pkg/yml/rule.go
new file mode 100644
index 0000000..1fd716d
--- /dev/null
+++ b/pkg/yml/rule.go
@@ -0,0 +1,36 @@
+/*
+ * 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 yml
+
+import "github.com/apache/apisix-control-plane/pkg/mem"
+
+func (r *Rule) ToMem() []mem.MemModel {
+	result := make([]mem.MemModel, 0)
+	fullName := *r.Kind + seprator + *r.Name
+	for _, http := range r.HTTP {
+		route := &mem.Route{
+			Kind:     r.Kind,
+			FullName: &fullName,
+			Name:     r.Name,
+			Hosts:    r.Hosts,
+			Match:    http.Match,
+		}
+		result = append(result, route)
+	}
+	return result
+}
diff --git a/pkg/yml/trans_test.go b/pkg/yml/trans_test.go
index 3c5caa9..4a319c6 100644
--- a/pkg/yml/trans_test.go
+++ b/pkg/yml/trans_test.go
@@ -92,8 +92,7 @@ http:
 				Expect(v).To(Equal("*yml.Rule"))
 				r, ok := ym.(*yml.Rule)
 				Expect(ok).To(Equal(true))
-				Expect(r.Kind).To(Equal("Rule"))
-				Expect(r.Kind).To(Equal("Rule"))
+				Expect(*r.Kind).To(Equal("Rule"))
 			})
 
 			It("trans to destination no error", func() {
@@ -118,8 +117,8 @@ subsets:
 				Expect(v).To(Equal("*yml.Destination"))
 				g, ok := ym.(*yml.Destination)
 				Expect(ok).To(Equal(true))
-				Expect(g.Kind).To(Equal("Destination"))
-				Expect(g.Host).To(Equal("foo-server"))
+				Expect(*g.Kind).To(Equal("Destination"))
+				Expect(*g.Host).To(Equal("foo-server"))
 			})
 
 			It("trans to plugin no error", func() {
@@ -147,7 +146,7 @@ sets:
 				Expect(v).To(Equal("*yml.Plugin"))
 				g, ok := ym.(*yml.Plugin)
 				Expect(ok).To(Equal(true))
-				Expect(g.Kind).To(Equal("Plugin"))
+				Expect(*g.Kind).To(Equal("Plugin"))
 				fmt.Println(g.Sets)
 				Expect(len(g.Sets)).To(Equal(2))
 				Expect(g.Selector["app"]).To(Equal("foo"))