dewrich closed pull request #2441: Add TO Go delete deliveryservice_server
URL: https://github.com/apache/trafficcontrol/pull/2441
 
 
   

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/deliveryservices.go b/lib/go-tc/deliveryservices.go
index 9f8f56e0e..6f6093f59 100644
--- a/lib/go-tc/deliveryservices.go
+++ b/lib/go-tc/deliveryservices.go
@@ -543,3 +543,9 @@ type DeliveryServiceRouting struct {
        RegionalAlternate int     `json:"regionalAlternate"`
        RegionalDenied    int     `json:"regionalDenied"`
 }
+
+type DSServerIDs struct {
+       DeliveryServiceID *int  `json:"dsId", db:"deliveryservice"`
+       ServerIDs         []int `json:"servers"`
+       Replace           *bool `json:"replace"`
+}
diff --git a/traffic_ops/client/v13/deliveryserviceserver.go 
b/traffic_ops/client/v13/deliveryserviceserver.go
new file mode 100644
index 000000000..75ef91222
--- /dev/null
+++ b/traffic_ops/client/v13/deliveryserviceserver.go
@@ -0,0 +1,67 @@
+/*
+
+   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 (
+       "encoding/json"
+       "strconv"
+
+       "github.com/apache/trafficcontrol/lib/go-tc"
+       "github.com/apache/trafficcontrol/lib/go-util"
+)
+
+func (to *Session) GetDeliveryServiceServers() ([]tc.DeliveryServiceServer, 
ReqInf, error) {
+       path := apiBase + `/deliveryserviceserver`
+       // deliveryService
+       resp := tc.DeliveryServiceServerResponse{}
+       reqInf, err := get(to, path, &resp)
+       if err != nil {
+               return nil, reqInf, err
+       }
+       return resp.Response, reqInf, nil
+}
+
+// CreateDeliveryServiceServers associates the given servers with the given 
delivery services. If replace is true, it deletes any existing associations for 
the given delivery service.
+func (to *Session) CreateDeliveryServiceServers(dsID int, serverIDs []int, 
replace bool) (*tc.DSServerIDs, error) {
+       path := apiBase + `/deliveryserviceserver`
+       req := tc.DSServerIDs{
+               DeliveryServiceID: util.IntPtr(dsID),
+               ServerIDs:         serverIDs,
+               Replace:           util.BoolPtr(replace),
+       }
+       jsonReq, err := json.Marshal(&req)
+       if err != nil {
+               return nil, err
+       }
+       resp := struct {
+               Response tc.DSServerIDs `json:"response"`
+       }{}
+       if err := post(to, path, jsonReq, &resp); err != nil {
+               return nil, err
+       }
+       return &resp.Response, nil
+}
+
+// DeleteDeliveryService deletes the given delivery service server association.
+func (to *Session) DeleteDeliveryServiceServer(dsID int, serverID int) error {
+       path := apiBase + `/deliveryservice_server/` + strconv.Itoa(dsID) + `/` 
+ strconv.Itoa(serverID)
+       resp := struct{ tc.Alerts }{}
+       err := del(to, path, &resp)
+       if err != nil {
+               return err
+       }
+       return nil
+}
diff --git a/traffic_ops/testing/api/v13/deliveryserviceservers_test.go 
b/traffic_ops/testing/api/v13/deliveryserviceservers_test.go
new file mode 100644
index 000000000..2c60ae15d
--- /dev/null
+++ b/traffic_ops/testing/api/v13/deliveryserviceservers_test.go
@@ -0,0 +1,111 @@
+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 TestDeliveryServiceServers(t *testing.T) {
+       CreateTestCDNs(t)
+       CreateTestTypes(t)
+       CreateTestProfiles(t)
+       CreateTestStatuses(t)
+       CreateTestDivisions(t)
+       CreateTestRegions(t)
+       CreateTestPhysLocations(t)
+       CreateTestCacheGroups(t)
+       CreateTestServers(t)
+       CreateTestDeliveryServices(t)
+
+       DeleteTestDeliveryServiceServers(t)
+
+       DeleteTestDeliveryServices(t)
+       DeleteTestServers(t)
+       DeleteTestCacheGroups(t)
+       DeleteTestPhysLocations(t)
+       DeleteTestRegions(t)
+       DeleteTestDivisions(t)
+       DeleteTestStatuses(t)
+       DeleteTestProfiles(t)
+       DeleteTestTypes(t)
+       DeleteTestCDNs(t)
+}
+
+func DeleteTestDeliveryServiceServers(t *testing.T) {
+       log.Debugln("DeleteTestDeliveryServiceServers")
+
+       dses, _, err := TOSession.GetDeliveryServices()
+       if err != nil {
+               t.Fatalf("cannot GET DeliveryServices: %v\n", err)
+       }
+       if len(dses) < 1 {
+               t.Fatalf("GET DeliveryServices returned no dses, must have at 
least 1 to test ds-servers")
+       }
+       ds := dses[0]
+
+       servers, _, err := TOSession.GetServers()
+       if err != nil {
+               t.Fatalf("cannot GET Servers: %v\n", err)
+       }
+       if len(servers) < 1 {
+               t.Fatalf("GET Servers returned no dses, must have at least 1 to 
test ds-servers")
+       }
+       server := servers[0]
+
+       _, err = TOSession.CreateDeliveryServiceServers(ds.ID, 
[]int{server.ID}, true)
+       if err != nil {
+               t.Fatalf("POST delivery service servers: %v\n", err)
+       }
+
+       dsServers, _, err := TOSession.GetDeliveryServiceServers()
+       if err != nil {
+               t.Fatalf("GET delivery service servers: %v\n", err)
+       }
+
+       found := false
+       for _, dss := range dsServers {
+               if *dss.DeliveryService == ds.ID && *dss.Server == server.ID {
+                       found = true
+                       break
+               }
+       }
+       if !found {
+               t.Fatalf("POST delivery service servers returned success, but 
ds-server not in GET")
+       }
+
+       if err := TOSession.DeleteDeliveryServiceServer(ds.ID, server.ID); err 
!= nil {
+               t.Fatalf("DELETE delivery service server: %v\n", err)
+       }
+
+       dsServers, _, err = TOSession.GetDeliveryServiceServers()
+       if err != nil {
+               t.Fatalf("GET delivery service servers: %v\n", err)
+       }
+
+       found = false
+       for _, dss := range dsServers {
+               if *dss.DeliveryService == ds.ID && *dss.Server == server.ID {
+                       found = true
+                       break
+               }
+       }
+       if found {
+               t.Fatalf("DELETE delivery service servers returned success, but 
still in GET")
+       }
+}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go
new file mode 100644
index 000000000..77234ca32
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/delete.go
@@ -0,0 +1,72 @@
+package servers
+
+/*
+ * 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"
+       "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+)
+
+func Delete(w http.ResponseWriter, r *http.Request) {
+       inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"serverid", 
"dsid"}, []string{"serverid", "dsid"})
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, errCode, userErr, sysErr)
+               return
+       }
+       defer inf.Close()
+
+       dsID := inf.IntParams["dsid"]
+       serverID := inf.IntParams["serverid"]
+
+       userErr, sysErr, errCode = tenant.CheckID(inf.Tx.Tx, inf.User, dsID)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, errCode, userErr, sysErr)
+               return
+       }
+
+       ok, err := deleteDSServer(inf.Tx.Tx, dsID, serverID)
+       if err != nil {
+               api.HandleErr(w, r, http.StatusInternalServerError, nil, 
errors.New("deleting delivery service server: "+err.Error()))
+               return
+       }
+       if !ok {
+               api.HandleErr(w, r, http.StatusNotFound, nil, nil)
+               return
+       }
+       *inf.CommitTx = true
+       api.WriteRespAlert(w, r, tc.SuccessLevel, "Server unlinked from 
delivery service.")
+}
+
+// deleteDSServer deletes the given deliveryservice_server. Returns whether 
the server existed, and any error.
+func deleteDSServer(tx *sql.Tx, dsID int, serverID int) (bool, error) {
+       deletedServerID := 0
+       if err := tx.QueryRow(`DELETE FROM deliveryservice_server WHERE 
deliveryservice = $1 AND server = $2 RETURNING server`, dsID, 
serverID).Scan(&deletedServerID); err != nil {
+               if err == sql.ErrNoRows {
+                       return false, nil
+               }
+               return false, errors.New("deleting delivery service server: " + 
err.Error())
+       }
+       return true, nil
+}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index a65fd3fef..a49794610 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -143,8 +143,8 @@ func (dss *TODeliveryServiceServer) readDSS(db *sqlx.DB, 
params map[string]strin
        pagestr := params["page"]
        orderby := params["orderby"]
        limit := 20
-       offset := 1
-       page := 1
+       offset := 0
+       page := 0
        var err error = nil
 
        if limitstr != "" {
diff --git a/traffic_ops/traffic_ops_golang/routes.go 
b/traffic_ops/traffic_ops_golang/routes.go
index 2af14643a..91d847c96 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -169,6 +169,8 @@ func Routes(d ServerData) ([]Route, []RawRoute, 
http.Handler, error) {
                {1.1, http.MethodPost, `regions/?$`, 
api.CreateHandler(region.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
                {1.1, http.MethodDelete, `regions/{id}$`, 
api.DeleteHandler(region.GetRefType(), d.DB), auth.PrivLevelOperations, 
Authenticated, nil},
 
+               {1.1, http.MethodDelete, 
`deliveryservice_server/{dsid}/{serverid}`, dsserver.Delete, 
auth.PrivLevelReadOnly, Authenticated, nil},
+
                // get all edge servers associated with a delivery service 
(from deliveryservice_server table)
                {1.1, http.MethodGet, `deliveryserviceserver$`, 
dsserver.ReadDSSHandler(d.DB), auth.PrivLevelReadOnly, Authenticated, nil},
                {1.1, http.MethodPost, `deliveryserviceserver$`, 
dsserver.GetReplaceHandler(d.DB), auth.PrivLevelOperations, Authenticated, nil},
diff --git a/traffic_ops/traffic_ops_golang/tenant/tenancy.go 
b/traffic_ops/traffic_ops_golang/tenant/tenancy.go
index 44f1363f6..b2c5319d6 100644
--- a/traffic_ops/traffic_ops_golang/tenant/tenancy.go
+++ b/traffic_ops/traffic_ops_golang/tenant/tenancy.go
@@ -85,6 +85,37 @@ func Check(user *auth.CurrentUser, XMLID string, tx *sql.Tx) 
(error, error, int)
        return nil, nil, http.StatusOK
 }
 
+// Check checks that the given user has access to the given delivery service. 
Returns a user error, a system error, and an HTTP error code. If both the user 
and system error are nil, the error code should be ignored.
+func CheckID(tx *sql.Tx, user *auth.CurrentUser, dsID int) (error, error, int) 
{
+       ok, err := IsTenancyEnabledTx(tx)
+       if err != nil {
+               return nil, errors.New("checking tenancy enabled: " + 
err.Error()), http.StatusInternalServerError
+       }
+       if !ok {
+               return nil, nil, http.StatusOK
+       }
+
+       dsTenantID, ok, err := getDSTenantIDByIDTx(tx, dsID)
+       if err != nil {
+               return nil, errors.New("checking tenant: " + err.Error()), 
http.StatusInternalServerError
+       }
+       if !ok {
+               return errors.New("delivery service " + strconv.Itoa(dsID) + " 
not found"), nil, http.StatusNotFound
+       }
+       if dsTenantID == nil {
+               return nil, nil, http.StatusOK
+       }
+
+       authorized, err := IsResourceAuthorizedToUserTx(*dsTenantID, user, tx)
+       if err != nil {
+               return nil, errors.New("checking tenant: " + err.Error()), 
http.StatusInternalServerError
+       }
+       if !authorized {
+               return errors.New("not authorized on this tenant"), nil, 
http.StatusForbidden
+       }
+       return nil, nil, http.StatusOK
+}
+
 // returns a Tenant list that the specified user has access too.
 // NOTE: This method does not use the use_tenancy parameter and if this method 
is being used
 // to control tenancy the parameter must be checked. The method 
IsResourceAuthorizedToUser checks the use_tenancy parameter
@@ -164,6 +195,15 @@ func IsTenancyEnabled(db *sqlx.DB) bool {
        return useTenancy
 }
 
+func IsTenancyEnabledTx(tx *sql.Tx) (bool, error) {
+       query := `SELECT COALESCE(value::boolean,FALSE) AS value FROM parameter 
WHERE name = 'use_tenancy' AND config_file = 'global' UNION ALL SELECT FALSE 
FETCH FIRST 1 ROW ONLY`
+       useTenancy := false
+       if err := tx.QueryRow(query).Scan(&useTenancy); err != nil {
+               return false, errors.New("checking if tenancy is enabled: " + 
err.Error())
+       }
+       return useTenancy, nil
+}
+
 // returns a boolean value describing if the user has access to the provided 
resource tenant id and an error
 // if use_tenancy is set to false (0 in the db) this method will return true 
allowing access.
 func IsResourceAuthorizedToUser(resourceTenantID int, user auth.CurrentUser, 
db *sqlx.DB) (bool, error) {
@@ -581,3 +621,17 @@ func deleteQuery() string {
 WHERE id=:id`
        return query
 }
+
+// getDSTenantIDByIDTx returns the tenant ID, whether the delivery service 
exists, and any error.
+// Note the id may be nil, even if true is returned, if the delivery service 
exists but its tenant_id field is null.
+// TODO move somewhere generic
+func getDSTenantIDByIDTx(tx *sql.Tx, id int) (*int, bool, error) {
+       tenantID := (*int)(nil)
+       if err := tx.QueryRow(`SELECT tenant_id FROM deliveryservice where id = 
$1`, id).Scan(&tenantID); err != nil {
+               if err == sql.ErrNoRows {
+                       return nil, false, nil
+               }
+               return nil, false, fmt.Errorf("querying tenant ID for delivery 
service ID '%v': %v", id, err)
+       }
+       return tenantID, true, 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:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to