From 7a9bfe7f07f5cfcb51cf07dcd676a191aa40b46e Mon Sep 17 00:00:00 2001 From: kv Date: Thu, 3 Sep 2020 22:43:08 +0800 Subject: [PATCH] feat: add mem object group & apisix model (#14) * feat: add mem object group & apisix model * merge go.mod --- go.mod | 4 +- go.sum | 15 ++++++ pkg/adapter/route.go | 96 +++++++++++++++++++++++++++++++++++++++ pkg/conf/conf.go | 23 ++++++++++ pkg/dp/apisix/model.go | 53 +++++++++++++++++++++ pkg/dp/apisix/route.go | 79 ++++++++++++++++++++++++++++++++ pkg/dp/apisix/upstream.go | 74 ++++++++++++++++++++++++++++++ pkg/mem/deps.go | 39 ++++++++++++++++ pkg/mem/model.go | 5 ++ pkg/utils/http.go | 75 ++++++++++++++++++++++++++++++ 10 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 pkg/adapter/route.go create mode 100644 pkg/conf/conf.go create mode 100644 pkg/dp/apisix/model.go create mode 100644 pkg/dp/apisix/route.go create mode 100644 pkg/dp/apisix/upstream.go create mode 100644 pkg/mem/deps.go create mode 100644 pkg/utils/http.go diff --git a/go.mod b/go.mod index 023ec91..893e890 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,13 @@ go 1.13 require ( github.com/ghodss/yaml v1.0.0 + github.com/gxthrj/seven v0.1.9 github.com/hashicorp/go-memdb v1.2.1 github.com/onsi/ginkgo v1.14.0 github.com/onsi/gomega v1.10.1 - github.com/sergi/go-diff v1.1.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 github.com/yudai/gojsondiff v1.0.0 - github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect go.uber.org/zap v1.15.0 + gopkg.in/resty.v1 v1.12.0 gopkg.in/yaml.v2 v2.3.0 ) diff --git a/go.sum b/go.sum index b8fc16d..772ae66 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,7 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -19,8 +20,13 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/gxthrj/apisix-types v0.1.0/go.mod h1:STdHATWxqIeJhUEXt6dZTd6z0To0qO70K/1mnfBtlC0= +github.com/gxthrj/seven v0.1.9 h1:EccFVE5PIqZXyt91laXxGu9tydCjg31EXn/Q4aFfwD4= +github.com/gxthrj/seven v0.1.9/go.mod h1:epDVCYT1ibfV6fgaeM918QAer9u0/M2LXW6OcIRdfQc= +github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 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.0.4/go.mod h1:LWQ8R70vPrS4OEY9k28D2z8/Zzyu34NVzeRibGAzHO0= 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= @@ -32,13 +38,17 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -61,6 +71,7 @@ github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCO github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= @@ -73,6 +84,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -82,6 +94,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -112,6 +125,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/adapter/route.go b/pkg/adapter/route.go new file mode 100644 index 0000000..635573b --- /dev/null +++ b/pkg/adapter/route.go @@ -0,0 +1,96 @@ +/* + * 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 adapter + +import ( + "github.com/apache/apisix-control-plane/pkg/dp/apisix" + "github.com/apache/apisix-control-plane/pkg/mem" + "reflect" +) + +func ToRoute(r *mem.Route) *apisix.Route { + return &apisix.Route{ + Name: r.FullName, + Hosts: r.Hosts, + Desc: r.Name, + Uris: toUris(r), + Vars: toVars(r), + Methods: r.Methods, + } +} + +func toUris(r *mem.Route) []*string { + result := make([]*string, 0) + for _, m := range r.Match { + // uris + matchUris := m["uris"] + switch reflect.TypeOf(matchUris).Kind() { + case reflect.Slice: + s := reflect.ValueOf(matchUris) + if slice, ok := s.Interface().([]map[string]string); ok { + for _, s := range slice { + for k, v := range s { + switch k { + case "prefix": + uri := v + "*" + result = append(result, &uri) + case "exact": + result = append(result, &v) + } + } + } + } + } + } + return result +} + +func toVars(r *mem.Route) [][]*string { + result := make([][]*string, 0) + for _, m := range r.Match { + // args + matchArgs := m["args"] + switch reflect.TypeOf(matchArgs).Kind() { + case reflect.Slice: + s := reflect.ValueOf(matchArgs) + if slice, ok := s.Interface().([]map[string]map[string]string); ok { + for _, s := range slice { + tmp := make([]*string, 0) + for p, value := range s { + tmp = append(tmp, &p) + for k, v := range value { + switch k { + case "greater": + greater := ">" + tmp = append(tmp, &greater) + tmp = append(tmp, &v) + case "exact": + equals := "==" + tmp = append(tmp, &equals) + tmp = append(tmp, &v) + } + } + result = append(result, tmp) + } + + } + } + } + } + return result +} diff --git a/pkg/conf/conf.go b/pkg/conf/conf.go new file mode 100644 index 0000000..f56d629 --- /dev/null +++ b/pkg/conf/conf.go @@ -0,0 +1,23 @@ +/* + * 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 conf + +var ( + ApiKey = "edd1c9f034335f136f87ad84b625c8f1" + BaseUrl = "http://127.0.0.1:9080/apisix/admin" +) diff --git a/pkg/dp/apisix/model.go b/pkg/dp/apisix/model.go new file mode 100644 index 0000000..093d18d --- /dev/null +++ b/pkg/dp/apisix/model.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 apisix + +type Route struct { + ID *string `json:"id,omitempty"` + Hosts []*string `json:"hosts,omitempty"` + Name *string `json:"name,omitempty"` + Desc *string `json:"desc,omitempty"` + Uris []*string `json:"uris"` + Vars [][]*string `json:"vars,omitempty"` + Methods []*string `json:"methods,omitempty"` + ServiceId *string `json:"service_id,omitempty"` + ServiceName *string `json:"service_name,omitempty"` + UpstreamId *string `json:"upstream_id,omitempty"` + UpstreamName *string `json:"upstream_name,omitempty"` + Plugins []*Plugin `json:"plugins,omitempty"` +} + +type Plugin map[string]interface{} + +type Upstream struct { + ID *string `json:"id,omitempty"` + Group *string `json:"group,omitempty"` + ResourceVersion *string `json:"resource_version,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + HashOn *string `json:"hash_on,omitemtpy"` + Key *string `json:"key,omitempty"` + Nodes []*Node `json:"nodes,omitempty"` + FromKind *string `json:"from_kind,omitempty"` +} + +type Node struct { + IP *string `json:"ip,omitempty"` + Port *int `json:"port,omitempty"` + Weight *int `json:"weight,omitempty"` +} diff --git a/pkg/dp/apisix/route.go b/pkg/dp/apisix/route.go new file mode 100644 index 0000000..bfa2a21 --- /dev/null +++ b/pkg/dp/apisix/route.go @@ -0,0 +1,79 @@ +/* + * 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 apisix + +import ( + "encoding/json" + "fmt" + "github.com/apache/apisix-control-plane/pkg/conf" + "github.com/apache/apisix-control-plane/pkg/utils" +) + +func (route *Route) Add() (*RouteResponse, error) { + baseUrl := conf.BaseUrl + url := fmt.Sprintf("%s/routes", baseUrl) + if b, err := json.Marshal(route); err != nil { + return nil, err + } else { + if res, err := utils.Post(url, b); err != nil { + return nil, err + } else { + var routeResp RouteResponse + if err = json.Unmarshal(res, &routeResp); err != nil { + return nil, err + } else { + if routeResp.Route.Key != nil { + return &routeResp, nil + } else { + return nil, fmt.Errorf("apisix route not expected response") + } + + } + } + } +} + +func (route *Route) Update() (*RouteResponse, error) { + // todo + return nil, nil +} + +func (route *Route) Delete() (*RouteResponse, error) { + // todo + return nil, nil +} + +type RouteResponse struct { + Action string `json:"action"` + Route RouteNode `json:"node"` +} + +type RouteNode struct { + Key *string `json:"key"` + Value Value `json:"value"` +} + +type Value struct { + UpstreamId *string `json:"upstream_id"` + ServiceId *string `json:"service_id"` + Plugins map[string]interface{} `json:"plugins"` + Host *string `json:"host,omitempty"` + Uri *string `json:"uri"` + Desc *string `json:"desc"` + Methods []*string `json:"methods,omitempty"` +} diff --git a/pkg/dp/apisix/upstream.go b/pkg/dp/apisix/upstream.go new file mode 100644 index 0000000..ce85e2e --- /dev/null +++ b/pkg/dp/apisix/upstream.go @@ -0,0 +1,74 @@ +/* + * 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 apisix + +import ( + "encoding/json" + "fmt" + "github.com/apache/apisix-control-plane/pkg/utils" + "github.com/gxthrj/seven/conf" +) + +func (upstream *Upstream) Add() (*UpstreamResponse, error) { + baseUrl := conf.BaseUrl + url := fmt.Sprintf("%s/upstreams", baseUrl) + if b, err := json.Marshal(upstream); err != nil { + return nil, err + } else { + if res, err := utils.Post(url, b); err != nil { + return nil, fmt.Errorf("http post failed, url: %s, err: %+v", url, err) + } else { + var uRes UpstreamResponse + if err = json.Unmarshal(res, &uRes); err != nil { + return nil, err + } else { + if uRes.Upstream.Key != nil { + return &uRes, nil + } else { + return nil, fmt.Errorf("apisix upstream not expected response") + } + } + } + } +} + +func (upstream *Upstream) Update() (*UpstreamResponse, error) { + // todo + return nil, nil +} + +func (upstream *Upstream) Delete() (*UpstreamResponse, error) { + // todo + return nil, nil +} + +type UpstreamResponse struct { + Action string `json:"action"` + Upstream UpstreamNode `json:"node"` +} + +type UpstreamNode struct { + Key *string `json:"key"` + UpstreamNodes UpstreamNodes `json:"value"` +} + +type UpstreamNodes struct { + Nodes map[string]int64 `json:"nodes"` + Desc *string `json:"desc"` + LBType *string `json:"type"` +} diff --git a/pkg/mem/deps.go b/pkg/mem/deps.go new file mode 100644 index 0000000..ed190e4 --- /dev/null +++ b/pkg/mem/deps.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 + +func Map(raws []MemModel) map[string][]MemModel { + result := make(map[string][]MemModel) + result[GatewayKind] = make([]MemModel, 0) + result[RouteKind] = make([]MemModel, 0) + result[UpstreamKind] = make([]MemModel, 0) + result[PluginKind] = make([]MemModel, 0) + for _, r := range raws { + switch v := r.(type) { + case *Gateway: + result[*v.Kind] = append(result[*v.Kind], v) + case *Route: + result[*v.Kind] = append(result[*v.Kind], v) + case *Upstream: + result[*v.Kind] = append(result[*v.Kind], v) + case *Plugin: + result[*v.Kind] = append(result[*v.Kind], v) + } + } + return result +} diff --git a/pkg/mem/model.go b/pkg/mem/model.go index d82ba64..476cd1a 100644 --- a/pkg/mem/model.go +++ b/pkg/mem/model.go @@ -17,6 +17,11 @@ package mem +const GatewayKind = "Gateway" +const RouteKind = "Route" +const UpstreamKind = "Upstream" +const PluginKind = "Plugin" + type MemModel interface { Diff(m MemModel) bool } diff --git a/pkg/utils/http.go b/pkg/utils/http.go new file mode 100644 index 0000000..45e5c17 --- /dev/null +++ b/pkg/utils/http.go @@ -0,0 +1,75 @@ +/* + * 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 utils + +import ( + "fmt" + "net/http" + "time" + + "gopkg.in/resty.v1" +) + +const timeout = 3000 + +func Post(url string, bytes []byte) ([]byte, error) { + r := resty.New(). + SetTimeout(time.Duration(timeout)*time.Millisecond). + R(). + SetHeader("content-type", "application/json") + r.SetBody(bytes) + resp, err := r.Post(url) + if err != nil { + return nil, err + } + if resp.StatusCode() != http.StatusOK && resp.StatusCode() != http.StatusCreated { + return nil, fmt.Errorf("status: %d, body: %s", resp.StatusCode(), resp.Body()) + } + return resp.Body(), nil +} + +func Patch(url string, bytes []byte) ([]byte, error) { + r := resty.New(). + SetTimeout(time.Duration(timeout)*time.Millisecond). + R(). + SetHeader("content-type", "application/json") + r.SetBody(bytes) + resp, err := r.Patch(url) + if err != nil { + return nil, err + } + if resp.StatusCode() != http.StatusOK { + return nil, fmt.Errorf("status: %d, body: %s", resp.StatusCode(), resp.Body()) + } + return resp.Body(), nil +} + +func Delete(url string) ([]byte, error) { + r := resty.New(). + SetTimeout(time.Duration(timeout)*time.Millisecond). + R(). + SetHeader("content-type", "application/json") + resp, err := r.Delete(url) + if err != nil { + return nil, err + } + if resp.StatusCode() != http.StatusOK { + return nil, fmt.Errorf("status: %d, body: %s", resp.StatusCode(), resp.Body()) + } + return resp.Body(), nil +}