ocket8888 commented on a change in pull request #4015: Rewrite /federations to
Go - POST/PUT/DELETE
URL: https://github.com/apache/trafficcontrol/pull/4015#discussion_r339835857
##########
File path: traffic_ops/traffic_ops_golang/federations/federations.go
##########
@@ -167,3 +206,296 @@ ORDER BY
}
return feds, nil
}
+
+// AddFederationResorverMappingsForCurrentUser is the handler for a POST
request to /federations.
+// Confusingly, it does not create a federation, but is instead used to
manipulate the resolvers
+// used by one or more particular Delivery Services for one or more particular
Federations.
+func AddFederationResolverMappingsForCurrentUser(w http.ResponseWriter, r
*http.Request) {
+ inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+ tx := inf.Tx.Tx
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+ return
+ }
+ defer inf.Close()
+
+ mappings, userErr, sysErr := getMappingsFromRequestBody(*inf.Version,
r.Body)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, tx, http.StatusBadRequest, userErr, sysErr)
+ return
+ }
+
+ if err := mappings.Validate(tx); err != nil {
+ errCode = http.StatusBadRequest
+ userErr = fmt.Errorf("validating request: %v", err)
+ api.HandleErr(w, r, tx, errCode, userErr, nil)
+ return
+ }
+
+ userErr, sysErr, errCode =
addFederationResolverMappingsForCurrentUser(inf.User, tx, mappings)
+ if userErr != nil || sysErr != nil {
+ api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+ return
+ }
+
+ msg := fmt.Sprintf("%s successfully created federation resolvers.",
inf.User.UserName)
+ if inf.Version.Minor <= 3 {
+ api.WriteResp(w, r, msg)
+ } else {
+ api.WriteRespAlertObj(w, r, tc.SuccessLevel, msg, msg)
+ }
+}
+
+// handles the main logic of the POST handler, separated out for convenience
+func addFederationResolverMappingsForCurrentUser(u *auth.CurrentUser, tx
*sql.Tx, mappings []tc.DeliveryServiceFederationResolverMapping) (error, error,
int) {
+ for _, fed := range mappings {
+ dsTenant, ok, err := dbhelpers.GetDSTenantIDFromXMLID(tx,
fed.DeliveryService)
+ if err != nil {
+ return nil, err, http.StatusInternalServerError
+ } else if !ok {
+ return fmt.Errorf("'%s' - no such Delivery Service",
fed.DeliveryService), nil, http.StatusConflict
+ }
+
+ if ok, err = tenant.IsResourceAuthorizedToUserTx(dsTenant, u,
tx); err != nil {
+ err = fmt.Errorf("Checking user #%d tenancy permissions
on DS '%s' (tenant #%d)", u.ID, fed.DeliveryService, dsTenant)
+ return nil, err, http.StatusInternalServerError
+ } else if !ok {
+ userErr := fmt.Errorf("'%s' - no such Delivery
Service", fed.DeliveryService)
+ sysErr := fmt.Errorf("User '%s' requested unauthorized
federation resolver mapping modification on the '%s' Delivery Service",
u.UserName, fed.DeliveryService)
+ return userErr, sysErr, http.StatusConflict
+ }
+
+ fedID, ok, err := dbhelpers.GetFederationIDForUserIDByXMLID(tx,
u.ID, fed.DeliveryService)
+ if err != nil {
+ return nil, fmt.Errorf("Getting Federation ID: %v",
err), http.StatusInternalServerError
+ } else if !ok {
+ err = fmt.Errorf("No federation(s) found for user %s on
delivery service '%s'.", u.UserName, fed.DeliveryService)
+ return err, nil, http.StatusConflict
+ }
+
+ inserted, err :=
addFederationResolverMappingsToFederation(fed.Mappings, fed.DeliveryService,
fedID, tx)
+ if err != nil {
+ err = fmt.Errorf("Adding federation resolver mapping(s)
to federation: %v", err)
+ return nil, err, http.StatusInternalServerError
+ }
+
+ changelogMsg := "FEDERATION DELIVERY SERVICE: %s, ID: %d,
ACTION: User %s successfully added federation resolvers [ %s ]"
+ changelogMsg = fmt.Sprintf(changelogMsg, fed.DeliveryService,
fedID, u.UserName, inserted)
+ api.CreateChangeLogRawTx(api.ApiChange, changelogMsg, u, tx)
+ }
+ return nil, nil, http.StatusOK
+}
+
+// adds federation resolver mappings for a particular delivery service to a
given federation, creating said resolvers if
+// they don't already exist.
+func addFederationResolverMappingsToFederation(res tc.ResolverMapping, xmlid
string, fed uint, tx *sql.Tx) (string, error) {
+ var resp string
+ if len(res.Resolve4) > 0 {
+ inserted, err := addFederationResolver(res.Resolve4,
tc.FederationResolverType4, fed, tx)
+ if err != nil {
+ return "", err
+ }
+ resp = strings.Join(inserted, ", ")
+ }
+ if len(res.Resolve6) > 0 {
+ inserted, err := addFederationResolver(res.Resolve6,
tc.FederationResolverType6, fed, tx)
+ if err != nil {
+ return "", err
+ }
+ resp += strings.Join(inserted, ", ")
+ }
+ return resp, nil
+}
+
+// adds federation resolvers of a specific type to the given federation
+func addFederationResolver(res []string, t tc.FederationResolverType, fedID
uint, tx *sql.Tx) ([]string, error) {
+ inserted := []string{}
+ for _, r := range res {
+ var ip string
+ var id uint
+ if err := tx.QueryRow(insertResolverQuery, r, t).Scan(&ip,
&id); err != nil && err != sql.ErrNoRows {
+ return nil, err
+ }
+ if ip != "" && id > 0 {
Review comment:
Yep, those are the zero values of those two variables. The `ON CONFLICT DO
NOTHING` means that rows that already exist aren't inserted, and thus return
nothing. For whatever reason that's not a scan error and just leaves the
variables unchanged. AFAIK there's no db restriction on the ip string length,
but an ID can't be zero because the series generators explicitly start at one.
So an ip could be blank (which means something very odd happened but ostensibly
nothing changed) or the id could be zero, either of which means that nothing
changed.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services