dangogh closed pull request #1896: Updated /phys_locations to use the CRUD 
interface
URL: https://github.com/apache/incubator-trafficcontrol/pull/1896
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/lib/go-tc/physlocations.go b/lib/go-tc/physlocations.go
index 92f6a9e533..4d506b842a 100644
--- a/lib/go-tc/physlocations.go
+++ b/lib/go-tc/physlocations.go
@@ -24,18 +24,39 @@ type PhysLocationsResponse struct {
 }
 
 type PhysLocation struct {
-       Address      string `json:"address" db:"address"`
-       City         string `json:"city" db:"city"`
-       Comments     string `json:"comments" db:"comments"`
-       Email        string `json:"email" db:"email"`
-       ID           int    `json:"id" db:"id"`
-       LastUpdated  Time   `json:"lastUpdated" db:"last_updated"`
-       Name         string `json:"name" db:"name"`
-       Phone        string `json:"phone" db:"phone"`
-       POC          string `json:"poc" db:"poc"`
-       RegionId     int    `json:"regionId" db:"regionid"`
-       Region       string `json:"region" db:"region"`
-       ShortName    string `json:"shortName" db:"short_name"`
-       State        string `json:"state" db:"state"`
-       Zip          string `json:"zip" db:"zip"`
+       Address     string `json:"address" db:"address"`
+       City        string `json:"city" db:"city"`
+       Comments    string `json:"comments" db:"comments"`
+       Email       string `json:"email" db:"email"`
+       ID          int    `json:"id" db:"id"`
+       LastUpdated Time   `json:"lastUpdated" db:"last_updated"`
+       Name        string `json:"name" db:"name"`
+       Phone       string `json:"phone" db:"phone"`
+       POC         string `json:"poc" db:"poc"`
+       RegionID    int    `json:"regionId" db:"region"`
+       RegionName  string `json:"region" db:"region_name"`
+       ShortName   string `json:"shortName" db:"short_name"`
+       State       string `json:"state" db:"state"`
+       Zip         string `json:"zip" db:"zip"`
+}
+
+// PhysLocationNullable - a struct version that allows for all fields to be 
null
+type PhysLocationNullable struct {
+       //
+       // NOTE: the db: struct tags are used for testing to map to their 
equivalent database column (if there is one)
+       //
+       Address     *string `json:"address" db:"address"`
+       City        *string `json:"city" db:"city"`
+       Comments    *string `json:"comments" db:"comments"`
+       Email       *string `json:"email" db:"email"`
+       ID          *int    `json:"id" db:"id"`
+       LastUpdated Time    `json:"lastUpdated" db:"last_updated"`
+       Name        *string `json:"name" db:"name"`
+       Phone       *string `json:"phone" db:"phone"`
+       POC         *string `json:"poc" db:"poc"`
+       RegionID    *int    `json:"regionId" db:"region"`
+       RegionName  *string `json:"region" db:"region_name"`
+       ShortName   *string `json:"shortName" db:"short_name"`
+       State       *string `json:"state" db:"state"`
+       Zip         *string `json:"zip" db:"zip"`
 }
diff --git a/traffic_ops/client/phys_location.go 
b/traffic_ops/client/phys_location.go
new file mode 100644
index 0000000000..f0b0f15a53
--- /dev/null
+++ b/traffic_ops/client/phys_location.go
@@ -0,0 +1,132 @@
+/*
+
+   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"
+       "fmt"
+       "net"
+       "net/http"
+
+       "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+)
+
+const (
+       API_v13_PHYS_LOCATIONS = "/api/1.3/phys_locations"
+)
+
+// Create a PhysLocation
+func (to *Session) CreatePhysLocation(physLocation tc.PhysLocation) 
(tc.Alerts, ReqInf, error) {
+
+       var remoteAddr net.Addr
+       reqBody, err := json.Marshal(physLocation)
+       reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: 
remoteAddr}
+       if err != nil {
+               return tc.Alerts{}, reqInf, err
+       }
+       resp, remoteAddr, err := to.request(http.MethodPost, 
API_v13_PHYS_LOCATIONS, reqBody)
+       if err != nil {
+               return tc.Alerts{}, reqInf, err
+       }
+       defer resp.Body.Close()
+       var alerts tc.Alerts
+       err = json.NewDecoder(resp.Body).Decode(&alerts)
+       return alerts, reqInf, nil
+}
+
+// Update a PhysLocation by ID
+func (to *Session) UpdatePhysLocationByID(id int, physLocation 
tc.PhysLocation) (tc.Alerts, ReqInf, error) {
+
+       var remoteAddr net.Addr
+       reqBody, err := json.Marshal(physLocation)
+       reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: 
remoteAddr}
+       if err != nil {
+               return tc.Alerts{}, reqInf, err
+       }
+       route := fmt.Sprintf("%s/%d", API_v13_PHYS_LOCATIONS, id)
+       resp, remoteAddr, err := to.request(http.MethodPut, route, reqBody)
+       if err != nil {
+               return tc.Alerts{}, reqInf, err
+       }
+       defer resp.Body.Close()
+       var alerts tc.Alerts
+       err = json.NewDecoder(resp.Body).Decode(&alerts)
+       return alerts, reqInf, nil
+}
+
+// Returns a list of physLocations
+func (to *Session) GetPhysLocations() ([]tc.PhysLocation, ReqInf, error) {
+       resp, remoteAddr, err := to.request(http.MethodGet, 
API_v13_PHYS_LOCATIONS, nil)
+       reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: 
remoteAddr}
+       if err != nil {
+               return nil, reqInf, err
+       }
+       defer resp.Body.Close()
+
+       var data tc.PhysLocationsResponse
+       err = json.NewDecoder(resp.Body).Decode(&data)
+       return data.Response, reqInf, nil
+}
+
+// GET a PhysLocation by the PhysLocation id
+func (to *Session) GetPhysLocationByID(id int) ([]tc.PhysLocation, ReqInf, 
error) {
+       route := fmt.Sprintf("%s/%d", API_v13_PHYS_LOCATIONS, id)
+       resp, remoteAddr, err := to.request(http.MethodGet, route, nil)
+       reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: 
remoteAddr}
+       if err != nil {
+               return nil, reqInf, err
+       }
+       defer resp.Body.Close()
+
+       var data tc.PhysLocationsResponse
+       if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
+               return nil, reqInf, err
+       }
+
+       return data.Response, reqInf, nil
+}
+
+// GET a PhysLocation by the PhysLocation name
+func (to *Session) GetPhysLocationByName(name string) ([]tc.PhysLocation, 
ReqInf, error) {
+       url := fmt.Sprintf("%s?name=%s", API_v13_PHYS_LOCATIONS, name)
+       resp, remoteAddr, err := to.request(http.MethodGet, url, nil)
+       reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: 
remoteAddr}
+       if err != nil {
+               return nil, reqInf, err
+       }
+       defer resp.Body.Close()
+
+       var data tc.PhysLocationsResponse
+       if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
+               return nil, reqInf, err
+       }
+
+       return data.Response, reqInf, nil
+}
+
+// DELETE a PhysLocation by ID
+func (to *Session) DeletePhysLocationByID(id int) (tc.Alerts, ReqInf, error) {
+       route := fmt.Sprintf("%s/%d", API_v13_PHYS_LOCATIONS, id)
+       resp, remoteAddr, err := to.request(http.MethodDelete, route, nil)
+       reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: 
remoteAddr}
+       if err != nil {
+               return tc.Alerts{}, reqInf, err
+       }
+       defer resp.Body.Close()
+       var alerts tc.Alerts
+       err = json.NewDecoder(resp.Body).Decode(&alerts)
+       return alerts, reqInf, nil
+}
diff --git a/traffic_ops/testing/api/phys_location_test.go 
b/traffic_ops/testing/api/phys_location_test.go
new file mode 100644
index 0000000000..ef21730c48
--- /dev/null
+++ b/traffic_ops/testing/api/phys_location_test.go
@@ -0,0 +1,107 @@
+/*
+
+   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 api
+
+import (
+       "testing"
+
+       "github.com/apache/incubator-trafficcontrol/lib/go-log"
+       "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+)
+
+func TestPhysLocations(t *testing.T) {
+
+       CreateTestPhysLocations(t)
+       //UpdateTestPhysLocations(t)
+       //GetTestPhysLocations(t)
+       //DeleteTestPhysLocations(t)
+
+}
+
+func CreateTestPhysLocations(t *testing.T) {
+       for _, physLocation := range testData.PhysLocations {
+               resp, _, err := TOSession.CreatePhysLocation(physLocation)
+               log.Debugln("Response: ", resp)
+               if err != nil {
+                       t.Errorf("could not CREATE physLocation: %v\n", err)
+               }
+       }
+}
+
+func UpdateTestPhysLocations(t *testing.T) {
+
+       firstPhysLocation := testData.PhysLocations[0]
+       // Retrieve the PhysLocation by physLocation so we can get the id for 
the Update
+       resp, _, err := TOSession.GetPhysLocationByName(firstPhysLocation.Name)
+       if err != nil {
+               t.Errorf("cannot GET PhysLocation by physLocation: %v - %v\n", 
firstPhysLocation.Name, err)
+       }
+       remotePhysLocation := resp[0]
+       expectedPhysLocationName := "UPDATED"
+       remotePhysLocation.Name = expectedPhysLocation
+       var alert tc.Alerts
+       alert, _, err = TOSession.UpdatePhysLocationByID(remotePhysLocation.ID, 
remotePhysLocation)
+       if err != nil {
+               t.Errorf("cannot UPDATE PhysLocation by id: %v - %v\n", err, 
alert)
+       }
+
+       // Retrieve the PhysLocation to check physLocation got updated
+       resp, _, err = TOSession.GetPhysLocationByID(remotePhysLocation.ID)
+       if err != nil {
+               t.Errorf("cannot GET PhysLocation by physLocation: %v - %v\n", 
firstPhysLocation.Name, err)
+       }
+       respPhysLocation := resp[0]
+       if respPhysLocation.Name != expectedPhysLocation {
+               t.Errorf("results do not match actual: %s, expected: %s\n", 
respPhysLocation.Name, expectedPhysLocation)
+       }
+
+}
+
+func GetTestPhysLocations(t *testing.T) {
+       for _, physLocation := range testData.PhysLocations {
+               resp, _, err := 
TOSession.GetPhysLocationByName(physLocation.Name)
+               if err != nil {
+                       t.Errorf("cannot GET PhysLocation by physLocation: %v - 
%v\n", err, resp)
+               }
+       }
+}
+
+func DeleteTestPhysLocations(t *testing.T) {
+
+       physLocation := testData.PhysLocations[1]
+
+       // Retrieve the PhysLocation by name so we can get the id
+       resp, _, err := TOSession.GetPhysLocationByName(physLocation.Name)
+       if err != nil {
+               t.Errorf("cannot GET PhysLocation by name: %v - %v\n", 
physLocation.Name, err)
+       }
+       respPhysLocation := resp[0]
+
+       delResp, _, err := TOSession.DeletePhysLocationByID(respPhysLocation.ID)
+       if err != nil {
+               t.Errorf("cannot DELETE PhysLocation by physLocation: %v - 
%v\n", err, delResp)
+       }
+
+       // Retrieve the PhysLocation to see if it got deleted
+       physLocationResp, _, err := 
TOSession.GetPhysLocationByName(physLocation.Name)
+       if err != nil {
+               t.Errorf("error deleting PhysLocation: %s\n", err.Error())
+       }
+       if len(physLocationResp) > 0 {
+               t.Errorf("expected PhysLocation: %s to be deleted\n", 
physLocation.Name)
+       }
+
+}
diff --git a/traffic_ops/testing/api/tc-fixtures.json 
b/traffic_ops/testing/api/tc-fixtures.json
index 2d3a65b6d8..105838827d 100644
--- a/traffic_ops/testing/api/tc-fixtures.json
+++ b/traffic_ops/testing/api/tc-fixtures.json
@@ -86,6 +86,50 @@
             "name": "division2"
         }
     ],
+    "physLocations": [
+        {
+            "address": "1234 mile high circle",
+            "name": "Denver",
+            "comments": "comments 1",
+            "email": "[email protected]",
+            "shortName": "denver",
+            "poc": "Point Of Contact1",
+            "phone": "303-111-1111",
+            "city": "Denver",
+            "state": "CO",
+            "zip": "80202",
+            "region": "region1",
+            "regionId": 100
+        },
+        {
+            "address": "1234 green way",
+            "name": "Boulder",
+            "comments": "comments 2",
+            "email": "[email protected]",
+            "shortName": "boulder",
+            "poc": "Point Of Contact1",
+            "phone": "303-222-2222",
+            "city": "Boulder",
+            "state": "CO",
+            "zip": "80301",
+            "region": "region1",
+            "regionId": 100
+        },
+        {
+            "address": "1234 green way",
+            "name": "HotAtlanta",
+            "comments": "comments 3",
+            "email": "[email protected]",
+            "shortName": "boulder",
+            "poc": "Point Of Contact1",
+            "phone": "404-222-2222",
+            "city": "Atlanta",
+            "state": "GA",
+            "zip": "30301",
+            "region": "region2",
+            "regionId": 200
+        }
+    ],
     "regions": [
         {
             "divisionName": "division1",
diff --git a/traffic_ops/testing/api/v13/phys_locations_test.go 
b/traffic_ops/testing/api/v13/phys_locations_test.go
new file mode 100644
index 0000000000..aa5f787aa2
--- /dev/null
+++ b/traffic_ops/testing/api/v13/phys_locations_test.go
@@ -0,0 +1,108 @@
+/*
+
+   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 v13
+
+import (
+       "testing"
+
+       "github.com/apache/incubator-trafficcontrol/lib/go-log"
+       tc "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+)
+
+func TestPhysLocations(t *testing.T) {
+
+       CreateTestPhysLocations(t)
+       UpdateTestPhysLocations(t)
+       GetTestPhysLocations(t)
+       DeleteTestPhysLocations(t)
+
+}
+
+func CreateTestPhysLocations(t *testing.T) {
+
+       for _, pl := range testData.PhysLocations {
+               resp, _, err := TOSession.CreatePhysLocation(pl)
+               log.Debugln("Response: ", resp)
+               if err != nil {
+                       t.Errorf("could not CREATE phys_locations: %v\n", err)
+               }
+       }
+
+}
+
+func UpdateTestPhysLocations(t *testing.T) {
+
+       firstPhysLocation := testData.PhysLocations[0]
+       // Retrieve the PhysLocation by name so we can get the id for the Update
+       resp, _, err := TOSession.GetPhysLocationByName(firstPhysLocation.Name)
+       if err != nil {
+               t.Errorf("cannot GET PhysLocation by name: %v - %v\n", 
firstPhysLocation.Name, err)
+       }
+       remotePhysLocation := resp[0]
+       expectedPhysLocationName := "UPDATED"
+       remotePhysLocation.Name = expectedPhysLocationName
+       var alert tc.Alerts
+       alert, _, err = TOSession.UpdatePhysLocationByID(remotePhysLocation.ID, 
remotePhysLocation)
+       if err != nil {
+               t.Errorf("cannot UPDATE PhysLocation by id: %v - %v\n", err, 
alert)
+       }
+
+       // Retrieve the PhysLocation to check PhysLocation name got updated
+       resp, _, err = TOSession.GetPhysLocationByID(remotePhysLocation.ID)
+       if err != nil {
+               t.Errorf("cannot GET PhysLocation by name: %v - %v\n", 
firstPhysLocation.Name, err)
+       }
+       respPhysLocation := resp[0]
+       if respPhysLocation.Name != expectedPhysLocationName {
+               t.Errorf("results do not match actual: %s, expected: %s\n", 
respPhysLocation.Name, expectedPhysLocationName)
+       }
+
+}
+
+func GetTestPhysLocations(t *testing.T) {
+
+       for _, pl := range testData.PhysLocations {
+               resp, _, err := TOSession.GetPhysLocationByName(pl.Name)
+               if err != nil {
+                       t.Errorf("cannot GET PhysLocation by name: %v - %v\n", 
err, resp)
+               }
+       }
+}
+
+func DeleteTestPhysLocations(t *testing.T) {
+
+       pl := testData.PhysLocations[1]
+       // Retrieve the PhysLocation by name so we can get the id for the Update
+       resp, _, err := TOSession.GetPhysLocationByName(pl.Name)
+       if err != nil {
+               t.Errorf("cannot GET PhysLocation by name: %v - %v\n", pl.Name, 
err)
+       }
+       respPhysLocation := resp[0]
+
+       delResp, _, err := TOSession.DeletePhysLocationByID(respPhysLocation.ID)
+       if err != nil {
+               t.Errorf("cannot DELETE PhysLocation by name: %v - %v\n", err, 
delResp)
+       }
+
+       // Retrieve the PhysLocation to see if it got deleted
+       pls, _, err := TOSession.GetPhysLocationByName(pl.Name)
+       if err != nil {
+               t.Errorf("error deleting PhysLocation name: %s\n", err.Error())
+       }
+       if len(pls) > 0 {
+               t.Errorf("expected PhysLocation name: %s to be deleted\n", 
pl.Name)
+       }
+}
diff --git a/traffic_ops/testing/api/v13/tc-fixtures.json 
b/traffic_ops/testing/api/v13/tc-fixtures.json
index efef0a6770..dc121fd053 100644
--- a/traffic_ops/testing/api/v13/tc-fixtures.json
+++ b/traffic_ops/testing/api/v13/tc-fixtures.json
@@ -63,8 +63,8 @@
                 "active": true,
                 "ccrDnsTtl": 30,
                 "cdnId": 1,
-                "displayName": "Good Kabletown CDN",
                 "deepCachingType": "NEVER",
+                "displayName": "Good Kabletown CDN",
                 "dscp": 1,
                 "geoLimit": 1,
                 "geoProvider": 1,
@@ -85,8 +85,8 @@
                 "active": true,
                 "ccrDnsTtl": 30,
                 "cdnId": 1,
-                "displayName": "Bad Tenant",
                 "deepCachingType": "NEVER",
+                "displayName": "Bad Tenant",
                 "dscp": 0,
                 "geoLimit": 0,
                 "geoProvider": 0,
@@ -104,18 +104,18 @@
             "changeType": "create",
             "deliveryService": {
                 "ccrDnsTtl": 30,
-                "infoUrl": "xxx",
-                "orgServerFqdn": "xxx",
-                "routingName": "x routing",
                 "deepCachingType": "NEVER",
-                "dscp": 0,
                 "displayName": "Bad Test Case CDN",
+                "dscp": 0,
                 "geoLimit": 0,
                 "geoProvider": 1,
+                "infoUrl": "xxx",
                 "initialDispersion": 1,
                 "logsEnabled": true,
                 "longDesc": "long desc",
+                "orgServerFqdn": "xxx",
                 "regionalGeoBlocking": true,
+                "routingName": "x routing",
                 "tenantId": 2,
                 "xmlId": "test ds1"
             },
@@ -127,8 +127,8 @@
                 "active": false,
                 "ccrDnsTtl": 30,
                 "cdnId": 1,
-                "displayName": "Testing transitions",
                 "deepCachingType": "ALWAYS",
+                "displayName": "Testing transitions",
                 "dscp": 3,
                 "geoLimit": 1,
                 "geoProvider": 1,
@@ -166,6 +166,50 @@
             "name": "division2"
         }
     ],
+    "physLocations": [
+        {
+            "address": "1234 mile high circle",
+            "city": "Denver",
+            "comments": null,
+            "email": null,
+            "last_updated": "2018-01-19T21:19:32.081465+00:00",
+            "name": "Denver",
+            "phone": "303-111-1111",
+            "poc": null,
+            "region": 100,
+            "short_name": "denver",
+            "state": "CO",
+            "zip": "80202"
+        },
+        {
+            "address": "1234 green way",
+            "city": "Boulder",
+            "comments": null,
+            "email": null,
+            "last_updated": "2018-01-19T21:19:32.086195+00:00",
+            "name": "Boulder",
+            "phone": "303-222-2222",
+            "poc": null,
+            "region": 100,
+            "short_name": "boulder",
+            "state": "CO",
+            "zip": "80301"
+        },
+        {
+            "address": "1234 southern way",
+            "city": "Atlanta",
+            "comments": null,
+            "email": null,
+            "last_updated": "2018-01-19T21:19:32.089538+00:00",
+            "name": "HotAtlanta",
+            "phone": "404-222-2222",
+            "poc": null,
+            "region": 100,
+            "short_name": "atlanta",
+            "state": "GA",
+            "zip": "30301"
+        }
+    ],
     "regions": [
         {
             "divisionName": "division1",
diff --git a/traffic_ops/testing/api/v13/traffic_control.go 
b/traffic_ops/testing/api/v13/traffic_control.go
index 968b9e4aa4..af6637d75c 100644
--- a/traffic_ops/testing/api/v13/traffic_control.go
+++ b/traffic_ops/testing/api/v13/traffic_control.go
@@ -19,14 +19,14 @@ import tcapi 
"github.com/apache/incubator-trafficcontrol/lib/go-tc"
 
 // TrafficControl - maps to the tc-fixtures.json file
 type TrafficControl struct {
-       ASNs                    []tc.ASN                       `json:"asns"`
+       ASNs                    []tcapi.ASN                    `json:"asns"`
        CDNs                    []tcapi.CDN                    `json:"cdns"`
-       Cachegroups             []tc.CacheGroup                
`json:"cachegroups"`
+       Cachegroups             []tcapi.CacheGroup             
`json:"cachegroups"`
        DeliveryServiceRequests []tcapi.DeliveryServiceRequest 
`json:"deliveryServiceRequests"`
-       DeliveryServices        []tc.DeliveryService           
`json:"deliveryservices"`
        DeliveryServices        []tcapi.DeliveryService        
`json:"deliveryservices"`
-       Divisions               []tc.Division                  
`json:"divisions"`
-       Regions                 []tc.Region                    `json:"regions"`
-       Statuses                []tc.Status                    `json:"statuses"`
-       Tenants                 []tc.Tenant                    `json:"tenants"`
+       Divisions               []tcapi.Division               
`json:"divisions"`
+       PhysLocations           []tcapi.PhysLocation           
`json:"physLocations"`
+       Regions                 []tcapi.Region                 `json:"regions"`
+       Statuses                []tcapi.Status                 `json:"statuses"`
+       Tenants                 []tcapi.Tenant                 `json:"tenants"`
 }
diff --git a/traffic_ops/traffic_ops_golang/api/change_log.go 
b/traffic_ops/traffic_ops_golang/api/change_log.go
index 73c06fceba..ac47809e7a 100644
--- a/traffic_ops/traffic_ops_golang/api/change_log.go
+++ b/traffic_ops/traffic_ops_golang/api/change_log.go
@@ -48,6 +48,7 @@ func CreateChangeLog(level string, action string, i 
Identifier, user auth.Curren
        query := `INSERT INTO log (level, message, tm_user) VALUES ($1, $2, $3)`
        id, _ := i.GetID()
        message := action + " " + i.GetType() + ": " + i.GetAuditName() + " id: 
" + strconv.Itoa(id)
+       log.Debugf("about to exec ", query, " with ", message)
        _, err := db.Exec(query, level, message, user.ID)
        if err != nil {
                log.Errorf("received error: %++v from audit log insertion", err)
diff --git a/traffic_ops/traffic_ops_golang/phys_locations.go 
b/traffic_ops/traffic_ops_golang/phys_locations.go
deleted file mode 100644
index b76cafbabd..0000000000
--- a/traffic_ops/traffic_ops_golang/phys_locations.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package main
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import (
-       "encoding/json"
-       "fmt"
-       "net/http"
-
-       "github.com/apache/incubator-trafficcontrol/lib/go-log"
-       "github.com/apache/incubator-trafficcontrol/lib/go-tc"
-       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/api"
-       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
-       "github.com/jmoiron/sqlx"
-)
-
-func physLocationsHandler(db *sqlx.DB) http.HandlerFunc {
-       return func(w http.ResponseWriter, r *http.Request) {
-               handleErrs := tc.GetHandleErrorsFunc(w, r)
-
-               params, err := api.GetCombinedParams(r)
-               if err != nil {
-                       log.Errorf("unable to get parameters from request: %s", 
err)
-                       handleErrs(http.StatusInternalServerError, err)
-               }
-
-               resp, errs, errType := getPhysLocationsResponse(params, db)
-               if len(errs) > 0 {
-                       tc.HandleErrorsWithType(errs, errType, handleErrs)
-                       return
-               }
-
-               respBts, err := json.Marshal(resp)
-               if err != nil {
-                       handleErrs(http.StatusInternalServerError, err)
-                       return
-               }
-
-               w.Header().Set("Content-Type", "application/json")
-               fmt.Fprintf(w, "%s", respBts)
-       }
-}
-
-func getPhysLocationsResponse(params map[string]string, db *sqlx.DB) 
(*tc.PhysLocationsResponse, []error, tc.ApiErrorType) {
-       physLocations, errs, errType := getPhysLocations(params, db)
-       if len(errs) > 0 {
-               return nil, errs, errType
-       }
-       resp := tc.PhysLocationsResponse{
-               Response: physLocations,
-       }
-       return &resp, nil, tc.NoError
-}
-
-func getPhysLocations(params map[string]string, db *sqlx.DB) 
([]tc.PhysLocation, []error, tc.ApiErrorType) {
-       var rows *sqlx.Rows
-       var err error
-
-       // Query Parameters to Database Query column mappings
-       // see the fields mapped in the SQL query
-       queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{
-               "id":     dbhelpers.WhereColumnInfo{"pl.id", api.IsInt},
-               "region": dbhelpers.WhereColumnInfo{"pl.region", api.IsInt},
-       }
-
-       where, orderBy, queryValues, errs := 
dbhelpers.BuildWhereAndOrderBy(params, queryParamsToQueryCols)
-       if len(errs) > 0 {
-               return nil, errs, tc.DataConflictError
-       }
-
-       query := selectPhysLocationsQuery() + where + orderBy
-       log.Debugln("Query is ", query)
-
-       rows, err = db.NamedQuery(query, queryValues)
-       if err != nil {
-               return nil, []error{err}, tc.SystemError
-       }
-       defer rows.Close()
-
-       physLocations := []tc.PhysLocation{}
-       for rows.Next() {
-               var s tc.PhysLocation
-               if err = rows.StructScan(&s); err != nil {
-                       return nil, []error{fmt.Errorf("getting physLocations: 
%v", err)}, tc.SystemError
-               }
-               physLocations = append(physLocations, s)
-       }
-       return physLocations, nil, tc.NoError
-}
-
-func selectPhysLocationsQuery() string {
-
-       query := `SELECT
-pl.address,
-pl.city,
-COALESCE(pl.comments, '') as comments,
-COALESCE(pl.email, '') as email,
-pl.id,
-pl.last_updated,
-pl.name,
-COALESCE(pl.phone, '') as phone,
-COALESCE(pl.poc, '') as poc,
-pl.region as regionid,
-r.name as region,
-pl.short_name,
-pl.state,
-pl.zip
-FROM phys_location pl
-JOIN region r ON pl.region = r.id`
-       return query
-}
diff --git a/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go 
b/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go
new file mode 100644
index 0000000000..7632343fcb
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go
@@ -0,0 +1,370 @@
+package physlocation
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+       "errors"
+       "fmt"
+       "strconv"
+
+       "github.com/apache/incubator-trafficcontrol/lib/go-log"
+       "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/api"
+       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/auth"
+       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+       "github.com/jmoiron/sqlx"
+       "github.com/lib/pq"
+)
+
+//we need a type alias to define functions on
+type TOPhysLocation tc.PhysLocationNullable
+
+//the refType is passed into the handlers where a copy of its type is used to 
decode the json.
+var refType = TOPhysLocation(tc.PhysLocationNullable{})
+
+func GetRefType() *TOPhysLocation {
+       return &refType
+}
+
+//Implementation of the Identifier, Validator interface functions
+func (pl *TOPhysLocation) GetID() (int, bool) {
+       if pl.ID == nil {
+               return 0, false
+       }
+       return *pl.ID, true
+}
+
+func (pl *TOPhysLocation) GetAuditName() string {
+       if pl.Name != nil {
+               return *pl.Name
+       }
+       if pl.ID != nil {
+               return strconv.Itoa(*pl.ID)
+       }
+       return "unknown"
+}
+
+func (pl *TOPhysLocation) GetType() string {
+       return "physLocation"
+}
+
+func (pl *TOPhysLocation) SetID(i int) {
+       pl.ID = &i
+}
+
+func (pl *TOPhysLocation) Validate(db *sqlx.DB) []error {
+       errs := []error{}
+       name := pl.Name
+       if name != nil && len(*name) < 1 {
+               errs = append(errs, errors.New(`PhysLocation 'name' is 
required.`))
+       }
+       return errs
+}
+
+func (pl *TOPhysLocation) Read(db *sqlx.DB, parameters map[string]string, user 
auth.CurrentUser) ([]interface{}, []error, tc.ApiErrorType) {
+       var rows *sqlx.Rows
+
+       // Query Parameters to Database Query column mappings
+       // see the fields mapped in the SQL query
+       queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{
+               "name":   dbhelpers.WhereColumnInfo{"pl.name", nil},
+               "id":     dbhelpers.WhereColumnInfo{"pl.id", api.IsInt},
+               "region": dbhelpers.WhereColumnInfo{"pl.region", api.IsInt},
+       }
+       where, orderBy, queryValues, errs := 
dbhelpers.BuildWhereAndOrderBy(parameters, queryParamsToQueryCols)
+       if len(errs) > 0 {
+               return nil, errs, tc.DataConflictError
+       }
+
+       query := selectQuery() + where + orderBy
+       log.Debugln("Query is ", query)
+
+       rows, err := db.NamedQuery(query, queryValues)
+       if err != nil {
+               log.Errorf("Error querying PhysLocations: %v", err)
+               return nil, []error{tc.DBError}, tc.SystemError
+       }
+       defer rows.Close()
+
+       physLocations := []interface{}{}
+       for rows.Next() {
+               var s tc.PhysLocationNullable
+               if err = rows.StructScan(&s); err != nil {
+                       log.Errorf("error parsing PhysLocation rows: %v", err)
+                       return nil, []error{tc.DBError}, tc.SystemError
+               }
+               physLocations = append(physLocations, s)
+       }
+
+       return physLocations, []error{}, tc.NoError
+
+}
+
+func selectQuery() string {
+
+       query := `SELECT
+pl.address,
+pl.city,
+pl.comments,
+pl.email,
+pl.id,
+pl.last_updated,
+pl.name,
+pl.phone,
+pl.poc,
+r.id as region,
+r.name as region_name,
+pl.short_name,
+pl.state,
+pl.zip
+FROM phys_location pl
+JOIN region r ON pl.region = r.id`
+
+       return query
+}
+
+//The TOPhysLocation implementation of the Updater interface
+//all implementations of Updater should use transactions and return the proper 
errorType
+//ParsePQUniqueConstraintError is used to determine if a phys_location 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 (pl *TOPhysLocation) Update(db *sqlx.DB, user auth.CurrentUser) (error, 
tc.ApiErrorType) {
+       rollbackTransaction := true
+       tx, err := db.Beginx()
+       defer func() {
+               if tx == nil || !rollbackTransaction {
+                       return
+               }
+               err := tx.Rollback()
+               if err != nil {
+                       log.Errorln(errors.New("rolling back transaction: " + 
err.Error()))
+               }
+       }()
+
+       if err != nil {
+               log.Error.Printf("could not begin transaction: %v", err)
+               return tc.DBError, tc.SystemError
+       }
+       log.Debugf("about to run exec query: %s with phys_location: %++v", 
updateQuery(), pl)
+       resultRows, err := tx.NamedQuery(updateQuery(), pl)
+       if err != nil {
+               if pqErr, ok := err.(*pq.Error); ok {
+                       err, eType := 
dbhelpers.ParsePQUniqueConstraintError(pqErr)
+                       if eType == tc.DataConflictError {
+                               return errors.New("a phys_location with " + 
err.Error()), eType
+                       }
+                       return err, eType
+               }
+               log.Errorf("received error: %++v from update execution", err)
+               return tc.DBError, tc.SystemError
+       }
+       defer resultRows.Close()
+
+       var lastUpdated tc.Time
+       rowsAffected := 0
+       for resultRows.Next() {
+               rowsAffected++
+               if err := resultRows.Scan(&lastUpdated); err != nil {
+                       log.Error.Printf("could not scan lastUpdated from 
insert: %s\n", err)
+                       return tc.DBError, tc.SystemError
+               }
+       }
+       log.Debugf("lastUpdated: %++v", lastUpdated)
+       pl.LastUpdated = lastUpdated
+       if rowsAffected != 1 {
+               if rowsAffected < 1 {
+                       return errors.New("no phys_location found with this 
id"), tc.DataMissingError
+               }
+               return fmt.Errorf("this update affected too many rows: %d", 
rowsAffected), tc.SystemError
+       }
+       err = tx.Commit()
+       if err != nil {
+               log.Errorln("Could not commit transaction: ", err)
+               return tc.DBError, tc.SystemError
+       }
+       rollbackTransaction = false
+       return nil, tc.NoError
+}
+
+//The TOPhysLocation implementation of the Creator interface
+//all implementations of Creator should use transactions and return the proper 
errorType
+//ParsePQUniqueConstraintError is used to determine if a phys_location 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 
phys_location and have
+//to be added to the struct
+func (pl *TOPhysLocation) Create(db *sqlx.DB, user auth.CurrentUser) (error, 
tc.ApiErrorType) {
+       rollbackTransaction := true
+       tx, err := db.Beginx()
+       defer func() {
+               if tx == nil || !rollbackTransaction {
+                       return
+               }
+               err := tx.Rollback()
+               if err != nil {
+                       log.Errorln(errors.New("rolling back transaction: " + 
err.Error()))
+               }
+       }()
+
+       if err != nil {
+               log.Error.Printf("could not begin transaction: %v", err)
+               return tc.DBError, tc.SystemError
+       }
+       resultRows, err := tx.NamedQuery(insertQuery(), pl)
+       if err != nil {
+               if pqErr, ok := err.(*pq.Error); ok {
+                       err, eType := 
dbhelpers.ParsePQUniqueConstraintError(pqErr)
+                       if eType == tc.DataConflictError {
+                               return errors.New("a phys_location with " + 
err.Error()), eType
+                       }
+                       return err, eType
+               }
+               log.Errorf("received non pq error: %++v from create execution", 
err)
+               return tc.DBError, tc.SystemError
+       }
+       defer resultRows.Close()
+
+       var id int
+       var lastUpdated tc.Time
+       rowsAffected := 0
+       for resultRows.Next() {
+               rowsAffected++
+               if err := resultRows.Scan(&id, &lastUpdated); err != nil {
+                       log.Error.Printf("could not scan id from insert: %s\n", 
err)
+                       return tc.DBError, tc.SystemError
+               }
+       }
+       if rowsAffected == 0 {
+               err = errors.New("no phys_location was inserted, no id was 
returned")
+               log.Errorln(err)
+               return tc.DBError, tc.SystemError
+       }
+       if rowsAffected > 1 {
+               err = errors.New("too many ids returned from phys_location 
insert")
+               log.Errorln(err)
+               return tc.DBError, tc.SystemError
+       }
+
+       pl.SetID(id)
+       pl.LastUpdated = lastUpdated
+       err = tx.Commit()
+       if err != nil {
+               log.Errorln("Could not commit transaction: ", err)
+               return tc.DBError, tc.SystemError
+       }
+       rollbackTransaction = false
+       return nil, tc.NoError
+}
+
+//The PhysLocation implementation of the Deleter interface
+//all implementations of Deleter should use transactions and return the proper 
errorType
+func (pl *TOPhysLocation) Delete(db *sqlx.DB, user auth.CurrentUser) (error, 
tc.ApiErrorType) {
+       rollbackTransaction := true
+       tx, err := db.Beginx()
+       defer func() {
+               if tx == nil || !rollbackTransaction {
+                       return
+               }
+               err := tx.Rollback()
+               if err != nil {
+                       log.Errorln(errors.New("rolling back transaction: " + 
err.Error()))
+               }
+       }()
+
+       if err != nil {
+               log.Error.Printf("could not begin transaction: %v", err)
+               return tc.DBError, tc.SystemError
+       }
+       log.Debugf("about to run exec query: %s with phys_location: %++v", 
deleteQuery(), pl)
+       result, err := tx.NamedExec(deleteQuery(), pl)
+       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 {
+               return errors.New("no phys_location with that id found"), 
tc.DataMissingError
+       }
+       if rowsAffected > 1 {
+               return fmt.Errorf("this create affected too many rows: %d", 
rowsAffected), tc.SystemError
+       }
+
+       err = tx.Commit()
+       if err != nil {
+               log.Errorln("Could not commit transaction: ", err)
+               return tc.DBError, tc.SystemError
+       }
+       rollbackTransaction = false
+       return nil, tc.NoError
+}
+
+func updateQuery() string {
+       query := `UPDATE
+phys_location SET
+address=:address,
+city=:city,
+comments=:comments,
+email=:email,
+name=:name,
+phone=:phone,
+poc=:poc,
+region=:region,
+short_name=:short_name,
+state=:state,
+zip=:zip
+WHERE id=:id RETURNING last_updated`
+       return query
+}
+
+func insertQuery() string {
+       query := `INSERT INTO phys_location (
+address,
+city,
+comments,
+email,
+name,
+phone,
+poc,
+region,
+short_name,
+state,
+zip) VALUES (
+:address,
+:city,
+:comments,
+:email,
+:name,
+:phone,
+:poc,
+:region,
+:short_name,
+:state,
+:zip) RETURNING id,last_updated`
+       return query
+}
+
+func deleteQuery() string {
+       query := `DELETE FROM phys_location
+WHERE id=:id`
+       return query
+}
diff --git a/traffic_ops/traffic_ops_golang/phys_locations_test.go 
b/traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go
similarity index 70%
rename from traffic_ops/traffic_ops_golang/phys_locations_test.go
rename to traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go
index b47c69c9bb..ff61e435ba 100644
--- a/traffic_ops/traffic_ops_golang/phys_locations_test.go
+++ b/traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go
@@ -1,4 +1,4 @@
-package main
+package physlocation
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -24,6 +24,8 @@ import (
        "time"
 
        "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/test"
        "github.com/jmoiron/sqlx"
 
@@ -41,8 +43,8 @@ func getTestPhysLocations() []tc.PhysLocation {
                Name:        "physLocation1",
                Phone:       "303-210-0000",
                POC:         "Dennis Thompson",
-               RegionId:    1,
-               Region:      "Central",
+               RegionID:    1,
+               RegionName:  "region1",
                ShortName:   "pl1",
                State:       "CO",
                Zip:         "80210",
@@ -81,8 +83,8 @@ func TestGetPhysLocations(t *testing.T) {
                        ts.Name,
                        ts.Phone,
                        ts.POC,
-                       ts.RegionId,
-                       ts.Region,
+                       ts.RegionID,
+                       ts.RegionName,
                        ts.ShortName,
                        ts.State,
                        ts.Zip,
@@ -91,25 +93,34 @@ func TestGetPhysLocations(t *testing.T) {
        mock.ExpectQuery("SELECT").WillReturnRows(rows)
        v := map[string]string{"dsId": "1"}
 
-       servers, errs, errType := getPhysLocations(v, db)
+       physLocations, errs, _ := refType.Read(db, v, auth.CurrentUser{})
        if len(errs) > 0 {
-               t.Errorf("getPhysLocations expected: no errors, actual: %v with 
error type: %s", err, errType.String())
+               t.Errorf("physLocation.Read expected: no errors, actual: %v", 
errs)
        }
 
-       if len(servers) != 2 {
-               t.Errorf("getPhysLocations expected: len(servers) == 2, actual: 
%v", len(servers))
+       if len(physLocations) != 2 {
+               t.Errorf("physLocation.Read expected: len(physLocations) == 2, 
actual: %v", len(physLocations))
        }
 
 }
 
-type SortablePhysLocations []tc.PhysLocation
+func TestInterfaces(t *testing.T) {
+       var i interface{}
+       i = &TOPhysLocation{}
 
-func (s SortablePhysLocations) Len() int {
-       return len(s)
-}
-func (s SortablePhysLocations) Swap(i, j int) {
-       s[i], s[j] = s[j], s[i]
-}
-func (s SortablePhysLocations) Less(i, j int) bool {
-       return s[i].Name < s[j].Name
+       if _, ok := i.(api.Creator); !ok {
+               t.Errorf("PhysLocation must be Creator")
+       }
+       if _, ok := i.(api.Reader); !ok {
+               t.Errorf("PhysLocation must be Reader")
+       }
+       if _, ok := i.(api.Updater); !ok {
+               t.Errorf("PhysLocation must be Updater")
+       }
+       if _, ok := i.(api.Deleter); !ok {
+               t.Errorf("PhysLocation must be Deleter")
+       }
+       if _, ok := i.(api.Identifier); !ok {
+               t.Errorf("PhysLocation must be Identifier")
+       }
 }
diff --git a/traffic_ops/traffic_ops_golang/routes.go 
b/traffic_ops/traffic_ops_golang/routes.go
index 317d71de84..8c847bbf0e 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -35,6 +35,7 @@ import (
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/cdn"
        dsrequest 
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/request"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/division"
+       
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/physlocation"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/region"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/status"
        
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/systeminfo"
@@ -97,6 +98,13 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                {1.3, http.MethodPut, `deliveryservices/{xmlID}/urisignkeys$`, 
saveDeliveryServiceURIKeysHandler(d.DB, d.Config), auth.PrivLevelAdmin, 
Authenticated, nil},
                {1.3, http.MethodDelete, 
`deliveryservices/{xmlID}/urisignkeys$`, 
removeDeliveryServiceURIKeysHandler(d.DB, d.Config), auth.PrivLevelAdmin, 
Authenticated, nil},
 
+               //Phys_Locations
+               {1.3, http.MethodGet, `phys_locations/?(\.json)?$`, 
api.ReadHandler(physlocation.GetRefType(), d.DB), auth.PrivLevelReadOnly, 
Authenticated, nil},
+               {1.3, http.MethodGet, `phys_locations/{id}$`, 
api.ReadHandler(physlocation.GetRefType(), d.DB), auth.PrivLevelReadOnly, 
Authenticated, nil},
+               {1.3, http.MethodPut, `phys_locations/{id}$`, 
api.UpdateHandler(physlocation.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
+               {1.3, http.MethodPost, `phys_locations/?$`, 
api.CreateHandler(physlocation.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
+               {1.3, http.MethodDelete, `phys_locations/{id}$`, 
api.DeleteHandler(physlocation.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
+
                //Statuses
                {1.3, http.MethodGet, `statuses/?(\.json)?$`, 
api.ReadHandler(status.GetRefType(), d.DB), auth.PrivLevelReadOnly, 
Authenticated, nil},
                {1.3, http.MethodGet, `statuses/{id}$`, 
api.ReadHandler(status.GetRefType(), d.DB), auth.PrivLevelReadOnly, 
Authenticated, nil},
@@ -141,10 +149,6 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
 
                //System
                {1.2, http.MethodGet, `system/info/?(\.json)?$`, 
systeminfo.Handler(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
-
-               //Phys_Locations
-               {1.2, http.MethodGet, `phys_locations/?(\.json)?$`, 
physLocationsHandler(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
-               {1.2, http.MethodGet, `phys_locations/{id}$`, 
physLocationsHandler(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
        }
        return routes, proxyHandler, nil
 }


 

----------------------------------------------------------------
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:
[email protected]


With regards,
Apache Git Services

Reply via email to