rob05c commented on a change in pull request #2124: Add TO Go GET deliveryservices routes URL: https://github.com/apache/incubator-trafficcontrol/pull/2124#discussion_r181101662
########## File path: traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go ########## @@ -0,0 +1,272 @@ +package deliveryservice + +import ( + "errors" + "fmt" + + "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/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tenant" + + "github.com/jmoiron/sqlx" + "github.com/lib/pq" +) + +//we need a type alias to define functions on +type TODeliveryServiceV13 tc.DeliveryServiceNullableV13 + +//the refType is passed into the handlers where a copy of its type is used to decode the json. +var refTypeV13 = TODeliveryServiceV13{} + +func GetRefTypeV13() *TODeliveryServiceV13 { + return &refTypeV13 +} + +func (ds TODeliveryServiceV13) GetKeyFieldsInfo() []api.KeyFieldInfo { + return TODeliveryServiceV12(ds.DeliveryServiceNullableV12).GetKeyFieldsInfo() +} + +//Implementation of the Identifier, Validator interface functions +func (ds TODeliveryServiceV13) GetKeys() (map[string]interface{}, bool) { + v12 := TODeliveryServiceV12(ds.DeliveryServiceNullableV12) + return v12.GetKeys() +} + +func (ds *TODeliveryServiceV13) SetKeys(keys map[string]interface{}) { + v12 := TODeliveryServiceV12(ds.DeliveryServiceNullableV12) + v12.SetKeys(keys) +} + +func (ds *TODeliveryServiceV13) GetAuditName() string { + v12 := TODeliveryServiceV12(ds.DeliveryServiceNullableV12) + return v12.GetAuditName() +} + +func (ds *TODeliveryServiceV13) GetType() string { + v12 := TODeliveryServiceV12(ds.DeliveryServiceNullableV12) + return v12.GetType() +} + +func ValidateV13(db *sqlx.DB, ds *tc.DeliveryServiceNullableV13) []error { + if ds == nil { + return []error{} + } + tods := TODeliveryServiceV13(*ds) + return tods.Validate(db) +} + +func (ds *TODeliveryServiceV13) Validate(db *sqlx.DB) []error { + v12 := TODeliveryServiceV12(ds.DeliveryServiceNullableV12) + return v12.Validate(db) +} + +// Create implements the Creator interface. +//all implementations of Creator should use transactions and return the proper errorType +//ParsePQUniqueConstraintError is used to determine if a ds 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 ds and have +//to be added to the struct +func (ds *TODeliveryServiceV13) Create(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) { + tx, err := db.Beginx() + defer func() { + if tx == nil { + return + } + if err != nil { + tx.Rollback() + return + } + tx.Commit() + }() + + if err != nil { + log.Error.Printf("could not begin transaction: %v", err) + return tc.DBError, tc.SystemError + } + fmt.Printf("ds ---> %v\n", ds) + resultRows, err := tx.NamedQuery(insertDSQuery(), ds) + if err != nil { + if pqerr, ok := err.(*pq.Error); ok { + err, eType := dbhelpers.ParsePQUniqueConstraintError(pqerr) + return errors.New("a delivery service with " + err.Error()), eType + } + log.Errorf("received non pq error: %++v from create execution", err) + return tc.DBError, tc.SystemError + } + var id int + var lastUpdated tc.TimeNoMod + 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 delivery service 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 delivery service insert") + log.Errorln(err) + return tc.DBError, tc.SystemError + } + ds.SetKeys(map[string]interface{}{"id": id}) + ds.LastUpdated = &lastUpdated + return nil, tc.NoError +} + +func (ds *TODeliveryServiceV13) Read(db *sqlx.DB, params map[string]string, user auth.CurrentUser) ([]interface{}, []error, tc.ApiErrorType) { + returnable := []interface{}{} + dses, errs, errType := readGetDeliveryServices(params, db, user.PrivLevel) + if len(errs) > 0 { + for _, err := range errs { + if err.Error() == `id cannot parse to integer` { + return nil, []error{errors.New("Resource not found.")}, tc.DataMissingError //matches perl response + } + } + return nil, errs, errType + } + + for _, ds := range dses { + returnable = append(returnable, ds) + } + log.Debugln("TODeliveryServiceV13.Read returning") + return returnable, nil, tc.NoError +} + +//The TODeliveryService implementation of the Updater interface +//all implementations of Updater should use transactions and return the proper errorType +//ParsePQUniqueConstraintError is used to determine if a delivery service 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 (ds *TODeliveryServiceV13) Update(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) { + tx, err := db.Beginx() + defer func() { + if tx == nil { + return + } + if err != nil { + tx.Rollback() + return + } + tx.Commit() + }() + + 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 ds: %++v", updateDSQuery(), ds) + resultRows, err := tx.NamedQuery(updateDSQuery(), ds) + if err != nil { + if err, ok := err.(*pq.Error); ok { + err, eType := dbhelpers.ParsePQUniqueConstraintError(err) + if eType == tc.DataConflictError { + return errors.New("a delivery service with " + err.Error()), eType + } + return err, eType + } + log.Errorf("received error: %++v from update execution", err) + return tc.DBError, tc.SystemError + } + var lastUpdated tc.TimeNoMod + 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) + ds.LastUpdated = &lastUpdated + if rowsAffected != 1 { + if rowsAffected < 1 { + return errors.New("no delivery service found with this id"), tc.DataMissingError + } + return fmt.Errorf("this update affected too many rows: %d", rowsAffected), tc.SystemError + } + return nil, tc.NoError +} + +//The DeliveryService implementation of the Deleter interface +//all implementations of Deleter should use transactions and return the proper errorType +func (ds *TODeliveryServiceV13) Delete(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) { + tx, err := db.Beginx() + defer func() { + if tx == nil { + return + } + if err != nil { + tx.Rollback() + return + } + tx.Commit() + }() + + 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 Delivery Service: %++v", deleteDSQuery(), ds) + result, err := tx.NamedExec(deleteDSQuery(), ds) + 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 delivery service with that id found"), tc.DataMissingError + } + return fmt.Errorf("this create affected too many rows: %d", rowsAffected), tc.SystemError + } + return nil, tc.NoError +} + +// IsTenantAuthorized implements the Tenantable interface to ensure the user is authorized on the deliveryservice tenant +func (ds *TODeliveryServiceV13) IsTenantAuthorized(user auth.CurrentUser, db *sqlx.DB) (bool, error) { + if ds.TenantID == nil { + log.Debugf("tenantID is nil") + return false, errors.New("tenantID is nil") + } + return tenant.IsResourceAuthorizedToUser(*ds.TenantID, user, db) +} + +//TODO: drichardson - plumb these out! Review comment: Done. I didn't change that code, it was moved from `deliveryservices.go`. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services