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

dangogh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git

commit a0bdfc89a04295c1a2360a1dfb6f68f58f3de5f8
Author: Dewayne Richardson <dewr...@apache.org>
AuthorDate: Wed Feb 14 14:36:49 2018 -0700

    refactored the asns to refer to the CRUD interface framework
---
 traffic_ops/traffic_ops_golang/asn/asns.go         | 326 +++++++++++++++++++++
 .../traffic_ops_golang/{ => asn}/asns_test.go      |   2 +-
 traffic_ops/traffic_ops_golang/asns.go             | 125 --------
 traffic_ops/traffic_ops_golang/routes.go           |   8 +-
 4 files changed, 334 insertions(+), 127 deletions(-)

diff --git a/traffic_ops/traffic_ops_golang/asn/asns.go 
b/traffic_ops/traffic_ops_golang/asn/asns.go
new file mode 100644
index 0000000..59ea4cc
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/asn/asns.go
@@ -0,0 +1,326 @@
+package asn
+
+/*
+ * 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 (
+       "errors"
+       "fmt"
+       "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/dbhelpers"
+       "github.com/jmoiron/sqlx"
+       "github.com/lib/pq"
+)
+
+// ASNsPrivLevel ...
+const ASNsPrivLevel = 10
+
+//we need a type alias to define functions on
+type TOASN tc.ASN
+
+//the refType is passed into the handlers where a copy of its type is used to 
decode the json.
+var refType = TOASN(tc.ASN{})
+
+func GetRefType() *TOASN {
+       return &refType
+}
+
+//Implementation of the Identifier, Validator interface functions
+func (asn *TOASN) GetID() int {
+       return asn.ID
+}
+
+func (asn *TOASN) GetAuditName() string {
+       return strconv.Itoa(asn.ASN)
+}
+
+func (asn *TOASN) GetType() string {
+       return "asn"
+}
+
+func (asn *TOASN) SetID(i int) {
+       asn.ID = i
+}
+
+func (asn *TOASN) Validate(db *sqlx.DB) []error {
+       errs := []error{}
+       if asn.ASN < 1 {
+               errs = append(errs, errors.New(`ASN 'asn' is required.`))
+       }
+       return errs
+}
+
+//The TOASN implementation of the Creator interface
+//all implementations of Creator should use transactions and return the proper 
errorType
+//ParsePQUniqueConstraintError is used to determine if a asn with conflicting 
values exists
+//if so, it will return an errorType of DataConflict and the type should be 
appended to the
+//generic error message returned
+//The insert sql returns the id and lastUpdated values of the newly inserted 
asn and have
+//to be added to the struct
+func (asn *TOASN) Create(db *sqlx.DB, user auth.CurrentUser) (error, 
tc.ApiErrorType) {
+       rollbackTransaction := true
+       tx, err := db.Beginx()
+       defer func() {
+               if tx == nil || !rollbackTransaction {
+                       return
+               }
+               err := tx.Rollback()
+               if err != nil {
+                       log.Errorln(errors.New("rolling back transaction: " + 
err.Error()))
+               }
+       }()
+
+       if err != nil {
+               log.Error.Printf("could not begin transaction: %v", err)
+               return tc.DBError, tc.SystemError
+       }
+       resultRows, err := tx.NamedQuery(insertQuery(), asn)
+       if err != nil {
+               if pqErr, ok := err.(*pq.Error); ok {
+                       err, eType := 
dbhelpers.ParsePQUniqueConstraintError(pqErr)
+                       if eType == tc.DataConflictError {
+                               return errors.New("a asn with " + err.Error()), 
eType
+                       }
+                       return err, eType
+               } else {
+                       log.Errorf("received non pq error: %++v from create 
execution", err)
+                       return tc.DBError, tc.SystemError
+               }
+       }
+       defer resultRows.Close()
+
+       var id int
+       var lastUpdated tc.Time
+       rowsAffected := 0
+       for resultRows.Next() {
+               rowsAffected++
+               if err := resultRows.Scan(&id, &lastUpdated); err != nil {
+                       log.Error.Printf("could not scan id from insert: %s\n", 
err)
+                       return tc.DBError, tc.SystemError
+               }
+       }
+       if rowsAffected == 0 {
+               err = errors.New("no asn was inserted, no id was returned")
+               log.Errorln(err)
+               return tc.DBError, tc.SystemError
+       } else if rowsAffected > 1 {
+               err = errors.New("too many ids returned from asn insert")
+               log.Errorln(err)
+               return tc.DBError, tc.SystemError
+       }
+       asn.SetID(id)
+       asn.LastUpdated = lastUpdated
+       err = tx.Commit()
+       if err != nil {
+               log.Errorln("Could not commit transaction: ", err)
+               return tc.DBError, tc.SystemError
+       }
+       rollbackTransaction = false
+       return nil, tc.NoError
+}
+
+func (asn *TOASN) Read(db *sqlx.DB, parameters map[string]string, user 
auth.CurrentUser) ([]interface{}, []error, tc.ApiErrorType) {
+       var rows *sqlx.Rows
+
+       // Query Parameters to Database Query column mappings
+       // see the fields mapped in the SQL query
+       queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{
+               "domainName":    dbhelpers.WhereColumnInfo{"domain_name", nil},
+               "dnssecEnabled": dbhelpers.WhereColumnInfo{"dnssec_enabled", 
nil},
+               "id":            dbhelpers.WhereColumnInfo{"id", api.IsInt},
+               "name":          dbhelpers.WhereColumnInfo{"name", nil},
+       }
+       where, orderBy, queryValues, errs := 
dbhelpers.BuildWhereAndOrderBy(parameters, queryParamsToQueryCols)
+       if len(errs) > 0 {
+               return nil, errs, tc.DataConflictError
+       }
+
+       query := selectQuery() + where + orderBy
+       log.Debugln("Query is ", query)
+
+       rows, err := db.NamedQuery(query, queryValues)
+       if err != nil {
+               log.Errorf("Error querying ASNs: %v", err)
+               return nil, []error{tc.DBError}, tc.SystemError
+       }
+       defer rows.Close()
+
+       ASNs := []interface{}{}
+       for rows.Next() {
+               var s tc.ASN
+               if err = rows.StructScan(&s); err != nil {
+                       log.Errorf("error parsing ASN rows: %v", err)
+                       return nil, []error{tc.DBError}, tc.SystemError
+               }
+               ASNs = append(ASNs, s)
+       }
+
+       return ASNs, []error{}, tc.NoError
+}
+
+func selectQuery() string {
+       query := `SELECT
+id,
+asn,
+last_updated,
+cachegroup
+
+FROM asn a`
+       return query
+}
+
+//The TOASN implementation of the Updater interface
+//all implementations of Updater should use transactions and return the proper 
errorType
+//ParsePQUniqueConstraintError is used to determine if a asn with conflicting 
values exists
+//if so, it will return an errorType of DataConflict and the type should be 
appended to the
+//generic error message returned
+func (asn *TOASN) Update(db *sqlx.DB, user auth.CurrentUser) (error, 
tc.ApiErrorType) {
+       rollbackTransaction := true
+       tx, err := db.Beginx()
+       defer func() {
+               if tx == nil || !rollbackTransaction {
+                       return
+               }
+               err := tx.Rollback()
+               if err != nil {
+                       log.Errorln(errors.New("rolling back transaction: " + 
err.Error()))
+               }
+       }()
+
+       if err != nil {
+               log.Error.Printf("could not begin transaction: %v", err)
+               return tc.DBError, tc.SystemError
+       }
+       log.Debugf("about to run exec query: %s with asn: %++v", updateQuery(), 
asn)
+       resultRows, err := tx.NamedQuery(updateQuery(), asn)
+       if err != nil {
+               if pqErr, ok := err.(*pq.Error); ok {
+                       err, eType := 
dbhelpers.ParsePQUniqueConstraintError(pqErr)
+                       if eType == tc.DataConflictError {
+                               return errors.New("a asn with " + err.Error()), 
eType
+                       }
+                       return err, eType
+               } else {
+                       log.Errorf("received error: %++v from update 
execution", err)
+                       return tc.DBError, tc.SystemError
+               }
+       }
+       defer resultRows.Close()
+
+       var lastUpdated tc.Time
+       rowsAffected := 0
+       for resultRows.Next() {
+               rowsAffected++
+               if err := resultRows.Scan(&lastUpdated); err != nil {
+                       log.Error.Printf("could not scan lastUpdated from 
insert: %s\n", err)
+                       return tc.DBError, tc.SystemError
+               }
+       }
+       log.Debugf("lastUpdated: %++v", lastUpdated)
+       asn.LastUpdated = lastUpdated
+       if rowsAffected != 1 {
+               if rowsAffected < 1 {
+                       return errors.New("no asn found with this id"), 
tc.DataMissingError
+               } else {
+                       return fmt.Errorf("this update affected too many rows: 
%d", rowsAffected), tc.SystemError
+               }
+       }
+       err = tx.Commit()
+       if err != nil {
+               log.Errorln("Could not commit transaction: ", err)
+               return tc.DBError, tc.SystemError
+       }
+       rollbackTransaction = false
+       return nil, tc.NoError
+}
+
+//The ASN implementation of the Deleter interface
+//all implementations of Deleter should use transactions and return the proper 
errorType
+func (asn *TOASN) Delete(db *sqlx.DB, user auth.CurrentUser) (error, 
tc.ApiErrorType) {
+       rollbackTransaction := true
+       tx, err := db.Beginx()
+       defer func() {
+               if tx == nil || !rollbackTransaction {
+                       return
+               }
+               err := tx.Rollback()
+               if err != nil {
+                       log.Errorln(errors.New("rolling back transaction: " + 
err.Error()))
+               }
+       }()
+
+       if err != nil {
+               log.Error.Printf("could not begin transaction: %v", err)
+               return tc.DBError, tc.SystemError
+       }
+       log.Debugf("about to run exec query: %s with asn: %++v", deleteQuery(), 
asn)
+       result, err := tx.NamedExec(deleteQuery(), asn)
+       if err != nil {
+               log.Errorf("received error: %++v from delete execution", err)
+               return tc.DBError, tc.SystemError
+       }
+       rowsAffected, err := result.RowsAffected()
+       if err != nil {
+               return tc.DBError, tc.SystemError
+       }
+       if rowsAffected != 1 {
+               if rowsAffected < 1 {
+                       return errors.New("no asn with that id found"), 
tc.DataMissingError
+               } else {
+                       return fmt.Errorf("this create affected too many rows: 
%d", rowsAffected), tc.SystemError
+               }
+       }
+       err = tx.Commit()
+       if err != nil {
+               log.Errorln("Could not commit transaction: ", err)
+               return tc.DBError, tc.SystemError
+       }
+       rollbackTransaction = false
+       return nil, tc.NoError
+}
+
+func insertQuery() string {
+       query := `INSERT INTO asn (
+asn,
+cachegroup) 
+VALUES (
+:asn,
+:cachegroup) RETURNING id,last_updated`
+       return query
+}
+
+func updateQuery() string {
+       query := `UPDATE
+asn SET
+asn=:asn,
+cachegroup=:cachegroup,
+WHERE id=:id RETURNING last_updated`
+       return query
+}
+
+func deleteQuery() string {
+       query := `DELETE FROM asn
+WHERE id=:id`
+       return query
+}
diff --git a/traffic_ops/traffic_ops_golang/asns_test.go 
b/traffic_ops/traffic_ops_golang/asn/asns_test.go
similarity index 99%
rename from traffic_ops/traffic_ops_golang/asns_test.go
rename to traffic_ops/traffic_ops_golang/asn/asns_test.go
index 64101c0..6501a72 100644
--- a/traffic_ops/traffic_ops_golang/asns_test.go
+++ b/traffic_ops/traffic_ops_golang/asn/asns_test.go
@@ -1,4 +1,4 @@
-package main
+package asn
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
diff --git a/traffic_ops/traffic_ops_golang/asns.go 
b/traffic_ops/traffic_ops_golang/asns.go
deleted file mode 100644
index 86a2fa7..0000000
--- a/traffic_ops/traffic_ops_golang/asns.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package main
-
-/*
- * 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 (
-       "encoding/json"
-       "fmt"
-       "net/http"
-
-       "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/dbhelpers"
-       "github.com/jmoiron/sqlx"
-)
-
-// ASNsPrivLevel ...
-const ASNsPrivLevel = 10
-
-// ASNsHandler ...
-func ASNsHandler(db *sqlx.DB) http.HandlerFunc {
-       return func(w http.ResponseWriter, r *http.Request) {
-               handleErrs := tc.GetHandleErrorsFunc(w, r)
-
-               params, err := api.GetCombinedParams(r)
-               if err != nil {
-                       log.Errorf("unable to get parameters from request: %s", 
err)
-                       handleErrs(http.StatusInternalServerError, err)
-               }
-
-               resp, errs, errType := getASNsResponse(params, db)
-               if len(errs) > 0 {
-                       tc.HandleErrorsWithType(errs, errType, handleErrs)
-                       return
-               }
-
-               respBts, err := json.Marshal(resp)
-               if err != nil {
-                       handleErrs(http.StatusInternalServerError, err)
-                       return
-               }
-
-               w.Header().Set("Content-Type", "application/json")
-               fmt.Fprintf(w, "%s", respBts)
-       }
-}
-
-func getASNsResponse(parameters map[string]string, db *sqlx.DB) 
(*tc.ASNsResponse, []error, tc.ApiErrorType) {
-       asns, errs, errType := getASNs(parameters, db)
-       if len(errs) > 0 {
-               return nil, errs, errType
-       }
-
-       resp := tc.ASNsResponse{
-               Response: asns,
-       }
-       return &resp, nil, tc.NoError
-}
-
-func getASNs(parameters map[string]string, db *sqlx.DB) ([]tc.ASN, []error, 
tc.ApiErrorType) {
-       var rows *sqlx.Rows
-       var err error
-
-       // Query Parameters to Database Query column mappings
-       // see the fields mapped in the SQL query
-       queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{
-               "asn":        dbhelpers.WhereColumnInfo{"a.asn", api.IsInt},
-               "id":         dbhelpers.WhereColumnInfo{"a.id", api.IsInt},
-               "cachegroup": dbhelpers.WhereColumnInfo{"cg.id", api.IsInt},
-       }
-
-       where, orderBy, queryValues, errs := 
dbhelpers.BuildWhereAndOrderBy(parameters, queryParamsToQueryCols)
-       if len(errs) > 0 {
-               return nil, errs, tc.DataConflictError
-       }
-       query := selectASNsQuery() + where + orderBy
-       log.Debugln("Query is ", query)
-
-       rows, err = db.NamedQuery(query, queryValues)
-       if err != nil {
-               return nil, []error{err}, tc.SystemError
-       }
-       defer rows.Close()
-
-       ASNs := []tc.ASN{}
-       for rows.Next() {
-               var s tc.ASN
-               if err = rows.StructScan(&s); err != nil {
-                       return nil, []error{fmt.Errorf("getting ASNs: %v", 
err)}, tc.SystemError
-               }
-               ASNs = append(ASNs, s)
-       }
-       return ASNs, nil, tc.NoError
-}
-
-func selectASNsQuery() string {
-
-       query := `SELECT
-a.asn,
-cg.name as cachegroup,
-a.cachegroup as cachegroup_id,
-a.id,
-a.last_updated
-
-FROM asn a
-JOIN cachegroup cg ON cg.id = a.cachegroup`
-       return query
-}
diff --git a/traffic_ops/traffic_ops_golang/routes.go 
b/traffic_ops/traffic_ops_golang/routes.go
index 8da3ce0..58f2a54 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -30,6 +30,7 @@ import (
 
        tclog "github.com/apache/incubator-trafficcontrol/lib/go-log"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/api"
+       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/asn"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/auth"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/cdn"
        dsrequest 
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/request"
@@ -55,7 +56,12 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
 
        routes := []Route{
                //ASNs
-               {1.2, http.MethodGet, `asns/?(\.json)?$`, ASNsHandler(d.DB), 
ASNsPrivLevel, Authenticated, nil},
+               {1.3, http.MethodGet, `asns/?(\.json)?$`, 
api.ReadHandler(asn.GetRefType(), d.DB), auth.PrivLevelReadOnly, Authenticated, 
nil},
+               {1.3, http.MethodGet, `asns/{id}$`, 
api.ReadHandler(asn.GetRefType(), d.DB), auth.PrivLevelReadOnly, Authenticated, 
nil},
+               {1.3, http.MethodPut, `asns/{id}$`, 
api.UpdateHandler(asn.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
+               {1.3, http.MethodPost, `asns/?$`, 
api.CreateHandler(asn.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
+               {1.3, http.MethodDelete, `asns/{id}$`, 
api.DeleteHandler(asn.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
+
                //CDNs
                // explicitly passed to legacy system until fully implemented.  
Auth handled by legacy system.
                {1.2, http.MethodGet, `cdns/capacity$`, 
handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},

-- 
To stop receiving notification emails like this one, please contact
dang...@apache.org.

Reply via email to