You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ra...@apache.org on 2018/10/04 14:39:32 UTC

[trafficcontrol] branch master updated (2845557 -> 049b85f)

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

rawlin pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git.


    from 2845557  upgrade setuptools prior to installing sphinx
     new 0e997f5  Add TO Go federations?all for internal fed route
     new 37813d1  Add TO Go GET federations
     new d24b91a  Add TO Go POST federations/id/deliveryservices
     new 7594b37  Add TO Go federations tests
     new 7b1aa70  Fix TO Go fed/id/ds priv to admin, to match Perl
     new a607a55  Change TO Go fed/all to priv admin, matching Perl
     new 1e23a16  Fix TO Go missing inf.Close()
     new 24d374a  Change TO Go feds func to take name not user
     new 84257c8  Fix TO Go feds to prevent assigning 0 dses
     new 049b85f  Fix TO Go /federations PrivLevelFed to match Perl

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 lib/go-tc/enum.go                                  |  30 ++++
 lib/go-tc/federation.go                            |  41 +++++
 traffic_ops/client/federation.go                   |  80 ++++++++++
 traffic_ops/testing/api/v14/cdnfederations_test.go |   1 +
 traffic_ops/testing/api/v14/federations_test.go    | 126 +++++++++++++++
 .../federations/allfederations.go                  | 132 ++++++++++++++++
 traffic_ops/traffic_ops_golang/federations/ds.go   |  87 +++++++++++
 .../traffic_ops_golang/federations/federations.go  | 169 +++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routes.go           |   6 +
 9 files changed, 672 insertions(+)
 create mode 100644 traffic_ops/client/federation.go
 create mode 100644 traffic_ops/testing/api/v14/federations_test.go
 create mode 100644 traffic_ops/traffic_ops_golang/federations/allfederations.go
 create mode 100644 traffic_ops/traffic_ops_golang/federations/ds.go
 create mode 100644 traffic_ops/traffic_ops_golang/federations/federations.go


[trafficcontrol] 09/10: Fix TO Go feds to prevent assigning 0 dses

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 84257c800c0979fba753d0c465ef32f690d70302
Author: Robert Butts <ro...@apache.org>
AuthorDate: Mon Oct 1 21:16:43 2018 -0600

    Fix TO Go feds to prevent assigning 0 dses
    
    Emulates Perl behavior.
---
 .../testing/api/{v13 => v14}/federations_test.go    | 21 +--------------------
 traffic_ops/traffic_ops_golang/federations/ds.go    |  4 ++++
 2 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/traffic_ops/testing/api/v13/federations_test.go b/traffic_ops/testing/api/v14/federations_test.go
similarity index 82%
rename from traffic_ops/testing/api/v13/federations_test.go
rename to traffic_ops/testing/api/v14/federations_test.go
index 1473f27..02cd4ee 100644
--- a/traffic_ops/testing/api/v13/federations_test.go
+++ b/traffic_ops/testing/api/v14/federations_test.go
@@ -1,4 +1,4 @@
-package v13
+package v14
 
 /*
 
@@ -33,12 +33,9 @@ func TestFederations(t *testing.T) {
 	CreateTestDeliveryServices(t)
 	CreateTestUsersDeliveryServices(t)
 	CreateTestCDNFederations(t)
-	// UpdateTestCDNFederations(t)
-	// GetTestCDNFederations(t)
 
 	PostTestFederationsDeliveryServices(t)
 	GetTestFederations(t)
-	DeleteTestFederationsDeliveryServices(t)
 
 	DeleteTestCDNFederations(t)
 	DeleteTestUsersDeliveryServices(t)
@@ -127,19 +124,3 @@ func PostTestFederationsDeliveryServices(t *testing.T) {
 	}
 	log.Debugln("PostTestFederationsDeliveryServices PASSED")
 }
-
-func DeleteTestFederationsDeliveryServices(t *testing.T) {
-	log.Debugln("DeleteTestFederationsDeliveryServices")
-	// doesn't actually call a DELETE method; this exists primarily to clean up PostTestFederationsDeliveryServices
-
-	if len(fedIDs) == 0 {
-		t.Fatalf("no federations, must have at least 1 federation to test federations deliveryservices\n")
-	}
-	fedID := fedIDs[0]
-
-	_, err := TOSession.CreateFederationDeliveryServices(fedID, nil, true)
-	if err != nil {
-		t.Fatalf("creating (deleting) federations delivery services: %v\n", err)
-	}
-	log.Debugln("DeleteTestFederationsDeliveryServices PASSED")
-}
diff --git a/traffic_ops/traffic_ops_golang/federations/ds.go b/traffic_ops/traffic_ops_golang/federations/ds.go
index 7ab0628..ba4742f 100644
--- a/traffic_ops/traffic_ops_golang/federations/ds.go
+++ b/traffic_ops/traffic_ops_golang/federations/ds.go
@@ -48,6 +48,10 @@ func PostDSes(w http.ResponseWriter, r *http.Request) {
 	}
 
 	if post.Replace != nil && *post.Replace {
+		if len(post.DSIDs) < 1 {
+			api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("A federation must have at least one delivery service assigned"), nil)
+			return
+		}
 		if err := deleteDSFeds(inf.Tx.Tx, fedID); err != nil {
 			userErr, sysErr, errCode := api.ParseDBError(err)
 			api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)


[trafficcontrol] 07/10: Fix TO Go missing inf.Close()

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1e23a16e747430ff0e8d9797e6db460dde69d4dd
Author: Robert Butts <ro...@apache.org>
AuthorDate: Mon Oct 1 21:04:25 2018 -0600

    Fix TO Go missing inf.Close()
---
 traffic_ops/traffic_ops_golang/federations/allfederations.go | 1 +
 traffic_ops/traffic_ops_golang/federations/federations.go    | 1 +
 2 files changed, 2 insertions(+)

diff --git a/traffic_ops/traffic_ops_golang/federations/allfederations.go b/traffic_ops/traffic_ops_golang/federations/allfederations.go
index 04d15ba..109464e 100644
--- a/traffic_ops/traffic_ops_golang/federations/allfederations.go
+++ b/traffic_ops/traffic_ops_golang/federations/allfederations.go
@@ -34,6 +34,7 @@ func GetAll(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
 		return
 	}
+	defer inf.Close()
 
 	feds := []FedInfo{}
 	err := error(nil)
diff --git a/traffic_ops/traffic_ops_golang/federations/federations.go b/traffic_ops/traffic_ops_golang/federations/federations.go
index 29c9a60..7c984f6 100644
--- a/traffic_ops/traffic_ops_golang/federations/federations.go
+++ b/traffic_ops/traffic_ops_golang/federations/federations.go
@@ -39,6 +39,7 @@ func Get(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
 		return
 	}
+	defer inf.Close()
 
 	feds, err := getUserFederations(inf.Tx.Tx, inf.User)
 	if err != nil {


[trafficcontrol] 02/10: Add TO Go GET federations

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 37813d1d808cfd1bf6a860790110550a5cc2c1a2
Author: Robert Butts <ro...@apache.org>
AuthorDate: Thu Sep 20 08:34:36 2018 -0600

    Add TO Go GET federations
---
 .../federations/allfederations.go                  | 131 +++++++++++++++++++++
 .../traffic_ops_golang/federations/federations.go  | 121 ++++---------------
 traffic_ops/traffic_ops_golang/routes.go           |   3 +-
 3 files changed, 153 insertions(+), 102 deletions(-)

diff --git a/traffic_ops/traffic_ops_golang/federations/allfederations.go b/traffic_ops/traffic_ops_golang/federations/allfederations.go
new file mode 100644
index 0000000..04d15ba
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/federations/allfederations.go
@@ -0,0 +1,131 @@
+package federations
+
+/*
+ * 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"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+)
+
+func GetAll(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+		return
+	}
+
+	feds := []FedInfo{}
+	err := error(nil)
+	allFederations := []tc.IAllFederation{}
+
+	if cdnParam, ok := inf.Params["cdnName"]; ok {
+		cdnName := tc.CDNName(cdnParam)
+		feds, err = getAllFederationsForCDN(inf.Tx.Tx, cdnName)
+		if err != nil {
+			api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations: "+err.Error()))
+			return
+		}
+		allFederations = append(allFederations, tc.AllFederationCDN{CDNName: &cdnName})
+	} else {
+		feds, err = getAllFederations(inf.Tx.Tx)
+		if err != nil {
+			api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations by CDN: "+err.Error()))
+			return
+		}
+	}
+
+	fedsResolvers, err := getFederationResolvers(inf.Tx.Tx, fedInfoIDs(feds))
+	if err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.Get getting federations resolvers: "+err.Error()))
+		return
+	}
+	allFederations = addResolvers(allFederations, feds, fedsResolvers)
+
+	api.WriteResp(w, r, allFederations)
+}
+
+func getAllFederations(tx *sql.Tx) ([]FedInfo, error) {
+	qry := `
+SELECT
+  fds.federation,
+  fd.ttl,
+  fd.cname,
+  ds.xml_id
+FROM
+  federation_deliveryservice fds
+  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
+  JOIN federation fd ON fd.id = fds.federation
+ORDER BY
+  ds.xml_id
+`
+	rows, err := tx.Query(qry)
+	if err != nil {
+		return nil, errors.New("all federations querying: " + err.Error())
+	}
+	defer rows.Close()
+
+	feds := []FedInfo{}
+	for rows.Next() {
+		f := FedInfo{}
+		if err := rows.Scan(&f.ID, &f.TTL, &f.CName, &f.DS); err != nil {
+			return nil, errors.New("all federations scanning: " + err.Error())
+		}
+		feds = append(feds, f)
+	}
+	return feds, nil
+}
+
+func getAllFederationsForCDN(tx *sql.Tx, cdn tc.CDNName) ([]FedInfo, error) {
+	qry := `
+SELECT
+  fds.federation,
+  fd.ttl,
+  fd.cname,
+  ds.xml_id
+FROM
+  federation_deliveryservice fds
+  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
+  JOIN federation fd ON fd.id = fds.federation
+  JOIN cdn on cdn.id = ds.cdn_id
+WHERE
+  cdn.name = $1
+ORDER BY
+  ds.xml_id
+`
+	rows, err := tx.Query(qry, cdn)
+	if err != nil {
+		return nil, errors.New("all federations for cdn querying: " + err.Error())
+	}
+	defer rows.Close()
+
+	feds := []FedInfo{}
+	for rows.Next() {
+		f := FedInfo{}
+		if err := rows.Scan(&f.ID, &f.TTL, &f.CName, &f.DS); err != nil {
+			return nil, errors.New("all federations for cdn scanning: " + err.Error())
+		}
+		feds = append(feds, f)
+	}
+	return feds, nil
+}
diff --git a/traffic_ops/traffic_ops_golang/federations/federations.go b/traffic_ops/traffic_ops_golang/federations/federations.go
index 1d8051b..048c432 100644
--- a/traffic_ops/traffic_ops_golang/federations/federations.go
+++ b/traffic_ops/traffic_ops_golang/federations/federations.go
@@ -28,6 +28,8 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
+
 	"github.com/lib/pq"
 )
 
@@ -37,57 +39,23 @@ func Get(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
 		return
 	}
-	defer inf.Close()
-
-	if _, ok := inf.Params["all"]; ok {
-		GetAll(w, r, inf)
-		return
-	}
-
-	// TODO implement
-	api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotImplemented, nil, nil)
-}
-
-func GetAll(w http.ResponseWriter, r *http.Request, inf *api.APIInfo) {
-	// TODO handle cdnName param
-
-	// if cdnName, ok := inf.Params["cdnName"]; ok {
-	// 	feds, err = getAllFederationsByCDN(inf.Tx.Tx, tc.CDNName(cdnName))
-	// 	if err != nil {
-	// 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting: "+err.Error()))
-	// 		return
-	// 	}
-	// 	api.WriteResp(w, r, feds)
-	// 	return
-	// }
-
-	feds := []FedInfo{}
-	err := error(nil)
 
 	allFederations := []tc.IAllFederation{}
-
-	if cdnParam, ok := inf.Params["cdnName"]; ok {
-		cdnName := tc.CDNName(cdnParam)
-		feds, err = getAllFederationsForCDN(inf.Tx.Tx, cdnName)
-		if err != nil {
-			api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations: "+err.Error()))
-			return
-		}
-		allFederations = append(allFederations, tc.AllFederationCDN{CDNName: &cdnName})
-	} else {
-		feds, err = getAllFederations(inf.Tx.Tx)
-		if err != nil {
-			api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations by CDN: "+err.Error()))
-			return
-		}
+	feds, err := getUserFederations(inf.Tx.Tx, inf.User)
+	if err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.Get getting federations: "+err.Error()))
+		return
 	}
-
 	fedsResolvers, err := getFederationResolvers(inf.Tx.Tx, fedInfoIDs(feds))
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations resolvers: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.Get getting federations resolvers: "+err.Error()))
 		return
 	}
+	allFederations = addResolvers(allFederations, feds, fedsResolvers)
+	api.WriteResp(w, r, allFederations)
+}
 
+func addResolvers(allFederations []tc.IAllFederation, feds []FedInfo, fedsResolvers map[int][]FedResolverInfo) []tc.IAllFederation {
 	dsFeds := map[tc.DeliveryServiceName][]tc.AllFederationMapping{}
 	for _, fed := range feds {
 		mapping := tc.AllFederationMapping{}
@@ -100,17 +68,16 @@ func GetAll(w http.ResponseWriter, r *http.Request, inf *api.APIInfo) {
 			case tc.FederationResolverType6:
 				mapping.Resolve6 = append(mapping.Resolve6, resolver.IP)
 			default:
-				log.Errorln("federations.GetAll got invalid resolver type, skipping")
+				log.Warnf("federations addResolvers got invalid resolver type for federation '%v', skipping\n", fed.ID)
 			}
 		}
-		log.Errorf("DEBUG GetAll appending %+v %+v %+v\n", fed.DS, *mapping.CName, *mapping.TTL)
 		dsFeds[fed.DS] = append(dsFeds[fed.DS], mapping)
 	}
 
 	for ds, mappings := range dsFeds {
 		allFederations = append(allFederations, tc.AllFederation{DeliveryService: ds, Mappings: mappings})
 	}
-	api.WriteResp(w, r, allFederations)
+	return allFederations
 }
 
 func fedInfoIDs(feds []FedInfo) []int {
@@ -167,7 +134,7 @@ WHERE
 	return feds, nil
 }
 
-func getAllFederations(tx *sql.Tx) ([]FedInfo, error) {
+func getUserFederations(tx *sql.Tx, user *auth.CurrentUser) ([]FedInfo, error) {
 	qry := `
 SELECT
   fds.federation,
@@ -178,47 +145,16 @@ FROM
   federation_deliveryservice fds
   JOIN deliveryservice ds ON ds.id = fds.deliveryservice
   JOIN federation fd ON fd.id = fds.federation
-ORDER BY
-  ds.xml_id
-`
-	rows, err := tx.Query(qry)
-	if err != nil {
-		return nil, errors.New("all federations querying: " + err.Error())
-	}
-	defer rows.Close()
-
-	feds := []FedInfo{}
-	for rows.Next() {
-		f := FedInfo{}
-		if err := rows.Scan(&f.ID, &f.TTL, &f.CName, &f.DS); err != nil {
-			return nil, errors.New("all federations scanning: " + err.Error())
-		}
-		log.Errorf("DEBUG getAllFederations got %+v\n", f)
-		feds = append(feds, f)
-	}
-	return feds, nil
-}
-
-func getAllFederationsForCDN(tx *sql.Tx, cdn tc.CDNName) ([]FedInfo, error) {
-	qry := `
-SELECT
-  fds.federation,
-  fd.ttl,
-  fd.cname,
-  ds.xml_id
-FROM
-  federation_deliveryservice fds
-  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
-  JOIN federation fd ON fd.id = fds.federation
-  JOIN cdn on cdn.id = ds.cdn_id
+  JOIN federation_tmuser fu on fu.federation = fd.id
+  JOIN tm_user u on u.id = fu.tm_user
 WHERE
-  cdn.name = $1
+  u.username = $1
 ORDER BY
   ds.xml_id
 `
-	rows, err := tx.Query(qry, cdn)
+	rows, err := tx.Query(qry, user.UserName)
 	if err != nil {
-		return nil, errors.New("all federations querying: " + err.Error())
+		return nil, errors.New("user federations querying: " + err.Error())
 	}
 	defer rows.Close()
 
@@ -226,26 +162,9 @@ ORDER BY
 	for rows.Next() {
 		f := FedInfo{}
 		if err := rows.Scan(&f.ID, &f.TTL, &f.CName, &f.DS); err != nil {
-			return nil, errors.New("all federations scanning: " + err.Error())
+			return nil, errors.New("user federations scanning: " + err.Error())
 		}
-		log.Errorf("DEBUG getAllFederations got %+v\n", f)
 		feds = append(feds, f)
 	}
 	return feds, nil
 }
-
-func federationsIDsQuery() string {
-	return `
-SELECT
-  fds.federation,
-  fds.deliveryservice
-FROM
-  federation_deliveryservice fds
-  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
-  JOIN cdn on cdn.id = ds.cdn
-WHERE
-  fds.federation = ANY($1)
-ORDER BY
-  ds.xml_id
-`
-}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index c8da4ad..dbb5368 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -364,7 +364,8 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodPut, `snapshot/{cdn}/?$`, crconfig.SnapshotHandler, auth.PrivLevelOperations, Authenticated, nil},
 
 		// Federations
-		{1.4, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
+		{1.4, http.MethodGet, `federations/all/?(\.json)?$`, federations.GetAll, auth.PrivLevelReadOnly, Authenticated, nil},
+		{1.1, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
 
 		////DeliveryServices
 		{1.3, http.MethodGet, `deliveryservices/?(\.json)?$`, api.ReadHandler(deliveryservice.GetTypeV13Factory()), auth.PrivLevelReadOnly, Authenticated, nil},


[trafficcontrol] 01/10: Add TO Go federations?all for internal fed route

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 0e997f50584f03846ce7d2b74a1b7dee5ff4181c
Author: Robert Butts <ro...@apache.org>
AuthorDate: Wed Sep 19 15:07:15 2018 -0600

    Add TO Go federations?all for internal fed route
---
 lib/go-tc/enum.go                                  |  30 +++
 lib/go-tc/federation.go                            |  28 +++
 .../traffic_ops_golang/federations/federations.go  | 251 +++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routes.go           |   4 +
 4 files changed, 313 insertions(+)

diff --git a/lib/go-tc/enum.go b/lib/go-tc/enum.go
index b5fbe9b..943104f 100644
--- a/lib/go-tc/enum.go
+++ b/lib/go-tc/enum.go
@@ -365,6 +365,36 @@ func (t SteeringType) String() string {
 	}
 }
 
+type FederationResolverType string
+
+const (
+	FederationResolverType4       = FederationResolverType("RESOLVE4")
+	FederationResolverType6       = FederationResolverType("RESOLVE6")
+	FederationResolverTypeInvalid = FederationResolverType("")
+)
+
+func (t FederationResolverType) String() string {
+	switch t {
+	case FederationResolverType4:
+		fallthrough
+	case FederationResolverType6:
+		return string(t)
+	default:
+		return "INVALID"
+	}
+}
+
+func FederationResolverTypeFromString(s string) FederationResolverType {
+	switch strings.ToLower(s) {
+	case "resolve4":
+		return FederationResolverType4
+	case "resolve6":
+		return FederationResolverType6
+	default:
+		return FederationResolverTypeInvalid
+	}
+}
+
 // DSType is the Delivery Service type.
 type DSType string
 
diff --git a/lib/go-tc/federation.go b/lib/go-tc/federation.go
index e7b1d21..3781cf9 100644
--- a/lib/go-tc/federation.go
+++ b/lib/go-tc/federation.go
@@ -62,3 +62,31 @@ type FederationMapping struct {
 	CName string `json:"cname"`
 	TTL   int    `json:"ttl"`
 }
+
+// AllFederation is the JSON object returned by /api/1.x/federations?all
+type AllFederation struct {
+	Mappings        []AllFederationMapping `json:"mappings"`
+	DeliveryService DeliveryServiceName    `json:"deliveryService"`
+}
+
+func (a AllFederation) IsAllFederations() bool { return true }
+
+// AllFederation is the JSON object returned by /api/1.x/federations?all&cdnName=my-cdn-name
+type AllFederationCDN struct {
+	CDNName *CDNName `json:"cdnName"`
+}
+
+func (a AllFederationCDN) IsAllFederations() bool { return true }
+
+type AllFederationMapping struct {
+	TTL      *int     `json:"ttl"`
+	CName    *string  `json:"cname"`
+	Resolve4 []string `json:"resolve4,omitempty"`
+	Resolve6 []string `json:"resolve6,omitempty"`
+}
+
+// IAllFederation is an interface for the disparate objects returned by /api/1.x/federations?all.
+// Adds additional safety, allowing functions to only return one of the valid object types for the endpoint.
+type IAllFederation interface {
+	IsAllFederations() bool
+}
diff --git a/traffic_ops/traffic_ops_golang/federations/federations.go b/traffic_ops/traffic_ops_golang/federations/federations.go
new file mode 100644
index 0000000..1d8051b
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/federations/federations.go
@@ -0,0 +1,251 @@
+package federations
+
+/*
+ * 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"
+
+	"github.com/apache/trafficcontrol/lib/go-log"
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/lib/go-util"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+	"github.com/lib/pq"
+)
+
+func Get(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+		return
+	}
+	defer inf.Close()
+
+	if _, ok := inf.Params["all"]; ok {
+		GetAll(w, r, inf)
+		return
+	}
+
+	// TODO implement
+	api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotImplemented, nil, nil)
+}
+
+func GetAll(w http.ResponseWriter, r *http.Request, inf *api.APIInfo) {
+	// TODO handle cdnName param
+
+	// if cdnName, ok := inf.Params["cdnName"]; ok {
+	// 	feds, err = getAllFederationsByCDN(inf.Tx.Tx, tc.CDNName(cdnName))
+	// 	if err != nil {
+	// 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting: "+err.Error()))
+	// 		return
+	// 	}
+	// 	api.WriteResp(w, r, feds)
+	// 	return
+	// }
+
+	feds := []FedInfo{}
+	err := error(nil)
+
+	allFederations := []tc.IAllFederation{}
+
+	if cdnParam, ok := inf.Params["cdnName"]; ok {
+		cdnName := tc.CDNName(cdnParam)
+		feds, err = getAllFederationsForCDN(inf.Tx.Tx, cdnName)
+		if err != nil {
+			api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations: "+err.Error()))
+			return
+		}
+		allFederations = append(allFederations, tc.AllFederationCDN{CDNName: &cdnName})
+	} else {
+		feds, err = getAllFederations(inf.Tx.Tx)
+		if err != nil {
+			api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations by CDN: "+err.Error()))
+			return
+		}
+	}
+
+	fedsResolvers, err := getFederationResolvers(inf.Tx.Tx, fedInfoIDs(feds))
+	if err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.GetAll getting all federations resolvers: "+err.Error()))
+		return
+	}
+
+	dsFeds := map[tc.DeliveryServiceName][]tc.AllFederationMapping{}
+	for _, fed := range feds {
+		mapping := tc.AllFederationMapping{}
+		mapping.TTL = util.IntPtr(fed.TTL)
+		mapping.CName = util.StrPtr(fed.CName)
+		for _, resolver := range fedsResolvers[fed.ID] {
+			switch resolver.Type {
+			case tc.FederationResolverType4:
+				mapping.Resolve4 = append(mapping.Resolve4, resolver.IP)
+			case tc.FederationResolverType6:
+				mapping.Resolve6 = append(mapping.Resolve6, resolver.IP)
+			default:
+				log.Errorln("federations.GetAll got invalid resolver type, skipping")
+			}
+		}
+		log.Errorf("DEBUG GetAll appending %+v %+v %+v\n", fed.DS, *mapping.CName, *mapping.TTL)
+		dsFeds[fed.DS] = append(dsFeds[fed.DS], mapping)
+	}
+
+	for ds, mappings := range dsFeds {
+		allFederations = append(allFederations, tc.AllFederation{DeliveryService: ds, Mappings: mappings})
+	}
+	api.WriteResp(w, r, allFederations)
+}
+
+func fedInfoIDs(feds []FedInfo) []int {
+	ids := []int{}
+	for _, fed := range feds {
+		ids = append(ids, fed.ID)
+	}
+	return ids
+}
+
+type FedInfo struct {
+	ID    int
+	TTL   int
+	CName string
+	DS    tc.DeliveryServiceName
+}
+
+type FedResolverInfo struct {
+	Type tc.FederationResolverType
+	IP   string
+}
+
+// getFederationResolvers takes a slice of federation IDs, and returns a map[federationID]info.
+func getFederationResolvers(tx *sql.Tx, fedIDs []int) (map[int][]FedResolverInfo, error) {
+	qry := `
+SELECT
+  ffr.federation,
+  frt.name as resolver_type,
+  fr.ip_address
+FROM
+  federation_federation_resolver ffr
+  JOIN federation_resolver fr ON ffr.federation_resolver = fr.id
+  JOIN type frt on fr.type = frt.id
+WHERE
+  ffr.federation = ANY($1)
+`
+	rows, err := tx.Query(qry, pq.Array(fedIDs))
+	if err != nil {
+		return nil, errors.New("all federations resolvers querying: " + err.Error())
+	}
+	defer rows.Close()
+
+	feds := map[int][]FedResolverInfo{}
+	for rows.Next() {
+		fedID := 0
+		f := FedResolverInfo{}
+		fType := ""
+		if err := rows.Scan(&fedID, &fType, &f.IP); err != nil {
+			return nil, errors.New("all federations resolvers scanning: " + err.Error())
+		}
+		f.Type = tc.FederationResolverTypeFromString(fType)
+		feds[fedID] = append(feds[fedID], f)
+	}
+	return feds, nil
+}
+
+func getAllFederations(tx *sql.Tx) ([]FedInfo, error) {
+	qry := `
+SELECT
+  fds.federation,
+  fd.ttl,
+  fd.cname,
+  ds.xml_id
+FROM
+  federation_deliveryservice fds
+  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
+  JOIN federation fd ON fd.id = fds.federation
+ORDER BY
+  ds.xml_id
+`
+	rows, err := tx.Query(qry)
+	if err != nil {
+		return nil, errors.New("all federations querying: " + err.Error())
+	}
+	defer rows.Close()
+
+	feds := []FedInfo{}
+	for rows.Next() {
+		f := FedInfo{}
+		if err := rows.Scan(&f.ID, &f.TTL, &f.CName, &f.DS); err != nil {
+			return nil, errors.New("all federations scanning: " + err.Error())
+		}
+		log.Errorf("DEBUG getAllFederations got %+v\n", f)
+		feds = append(feds, f)
+	}
+	return feds, nil
+}
+
+func getAllFederationsForCDN(tx *sql.Tx, cdn tc.CDNName) ([]FedInfo, error) {
+	qry := `
+SELECT
+  fds.federation,
+  fd.ttl,
+  fd.cname,
+  ds.xml_id
+FROM
+  federation_deliveryservice fds
+  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
+  JOIN federation fd ON fd.id = fds.federation
+  JOIN cdn on cdn.id = ds.cdn_id
+WHERE
+  cdn.name = $1
+ORDER BY
+  ds.xml_id
+`
+	rows, err := tx.Query(qry, cdn)
+	if err != nil {
+		return nil, errors.New("all federations querying: " + err.Error())
+	}
+	defer rows.Close()
+
+	feds := []FedInfo{}
+	for rows.Next() {
+		f := FedInfo{}
+		if err := rows.Scan(&f.ID, &f.TTL, &f.CName, &f.DS); err != nil {
+			return nil, errors.New("all federations scanning: " + err.Error())
+		}
+		log.Errorf("DEBUG getAllFederations got %+v\n", f)
+		feds = append(feds, f)
+	}
+	return feds, nil
+}
+
+func federationsIDsQuery() string {
+	return `
+SELECT
+  fds.federation,
+  fds.deliveryservice
+FROM
+  federation_deliveryservice fds
+  JOIN deliveryservice ds ON ds.id = fds.deliveryservice
+  JOIN cdn on cdn.id = ds.cdn
+WHERE
+  fds.federation = ANY($1)
+ORDER BY
+  ds.xml_id
+`
+}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 57060af..c8da4ad 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -50,6 +50,7 @@ import (
 	dsserver "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/servers"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservicesregexes"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/division"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/federations"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/hwinfo"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/login"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/monitoring"
@@ -362,6 +363,9 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodPut, `cdns/{id}/snapshot/?$`, crconfig.SnapshotHandler, auth.PrivLevelOperations, Authenticated, nil},
 		{1.1, http.MethodPut, `snapshot/{cdn}/?$`, crconfig.SnapshotHandler, auth.PrivLevelOperations, Authenticated, nil},
 
+		// Federations
+		{1.4, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
+
 		////DeliveryServices
 		{1.3, http.MethodGet, `deliveryservices/?(\.json)?$`, api.ReadHandler(deliveryservice.GetTypeV13Factory()), auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `deliveryservices/?(\.json)?$`, api.ReadHandler(deliveryservice.GetTypeV12Factory()), auth.PrivLevelReadOnly, Authenticated, nil},


[trafficcontrol] 04/10: Add TO Go federations tests

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7594b3765b47ce36d8e46a9e139b3012a97789a1
Author: Robert Butts <ro...@apache.org>
AuthorDate: Fri Sep 21 17:17:19 2018 -0600

    Add TO Go federations tests
---
 lib/go-tc/federation.go                            |   4 -
 traffic_ops/client/federation.go                   |  80 ++++++++++++
 traffic_ops/testing/api/v13/federations_test.go    | 145 +++++++++++++++++++++
 traffic_ops/testing/api/v14/cdnfederations_test.go |   1 +
 traffic_ops/traffic_ops_golang/federations/ds.go   |  11 +-
 .../traffic_ops_golang/federations/federations.go  |   3 +-
 6 files changed, 234 insertions(+), 10 deletions(-)

diff --git a/lib/go-tc/federation.go b/lib/go-tc/federation.go
index 44ec733..33c604c 100644
--- a/lib/go-tc/federation.go
+++ b/lib/go-tc/federation.go
@@ -21,7 +21,6 @@ package tc
 
 import (
 	"database/sql"
-	"errors"
 )
 
 type CDNFederationResponse struct {
@@ -102,8 +101,5 @@ type FederationDSPost struct {
 }
 
 func (f *FederationDSPost) Validate(tx *sql.Tx) error {
-	if len(f.DSIDs) == 0 {
-		return errors.New("no dsIds to assign")
-	}
 	return nil
 }
diff --git a/traffic_ops/client/federation.go b/traffic_ops/client/federation.go
new file mode 100644
index 0000000..84c26b6
--- /dev/null
+++ b/traffic_ops/client/federation.go
@@ -0,0 +1,80 @@
+/*
+
+   Licensed 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.
+*/
+
+package client
+
+import (
+	"encoding/json"
+	"errors"
+	"net/http"
+	"strconv"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+func (to *Session) Federations() ([]tc.AllFederation, ReqInf, error) {
+	type FederationResponse struct {
+		Response []tc.AllFederation `json:"response"`
+	}
+	data := FederationResponse{}
+	inf, err := get(to, apiBase+"/federations", &data)
+	return data.Response, inf, err
+}
+
+func (to *Session) AllFederations() ([]tc.AllFederation, ReqInf, error) {
+	type FederationResponse struct {
+		Response []tc.AllFederation `json:"response"`
+	}
+	data := FederationResponse{}
+	inf, err := get(to, apiBase+"/federations/all", &data)
+	return data.Response, inf, err
+}
+
+func (to *Session) AllFederationsForCDN(cdnName string) ([]tc.AllFederation, ReqInf, error) {
+	// because the Federations JSON array is heterogeneous (array members may be a AllFederation or AllFederationCDN), we have to try decoding each separately.
+	type FederationResponse struct {
+		Response []json.RawMessage `json:"response"`
+	}
+	data := FederationResponse{}
+	inf, err := get(to, apiBase+"/federations/all?cdnName="+cdnName, &data)
+	if err != nil {
+		return nil, inf, err
+	}
+
+	feds := []tc.AllFederation{}
+	for _, raw := range data.Response {
+		fed := tc.AllFederation{}
+		if err := json.Unmarshal([]byte(raw), &fed); err != nil {
+			// we don't actually need the CDN, but we want to return an error if we got something unexpected
+			cdnFed := tc.AllFederationCDN{}
+			if err := json.Unmarshal([]byte(raw), &cdnFed); err != nil {
+				return nil, inf, errors.New("Traffic Ops returned an unexpected object: '" + string(raw) + "'")
+			}
+		}
+		feds = append(feds, fed)
+	}
+	return feds, inf, nil
+}
+
+func (to *Session) CreateFederationDeliveryServices(federationID int, deliveryServiceIDs []int, replace bool) (ReqInf, error) {
+	req := tc.FederationDSPost{DSIDs: deliveryServiceIDs, Replace: &replace}
+	jsonReq, err := json.Marshal(req)
+	if err != nil {
+		return ReqInf{CacheHitStatus: CacheHitStatusMiss}, err
+	}
+	resp := map[string]interface{}{}
+	inf, err := makeReq(to, http.MethodPost, apiBase+`/federations/`+strconv.Itoa(federationID)+`/deliveryservices`, jsonReq, &resp)
+	return inf, err
+}
diff --git a/traffic_ops/testing/api/v13/federations_test.go b/traffic_ops/testing/api/v13/federations_test.go
new file mode 100644
index 0000000..1473f27
--- /dev/null
+++ b/traffic_ops/testing/api/v13/federations_test.go
@@ -0,0 +1,145 @@
+package v13
+
+/*
+
+   Licensed 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 (
+	"testing"
+
+	"github.com/apache/trafficcontrol/lib/go-log"
+)
+
+func TestFederations(t *testing.T) {
+	CreateTestCDNs(t)
+	CreateTestTypes(t)
+	CreateTestProfiles(t)
+	CreateTestStatuses(t)
+	CreateTestDivisions(t)
+	CreateTestRegions(t)
+	CreateTestPhysLocations(t)
+	CreateTestCacheGroups(t)
+	CreateTestDeliveryServices(t)
+	CreateTestUsersDeliveryServices(t)
+	CreateTestCDNFederations(t)
+	// UpdateTestCDNFederations(t)
+	// GetTestCDNFederations(t)
+
+	PostTestFederationsDeliveryServices(t)
+	GetTestFederations(t)
+	DeleteTestFederationsDeliveryServices(t)
+
+	DeleteTestCDNFederations(t)
+	DeleteTestUsersDeliveryServices(t)
+	DeleteTestDeliveryServices(t)
+	DeleteTestCacheGroups(t)
+	DeleteTestPhysLocations(t)
+	DeleteTestRegions(t)
+	DeleteTestDivisions(t)
+	DeleteTestStatuses(t)
+	DeleteTestProfiles(t)
+	DeleteTestTypes(t)
+	DeleteTestCDNs(t)
+}
+
+func GetTestFederations(t *testing.T) {
+	log.Debugln("GetTestFederations")
+
+	if len(testData.Federations) == 0 {
+		t.Fatalf("no federations test data")
+	}
+
+	feds, _, err := TOSession.AllFederations()
+	if err != nil {
+		t.Fatalf("getting federations: " + err.Error())
+	}
+
+	if len(feds) != 1 {
+		t.Fatalf("federations expected 1, actual: %+v", len(feds))
+	}
+	fed := feds[0]
+
+	if len(fed.Mappings) < 1 {
+		t.Fatalf("federation mappings expected <0, actual: 0")
+	}
+
+	mapping := fed.Mappings[0]
+	if mapping.CName == nil {
+		t.Fatalf("federation mapping expected cname, actual: nil")
+	}
+	if mapping.TTL == nil {
+		t.Fatalf("federation mapping expected ttl, actual: nil")
+	}
+
+	matched := false
+	for _, testFed := range testData.Federations {
+		if testFed.CName == nil {
+			t.Fatalf("test federation missing cname!")
+		}
+		if testFed.TTL == nil {
+			t.Fatalf("test federation missing ttl!")
+		}
+
+		if *mapping.CName != *testFed.CName {
+			continue
+		}
+		matched = true
+
+		if *mapping.TTL != *testFed.TTL {
+			t.Fatalf("federation mapping ttl expected: %v, actual: %v", *testFed.TTL, *mapping.TTL)
+		}
+	}
+	if !matched {
+		t.Fatalf("federation mapping expected to match test data, actual: cname %v not in test data", *mapping.CName)
+	}
+
+	log.Debugln("GetTestFederations PASSED")
+}
+
+func PostTestFederationsDeliveryServices(t *testing.T) {
+	log.Debugln("PostTestFederationsDeliveryServices")
+	dses, _, err := TOSession.GetDeliveryServices()
+	if err != nil {
+		t.Fatalf("cannot GET DeliveryServices: %v - %v\n", err, dses)
+	}
+	if len(dses) == 0 {
+		t.Fatalf("no delivery services, must have at least 1 ds to test federations deliveryservices\n")
+	}
+	ds := dses[0]
+	if len(fedIDs) == 0 {
+		t.Fatalf("no federations, must have at least 1 federation to test federations deliveryservices\n")
+	}
+	fedID := fedIDs[0]
+
+	if _, err = TOSession.CreateFederationDeliveryServices(fedID, []int{ds.ID}, true); err != nil {
+		t.Fatalf("creating federations delivery services: %v\n", err)
+	}
+	log.Debugln("PostTestFederationsDeliveryServices PASSED")
+}
+
+func DeleteTestFederationsDeliveryServices(t *testing.T) {
+	log.Debugln("DeleteTestFederationsDeliveryServices")
+	// doesn't actually call a DELETE method; this exists primarily to clean up PostTestFederationsDeliveryServices
+
+	if len(fedIDs) == 0 {
+		t.Fatalf("no federations, must have at least 1 federation to test federations deliveryservices\n")
+	}
+	fedID := fedIDs[0]
+
+	_, err := TOSession.CreateFederationDeliveryServices(fedID, nil, true)
+	if err != nil {
+		t.Fatalf("creating (deleting) federations delivery services: %v\n", err)
+	}
+	log.Debugln("DeleteTestFederationsDeliveryServices PASSED")
+}
diff --git a/traffic_ops/testing/api/v14/cdnfederations_test.go b/traffic_ops/testing/api/v14/cdnfederations_test.go
index 662e01c..970f4e4 100644
--- a/traffic_ops/testing/api/v14/cdnfederations_test.go
+++ b/traffic_ops/testing/api/v14/cdnfederations_test.go
@@ -128,4 +128,5 @@ func DeleteTestCDNFederations(t *testing.T) {
 			t.Errorf("expected federation to be deleted")
 		}
 	}
+	fedIDs = nil // reset the global variable for the next test
 }
diff --git a/traffic_ops/traffic_ops_golang/federations/ds.go b/traffic_ops/traffic_ops_golang/federations/ds.go
index 6619af9..7ab0628 100644
--- a/traffic_ops/traffic_ops_golang/federations/ds.go
+++ b/traffic_ops/traffic_ops_golang/federations/ds.go
@@ -55,10 +55,13 @@ func PostDSes(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
-	if err := insertDSFeds(inf.Tx.Tx, fedID, post.DSIDs); err != nil {
-		userErr, sysErr, errCode := api.ParseDBError(err)
-		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
-		return
+	if len(post.DSIDs) > 0 {
+		// there might be no DSes, if the user is trying to clear the assignments
+		if err := insertDSFeds(inf.Tx.Tx, fedID, post.DSIDs); err != nil {
+			userErr, sysErr, errCode := api.ParseDBError(err)
+			api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+			return
+		}
 	}
 
 	api.WriteRespAlertObj(w, r, tc.SuccessLevel, strconv.Itoa(len(post.DSIDs))+" delivery service(s) were assigned to the federation "+strconv.Itoa(fedID), post)
diff --git a/traffic_ops/traffic_ops_golang/federations/federations.go b/traffic_ops/traffic_ops_golang/federations/federations.go
index 048c432..29c9a60 100644
--- a/traffic_ops/traffic_ops_golang/federations/federations.go
+++ b/traffic_ops/traffic_ops_golang/federations/federations.go
@@ -40,7 +40,6 @@ func Get(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	allFederations := []tc.IAllFederation{}
 	feds, err := getUserFederations(inf.Tx.Tx, inf.User)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.Get getting federations: "+err.Error()))
@@ -51,7 +50,7 @@ func Get(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.Get getting federations resolvers: "+err.Error()))
 		return
 	}
-	allFederations = addResolvers(allFederations, feds, fedsResolvers)
+	allFederations := addResolvers([]tc.IAllFederation{}, feds, fedsResolvers)
 	api.WriteResp(w, r, allFederations)
 }
 


[trafficcontrol] 08/10: Change TO Go feds func to take name not user

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 24d374ac329c43a42265e3b1960bfcd00bb8d8b6
Author: Robert Butts <ro...@apache.org>
AuthorDate: Mon Oct 1 21:08:51 2018 -0600

    Change TO Go feds func to take name not user
---
 traffic_ops/traffic_ops_golang/federations/federations.go | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/traffic_ops/traffic_ops_golang/federations/federations.go b/traffic_ops/traffic_ops_golang/federations/federations.go
index 7c984f6..309607d 100644
--- a/traffic_ops/traffic_ops_golang/federations/federations.go
+++ b/traffic_ops/traffic_ops_golang/federations/federations.go
@@ -28,7 +28,6 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 
 	"github.com/lib/pq"
 )
@@ -41,7 +40,7 @@ func Get(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	feds, err := getUserFederations(inf.Tx.Tx, inf.User)
+	feds, err := getUserFederations(inf.Tx.Tx, inf.User.UserName)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("federations.Get getting federations: "+err.Error()))
 		return
@@ -134,7 +133,7 @@ WHERE
 	return feds, nil
 }
 
-func getUserFederations(tx *sql.Tx, user *auth.CurrentUser) ([]FedInfo, error) {
+func getUserFederations(tx *sql.Tx, userName string) ([]FedInfo, error) {
 	qry := `
 SELECT
   fds.federation,
@@ -152,7 +151,7 @@ WHERE
 ORDER BY
   ds.xml_id
 `
-	rows, err := tx.Query(qry, user.UserName)
+	rows, err := tx.Query(qry, userName)
 	if err != nil {
 		return nil, errors.New("user federations querying: " + err.Error())
 	}


[trafficcontrol] 06/10: Change TO Go fed/all to priv admin, matching Perl

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit a607a55d7009d175e222699c2362ac5269dba6ad
Author: Robert Butts <ro...@apache.org>
AuthorDate: Mon Oct 1 21:01:14 2018 -0600

    Change TO Go fed/all to priv admin, matching Perl
---
 traffic_ops/traffic_ops_golang/routes.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index f069439..2ebc9a9 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -364,7 +364,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodPut, `snapshot/{cdn}/?$`, crconfig.SnapshotHandler, auth.PrivLevelOperations, Authenticated, nil},
 
 		// Federations
-		{1.4, http.MethodGet, `federations/all/?(\.json)?$`, federations.GetAll, auth.PrivLevelReadOnly, Authenticated, nil},
+		{1.4, http.MethodGet, `federations/all/?(\.json)?$`, federations.GetAll, auth.PrivLevelAdmin, Authenticated, nil},
 		{1.1, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodPost, `federations/{id}/deliveryservices?(\.json)?$`, federations.PostDSes, auth.PrivLevelAdmin, Authenticated, nil},
 


[trafficcontrol] 03/10: Add TO Go POST federations/id/deliveryservices

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d24b91aab89e4bfecae9d1f0d3c13d62bd2d2a43
Author: Robert Butts <ro...@apache.org>
AuthorDate: Fri Sep 21 16:04:01 2018 -0600

    Add TO Go POST federations/id/deliveryservices
---
 lib/go-tc/federation.go                          | 17 +++++
 traffic_ops/traffic_ops_golang/federations/ds.go | 80 ++++++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routes.go         |  1 +
 3 files changed, 98 insertions(+)

diff --git a/lib/go-tc/federation.go b/lib/go-tc/federation.go
index 3781cf9..44ec733 100644
--- a/lib/go-tc/federation.go
+++ b/lib/go-tc/federation.go
@@ -19,6 +19,11 @@ package tc
  * under the License.
  */
 
+import (
+	"database/sql"
+	"errors"
+)
+
 type CDNFederationResponse struct {
 	Response []CDNFederation `json:"response"`
 }
@@ -90,3 +95,15 @@ type AllFederationMapping struct {
 type IAllFederation interface {
 	IsAllFederations() bool
 }
+
+type FederationDSPost struct {
+	DSIDs   []int `json:"dsIds"`
+	Replace *bool `json:"replace"`
+}
+
+func (f *FederationDSPost) Validate(tx *sql.Tx) error {
+	if len(f.DSIDs) == 0 {
+		return errors.New("no dsIds to assign")
+	}
+	return nil
+}
diff --git a/traffic_ops/traffic_ops_golang/federations/ds.go b/traffic_ops/traffic_ops_golang/federations/ds.go
new file mode 100644
index 0000000..6619af9
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/federations/ds.go
@@ -0,0 +1,80 @@
+package federations
+
+/*
+ * 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"
+	"strconv"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+
+	"github.com/lib/pq"
+)
+
+func PostDSes(w http.ResponseWriter, r *http.Request) {
+	inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, []string{"id"})
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+		return
+	}
+	defer inf.Close()
+
+	fedID := inf.IntParams["id"]
+
+	post := tc.FederationDSPost{}
+	if err := api.Parse(r.Body, inf.Tx.Tx, &post); err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("parse error: "+err.Error()), nil)
+		return
+	}
+
+	if post.Replace != nil && *post.Replace {
+		if err := deleteDSFeds(inf.Tx.Tx, fedID); err != nil {
+			userErr, sysErr, errCode := api.ParseDBError(err)
+			api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+			return
+		}
+	}
+
+	if err := insertDSFeds(inf.Tx.Tx, fedID, post.DSIDs); err != nil {
+		userErr, sysErr, errCode := api.ParseDBError(err)
+		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+		return
+	}
+
+	api.WriteRespAlertObj(w, r, tc.SuccessLevel, strconv.Itoa(len(post.DSIDs))+" delivery service(s) were assigned to the federation "+strconv.Itoa(fedID), post)
+}
+
+func deleteDSFeds(tx *sql.Tx, fedID int) error {
+	qry := `DELETE FROM federation_deliveryservice WHERE federation = $1`
+	_, err := tx.Exec(qry, fedID)
+	return err
+}
+
+func insertDSFeds(tx *sql.Tx, fedID int, dsIDs []int) error {
+	qry := `
+INSERT INTO federation_deliveryservice (federation, deliveryservice)
+VALUES ($1, unnest($2::integer[]))
+`
+	_, err := tx.Exec(qry, fedID, pq.Array(dsIDs))
+	return err
+}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index dbb5368..e741714 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -366,6 +366,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		// Federations
 		{1.4, http.MethodGet, `federations/all/?(\.json)?$`, federations.GetAll, auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
+		{1.1, http.MethodPost, `federations/{id}/deliveryservices?(\.json)?$`, federations.PostDSes, auth.PrivLevelOperations, Authenticated, nil},
 
 		////DeliveryServices
 		{1.3, http.MethodGet, `deliveryservices/?(\.json)?$`, api.ReadHandler(deliveryservice.GetTypeV13Factory()), auth.PrivLevelReadOnly, Authenticated, nil},


[trafficcontrol] 05/10: Fix TO Go fed/id/ds priv to admin, to match Perl

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7b1aa7064e1a0b0925d499e875c637529c1d5ed8
Author: Robert Butts <ro...@apache.org>
AuthorDate: Mon Oct 1 20:57:29 2018 -0600

    Fix TO Go fed/id/ds priv to admin, to match Perl
---
 traffic_ops/traffic_ops_golang/routes.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index e741714..f069439 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -366,7 +366,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		// Federations
 		{1.4, http.MethodGet, `federations/all/?(\.json)?$`, federations.GetAll, auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
-		{1.1, http.MethodPost, `federations/{id}/deliveryservices?(\.json)?$`, federations.PostDSes, auth.PrivLevelOperations, Authenticated, nil},
+		{1.1, http.MethodPost, `federations/{id}/deliveryservices?(\.json)?$`, federations.PostDSes, auth.PrivLevelAdmin, Authenticated, nil},
 
 		////DeliveryServices
 		{1.3, http.MethodGet, `deliveryservices/?(\.json)?$`, api.ReadHandler(deliveryservice.GetTypeV13Factory()), auth.PrivLevelReadOnly, Authenticated, nil},


[trafficcontrol] 10/10: Fix TO Go /federations PrivLevelFed to match Perl

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 049b85f63a4b479c61f195c866f9ee455ec43617
Author: Robert Butts <ro...@apache.org>
AuthorDate: Wed Oct 3 18:59:33 2018 -0600

    Fix TO Go /federations PrivLevelFed to match Perl
---
 traffic_ops/traffic_ops_golang/routes.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 2ebc9a9..677d1cd 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -365,7 +365,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 
 		// Federations
 		{1.4, http.MethodGet, `federations/all/?(\.json)?$`, federations.GetAll, auth.PrivLevelAdmin, Authenticated, nil},
-		{1.1, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelReadOnly, Authenticated, nil},
+		{1.1, http.MethodGet, `federations/?(\.json)?$`, federations.Get, auth.PrivLevelFederation, Authenticated, nil},
 		{1.1, http.MethodPost, `federations/{id}/deliveryservices?(\.json)?$`, federations.PostDSes, auth.PrivLevelAdmin, Authenticated, nil},
 
 		////DeliveryServices