You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ro...@apache.org on 2018/07/06 14:44:22 UTC

[trafficcontrol] branch master updated (16bef69 -> fb4d249)

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

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


    from 16bef69  add downloadjs (MIT) to rat excludes
     new 2757caa  Add TO Go cdns/domains
     new 84a8438  Update TO Go cdns/domains
     new fb4d249  Updated according to comments on PR

The 3 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/v13/domains.go                           | 47 ++++++++++++++
 .../v13/ping_test.go => client/v13/cdn_domains.go} | 21 +++---
 .../api/v13/{fixtures.go => cdn_domains_test.go}   | 36 ++++++-----
 traffic_ops/traffic_ops_golang/cdn/domains.go      | 74 ++++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routes.go           |  2 +-
 5 files changed, 150 insertions(+), 30 deletions(-)
 create mode 100644 lib/go-tc/v13/domains.go
 copy traffic_ops/{testing/api/v13/ping_test.go => client/v13/cdn_domains.go} (70%)
 copy traffic_ops/testing/api/v13/{fixtures.go => cdn_domains_test.go} (62%)
 create mode 100644 traffic_ops/traffic_ops_golang/cdn/domains.go


[trafficcontrol] 01/03: Add TO Go cdns/domains

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

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

commit 2757caa92b75115ae554ee9ca4a82285b6533e76
Author: moltzaum <ma...@moltzau.net>
AuthorDate: Fri Jun 29 15:13:23 2018 -0600

    Add TO Go cdns/domains
    
    Not yet complete. I need to set up a test while the route still points to perl,
    then test the new handler I made. The handler's error registering needs to be
    looked at.
---
 traffic_ops/testing/api/v13/cdn_domains_test.go | 22 ++++++
 traffic_ops/traffic_ops_golang/cdn/domains.go   | 97 +++++++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routes.go        |  3 +-
 3 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/traffic_ops/testing/api/v13/cdn_domains_test.go b/traffic_ops/testing/api/v13/cdn_domains_test.go
new file mode 100644
index 0000000..39d4ef3
--- /dev/null
+++ b/traffic_ops/testing/api/v13/cdn_domains_test.go
@@ -0,0 +1,22 @@
+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"
+
+func TestDomains(t *testing.T) {
+  //
+}
diff --git a/traffic_ops/traffic_ops_golang/cdn/domains.go b/traffic_ops/traffic_ops_golang/cdn/domains.go
new file mode 100644
index 0000000..d56cb9e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/cdn/domains.go
@@ -0,0 +1,97 @@
+package cdn
+
+/*
+ * 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 (
+  "net/http"
+  //"database/sql"
+  //"github.com/jmoiron/sqlx" //sql extra
+  "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+)
+
+func DomainsHandler (w http.ResponseWriter, r *http.Request) {
+
+  // inf is of type APIInfo
+  inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+  if userErr != nil || sysErr != nil {
+    api.HandleErr(w, r, errCode, userErr, sysErr)
+    return
+  }
+  defer inf.Close()
+
+  var (
+    cdn         int
+    id          int
+    name        string
+    description string
+    domain_name string
+    resp []interface{} //really not sure about this
+  )
+
+  //how to prefetch 'cdn'?
+  q := `SELECT cdn, id, name, description FROM 'Profile' WHERE name LIKE 'CCR%'`
+  rows, err := inf.Tx.Query(q)
+  if err != nil {
+    //TODO change errCode, userErr, and sysErr
+    //which one is errors.New("Error: " + err.Error()?
+    //api.HandleErr(w, r, errCode, userErr, sysErr)
+    return
+  }
+  defer rows.Close()
+
+  for rows.Next() {
+
+    //Do I even need to check for errors here since the perl doesn't?
+    if err := rows.Scan(&cdn, &id, &name, &description); err != nil {
+      //api.HandleErr(w, r, HTTP CODE,
+      //  errors.New("Error scanning ...: " + err.Error())  user or system error?
+    }
+
+    err = inf.Tx.QueryRow("SELECT DOMAIN_NAME FROM CDN WHERE id = $1", 1).Scan(&domain_name)
+    if err != nil {
+      //api.HandleErr(w, r, HTTP CODE,
+      //  errors.New("Error scanning ...: " + err.Error()") user or system error?
+    }
+
+    data := struct {
+      domain_name string
+      param_id    int
+      id          int
+      name        string
+      description string
+    } {
+      domain_name,
+      -1, // it's not a parameter anymore
+      id,
+      name,
+      description,
+    }
+    resp = append(resp, data)
+  }
+
+  api.WriteResp(w, r, resp)
+  /* {
+    "domainName"         => $row->cdn->domain_name,
+    "parameterId"        => -1,  # it's not a parameter anymore
+    "profileId"          => $row->id,
+    "profileName"        => $row->name,
+    "profileDescription" => $row->description,
+  } */
+}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 60670a3..ccef612 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -110,7 +110,8 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodGet, `cdns/metric_types`, notImplementedHandler, 0, NoAuth, nil}, // MUST NOT end in $, because the 1.x route is longer
 		{1.1, http.MethodGet, `cdns/capacity$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
 		{1.1, http.MethodGet, `cdns/configs/?(\.json)?$`, cdn.GetConfigs(d.DB.DB), auth.PrivLevelReadOnly, Authenticated, nil},
-		{1.1, http.MethodGet, `cdns/domains$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
+		{1.1, http.MethodGet, `cdns/domains$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}}, //old
+		//{1.1, http.MethodGet, `cdns/domains/?(\.json)?$`, cdn.DomainsHandler, auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `cdns/health$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
 		{1.1, http.MethodGet, `cdns/routing$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
 


[trafficcontrol] 03/03: Updated according to comments on PR

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

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

commit fb4d2490acffbf906174ffcde7486261627d0fbb
Author: moltzaum <ma...@moltzau.net>
AuthorDate: Thu Jul 5 14:45:33 2018 -0600

    Updated according to comments on PR
    
    Most significant issue was efficiency in using two separate queries instead of a join. Minor changes in coding style was added. Removed some hard-coded values in favor of variables.
---
 lib/go-tc/v13/domains.go                        | 25 ------------
 traffic_ops/client/v13/cdn_domains.go           |  2 +-
 traffic_ops/testing/api/v13/cdn_domains_test.go |  2 +-
 traffic_ops/traffic_ops_golang/cdn/domains.go   | 51 +++++++------------------
 4 files changed, 16 insertions(+), 64 deletions(-)

diff --git a/lib/go-tc/v13/domains.go b/lib/go-tc/v13/domains.go
index 4c9cb46..7908c4f 100644
--- a/lib/go-tc/v13/domains.go
+++ b/lib/go-tc/v13/domains.go
@@ -19,46 +19,21 @@ package v13
  * under the License.
  */
 
-/*
-TODO: Adapt the comments to be better used by swagger. I am writing comments
-that look similar to others in `go-tc/cdns.go`, but I'm unsure how it will
-end up looking. Note: I also made a few assumptions with the "required" field
-*/
-
-// A List of Domains Response
-// swagger:response DomainsResponse
-// in: body
 type DomainsResponse struct {
-	// in: body
 	Response []Domain `json:"response"`
 }
 
-// Domain ...
 type Domain struct {
 
-	// Profile ID
-	//
-	// required: true
 	ProfileID int `json:"profileId" db:"profile_id"`
 
-	// Parameter ID
-	//
-	// required: false
 	ParameterID int `json:"parameterId" db:"parameter_id"`
 
-	// Profile Name
-	//
-	// required: true
 	ProfileName string `json:"profileName" db:"profile_name"`
 
-	// Profile Description
-	//
-	// required: true
 	ProfileDescription string `json:"profileDescription" db:"profile_description"`
 
 	// DomainName of the CDN
-	//
-	// required: true
 	DomainName string `json:"domainName" db:"domain_name"`
 }
 
diff --git a/traffic_ops/client/v13/cdn_domains.go b/traffic_ops/client/v13/cdn_domains.go
index 42e748a..7da297f 100644
--- a/traffic_ops/client/v13/cdn_domains.go
+++ b/traffic_ops/client/v13/cdn_domains.go
@@ -21,7 +21,7 @@ import (
 
 func (to *Session) GetDomains() ([]v13.Domain, ReqInf, error) {
 	var data v13.DomainsResponse
-	inf, err := get(to, "/api/1.3/cdns/domains", &data)
+	inf, err := get(to, apiBase + "/cdns/domains", &data)
 	if err != nil {
 		return nil, inf, err
 	}
diff --git a/traffic_ops/testing/api/v13/cdn_domains_test.go b/traffic_ops/testing/api/v13/cdn_domains_test.go
index fd99e23..ea2523d 100644
--- a/traffic_ops/testing/api/v13/cdn_domains_test.go
+++ b/traffic_ops/testing/api/v13/cdn_domains_test.go
@@ -18,7 +18,7 @@ package v13
 import (
 	"testing"
 
-	log "github.com/apache/trafficcontrol/lib/go-log"
+	"github.com/apache/trafficcontrol/lib/go-log"
 )
 
 func GetTestDomains(t *testing.T) {
diff --git a/traffic_ops/traffic_ops_golang/cdn/domains.go b/traffic_ops/traffic_ops_golang/cdn/domains.go
index f85fddf..c3b6f27 100644
--- a/traffic_ops/traffic_ops_golang/cdn/domains.go
+++ b/traffic_ops/traffic_ops_golang/cdn/domains.go
@@ -22,51 +22,37 @@ package cdn
 import (
 	"fmt"
 	"net/http"
-
 	"github.com/apache/trafficcontrol/lib/go-tc/v13"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/jmoiron/sqlx"
 )
 
-// GetDomainsList gathers a list of domains, except for the domain name.
-// There seems to be an issue nesting queries (performing a query while
-// rows.Next still needs to iterate). https://github.com/lib/pq/issues/81
-func getDomainsList(tx *sqlx.Tx) ([]v13.Domain, []int, error) {
+const RouterProfilePrefix = "CCR"
 
-	var (
-		cdn  int
-		id   int
-		name string
-		desc string
-	)
+func getDomainsList(tx *sqlx.Tx) ([]v13.Domain, error) {
 
 	domains := []v13.Domain{}
-	cdn_ids := []int{}
 
-	q := `SELECT cdn, id, name, description FROM Profile WHERE name LIKE 'CCR%'`
+	q := `SELECT p.id, p.name, p.description, domain_name FROM profile AS p
+	JOIN cdn ON p.cdn = cdn.id WHERE p.name LIKE '` + RouterProfilePrefix + `%'`;
+
 	rows, err := tx.Query(q)
 	if err != nil {
-		return nil, nil, fmt.Errorf("querying for profile: %s", err)
+		return nil, fmt.Errorf("querying for profile: %s", err)
 	}
 	defer rows.Close()
 
 	for rows.Next() {
-		if err := rows.Scan(&cdn, &id, &name, &desc); err != nil {
-			return nil, nil, fmt.Errorf("getting profile: %s", err)
-		}
 
-		elem := v13.Domain{
-			ProfileID:          id,
-			ParameterID:        -1,
-			ProfileName:        name,
-			ProfileDescription: desc,
+		d := v13.Domain{ParameterID: -1}
+		err := rows.Scan(&d.ProfileID, &d.ProfileName, &d.ProfileDescription, &d.DomainName)
+		if err != nil {
+			return nil, fmt.Errorf("getting profile: %s", err)
 		}
-
-		cdn_ids = append(cdn_ids, cdn)
-		domains = append(domains, elem)
+		domains = append(domains, d)
 	}
 
-	return domains, cdn_ids, nil
+	return domains, nil
 }
 
 func DomainsHandler(w http.ResponseWriter, r *http.Request) {
@@ -78,20 +64,11 @@ func DomainsHandler(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	domains, cdn_ids, err := getDomainsList(inf.Tx)
+	domains, err := getDomainsList(inf.Tx)
 	if err != nil {
-		api.HandleErr(w, r, http.StatusInternalServerError, nil, err)
+		api.HandleErr(w, r, http.StatusInternalServerError, err, err)
 		return
 	}
 
-	for i, cdn := range cdn_ids {
-		row := inf.Tx.QueryRow(`SELECT DOMAIN_NAME FROM CDN WHERE id = $1`, cdn)
-		err := row.Scan(&domains[i].DomainName)
-		if err != nil {
-			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("getting domain name of cdn: %s", err))
-			return
-		}
-	}
-
 	api.WriteResp(w, r, domains)
 }


[trafficcontrol] 02/03: Update TO Go cdns/domains

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

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

commit 84a8438c414a11a4302e115978096287c023a751
Author: moltzaum <ma...@moltzau.net>
AuthorDate: Thu Jul 5 10:33:59 2018 -0600

    Update TO Go cdns/domains
    
    Test works for golang. Perl had its ProfileID as a string when I tested it, causing the test to fail, but the data looked good both in perl and go using localhost.
---
 lib/go-tc/v13/domains.go                           |  72 +++++++++++
 .../v13/cdn_domains.go}                            |  15 ++-
 traffic_ops/testing/api/v13/cdn_domains_test.go    |  24 +++-
 traffic_ops/traffic_ops_golang/cdn/domains.go      | 144 ++++++++++-----------
 traffic_ops/traffic_ops_golang/routes.go           |   3 +-
 5 files changed, 178 insertions(+), 80 deletions(-)

diff --git a/lib/go-tc/v13/domains.go b/lib/go-tc/v13/domains.go
new file mode 100644
index 0000000..4c9cb46
--- /dev/null
+++ b/lib/go-tc/v13/domains.go
@@ -0,0 +1,72 @@
+package v13
+
+/*
+ * 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.
+ */
+
+/*
+TODO: Adapt the comments to be better used by swagger. I am writing comments
+that look similar to others in `go-tc/cdns.go`, but I'm unsure how it will
+end up looking. Note: I also made a few assumptions with the "required" field
+*/
+
+// A List of Domains Response
+// swagger:response DomainsResponse
+// in: body
+type DomainsResponse struct {
+	// in: body
+	Response []Domain `json:"response"`
+}
+
+// Domain ...
+type Domain struct {
+
+	// Profile ID
+	//
+	// required: true
+	ProfileID int `json:"profileId" db:"profile_id"`
+
+	// Parameter ID
+	//
+	// required: false
+	ParameterID int `json:"parameterId" db:"parameter_id"`
+
+	// Profile Name
+	//
+	// required: true
+	ProfileName string `json:"profileName" db:"profile_name"`
+
+	// Profile Description
+	//
+	// required: true
+	ProfileDescription string `json:"profileDescription" db:"profile_description"`
+
+	// DomainName of the CDN
+	//
+	// required: true
+	DomainName string `json:"domainName" db:"domain_name"`
+}
+
+// DomainNullable - a struct version that allows for all fields to be null, mostly used by the API side
+type DomainNullable struct {
+	ProfileID          *int    `json:"profileId" db:"profile_id"`
+	ParameterID        *int    `json:"parameterId" db:"parameter_id"`
+	ProfileName        *string `json:"profileName" db:"profile_name"`
+	ProfileDescription *string `json:"profileDescription" db:"profile_description"`
+	DomainName         *string `json:"domainName" db:"domain_name"`
+}
diff --git a/traffic_ops/testing/api/v13/cdn_domains_test.go b/traffic_ops/client/v13/cdn_domains.go
similarity index 66%
copy from traffic_ops/testing/api/v13/cdn_domains_test.go
copy to traffic_ops/client/v13/cdn_domains.go
index 39d4ef3..42e748a 100644
--- a/traffic_ops/testing/api/v13/cdn_domains_test.go
+++ b/traffic_ops/client/v13/cdn_domains.go
@@ -1,5 +1,9 @@
 package v13
 
+import (
+	"github.com/apache/trafficcontrol/lib/go-tc/v13"
+)
+
 /*
 
    Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,8 +19,11 @@ package v13
    limitations under the License.
 */
 
-import "testing"
-
-func TestDomains(t *testing.T) {
-  //
+func (to *Session) GetDomains() ([]v13.Domain, ReqInf, error) {
+	var data v13.DomainsResponse
+	inf, err := get(to, "/api/1.3/cdns/domains", &data)
+	if err != nil {
+		return nil, inf, err
+	}
+	return data.Response, inf, nil
 }
diff --git a/traffic_ops/testing/api/v13/cdn_domains_test.go b/traffic_ops/testing/api/v13/cdn_domains_test.go
index 39d4ef3..fd99e23 100644
--- a/traffic_ops/testing/api/v13/cdn_domains_test.go
+++ b/traffic_ops/testing/api/v13/cdn_domains_test.go
@@ -15,8 +15,28 @@ package v13
    limitations under the License.
 */
 
-import "testing"
+import (
+	"testing"
+
+	log "github.com/apache/trafficcontrol/lib/go-log"
+)
+
+func GetTestDomains(t *testing.T) {
+	resp, _, err := TOSession.GetDomains()
+	log.Debugln("Response: ", resp)
+	if err != nil {
+		t.Errorf("could not GET domains: %v\n", err)
+	}
+}
 
 func TestDomains(t *testing.T) {
-  //
+	CreateTestCDNs(t)
+	CreateTestTypes(t)
+	CreateTestProfiles(t)
+	CreateTestStatuses(t)
+	GetTestDomains(t)
+	DeleteTestStatuses(t)
+	DeleteTestProfiles(t)
+	DeleteTestTypes(t)
+	DeleteTestCDNs(t)
 }
diff --git a/traffic_ops/traffic_ops_golang/cdn/domains.go b/traffic_ops/traffic_ops_golang/cdn/domains.go
index d56cb9e..f85fddf 100644
--- a/traffic_ops/traffic_ops_golang/cdn/domains.go
+++ b/traffic_ops/traffic_ops_golang/cdn/domains.go
@@ -20,78 +20,78 @@ package cdn
  */
 
 import (
-  "net/http"
-  //"database/sql"
-  //"github.com/jmoiron/sqlx" //sql extra
-  "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+	"fmt"
+	"net/http"
+
+	"github.com/apache/trafficcontrol/lib/go-tc/v13"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+	"github.com/jmoiron/sqlx"
 )
 
-func DomainsHandler (w http.ResponseWriter, r *http.Request) {
-
-  // inf is of type APIInfo
-  inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
-  if userErr != nil || sysErr != nil {
-    api.HandleErr(w, r, errCode, userErr, sysErr)
-    return
-  }
-  defer inf.Close()
-
-  var (
-    cdn         int
-    id          int
-    name        string
-    description string
-    domain_name string
-    resp []interface{} //really not sure about this
-  )
-
-  //how to prefetch 'cdn'?
-  q := `SELECT cdn, id, name, description FROM 'Profile' WHERE name LIKE 'CCR%'`
-  rows, err := inf.Tx.Query(q)
-  if err != nil {
-    //TODO change errCode, userErr, and sysErr
-    //which one is errors.New("Error: " + err.Error()?
-    //api.HandleErr(w, r, errCode, userErr, sysErr)
-    return
-  }
-  defer rows.Close()
-
-  for rows.Next() {
-
-    //Do I even need to check for errors here since the perl doesn't?
-    if err := rows.Scan(&cdn, &id, &name, &description); err != nil {
-      //api.HandleErr(w, r, HTTP CODE,
-      //  errors.New("Error scanning ...: " + err.Error())  user or system error?
-    }
-
-    err = inf.Tx.QueryRow("SELECT DOMAIN_NAME FROM CDN WHERE id = $1", 1).Scan(&domain_name)
-    if err != nil {
-      //api.HandleErr(w, r, HTTP CODE,
-      //  errors.New("Error scanning ...: " + err.Error()") user or system error?
-    }
-
-    data := struct {
-      domain_name string
-      param_id    int
-      id          int
-      name        string
-      description string
-    } {
-      domain_name,
-      -1, // it's not a parameter anymore
-      id,
-      name,
-      description,
-    }
-    resp = append(resp, data)
-  }
-
-  api.WriteResp(w, r, resp)
-  /* {
-    "domainName"         => $row->cdn->domain_name,
-    "parameterId"        => -1,  # it's not a parameter anymore
-    "profileId"          => $row->id,
-    "profileName"        => $row->name,
-    "profileDescription" => $row->description,
-  } */
+// GetDomainsList gathers a list of domains, except for the domain name.
+// There seems to be an issue nesting queries (performing a query while
+// rows.Next still needs to iterate). https://github.com/lib/pq/issues/81
+func getDomainsList(tx *sqlx.Tx) ([]v13.Domain, []int, error) {
+
+	var (
+		cdn  int
+		id   int
+		name string
+		desc string
+	)
+
+	domains := []v13.Domain{}
+	cdn_ids := []int{}
+
+	q := `SELECT cdn, id, name, description FROM Profile WHERE name LIKE 'CCR%'`
+	rows, err := tx.Query(q)
+	if err != nil {
+		return nil, nil, fmt.Errorf("querying for profile: %s", err)
+	}
+	defer rows.Close()
+
+	for rows.Next() {
+		if err := rows.Scan(&cdn, &id, &name, &desc); err != nil {
+			return nil, nil, fmt.Errorf("getting profile: %s", err)
+		}
+
+		elem := v13.Domain{
+			ProfileID:          id,
+			ParameterID:        -1,
+			ProfileName:        name,
+			ProfileDescription: desc,
+		}
+
+		cdn_ids = append(cdn_ids, cdn)
+		domains = append(domains, elem)
+	}
+
+	return domains, cdn_ids, nil
+}
+
+func DomainsHandler(w http.ResponseWriter, r *http.Request) {
+
+	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+	if userErr != nil || sysErr != nil {
+		api.HandleErr(w, r, errCode, userErr, sysErr)
+		return
+	}
+	defer inf.Close()
+
+	domains, cdn_ids, err := getDomainsList(inf.Tx)
+	if err != nil {
+		api.HandleErr(w, r, http.StatusInternalServerError, nil, err)
+		return
+	}
+
+	for i, cdn := range cdn_ids {
+		row := inf.Tx.QueryRow(`SELECT DOMAIN_NAME FROM CDN WHERE id = $1`, cdn)
+		err := row.Scan(&domains[i].DomainName)
+		if err != nil {
+			api.HandleErr(w, r, http.StatusInternalServerError, nil, fmt.Errorf("getting domain name of cdn: %s", err))
+			return
+		}
+	}
+
+	api.WriteResp(w, r, domains)
 }
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index ccef612..d1df3e8 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -110,8 +110,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		{1.1, http.MethodGet, `cdns/metric_types`, notImplementedHandler, 0, NoAuth, nil}, // MUST NOT end in $, because the 1.x route is longer
 		{1.1, http.MethodGet, `cdns/capacity$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
 		{1.1, http.MethodGet, `cdns/configs/?(\.json)?$`, cdn.GetConfigs(d.DB.DB), auth.PrivLevelReadOnly, Authenticated, nil},
-		{1.1, http.MethodGet, `cdns/domains$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}}, //old
-		//{1.1, http.MethodGet, `cdns/domains/?(\.json)?$`, cdn.DomainsHandler, auth.PrivLevelReadOnly, Authenticated, nil},
+		{1.1, http.MethodGet, `cdns/domains/?(\.json)?$`, cdn.DomainsHandler, auth.PrivLevelReadOnly, Authenticated, nil},
 		{1.1, http.MethodGet, `cdns/health$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
 		{1.1, http.MethodGet, `cdns/routing$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},