From 5b1f4bf584e5904687f6fcd7c9bd55d0b55a007a Mon Sep 17 00:00:00 2001 From: Rima Shah Date: Tue, 20 Sep 2022 18:37:32 -0600 Subject: [PATCH 01/30] Added TO logic to assign multiple servers per capability. --- CHANGELOG.md | 3 +- .../v4/multiple_servers_per_capability.rst | 83 +++++++++++++++++++ .../v5/multiple_servers_per_capability.rst | 81 ++++++++++++++++++ lib/go-tc/server_server_capability.go | 6 ++ .../api/v4/server_server_capabilities_test.go | 53 ++++++++++++ .../api/v5/server_server_capabilities_test.go | 53 ++++++++++++ .../traffic_ops_golang/routing/routes.go | 3 +- .../server/servers_server_capability.go | 67 +++++++++++++++ .../v4-client/server_server_capabilities.go | 14 +++- .../v5-client/server_server_capabilities.go | 14 +++- 10 files changed, 371 insertions(+), 6 deletions(-) create mode 100644 docs/source/api/v4/multiple_servers_per_capability.rst create mode 100644 docs/source/api/v5/multiple_servers_per_capability.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index a84a14f39a..2ac2f0d6d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ## [unreleased] ### Added +- [#6033](https://github.com/apache/trafficcontrol/issues/6033) *Traffic Ops, Traffic Portal* Added ability to assign multiple servers per capability. - [#7081](https://github.com/apache/trafficcontrol/issues/7081) *Traffic Router* Added better log messages for TR connection exceptions. - [#7089](https://github.com/apache/trafficcontrol/issues/7089) *Traffic Router* Added the ability to specify HTTPS certificate attributes. - [#7109](https://github.com/apache/trafficcontrol/pull/7109) *Traffic Router* Removed `dnssec.zone.diffing.enabled` and `dnssec.rrsig.cache.enabled` parameters. @@ -14,7 +15,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - [#7063](https://github.com/apache/trafficcontrol/pull/7063) *Traffic Ops* Added API version 5.0 (IN DEVELOPMENT) - [#2101](https://github.com/apache/trafficcontrol/issues/2101) *Traffic Portal* Added the ability to tell if a Delivery Service is the target of another steering DS. - [#6021](https://github.com/apache/trafficcontrol/issues/6021) *Traffic Portal* Added the ability to view a change logs message in it's entirety by clicking on it. -- [#6033](https://github.com/apache/trafficcontrol/issues/6033) *Traffic Ops, Traffic Portal* Added ability to assign multiple server capabilities to a server. +- [#7078](https://github.com/apache/trafficcontrol/issues/7078) *Traffic Ops, Traffic Portal* Added ability to assign multiple server capabilities to a server. - [#7096](https://github.com/apache/trafficcontrol/issues/7096) [Health Client] Added health client parent health - [#7032](https://github.com/apache/trafficcontrol/issues/7032) *Cache Config* Add t3c-apply flag to use local ATS version for config generation rather than Server package Parameter, to allow managing the ATS OS package via external tools. See 'man t3c-apply' and 'man t3c-generate' for details. - [#7097](https://github.com/apache/trafficcontrol/issues/7097) *Traffic Ops, Traffic Portal, t3c* Added the `regional` field to Delivery Services, which affects whether `maxOriginConnections` should be per Cache Group diff --git a/docs/source/api/v4/multiple_servers_per_capability.rst b/docs/source/api/v4/multiple_servers_per_capability.rst new file mode 100644 index 0000000000..b2c69fadd3 --- /dev/null +++ b/docs/source/api/v4/multiple_servers_per_capability.rst @@ -0,0 +1,83 @@ +.. +.. +.. 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. +.. + +.. _to-api-v4-multiple_servers_per_capability: + +*********************************** +``multiple_servers_per_capability`` +*********************************** + +.. versionadded:: 4.1 + +``PUT`` +======== +Associates a list of :term:`Servers` to a server capability. The API call replaces all the servers assigned to a server capability with the ones specified in the servers field. + +:Auth. Required: Yes +:Roles Required: "admin" or "operations" +:Permissions Required: SERVER:READ, SERVER-CAPABILITY:READ, SERVER-CAPABILITY:UPDATE +:Response Type: Object + +Request Structure +----------------- +:serverCapability: The unique identifier of a server capability to be associated with a :term:`Server` +:serverIds: List of :term:`Server` ids associated with a server capability + +.. code-block:: http + :caption: Request Example + + PUT /api/4.1/multiple_server_capabilities/ HTTP/1.1 + Host: trafficops.infra.ciab.test + User-Agent: curl/7.47.0 + Accept: */* + Cookie: mojolicious=... + Content-Length: 84 + Content-Type: application/json + + { + "serverCapability": "eas", + "serverIds": [2, 3] + } + +Response Structure +------------------ +:serverCapability: The unique identifier of a server capability to be associated with a :term:`Server` +:serverIds: List of :term:`Server` ids associated with a server capability + +.. code-block:: http + :caption: Response Example + + HTTP/1.1 200 OK + Access-Control-Allow-Credentials: true + Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Set-Cookie, Cookie + Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE + Access-Control-Allow-Origin: * + Content-Type: application/json + Set-Cookie: mojolicious=...; Path=/; Expires=Sat, 24 Sep 2022 22:40:54 GMT; Max-Age=3600; HttpOnly + Whole-Content-Sha512: eQrl48zWids0kDpfCYmmtYMpegjnFxfOVvlBYxxLSfp7P7p6oWX4uiC+/Cfh2X9i3G+MQ36eH95gukJqOBOGbQ== + X-Server-Name: traffic_ops_golang/ + Date: Tues, 20 Sep 2022 16:15:11 GMT + Content-Length: 157 + + { + "alerts": [{ + "text": "Multiple Servers assigned to a capability", + "level": "success" + }], + "response": { + "serverCapability": "eas", + "serverIds": [2, 3] + } + } diff --git a/docs/source/api/v5/multiple_servers_per_capability.rst b/docs/source/api/v5/multiple_servers_per_capability.rst new file mode 100644 index 0000000000..b3e1ce69bc --- /dev/null +++ b/docs/source/api/v5/multiple_servers_per_capability.rst @@ -0,0 +1,81 @@ +.. +.. +.. 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. +.. + +.. _to-api-v4-multiple_servers_per_capability: + +*********************************** +``multiple_servers_per_capability`` +*********************************** + +``PUT`` +======== +Associates a list of :term:`Servers` to a server capability. The API call replaces all the servers assigned to a server capability with the ones specified in the servers field. + +:Auth. Required: Yes +:Roles Required: "admin" or "operations" +:Permissions Required: SERVER:READ, SERVER-CAPABILITY:READ, SERVER-CAPABILITY:UPDATE +:Response Type: Object + +Request Structure +----------------- +:serverCapability: The unique identifier of a server capability to be associated with a :term:`Server` +:serverIds: List of :term:`Server` ids associated with a server capability + +.. code-block:: http + :caption: Request Example + + PUT /api/5.0/multiple_server_capabilities/ HTTP/1.1 + Host: trafficops.infra.ciab.test + User-Agent: curl/7.47.0 + Accept: */* + Cookie: mojolicious=... + Content-Length: 84 + Content-Type: application/json + + { + "serverCapability": "eas", + "serverIds": [2, 3] + } + +Response Structure +------------------ +:serverCapability: The unique identifier of a server capability to be associated with a :term:`Server` +:serverIds: List of :term:`Server` ids associated with a server capability + +.. code-block:: http + :caption: Response Example + + HTTP/1.1 200 OK + Access-Control-Allow-Credentials: true + Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Set-Cookie, Cookie + Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE + Access-Control-Allow-Origin: * + Content-Type: application/json + Set-Cookie: mojolicious=...; Path=/; Expires=Sat, 24 Sep 2022 22:40:54 GMT; Max-Age=3600; HttpOnly + Whole-Content-Sha512: eQrl48zWids0kDpfCYmmtYMpegjnFxfOVvlBYxxLSfp7P7p6oWX4uiC+/Cfh2X9i3G+MQ36eH95gukJqOBOGbQ== + X-Server-Name: traffic_ops_golang/ + Date: Tues, 20 Sep 2022 16:15:11 GMT + Content-Length: 157 + + { + "alerts": [{ + "text": "Multiple Servers assigned to a capability", + "level": "success" + }], + "response": { + "serverCapability": "eas", + "serverIds": [2, 3] + } + } diff --git a/lib/go-tc/server_server_capability.go b/lib/go-tc/server_server_capability.go index 535a95da7f..e2be10b75a 100644 --- a/lib/go-tc/server_server_capability.go +++ b/lib/go-tc/server_server_capability.go @@ -33,6 +33,12 @@ type MultipleServerCapabilities struct { ServerCapabilities []string `json:"serverCapabilities" db:"server_capability"` } +// MultipleServersToCapability represents an association between a server capability and list of servers. +type MultipleServersToCapability struct { + ServerCapability string `json:"serverCapability" db:"server_capability"` + ServersIDs []int `json:"serverIds" db:"server"` +} + // ServerServerCapabilitiesResponse is the type of a response from Traffic // Ops to a request made to its /server_server_capabilities. type ServerServerCapabilitiesResponse struct { diff --git a/traffic_ops/testing/api/v4/server_server_capabilities_test.go b/traffic_ops/testing/api/v4/server_server_capabilities_test.go index 320657cf20..0f602848c7 100644 --- a/traffic_ops/testing/api/v4/server_server_capabilities_test.go +++ b/traffic_ops/testing/api/v4/server_server_capabilities_test.go @@ -16,6 +16,7 @@ package v4 */ import ( + "encoding/json" "net/http" "net/url" "sort" @@ -37,6 +38,8 @@ func TestServerServerCapabilities(t *testing.T) { currentTime := time.Now().UTC().Add(-15 * time.Second) tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123) + var multipleSCs []string + var multipleServerIDs []int methodTests := utils.TestCase[client.Session, client.RequestOptions, tc.ServerServerCapability]{ "GET": { @@ -147,6 +150,24 @@ func TestServerServerCapabilities(t *testing.T) { Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)), }, }, + "PUT": { + "OK When Assigned Multiple Server Capabilities": { + ClientSession: TOSession, + RequestBody: map[string]interface{}{ + "serverId": GetServerID(t, "dtrc-mid-04")(), + "serverCapabilities": append(multipleSCs, "disk", "blah"), + }, + Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)), + }, + "OK When Assigned Multiple Servers Per Capability": { + ClientSession: TOSession, + RequestBody: map[string]interface{}{ + "serverIds": append(multipleServerIDs, GetServerID(t, "dtrc-mid-04")(), GetServerID(t, "dtrc-mid-01")()), + "serverCapability": "disk", + }, + Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)), + }, + }, "DELETE": { "OK when NOT the LAST SERVER of CACHE GROUP of TOPOLOGY DS which has REQUIRED CAPABILITIES": { ClientSession: TOSession, @@ -179,6 +200,23 @@ func TestServerServerCapabilities(t *testing.T) { for method, testCases := range methodTests { t.Run(method, func(t *testing.T) { for name, testCase := range testCases { + ssc := tc.ServerServerCapability{} + msc := tc.MultipleServerCapabilities{} + mspc := tc.MultipleServersToCapability{} + var serverId int + var serverCapability string + + if testCase.RequestBody != nil { + dat, err := json.Marshal(testCase.RequestBody) + assert.NoError(t, err, "Error occurred when marshalling request body: %v", err) + if method == "PUT" { + err = json.Unmarshal(dat, &msc) + } else { + err = json.Unmarshal(dat, &ssc) + } + assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err) + } + switch method { case "GET": t.Run(name, func(t *testing.T) { @@ -190,6 +228,21 @@ func TestServerServerCapabilities(t *testing.T) { case "POST": t.Run(name, func(t *testing.T) { alerts, reqInf, err := testCase.ClientSession.CreateServerServerCapability(testCase.RequestBody, testCase.RequestOpts) + alerts, reqInf, err := testCase.ClientSession.CreateServerServerCapability(ssc, testCase.RequestOpts) + for _, check := range testCase.Expectations { + check(t, reqInf, nil, alerts, err) + } + }) + case "PUT": + t.Run(name, func(t *testing.T) { + var alerts tc.Alerts + var reqInf toclientlib.ReqInf + var err error + if name == "OK When Assigned Multiple Server Capabilities" { + alerts, reqInf, err = testCase.ClientSession.AssignMultipleServerCapabilities(msc, testCase.RequestOpts) + } else if name == "OK When Assigned Multiple Servers Per Capability" { + alerts, reqInf, err = testCase.ClientSession.AssignMultipleServersPerCapability(mspc, testCase.RequestOpts) + } for _, check := range testCase.Expectations { check(t, reqInf, nil, alerts, err) } diff --git a/traffic_ops/testing/api/v5/server_server_capabilities_test.go b/traffic_ops/testing/api/v5/server_server_capabilities_test.go index abd114b97c..6361cac872 100644 --- a/traffic_ops/testing/api/v5/server_server_capabilities_test.go +++ b/traffic_ops/testing/api/v5/server_server_capabilities_test.go @@ -16,6 +16,7 @@ package v5 */ import ( + "encoding/json" "net/http" "net/url" "sort" @@ -37,6 +38,8 @@ func TestServerServerCapabilities(t *testing.T) { currentTime := time.Now().UTC().Add(-15 * time.Second) tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123) + var multipleSCs []string + var multipleServerIDs []int methodTests := utils.TestCase[client.Session, client.RequestOptions, tc.ServerServerCapability]{ "GET": { @@ -147,6 +150,24 @@ func TestServerServerCapabilities(t *testing.T) { Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)), }, }, + "PUT": { + "OK When Assigned Multiple Server Capabilities": { + ClientSession: TOSession, + RequestBody: map[string]interface{}{ + "serverId": GetServerID(t, "dtrc-mid-04")(), + "serverCapabilities": append(multipleSCs, "disk", "blah"), + }, + Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)), + }, + "OK When Assigned Multiple Servers Per Capability": { + ClientSession: TOSession, + RequestBody: map[string]interface{}{ + "serverIds": append(multipleServerIDs, GetServerID(t, "dtrc-mid-04")(), GetServerID(t, "dtrc-mid-01")()), + "serverCapability": "disk", + }, + Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)), + }, + }, "DELETE": { "OK when NOT the LAST SERVER of CACHE GROUP of TOPOLOGY DS which has REQUIRED CAPABILITIES": { ClientSession: TOSession, @@ -179,6 +200,23 @@ func TestServerServerCapabilities(t *testing.T) { for method, testCases := range methodTests { t.Run(method, func(t *testing.T) { for name, testCase := range testCases { + ssc := tc.ServerServerCapability{} + msc := tc.MultipleServerCapabilities{} + mspc := tc.MultipleServersToCapability{} + var serverId int + var serverCapability string + + if testCase.RequestBody != nil { + dat, err := json.Marshal(testCase.RequestBody) + assert.NoError(t, err, "Error occurred when marshalling request body: %v", err) + if method == "PUT" { + err = json.Unmarshal(dat, &msc) + } else { + err = json.Unmarshal(dat, &ssc) + } + assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err) + } + switch method { case "GET": t.Run(name, func(t *testing.T) { @@ -190,6 +228,21 @@ func TestServerServerCapabilities(t *testing.T) { case "POST": t.Run(name, func(t *testing.T) { alerts, reqInf, err := testCase.ClientSession.CreateServerServerCapability(testCase.RequestBody, testCase.RequestOpts) + alerts, reqInf, err := testCase.ClientSession.CreateServerServerCapability(ssc, testCase.RequestOpts) + for _, check := range testCase.Expectations { + check(t, reqInf, nil, alerts, err) + } + }) + case "PUT": + t.Run(name, func(t *testing.T) { + var alerts tc.Alerts + var reqInf toclientlib.ReqInf + var err error + if name == "OK When Assigned Multiple Server Capabilities" { + alerts, reqInf, err = testCase.ClientSession.AssignMultipleServerCapabilities(msc, testCase.RequestOpts) + } else if name == "OK When Assigned Multiple Servers Per Capability" { + alerts, reqInf, err = testCase.ClientSession.AssignMultipleServersPerCapability(mspc, testCase.RequestOpts) + } for _, check := range testCase.Expectations { check(t, reqInf, nil, alerts, err) } diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go b/traffic_ops/traffic_ops_golang/routing/routes.go index 387e015cd6..ee1ad151be 100644 --- a/traffic_ops/traffic_ops_golang/routing/routes.go +++ b/traffic_ops/traffic_ops_golang/routing/routes.go @@ -530,7 +530,8 @@ func Routes(d ServerData) ([]Route, http.Handler, error) { /** * 4.x API */ - + // Assign Multiple Servers to a capability + {Version: api.Version{Major: 4, Minor: 1}, Method: http.MethodPut, Path: `multiple_servers_per_capability.rst/?$`, Handler: server.AssignMultipleServersToCapability, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:READ", "SERVER-CAPABILITY:READ", "SERVER-CAPABILITY:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 40752312825}, // Assign Multiple Server Capabilities {Version: api.Version{Major: 4, Minor: 1}, Method: http.MethodPut, Path: `multiple_server_capabilities/?$`, Handler: server.AssignMultipleServerCapabilities, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:UPDATE", "SERVER:READ", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 40792419258}, diff --git a/traffic_ops/traffic_ops_golang/server/servers_server_capability.go b/traffic_ops/traffic_ops_golang/server/servers_server_capability.go index 21ae31db2a..2191cd7a8b 100644 --- a/traffic_ops/traffic_ops_golang/server/servers_server_capability.go +++ b/traffic_ops/traffic_ops_golang/server/servers_server_capability.go @@ -527,3 +527,70 @@ func AssignMultipleServerCapabilities(w http.ResponseWriter, r *http.Request) { api.WriteAlertsObj(w, r, http.StatusOK, alerts, msc) return } + +// AssignMultipleServersToCapability helps assign multiple servers to a given capability. +func AssignMultipleServersToCapability(w http.ResponseWriter, r *http.Request) { + inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil) + tx := inf.Tx.Tx + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr) + return + } + defer inf.Close() + + var mspc tc.MultipleServersToCapability + if err := json.NewDecoder(r.Body).Decode(&mspc); err != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil) + return + } + + //loop through server list to check if the type is MID and/opr EDGE + for _, sid := range mspc.ServersIDs { + correctType := true + if err := tx.QueryRow(scCheckServerTypeQuery(), sid).Scan(&correctType); err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, fmt.Errorf("checking server type: %w", err)) + return + } + if !correctType { + userErr := fmt.Errorf("server %d has an incorrect server type. Server capability can only be assigned to EDGE or MID servers", sid) + api.HandleErr(w, r, tx, http.StatusBadRequest, userErr, nil) + return + } + } + + multipleServersPerCapability := make([]string, 0, len(mspc.ServersIDs)) + + //Delete existing rows from server_server_capability for a given server capability + _, err := tx.Exec("DELETE FROM server_server_capability ssc WHERE ssc.server_capability=$1", mspc.ServerCapability) + if err != nil { + useErr, sysErr, statusCode := api.ParseDBError(err) + api.HandleErr(w, r, tx, statusCode, useErr, sysErr) + return + } + + mspcQuery := `WITH inserted AS ( + INSERT INTO server_server_capability + SELECT $2, "server" + FROM UNNEST($1::int[]) AS tmp("server") + RETURNING server + ) + SELECT ARRAY_AGG(server) + FROM ( + SELECT server + FROM inserted + ) AS returned(server)` + + err = tx.QueryRow(mspcQuery, pq.Array(mspc.ServersIDs), mspc.ServerCapability).Scan(pq.Array(&multipleServersPerCapability)) + if err != nil { + useErr, sysErr, statusCode := api.ParseDBError(err) + api.HandleErr(w, r, tx, statusCode, useErr, sysErr) + return + } + for i, val := range multipleServersPerCapability { + mspc.ServersIDs[i], _ = strconv.Atoi(val) + } + alerts := tc.CreateAlerts(tc.SuccessLevel, "Multiple Servers assigned to a capability") + api.WriteAlertsObj(w, r, http.StatusOK, alerts, mspc) + return + +} diff --git a/traffic_ops/v4-client/server_server_capabilities.go b/traffic_ops/v4-client/server_server_capabilities.go index dd17238517..8c2871b0fe 100644 --- a/traffic_ops/v4-client/server_server_capabilities.go +++ b/traffic_ops/v4-client/server_server_capabilities.go @@ -30,6 +30,9 @@ const apiServerServerCapabilities = "/server_server_capabilities" // apiMultipleServerCapabilities is the API version-relative path to the /multiple_server_capabilities API endpoint. const apiMultipleServerCapabilities = "/multiple_server_capabilities" +// apiMultipleServersPerCapability is the API version-relative path to the /multiple_servers_per_capability API endpoint. +const apiMultipleServersPerCapability = "/multiple_servers_per_capability" + // CreateServerServerCapability assigns a Server Capability to a Server. func (to *Session) CreateServerServerCapability(ssc tc.ServerServerCapability, opts RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) { var alerts tc.Alerts @@ -57,9 +60,16 @@ func (to *Session) GetServerServerCapabilities(opts RequestOptions) (tc.ServerSe return resp, reqInf, err } -// AssignMultipleServerCapability assigns multiple server capabilities to a server. -func (to *Session) AssignMultipleServerCapability(msc tc.MultipleServerCapabilities, opts RequestOptions, id int) (tc.Alerts, toclientlib.ReqInf, error) { +// AssignMultipleServerCapabilities assigns multiple server capabilities to a server. +func (to *Session) AssignMultipleServerCapabilities(msc tc.MultipleServerCapabilities, opts RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) { var alerts tc.Alerts reqInf, err := to.put(apiMultipleServerCapabilities, opts, msc, &alerts) return alerts, reqInf, err } + +// AssignMultipleServersPerCapability assigns multiple servers to a given capability. +func (to *Session) AssignMultipleServersPerCapability(mspc tc.MultipleServersToCapability, opts RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) { + var alerts tc.Alerts + reqInf, err := to.put(apiMultipleServerCapabilities, opts, mspc, &alerts) + return alerts, reqInf, err +} diff --git a/traffic_ops/v5-client/server_server_capabilities.go b/traffic_ops/v5-client/server_server_capabilities.go index dd17238517..8c2871b0fe 100644 --- a/traffic_ops/v5-client/server_server_capabilities.go +++ b/traffic_ops/v5-client/server_server_capabilities.go @@ -30,6 +30,9 @@ const apiServerServerCapabilities = "/server_server_capabilities" // apiMultipleServerCapabilities is the API version-relative path to the /multiple_server_capabilities API endpoint. const apiMultipleServerCapabilities = "/multiple_server_capabilities" +// apiMultipleServersPerCapability is the API version-relative path to the /multiple_servers_per_capability API endpoint. +const apiMultipleServersPerCapability = "/multiple_servers_per_capability" + // CreateServerServerCapability assigns a Server Capability to a Server. func (to *Session) CreateServerServerCapability(ssc tc.ServerServerCapability, opts RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) { var alerts tc.Alerts @@ -57,9 +60,16 @@ func (to *Session) GetServerServerCapabilities(opts RequestOptions) (tc.ServerSe return resp, reqInf, err } -// AssignMultipleServerCapability assigns multiple server capabilities to a server. -func (to *Session) AssignMultipleServerCapability(msc tc.MultipleServerCapabilities, opts RequestOptions, id int) (tc.Alerts, toclientlib.ReqInf, error) { +// AssignMultipleServerCapabilities assigns multiple server capabilities to a server. +func (to *Session) AssignMultipleServerCapabilities(msc tc.MultipleServerCapabilities, opts RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) { var alerts tc.Alerts reqInf, err := to.put(apiMultipleServerCapabilities, opts, msc, &alerts) return alerts, reqInf, err } + +// AssignMultipleServersPerCapability assigns multiple servers to a given capability. +func (to *Session) AssignMultipleServersPerCapability(mspc tc.MultipleServersToCapability, opts RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) { + var alerts tc.Alerts + reqInf, err := to.put(apiMultipleServerCapabilities, opts, mspc, &alerts) + return alerts, reqInf, err +} From bb9b7008d358d655237181ec9e2a701bebeefcc3 Mon Sep 17 00:00:00 2001 From: Rima Shah Date: Wed, 21 Sep 2022 12:06:19 -0600 Subject: [PATCH 02/30] Added TP logic to assign multiple servers per capability. --- .../traffic_ops_golang/routing/routes.go | 3 +- .../server/servers_server_capability.go | 2 +- .../src/common/api/ServerCapabilityService.js | 13 ++++ .../form.serverCapability.tpl.html | 2 +- ...bleAssignServersPerCapabilityController.js | 67 +++++++++++++++++++ .../TableServerCapabilityServersController.js | 36 +++++++++- .../table/serverCapabilityServers/index.js | 3 +- .../table.assignServersPerCapability.tpl.html | 31 +++++++++ 8 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js create mode 100644 traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go b/traffic_ops/traffic_ops_golang/routing/routes.go index ee1ad151be..8f34d87997 100644 --- a/traffic_ops/traffic_ops_golang/routing/routes.go +++ b/traffic_ops/traffic_ops_golang/routing/routes.go @@ -329,6 +329,7 @@ func Routes(d ServerData) ([]Route, http.Handler, error) { {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPut, Path: `server_capabilities$`, Handler: api.UpdateHandler(&servercapability.TOServerCapability{}), RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER-CAPABILITY:UPDATE", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 425437701091}, {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodDelete, Path: `server_capabilities$`, Handler: api.DeleteHandler(&servercapability.TOServerCapability{}), RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER-CAPABILITY:DELETE", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 43641503831}, {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPut, Path: `multiple_server_capabilities/?$`, Handler: server.AssignMultipleServerCapabilities, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:UPDATE", "SERVER:READ", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 407924192581}, + {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPut, Path: `multiple_servers_per_capability/?$`, Handler: server.AssignMultipleServersToCapability, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:READ", "SERVER-CAPABILITY:READ", "SERVER-CAPABILITY:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 407523128251}, //Server Server Capabilities: CRUD {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodGet, Path: `server_server_capabilities/?$`, Handler: api.ReadHandler(&server.TOServerServerCapability{}), RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: []string{"SERVER:READ", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 480023188931}, @@ -531,7 +532,7 @@ func Routes(d ServerData) ([]Route, http.Handler, error) { * 4.x API */ // Assign Multiple Servers to a capability - {Version: api.Version{Major: 4, Minor: 1}, Method: http.MethodPut, Path: `multiple_servers_per_capability.rst/?$`, Handler: server.AssignMultipleServersToCapability, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:READ", "SERVER-CAPABILITY:READ", "SERVER-CAPABILITY:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 40752312825}, + {Version: api.Version{Major: 4, Minor: 1}, Method: http.MethodPut, Path: `multiple_servers_per_capability/?$`, Handler: server.AssignMultipleServersToCapability, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:READ", "SERVER-CAPABILITY:READ", "SERVER-CAPABILITY:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 40752312825}, // Assign Multiple Server Capabilities {Version: api.Version{Major: 4, Minor: 1}, Method: http.MethodPut, Path: `multiple_server_capabilities/?$`, Handler: server.AssignMultipleServerCapabilities, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"SERVER:UPDATE", "SERVER:READ", "SERVER-CAPABILITY:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 40792419258}, diff --git a/traffic_ops/traffic_ops_golang/server/servers_server_capability.go b/traffic_ops/traffic_ops_golang/server/servers_server_capability.go index 2191cd7a8b..13382caae7 100644 --- a/traffic_ops/traffic_ops_golang/server/servers_server_capability.go +++ b/traffic_ops/traffic_ops_golang/server/servers_server_capability.go @@ -544,7 +544,7 @@ func AssignMultipleServersToCapability(w http.ResponseWriter, r *http.Request) { return } - //loop through server list to check if the type is MID and/opr EDGE + //loop through server list to check if the type is MID and/or EDGE for _, sid := range mspc.ServersIDs { correctType := true if err := tx.QueryRow(scCheckServerTypeQuery(), sid).Scan(&correctType); err != nil { diff --git a/traffic_portal/app/src/common/api/ServerCapabilityService.js b/traffic_portal/app/src/common/api/ServerCapabilityService.js index ca8a827f28..a595b4dde4 100644 --- a/traffic_portal/app/src/common/api/ServerCapabilityService.js +++ b/traffic_portal/app/src/common/api/ServerCapabilityService.js @@ -81,6 +81,19 @@ var ServerCapabilityService = function($http, ENV, locationUtils, messageModel) ); }; + this.assignServersPerSC = function(serverCapability, serverIds) { + return $http.put(ENV.api.unstable + 'multiple_servers_per_capability',{ serverCapability: serverCapability, serverIds: serverIds, replace: true } ).then( + function(result) { + messageModel.setMessages(result.data.alerts, false); + return result; + }, + function(err) { + messageModel.setMessages(err.data.alerts, false); + throw err; + } + ); + }; + this.updateServerCapability = function(currentName, serverCapability) { return $http.put(ENV.api.unstable + 'server_capabilities', serverCapability, {params: {"name": currentName}}).then( function(result) { diff --git a/traffic_portal/app/src/common/modules/form/serverCapability/form.serverCapability.tpl.html b/traffic_portal/app/src/common/modules/form/serverCapability/form.serverCapability.tpl.html index 3bd82b9e12..f2875fda32 100644 --- a/traffic_portal/app/src/common/modules/form/serverCapability/form.serverCapability.tpl.html +++ b/traffic_portal/app/src/common/modules/form/serverCapability/form.serverCapability.tpl.html @@ -25,7 +25,7 @@
- +
diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js new file mode 100644 index 0000000000..24c3b13ef1 --- /dev/null +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/** @typedef { import('../../../../common/modules/table/agGrid/CommonGridController').CGC } CGC */ + +var TableAssignServersPerCapabilityController = function(servers, serverCapability, assignedServers, $scope, $uibModalInstance) { + + $scope.selectedServers = []; + + $scope.serverCapability = serverCapability; + + /** @type CGC.ColumnDefinition */ + $scope.columns = [ + { + headerName: "Servers", + field: "hostName", + checkboxSelection: true, + headerCheckboxSelection: true, + }, + { + headerName: "Type", + field: "type", + } + ]; + + $scope.serverss = servers.map(server => { + let isAssigned = assignedServers.find(assignedServers => assignedServers.servers === server.id); + if (isAssigned) { + server['selected'] = true; + } + return SCs; + }); + + $scope.submit = function() { + const selectedServerIds = this.selectedServers.map(spc => spc["id"]); + $uibModalInstance.close(selectedServerIds); + }; + + $scope.cancel = function () { + $uibModalInstance.dismiss('cancel'); + }; + + /** @type CGC.GridSettings */ + $scope.gridOptions = { + selectRows: true, + selectionProperty: "selected" + }; +}; + +TableAssignServersPerCapabilityController.$inject = ['servers', 'serverCapability', 'assignedServers', '$scope', '$uibModalInstance']; +module.exports = TableAssignServersPerCapabilityController; diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js index 7911132cd3..ffcac9b9c9 100644 --- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js @@ -17,7 +17,7 @@ * under the License. */ -var TableServerCapabilityServersController = function(serverCapability, servers, $scope, $state, $uibModal, $window, locationUtils, serverService, messageModel) { +var TableServerCapabilityServersController = function(serverCapability, servers, $scope, $state, $uibModal, $window, locationUtils, serverService, messageModel, serverCapabilityService) { var removeCapability = function(serverId) { serverService.removeServerCapability(serverId, serverCapability.name) @@ -66,6 +66,36 @@ var TableServerCapabilityServersController = function(serverCapability, servers, locationUtils.navigateToPath('/servers/' + id); }; + $scope.selectServers = function () { + var modalInstance = $uibModal.open({ + templateUrl: 'common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html', + controller: 'TableAssignServersPerCapabilityController', + size: 'md', + resolve: { + serverCapability: function() { + return serverCapability; + }, + servers: function(servers) { + return servers.getServers({cdn: servers.cdnId}); + }, + assignedServers: function() { + return servers + } + } + }); + console.log(servers, serverCapability) + modalInstance.result.then(function(selectedServers) { + serverCapabilityService.assignServersPerSC(serverCapability, selectedServers) + .then( + function() { + $scope.refresh(); + } + ); + }, function () { + // do nothing + }); + }; + $scope.confirmRemoveCapability = function(serverId, $event) { if ($event) { $event.stopPropagation(); // this kills the click event so it doesn't trigger anything else @@ -94,6 +124,8 @@ var TableServerCapabilityServersController = function(serverCapability, servers, $state.reload(); // reloads all the resolves for the view }; + $scope.navigateToPath = locationUtils.navigateToPath; + angular.element(document).ready(function () { $('#serverCapabilityServersTable').dataTable({ "lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]], @@ -104,5 +136,5 @@ var TableServerCapabilityServersController = function(serverCapability, servers, }; -TableServerCapabilityServersController.$inject = ['serverCapability', 'servers', '$scope', '$state', '$uibModal', '$window', 'locationUtils', 'serverService', 'messageModel']; +TableServerCapabilityServersController.$inject = ['serverCapability', 'servers', '$scope', '$state', '$uibModal', '$window', 'locationUtils', 'serverService', 'messageModel', 'serverCapabilityService']; module.exports = TableServerCapabilityServersController; diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/index.js b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/index.js index 536f9b7d16..1bf68bdebf 100644 --- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/index.js +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/index.js @@ -18,4 +18,5 @@ */ module.exports = angular.module('trafficPortal.table.serverCapability.servers', []) - .controller('TableServerCapabilityServersController', require('./TableServerCapabilityServersController')); + .controller('TableServerCapabilityServersController', require('./TableServerCapabilityServersController')) + .controller('TableAssignServersPerCapabilityController', require('./TableAssignServersPerCapabilityController')); diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html new file mode 100644 index 0000000000..19c832f01b --- /dev/null +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html @@ -0,0 +1,31 @@ + + + + + From 9d371c19e24faf36c6940f0b869acea91bb04378 Mon Sep 17 00:00:00 2001 From: Rima Shah Date: Wed, 21 Sep 2022 15:29:59 -0600 Subject: [PATCH 03/30] minor corrections and variable name change --- .../TableAssignServersPerCapabilityController.js | 4 ++-- .../TableServerCapabilityServersController.js | 7 +++---- .../table.assignServersPerCapability.tpl.html | 2 +- .../table.serverServerCapabilities.tpl.html | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js index 24c3b13ef1..0294d25e5a 100644 --- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableAssignServersPerCapabilityController.js @@ -39,7 +39,7 @@ var TableAssignServersPerCapabilityController = function(servers, serverCapabili } ]; - $scope.serverss = servers.map(server => { + $scope.servers = servers.map(server => { let isAssigned = assignedServers.find(assignedServers => assignedServers.servers === server.id); if (isAssigned) { server['selected'] = true; @@ -48,7 +48,7 @@ var TableAssignServersPerCapabilityController = function(servers, serverCapabili }); $scope.submit = function() { - const selectedServerIds = this.selectedServers.map(spc => spc["id"]); + const selectedServerIds = this.selectedServers.map(mspc => mspc["id"]); $uibModalInstance.close(selectedServerIds); }; diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js index ffcac9b9c9..191416482b 100644 --- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/TableServerCapabilityServersController.js @@ -75,15 +75,14 @@ var TableServerCapabilityServersController = function(serverCapability, servers, serverCapability: function() { return serverCapability; }, - servers: function(servers) { - return servers.getServers({cdn: servers.cdnId}); + servers: function(serversList) { + return serversList.getServers(); }, assignedServers: function() { - return servers + return servers; } } }); - console.log(servers, serverCapability) modalInstance.result.then(function(selectedServers) { serverCapabilityService.assignServersPerSC(serverCapability, selectedServers) .then( diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html index 19c832f01b..e107273f19 100644 --- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.assignServersPerCapability.tpl.html @@ -19,7 +19,7 @@ diff --git a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html index a028af4e88..7f4d32b32e 100644 --- a/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html +++ b/traffic_portal/app/src/common/modules/table/serverCapabilityServers/table.serverCapabilityServers.tpl.html @@ -25,6 +25,7 @@
  • Servers
  • +
    diff --git a/traffic_portal/app/src/common/modules/table/serverServerCapabilities/TableServerServerCapabilitiesController.js b/traffic_portal/app/src/common/modules/table/serverServerCapabilities/TableServerServerCapabilitiesController.js index d79c1f95ed..3dbcf5f1e3 100644 --- a/traffic_portal/app/src/common/modules/table/serverServerCapabilities/TableServerServerCapabilitiesController.js +++ b/traffic_portal/app/src/common/modules/table/serverServerCapabilities/TableServerServerCapabilitiesController.js @@ -33,7 +33,7 @@ var TableServerServerCapabilitiesController = function(server, serverCapabilitie ]; $scope.selectSCs = function () { - var modalInstance = $uibModal.open({ + const modalInstance = $uibModal.open({ templateUrl: 'common/modules/table/serverServerCapabilities/table.assignServerSCs.tpl.html', controller: 'TableAssignServerSCsController', size: 'md', @@ -121,7 +121,7 @@ var TableServerServerCapabilitiesController = function(server, serverCapabilitie }; $scope.editServerCapability = function(capabilityName) { - locationUtils.navigateToPath('/server-capabilities/edit?name=' + capabilityName); + locationUtils.navigateToPath('/server-capabilities/' + capabilityName); }; $scope.refresh = function() { diff --git a/traffic_portal/app/src/common/modules/table/serverServerCapabilities/table.assignServerSCs.tpl.html b/traffic_portal/app/src/common/modules/table/serverServerCapabilities/table.assignServerSCs.tpl.html index cb1bbf09e7..8b760bbfb1 100644 --- a/traffic_portal/app/src/common/modules/table/serverServerCapabilities/table.assignServerSCs.tpl.html +++ b/traffic_portal/app/src/common/modules/table/serverServerCapabilities/table.assignServerSCs.tpl.html @@ -26,7 +26,7 @@