You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by mi...@apache.org on 2018/05/18 18:03:04 UTC
[incubator-trafficcontrol] branch master updated: Add TO Go
deliveryservicesregexes
This is an automated email from the ASF dual-hosted git repository.
mitchell852 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new 2486016 Add TO Go deliveryservicesregexes
2486016 is described below
commit 2486016d3e6a45d1b70948ee43393b2dc7fd3784
Author: Robert Butts <ro...@apache.org>
AuthorDate: Tue Apr 24 08:37:55 2018 -0600
Add TO Go deliveryservicesregexes
---
lib/go-tc/deliveryservice_regexes.go | 34 ++
traffic_ops/traffic_ops_golang/api/change_log.go | 42 +-
.../deliveryservicesregexes.go | 591 +++++++++++++++++++++
traffic_ops/traffic_ops_golang/routes.go | 13 +-
4 files changed, 660 insertions(+), 20 deletions(-)
diff --git a/lib/go-tc/deliveryservice_regexes.go b/lib/go-tc/deliveryservice_regexes.go
index df214fe..117d61f 100644
--- a/lib/go-tc/deliveryservice_regexes.go
+++ b/lib/go-tc/deliveryservice_regexes.go
@@ -31,3 +31,37 @@ type DeliveryServiceRegex struct {
SetNumber int `json:"setNumber"`
Pattern string `json:"pattern"`
}
+
+type DeliveryServiceRegexV12 struct {
+ DeliveryServiceRegex
+}
+
+type DeliveryServiceRegexV13 struct {
+ DeliveryServiceRegexV12
+}
+
+type DeliveryServiceIDRegexResponse struct {
+ Response []DeliveryServiceIDRegex `json:"response"`
+}
+
+type DeliveryServiceIDRegex struct {
+ ID int `json:"id"`
+ Type int `json:"type"`
+ TypeName string `json:"typeName"`
+ SetNumber int `json:"setNumber"`
+ Pattern string `json:"pattern"`
+}
+
+type DeliveryServiceIDRegexV12 struct {
+ DeliveryServiceIDRegex
+}
+
+type DeliveryServiceIDRegexV13 struct {
+ DeliveryServiceIDRegexV12
+}
+
+type DeliveryServiceRegexPost struct {
+ Type int `json:"type"`
+ SetNumber int `json:"setNumber"`
+ Pattern string `json:"pattern"`
+}
diff --git a/traffic_ops/traffic_ops_golang/api/change_log.go b/traffic_ops/traffic_ops_golang/api/change_log.go
index f2fb18f..1b30429 100644
--- a/traffic_ops/traffic_ops_golang/api/change_log.go
+++ b/traffic_ops/traffic_ops_golang/api/change_log.go
@@ -51,28 +51,34 @@ const (
)
func CreateChangeLog(level string, action string, i Identifier, user auth.CurrentUser, db *sqlx.DB) error {
- keys, _ := i.GetKeys()
- keysString := "{ "
- for key, value := range keys {
- keysString += key + ":" + fmt.Sprintf("%v", value) + " "
+ t, ok := i.(ChangeLogger)
+ if !ok {
+ keys, _ := i.GetKeys()
+ return CreateChangeLogBuildMsg(level, action, user, db, i.GetType(), i.GetAuditName(), keys)
+ }
+ msg, err := t.ChangeLogMessage(action)
+ if err != nil {
+ log.Errorf("%++v creating log message for %++v", err, t)
+ keys, _ := i.GetKeys()
+ return CreateChangeLogBuildMsg(level, action, user, db, i.GetType(), i.GetAuditName(), keys)
}
- keysString += "}"
- message := action + " " + i.GetType() + ": " + i.GetAuditName() + " keys: " + keysString
- // if the object has its own log message generation, use it
- if t, ok := i.(ChangeLogger); ok {
- m, err := t.ChangeLogMessage(action)
- if err != nil {
- log.Errorf("error %++v creating log message for %++v", err, t)
- // use the default message in this case
- } else {
- message = m
- }
+ return CreateChangeLogMsg(level, user, db, msg)
+}
+
+func CreateChangeLogBuildMsg(level string, action string, user auth.CurrentUser, db *sqlx.DB, objType string, auditName string, keys map[string]interface{}) error {
+ keyStr := "{ "
+ for key, value := range keys {
+ keyStr += key + ":" + fmt.Sprintf("%v", value) + " "
}
+ keyStr += "}"
+ msg := action + " " + objType + ": " + auditName + " keys: " + keyStr
+ return CreateChangeLogMsg(level, user, db, msg)
+}
+func CreateChangeLogMsg(level string, user auth.CurrentUser, db *sqlx.DB, msg string) error {
query := `INSERT INTO log (level, message, tm_user) VALUES ($1, $2, $3)`
- log.Debugf("about to exec %s with %s", query, message)
- _, err := db.Exec(query, level, message, user.ID)
- if err != nil {
+ log.Debugf("about to exec %s with %s", query, msg)
+ if _, err := db.Exec(query, level, msg, user.ID); err != nil {
log.Errorf("received error: %++v from audit log insertion", err)
return err
}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go b/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go
new file mode 100644
index 0000000..8284242
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservicesregexes/deliveryservicesregexes.go
@@ -0,0 +1,591 @@
+package deliveryservicesregexes
+
+/*
+ * 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"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "strconv"
+
+ "github.com/apache/incubator-trafficcontrol/lib/go-log"
+ "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/api"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/auth"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+ // "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+ // "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tovalidate"
+
+ // "github.com/asaskevich/govalidator"
+ // "github.com/go-ozzo/ozzo-validation"
+ "github.com/jmoiron/sqlx"
+ // "github.com/lib/pq"
+)
+
+func Get(dbx *sqlx.DB) http.HandlerFunc {
+ db := dbx.DB
+ return func(w http.ResponseWriter, r *http.Request) {
+ handleErrs := tc.GetHandleErrorsFunc(w, r)
+ user, err := auth.GetCurrentUser(r.Context())
+ if err != nil {
+ log.Errorf("unable to retrieve current user from context: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ q := `
+SELECT ds.xml_id, ds.tenant_id, dsr.set_number, r.pattern, rt.name as type
+FROM deliveryservice_regex as dsr
+JOIN deliveryservice as ds ON dsr.deliveryservice = ds.id
+JOIN regex as r ON dsr.regex = r.id
+JOIN type as rt ON r.type = rt.id
+`
+ rows, err := db.Query(q)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("querying: "+err.Error()))
+ return
+ }
+ dsRegexes := map[tc.DeliveryServiceName][]tc.DeliveryServiceRegex{}
+ for rows.Next() {
+ // if (!$tenant_utils->is_ds_resource_accessible($tenants_data, $ds->tenant_id)) {
+ // next;
+ // }
+ dsName := ""
+ dsTenantID := 0
+ setNumber := 0
+ pattern := ""
+ typeName := ""
+ if err = rows.Scan(&dsName, &dsTenantID, &setNumber, &pattern, &typeName); err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("querying: "+err.Error()))
+ return
+ }
+ if ok, err := tenant.IsResourceAuthorizedToUser(dsTenantID, *user, dbx); !ok {
+ continue
+ } else if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("checking tenancy: "+err.Error()))
+ return
+ }
+ dsRegexes[tc.DeliveryServiceName(dsName)] = append(dsRegexes[tc.DeliveryServiceName(dsName)], tc.DeliveryServiceRegex{
+ Type: typeName,
+ SetNumber: setNumber,
+ Pattern: pattern,
+ })
+ }
+ respRegexes := []tc.DeliveryServiceRegexes{}
+ for dsName, regexes := range dsRegexes {
+ respRegexes = append(respRegexes, tc.DeliveryServiceRegexes{DSName: string(dsName), Regexes: regexes})
+ }
+ respBts, err := json.Marshal(&tc.DeliveryServiceRegexResponse{Response: respRegexes})
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("marshalling JSON: "+err.Error()))
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(respBts)
+ }
+}
+
+func DSGet(dbx *sqlx.DB) http.HandlerFunc {
+ db := dbx.DB
+ return func(w http.ResponseWriter, r *http.Request) {
+ handleErrs := tc.GetHandleErrorsFunc(w, r)
+ user, err := auth.GetCurrentUser(r.Context())
+ if err != nil {
+ log.Errorf("unable to retrieve current user from context: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ params, err := api.GetCombinedParams(r)
+ if err != nil {
+ log.Errorf("unable to get parameters from request: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ dsIDStr, ok := params["dsid"]
+ if !ok {
+ log.Errorln("no delivery service ID")
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ dsID, err := strconv.Atoi(dsIDStr)
+ if err != nil {
+ log.Errorln("Delivery service ID '" + dsIDStr + "' not an integer")
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+
+ q := `
+SELECT ds.tenant_id, dsr.set_number, r.id, r.pattern, rt.id as type, rt.name as type_name
+FROM deliveryservice_regex as dsr
+JOIN deliveryservice as ds ON dsr.deliveryservice = ds.id
+JOIN regex as r ON dsr.regex = r.id
+JOIN type as rt ON r.type = rt.id
+WHERE ds.ID = $1
+ORDER BY dsr.set_number ASC
+`
+ rows, err := db.Query(q, dsID)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("querying: "+err.Error()))
+ return
+ }
+ regexes := []tc.DeliveryServiceIDRegex{}
+ for rows.Next() {
+ dsTenantID := 0
+ setNumber := 0
+ id := 0
+ pattern := ""
+ typeID := 0
+ typeName := ""
+ if err = rows.Scan(&dsTenantID, &setNumber, &id, &pattern, &typeID, &typeName); err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("querying: "+err.Error()))
+ return
+ }
+ if ok, err := tenant.IsResourceAuthorizedToUser(dsTenantID, *user, dbx); !ok {
+ continue
+ } else if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("checking tenancy: "+err.Error()))
+ return
+ }
+ regexes = append(regexes, tc.DeliveryServiceIDRegex{
+ ID: id,
+ Type: typeID,
+ TypeName: typeName,
+ SetNumber: setNumber,
+ Pattern: pattern,
+ })
+ }
+ respBts, err := json.Marshal(&tc.DeliveryServiceIDRegexResponse{Response: regexes})
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("marshalling JSON: "+err.Error()))
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(respBts)
+ }
+}
+
+func DSGetID(dbx *sqlx.DB) http.HandlerFunc {
+ db := dbx.DB
+ return func(w http.ResponseWriter, r *http.Request) {
+ handleErrs := tc.GetHandleErrorsFunc(w, r)
+ user, err := auth.GetCurrentUser(r.Context())
+ if err != nil {
+ log.Errorf("unable to retrieve current user from context: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ params, err := api.GetCombinedParams(r)
+ if err != nil {
+ log.Errorf("unable to get parameters from request: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ dsIDStr, ok := params["dsid"]
+ if !ok {
+ log.Errorln("no delivery service ID")
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ dsID, err := strconv.Atoi(dsIDStr)
+ if err != nil {
+ log.Errorln("Delivery service ID '" + dsIDStr + "' not an integer")
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ regexIDStr, ok := params["regexid"]
+ if !ok {
+ log.Errorln("no regex ID")
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ regexID, err := strconv.Atoi(regexIDStr)
+ if err != nil {
+ log.Errorln("Regex ID '" + regexIDStr + "' not an integer")
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+
+ q := `
+SELECT ds.tenant_id, dsr.set_number, r.id, r.pattern, rt.id as type, rt.name as type_name
+FROM deliveryservice_regex as dsr
+JOIN deliveryservice as ds ON dsr.deliveryservice = ds.id
+JOIN regex as r ON dsr.regex = r.id
+JOIN type as rt ON r.type = rt.id
+WHERE ds.ID = $1
+AND r.ID = $2
+ORDER BY dsr.set_number ASC
+`
+ rows, err := db.Query(q, dsID, regexID)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("querying: "+err.Error()))
+ return
+ }
+ regexes := []tc.DeliveryServiceIDRegex{}
+ for rows.Next() {
+ dsTenantID := 0
+ setNumber := 0
+ id := 0
+ pattern := ""
+ typeID := 0
+ typeName := ""
+ if err = rows.Scan(&dsTenantID, &setNumber, &id, &pattern, &typeID, &typeName); err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("querying: "+err.Error()))
+ return
+ }
+ if ok, err := tenant.IsResourceAuthorizedToUser(dsTenantID, *user, dbx); !ok {
+ continue
+ } else if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("checking tenancy: "+err.Error()))
+ return
+ }
+ regexes = append(regexes, tc.DeliveryServiceIDRegex{
+ ID: id,
+ Type: typeID,
+ TypeName: typeName,
+ SetNumber: setNumber,
+ Pattern: pattern,
+ })
+ }
+ respBts, err := json.Marshal(&tc.DeliveryServiceIDRegexResponse{Response: regexes})
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("marshalling JSON: "+err.Error()))
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(respBts)
+ }
+}
+
+func Post(dbx *sqlx.DB) http.HandlerFunc {
+ db := dbx.DB
+ return func(w http.ResponseWriter, r *http.Request) {
+ handleErrs := tc.GetHandleErrorsFunc(w, r)
+ user, err := auth.GetCurrentUser(r.Context())
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("unable to retrieve current user from context: "+err.Error()))
+ return
+ }
+ params, err := api.GetCombinedParams(r)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("unable to get parameters from request: "+err.Error()))
+ return
+ }
+ dsIDStr, ok := params["dsid"]
+ if !ok {
+ handleErrs(http.StatusInternalServerError, errors.New("no deliveryservice ID"))
+ return
+ }
+ dsID, err := strconv.Atoi(dsIDStr)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("deliveryservice ID not an integer"))
+ return
+ }
+ dsTenantID := 0
+ if err := db.QueryRow(`SELECT tenant_id from deliveryservice where id = $1`, dsID).Scan(&dsTenantID); err != nil {
+ if err != sql.ErrNoRows {
+ log.Errorln("getting deliveryservice name: " + err.Error())
+ }
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ if ok, err := tenant.IsResourceAuthorizedToUser(dsTenantID, *user, dbx); !ok {
+ handleErrs(http.StatusInternalServerError, errors.New("unauthorized"))
+ return
+ } else if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("checking tenancy: "+err.Error()))
+ return
+ }
+ dsr := tc.DeliveryServiceRegexPost{}
+ if err := json.NewDecoder(r.Body).Decode(&dsr); err != nil {
+ log.Errorln("failed to parse body: " + err.Error())
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+
+ regexID := 0
+ if err := db.QueryRow(`INSERT INTO regex (pattern, type) VALUES ($1, $2) RETURNING id`, dsr.Pattern, dsr.Type).Scan(®exID); err != nil {
+ log.Errorln("inserting regex: " + err.Error())
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+
+ if _, err := db.Exec(`INSERT INTO deliveryservice_regex (deliveryservice, regex, set_number) values ($1, $2, $3)`, dsID, regexID, dsr.SetNumber); err != nil {
+ log.Errorln("inserting deliveryservice_regex: " + err.Error())
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+
+ typeName := ""
+ if err := db.QueryRow(`SELECT name from type where id = $1`, dsr.Type).Scan(&typeName); err != nil {
+ if err != sql.ErrNoRows {
+ log.Errorln("getting regex type: " + err.Error())
+ }
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+
+ respObj := tc.DeliveryServiceIDRegex{
+ ID: regexID,
+ Pattern: dsr.Pattern,
+ Type: dsr.Type,
+ TypeName: typeName,
+ SetNumber: dsr.SetNumber,
+ }
+ resp := struct {
+ Response tc.DeliveryServiceIDRegex `json:"response"`
+ tc.Alerts
+ }{respObj, tc.CreateAlerts(tc.SuccessLevel, "Delivery service regex creation was successful.")}
+
+ respBts, err := json.Marshal(&resp)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("marshalling JSON: "+err.Error()))
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(respBts)
+ }
+}
+
+func Put(dbx *sqlx.DB) http.HandlerFunc {
+ db := dbx.DB
+ return func(w http.ResponseWriter, r *http.Request) {
+ handleErrs := tc.GetHandleErrorsFunc(w, r)
+ user, err := auth.GetCurrentUser(r.Context())
+ if err != nil {
+ log.Errorf("unable to retrieve current user from context: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ params, err := api.GetCombinedParams(r)
+ if err != nil {
+ log.Errorf("unable to get parameters from request: %s", err)
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ dsIDStr, ok := params["dsid"]
+ if !ok {
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ dsID, err := strconv.Atoi(dsIDStr)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ regexIDStr, ok := params["regexid"]
+ if !ok {
+ handleErrs(http.StatusInternalServerError, errors.New("no regex ID"))
+ return
+ }
+ regexID, err := strconv.Atoi(regexIDStr)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("Regex ID '"+regexIDStr+"' not an integer"))
+ return
+ }
+ dsTenantID := 0
+ if err := db.QueryRow(`SELECT tenant_id from deliveryservice where id = $1`, dsID).Scan(&dsTenantID); err != nil {
+ if err != sql.ErrNoRows {
+ log.Errorln("getting deliveryservice name: " + err.Error())
+ }
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ if ok, err := tenant.IsResourceAuthorizedToUser(dsTenantID, *user, dbx); !ok {
+ handleErrs(http.StatusInternalServerError, errors.New("unauthorized"))
+ return
+ } else if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("checking tenancy: "+err.Error()))
+ return
+ }
+ dsr := tc.DeliveryServiceRegexPost{} // PUT uses same format as POST
+ if err := json.NewDecoder(r.Body).Decode(&dsr); err != nil {
+ log.Errorln("failed to parse body: " + err.Error())
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ if _, err := db.Exec(`UPDATE regex SET pattern=$1, type=$2 WHERE id=$3`, dsr.Pattern, dsr.Type, regexID); err != nil {
+ log.Errorln("deliveryservicesregexes.Put: updating regex: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ if _, err := db.Exec(`UPDATE deliveryservice_regex SET set_number=$1 WHERE deliveryservice=$2 AND regex=$3`, dsr.SetNumber, dsID, regexID); err != nil {
+ log.Errorln("deliveryservicesregexes.Put: updating deliveryservice_regex: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ typeName := ""
+ if err := db.QueryRow(`SELECT name from type where id = $1`, dsr.Type).Scan(&typeName); err != nil {
+ if err != sql.ErrNoRows {
+ log.Errorln("getting regex type: " + err.Error())
+ }
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ respObj := tc.DeliveryServiceIDRegex{
+ ID: regexID,
+ Pattern: dsr.Pattern,
+ Type: dsr.Type,
+ TypeName: typeName,
+ SetNumber: dsr.SetNumber,
+ }
+ resp := struct {
+ Response tc.DeliveryServiceIDRegex `json:"response"`
+ tc.Alerts
+ }{respObj, tc.CreateAlerts(tc.SuccessLevel, "Delivery service regex creation was successful.")}
+ respBts, err := json.Marshal(&resp)
+ if err != nil {
+ handleErrs(http.StatusInternalServerError, errors.New("marshalling JSON: "+err.Error()))
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(respBts)
+ }
+}
+
+func Delete(dbx *sqlx.DB) http.HandlerFunc {
+ db := dbx.DB
+ return func(w http.ResponseWriter, r *http.Request) {
+ handleErrs := tc.GetHandleErrorsFunc(w, r)
+ user, err := auth.GetCurrentUser(r.Context())
+ if err != nil {
+ log.Errorf("unable to retrieve current user from context: %s", err)
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ params, err := api.GetCombinedParams(r)
+ if err != nil {
+ log.Errorf("unable to get parameters from request: %s", err)
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ dsIDStr, ok := params["dsid"]
+ if !ok {
+ log.Errorf("deliveryservicesregexes.Delete: no dsid parameter")
+ handleErrs(http.StatusInternalServerError, errors.New("internal server error"))
+ return
+ }
+ dsID, err := strconv.Atoi(dsIDStr)
+ if err != nil {
+ handleErrs(http.StatusBadRequest, errors.New("delivery service ID is not an integer"))
+ return
+ }
+ regexIDStr, ok := params["regexid"]
+ if !ok {
+ handleErrs(http.StatusBadRequest, errors.New("no regex ID"))
+ return
+ }
+ regexID, err := strconv.Atoi(regexIDStr)
+ if err != nil {
+ handleErrs(http.StatusBadRequest, errors.New("Regex ID '"+regexIDStr+"' not an integer"))
+ return
+ }
+
+ tx, err := db.Begin()
+ if err != nil {
+ log.Errorln("could not begin transaction: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("could not begin transaction: "+err.Error()))
+ return
+ }
+ commitTx := false
+ defer FinishTx(tx, &commitTx)
+
+ count := 0
+ if err := db.QueryRow(`SELECT count(*) from deliveryservice_regex where deliveryservice = $1`, dsID).Scan(&count); err != nil {
+ if err != sql.ErrNoRows {
+ handleErrs(http.StatusNotFound, errors.New("not found"))
+ return
+ }
+ log.Errorln(errors.New("getting deliveryservice regex count: " + err.Error()))
+ handleErrs(http.StatusInternalServerError, errors.New("internal server error"))
+ return
+ }
+ if count < 2 {
+ handleErrs(http.StatusBadRequest, errors.New("a delivery service must have at least one regex"))
+ return
+ }
+
+ dsTenantID := 0
+ if err := db.QueryRow(`SELECT tenant_id from deliveryservice where id = $1`, dsID).Scan(&dsTenantID); err != nil {
+ if err != sql.ErrNoRows {
+ log.Errorln("getting deliveryservice name: " + err.Error())
+ }
+ handleErrs(http.StatusInternalServerError, err)
+ return
+ }
+ if ok, err := tenant.IsResourceAuthorizedToUser(dsTenantID, *user, dbx); !ok {
+ handleErrs(http.StatusUnauthorized, errors.New("unauthorized"))
+ return
+ } else if err != nil {
+ log.Errorln("checking tenancy: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+
+ result, err := tx.Exec(`DELETE FROM deliveryservice_regex WHERE deliveryservice = $1 and regex = $2`, dsID, regexID)
+ if err != nil {
+ log.Errorln("deliveryservicesregexes.Delete deleting delivery service regexes: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ rowsAffected, err := result.RowsAffected()
+ if err != nil {
+ log.Errorln("deliveryservicesregexes.Delete delete error: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ if rowsAffected != 1 {
+ if rowsAffected < 1 {
+ handleErrs(http.StatusNotFound, errors.New("not found"))
+ return
+ }
+ log.Errorf("this create affected too many rows: %d", rowsAffected)
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+
+ log.Debugf("changelog for delete on object")
+ api.CreateChangeLogMsg(api.ApiChange, *user, dbx, fmt.Sprintf(`deleted deliveryservice_regex {"ds": %d, "regex": %d}`, dsID, regexID))
+ resp := struct {
+ tc.Alerts
+ }{tc.CreateAlerts(tc.SuccessLevel, "deliveryservice_regex was deleted.")}
+ respBts, err := json.Marshal(resp)
+ if err != nil {
+ log.Errorln("deliveryservicesregexes.Delete creating JSON: " + err.Error())
+ handleErrs(http.StatusInternalServerError, errors.New("server error"))
+ return
+ }
+ w.Header().Set(tc.ContentType, tc.ApplicationJson)
+ w.Write(respBts)
+ commitTx = true
+ }
+}
+
+// FinishTx commits the transaction if commit is true when it's called, otherwise it rolls back the transaction. This is designed to be called in a defer.
+func FinishTx(tx *sql.Tx, commit *bool) {
+ if tx == nil {
+ return
+ }
+ if !*commit {
+ tx.Rollback()
+ return
+ }
+ tx.Commit()
+}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index cba2190..37a3b18 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -38,8 +38,9 @@ import (
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/coordinate"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/crconfig"
dsrequest "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/request"
- dsserver "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/servers"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/request/comment"
+ dsserver "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/servers"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservicesregexes"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/division"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/hwinfo"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/parameter"
@@ -154,7 +155,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
{1.1, http.MethodDelete, `regions/{id}$`, api.DeleteHandler(region.GetRefType(), d.DB), auth.PrivLevelOperations, Authenticated, nil},
// get all edge servers associated with a delivery service (from deliveryservice_server table)
- {1.1, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.1, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
//Server
{1.1, http.MethodGet, `servers/checks$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
@@ -224,6 +225,14 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
{1.3, http.MethodPost, `roles/?$`, api.CreateHandler(role.GetRefType(), d.DB), auth.PrivLevelAdmin, Authenticated, nil},
{1.3, http.MethodDelete, `roles/?$`, api.DeleteHandler(role.GetRefType(), d.DB), auth.PrivLevelAdmin, Authenticated, nil},
+ //Delivery Services Regexes
+ {1.1, http.MethodGet, `deliveryservices_regexes/?(\.json)?$`, deliveryservicesregexes.Get(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.1, http.MethodGet, `deliveryservices/{dsid}/regexes/?(\.json)?$`, deliveryservicesregexes.DSGet(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.1, http.MethodGet, `deliveryservices/{dsid}/regexes/{regexid}?(\.json)?$`, deliveryservicesregexes.DSGetID(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.1, http.MethodPost, `deliveryservices/{dsid}/regexes/?(\.json)?$`, deliveryservicesregexes.Post(d.DB), auth.PrivLevelOperations, Authenticated, nil},
+ {1.1, http.MethodPut, `deliveryservices/{dsid}/regexes/{regexid}?(\.json)?$`, deliveryservicesregexes.Put(d.DB), auth.PrivLevelOperations, Authenticated, nil},
+ {1.1, http.MethodDelete, `deliveryservices/{dsid}/regexes/{regexid}?(\.json)?$`, deliveryservicesregexes.Delete(d.DB), auth.PrivLevelOperations, Authenticated, nil},
+
//Servers
{1.3, http.MethodPost, `servers/{id}/deliveryservices$`, server.AssignDeliveryServicesToServerHandler(d.DB), auth.PrivLevelOperations, Authenticated, nil},
{1.3, http.MethodGet, `servers/{host_name}/update_status$`, server.GetServerUpdateStatusHandler(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
--
To stop receiving notification emails like this one, please contact
mitchell852@apache.org.