You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by el...@apache.org on 2018/07/06 17:17:11 UTC
[trafficcontrol] 01/02: Add TO Go deliveryservice_matches
This is an automated email from the ASF dual-hosted git repository.
elsloo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
commit 90279384b7b5c1436d4ba1925f7ed3b4bd125ee3
Author: Robert Butts <ro...@apache.org>
AuthorDate: Thu Jun 14 17:05:12 2018 -0600
Add TO Go deliveryservice_matches
---
lib/go-tc/deliveryservices.go | 7 ++
.../deliveryservice/deliveryservicesv13.go | 2 +-
.../traffic_ops_golang/deliveryservice/matches.go | 125 +++++++++++++++++++++
.../deliveryservice/request/requests.go | 2 +-
traffic_ops/traffic_ops_golang/routes.go | 2 +
traffic_ops/traffic_ops_golang/tenant/tenancy.go | 24 ++--
6 files changed, 147 insertions(+), 15 deletions(-)
diff --git a/lib/go-tc/deliveryservices.go b/lib/go-tc/deliveryservices.go
index 7cd1324..519e97b 100644
--- a/lib/go-tc/deliveryservices.go
+++ b/lib/go-tc/deliveryservices.go
@@ -526,6 +526,13 @@ type DeliveryServiceCapacity struct {
MaintenancePercent float64 `json:"maintenancePercent"`
}
+type DeliveryServiceMatchesResp []DeliveryServicePatterns
+
+type DeliveryServicePatterns struct {
+ Patterns []string `json:"patterns"`
+ DSName DeliveryServiceName `json:"dsName"`
+}
+
// DeliveryServiceRoutingResponse ...
type DeliveryServiceRoutingResponse struct {
Response DeliveryServiceRouting `json:"response"`
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go
index cd6bfa9..f48e948 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go
@@ -623,7 +623,7 @@ func readGetDeliveryServices(params map[string]string, tx *sqlx.Tx, user *auth.C
if tenancyEnabled {
log.Debugln("Tenancy is enabled")
- tenantIDs, err := tenant.GetUserTenantIDListTx(user, tx)
+ tenantIDs, err := tenant.GetUserTenantIDListTx(tx.Tx, user.TenantID)
if err != nil {
log.Errorln("received error querying for user's tenants: " + err.Error())
return nil, []error{tc.DBError}, tc.SystemError
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/matches.go b/traffic_ops/traffic_ops_golang/deliveryservice/matches.go
new file mode 100644
index 0000000..972a578
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/matches.go
@@ -0,0 +1,125 @@
+package deliveryservice
+
+/*
+ * 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.
+ */
+
+import (
+ "database/sql"
+ "errors"
+ "net/http"
+ "strings"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+
+ "github.com/lib/pq"
+)
+
+func GetMatches(w http.ResponseWriter, r *http.Request) {
+ inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, errCode, userErr, sysErr)
+ return
+ }
+ defer inf.Close()
+ matches, err := getUserDSMatches(inf.Tx.Tx, inf.User.TenantID)
+ if err != nil {
+ api.HandleErr(w, r, http.StatusInternalServerError, nil, errors.New("getting delivery service matches: "+err.Error()))
+ return
+ }
+ *inf.CommitTx = true
+ api.WriteResp(w, r, matches)
+}
+
+func getUserDSMatches(tx *sql.Tx, userTenantID int) ([]tc.DeliveryServicePatterns, error) {
+ q := `
+SELECT ds.xml_id, ds.remap_text, r.pattern
+FROM deliveryservice as ds
+JOIN deliveryservice_regex as dsr ON dsr.deliveryservice = ds.id
+JOIN regex as r ON r.id = dsr.regex
+WHERE ds.active = true
+`
+ qParams := []interface{}{}
+ tenancyEnabled, err := tenant.IsTenancyEnabledTx(tx)
+ if err != nil {
+ return nil, errors.New("checking tenancy enabled: " + err.Error())
+ }
+ if tenancyEnabled {
+ tenantIDs, err := tenant.GetUserTenantIDListTx(tx, userTenantID)
+ if err != nil {
+ return nil, errors.New("getting user tenant ID list: " + err.Error())
+ }
+ q += `
+AND ds.tenant_id = ANY($1)
+`
+ qParams = append(qParams, pq.Array(tenantIDs))
+ }
+
+ q += `
+ORDER BY dsr.set_number
+`
+
+ rows, err := tx.Query(q, qParams...)
+ if err != nil {
+ return nil, errors.New("querying delivery service matches: " + err.Error())
+ }
+ defer rows.Close()
+
+ matches := []tc.DeliveryServicePatterns{}
+ matchRegexes := map[tc.DeliveryServiceName][]string{}
+ for rows.Next() {
+ ds := tc.DeliveryServiceName("")
+ remapText := (*string)(nil)
+ pattern := ""
+ if err := rows.Scan(&ds, &remapText, &pattern); err != nil {
+ return nil, errors.New("scanning delivery service matches: " + err.Error())
+ }
+ if remapText != nil && strings.HasPrefix(*remapText, `regex_map`) {
+ matches = append(matches, tc.DeliveryServicePatterns{DSName: dsNameToUnderscores(ds), Patterns: []string{remapToMatch(*remapText)}})
+ } else {
+ matchRegexes[ds] = append(matchRegexes[ds], regexToMatch(pattern))
+ }
+ }
+ for ds, dsMatches := range matchRegexes {
+ matches = append(matches, tc.DeliveryServicePatterns{DSName: dsNameToUnderscores(ds), Patterns: dsMatches})
+ }
+ return matches, nil
+}
+
+// dsNameToUnderscores changes delivery service name (xml_id) hyphens to underscores, to emulate the behavior of the old Perl Traffic Ops API.
+func dsNameToUnderscores(ds tc.DeliveryServiceName) tc.DeliveryServiceName {
+ return tc.DeliveryServiceName(strings.Replace(string(ds), `-`, `_`, -1))
+}
+
+func remapToMatch(regex string) string {
+ // TODO: emulates old Perl behavior; verify correctness and usefulness
+ regex = strings.TrimPrefix(regex, `regex_map http://`)
+ hyphenI := strings.Index(regex, `-`)
+ if hyphenI > 0 {
+ regex = regex[:hyphenI+1]
+ }
+ return regex
+}
+
+func regexToMatch(remap string) string {
+ remap = strings.Replace(remap, `\`, ``, -1)
+ remap = strings.Replace(remap, `.*`, ``, -1)
+ return remap
+}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go b/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go
index 317a79e..78c4546 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go
@@ -108,7 +108,7 @@ func (req *TODeliveryServiceRequest) Read(parameters map[string]string) ([]inter
}
if tenancyEnabled {
log.Debugln("Tenancy is enabled")
- tenantIDs, err := tenant.GetUserTenantIDListTx(req.ReqInfo.User, req.ReqInfo.Tx)
+ tenantIDs, err := tenant.GetUserTenantIDListTx(req.ReqInfo.Tx.Tx, req.ReqInfo.User.TenantID)
if err != nil {
log.Errorln("received error querying for user's tenants: " + err.Error())
return nil, []error{tc.DBError}, tc.SystemError
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 6ce58df..cd6b623 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -195,6 +195,8 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
{1.1, http.MethodGet, `deliveryservices/{id}/unassigned_servers$`, dsserver.GetReadHandler(d.DB, tc.Unassigned), auth.PrivLevelReadOnly, Authenticated, nil},
//{1.1, http.MethodGet, `deliveryservices/{id}/servers/eligible$`, dsserver.GetReadHandler(d.Tx, tc.Eligible),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.1, http.MethodGet, `deliveryservice_matches/?(\.json)?$`, deliveryservice.GetMatches, auth.PrivLevelReadOnly, Authenticated, nil},
+
//Server
{1.1, http.MethodGet, `servers/checks$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
{1.1, http.MethodGet, `servers/status$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
diff --git a/traffic_ops/traffic_ops_golang/tenant/tenancy.go b/traffic_ops/traffic_ops_golang/tenant/tenancy.go
index 51f41ad..d24bab3 100644
--- a/traffic_ops/traffic_ops_golang/tenant/tenancy.go
+++ b/traffic_ops/traffic_ops_golang/tenant/tenancy.go
@@ -180,30 +180,26 @@ func GetUserTenantIDList(user auth.CurrentUser, db *sqlx.DB) ([]int, error) {
return tenants, nil
}
-func GetUserTenantIDListTx(user *auth.CurrentUser, tx *sqlx.Tx) ([]int, error) {
- query := `WITH RECURSIVE q AS (SELECT id, name, active, parent_id FROM tenant WHERE id = $1
- UNION SELECT t.id, t.name, t.active, t.parent_id FROM tenant t JOIN q ON q.id = t.parent_id)
- SELECT id FROM q;`
-
- log.Debugln("\nQuery: ", query)
-
- var tenantID int
-
- rows, err := tx.Query(query, user.TenantID)
+func GetUserTenantIDListTx(tx *sql.Tx, userTenantID int) ([]int, error) {
+ query := `
+WITH RECURSIVE q AS (SELECT id, name, active, parent_id FROM tenant WHERE id = $1
+UNION SELECT t.id, t.name, t.active, t.parent_id FROM tenant t JOIN q ON q.id = t.parent_id)
+SELECT id FROM q;
+`
+ rows, err := tx.Query(query, userTenantID)
if err != nil {
return nil, err
}
defer rows.Close()
tenants := []int{}
-
for rows.Next() {
+ tenantID := 0
if err := rows.Scan(&tenantID); err != nil {
return nil, err
}
tenants = append(tenants, tenantID)
}
-
return tenants, nil
}
@@ -219,10 +215,12 @@ func IsTenancyEnabled(db *sqlx.DB) bool {
return useTenancy
}
+// IsTenancyEnabledTx returns true if tenancy is enabled or false otherwise
func IsTenancyEnabledTx(tx *sql.Tx) (bool, error) {
query := `SELECT COALESCE(value::boolean,FALSE) AS value FROM parameter WHERE name = 'use_tenancy' AND config_file = 'global' UNION ALL SELECT FALSE FETCH FIRST 1 ROW ONLY`
useTenancy := false
- if err := tx.QueryRow(query).Scan(&useTenancy); err != nil {
+ err := tx.QueryRow(query).Scan(&useTenancy)
+ if err != nil {
return false, errors.New("checking if tenancy is enabled: " + err.Error())
}
return useTenancy, nil