From 6329dfb924421ee7234746d93efc84e85ef8193c Mon Sep 17 00:00:00 2001 From: Jagan Parthiban Date: Tue, 22 Aug 2023 22:32:16 +0530 Subject: [PATCH] RFC3339 Changes for ProfileParameters. Fixes https://github.com/apache/trafficcontrol/issues/7737 --- docs/source/api/v5/profileparameters.rst | 16 +- lib/go-tc/parameters.go | 33 ++ lib/go-tc/profile_parameters.go | 49 +++ traffic_ops/testing/api/v5/cdn_locks_test.go | 2 +- .../testing/api/v5/profile_parameters_test.go | 2 +- .../testing/api/v5/traffic_control_test.go | 2 +- .../dbhelpers/db_helpers.go | 15 + .../profileparameter/profile_parameters.go | 305 ++++++++++++++++++ .../traffic_ops_golang/routing/routes.go | 8 +- traffic_ops/v5-client/profile_parameter.go | 4 +- 10 files changed, 419 insertions(+), 17 deletions(-) diff --git a/docs/source/api/v5/profileparameters.rst b/docs/source/api/v5/profileparameters.rst index 58e184d3ae..7faca1af21 100644 --- a/docs/source/api/v5/profileparameters.rst +++ b/docs/source/api/v5/profileparameters.rst @@ -52,7 +52,7 @@ Request Structure Response Structure ------------------ -:lastUpdated: The date and time at which this :term:`Profile`/:term:`Parameter` association was last modified, in :ref:`non-rfc-datetime` +:lastUpdated: The date and time at which this :term:`Profile`/:term:`Parameter` association was last modified, in :rfc:`3339` :parameter: The :ref:`parameter-id` of a :term:`Parameter` assigned to ``profile`` :profile: The :ref:`profile-name` of the :term:`Profile` to which the :term:`Parameter` identified by ``parameter`` is assigned @@ -73,12 +73,12 @@ Response Structure { "response": [ { - "lastUpdated": "2018-12-05 17:50:49+00", + "lastUpdated": "2018-12-05T21:44:14.410503+05:30", "profile": "GLOBAL", "parameter": 4 }, { - "lastUpdated": "2018-12-05 17:50:49+00", + "lastUpdated": "2018-12-05T21:44:14.410503+05:30", "profile": "GLOBAL", "parameter": 5 } @@ -152,7 +152,7 @@ Array Format Response Structure ------------------ -:lastUpdated: The date and time at which the :term:`Profile`/:term:`Parameter` assignment was last modified, in :ref:`non-rfc-datetime` +:lastUpdated: The date and time at which the :term:`Profile`/:term:`Parameter` assignment was last modified, in :rfc:`3339` :parameter: :ref:`parameter-name` of the :term:`Parameter` which is assigned to ``profile`` :parameterId: The :ref:`parameter-id` of the assigned :term:`Parameter` :profile: :ref:`profile-name` of the :term:`Profile` to which the :term:`Parameter` is assigned @@ -175,14 +175,14 @@ Response Structure { "alerts": [ { - "text": "profileParameter was created.", + "text": "All Requested ProfileParameters were created.", "level": "success" } ], "response": { - "lastUpdated": null, - "profile": null, + "lastUpdated": "2018-12-05T21:44:14.410503+05:30", + "profile": "testProfile1", "profileId": 18, - "parameter": null, + "parameter": "testParam1", "parameterId": 1 }} diff --git a/lib/go-tc/parameters.go b/lib/go-tc/parameters.go index 57cce3206f..8b6a84aa5f 100644 --- a/lib/go-tc/parameters.go +++ b/lib/go-tc/parameters.go @@ -27,6 +27,7 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/apache/trafficcontrol/lib/go-util" @@ -295,6 +296,16 @@ type ProfileParametersNullable struct { Parameter *int `json:"parameter" db:"parameter_id"` } +// ProfileParametersNullableV5 is the latest minor version of the major version 5 +type ProfileParametersNullableV5 ProfileParametersNullableV50 + +// ProfileParametersNullableV50 is an object of the form returned by the Traffic Ops /profileparameters endpoint. +type ProfileParametersNullableV50 struct { + LastUpdated *time.Time `json:"lastUpdated" db:"last_updated"` + Profile *string `json:"profile" db:"profile"` + Parameter *int `json:"parameter" db:"parameter_id"` +} + // ProfileParametersNullableResponse is the structure of a response from // Traffic Ops to GET requests made to its /profileparameters API endpoint. // @@ -315,6 +326,18 @@ type ProfileParam struct { LastUpdated *TimeNoMod `json:"lastUpdated"` } +// ProfileParamV5 is the latest minor version of the major version 5 +type ProfileParamV5 ProfileParamV50 + +// ProfileParamV50 is a relationship between a Profile and some Parameter +// assigned to it as it appears in the Traffic Ops API's responses to the +// /profileparameters endpoint. +type ProfileParamV50 struct { + Parameter int `json:"parameter"` + Profile string `json:"profile"` + LastUpdated *time.Time `json:"lastUpdated"` +} + // ProfileParameterCreationRequest is the type of data accepted by Traffic // Ops as payloads in POST requests to its /profileparameters endpoint. type ProfileParameterCreationRequest struct { @@ -329,6 +352,16 @@ type ProfileParametersAPIResponse struct { Alerts } +// ProfileParametersAPIResponseV5 is the latest minor version of the major version 5 +type ProfileParametersAPIResponseV5 ProfileParametersAPIResponseV50 + +// ProfileParametersAPIResponseV50 is the type of a response from Traffic Ops to +// requests made to its /profileparameters endpoint. +type ProfileParametersAPIResponseV50 struct { + Response []ProfileParamV5 `json:"response"` + Alerts +} + // ProfileExportImportParameterNullable is an object of the form used by Traffic Ops // to represent parameters for exported and imported profiles. type ProfileExportImportParameterNullable struct { diff --git a/lib/go-tc/profile_parameters.go b/lib/go-tc/profile_parameters.go index f4ff9d7070..b34f958c4f 100644 --- a/lib/go-tc/profile_parameters.go +++ b/lib/go-tc/profile_parameters.go @@ -19,6 +19,8 @@ package tc * under the License. */ +import "time" + // ProfileParametersResponse is the type of the response from Traffic Ops to // GET requests made to its /profileparameters API endpoint. type ProfileParametersResponse struct { @@ -59,3 +61,50 @@ type ProfileParameterNullable struct { Parameter *string `json:"parameter" db:"parameter"` ParameterID *int `json:"parameterId" db:"parameter_id"` } + +// ProfileParametersResponseV5 is the type of the response from Traffic Ops to +// GET requests made to its /profileparameters API endpoint. +type ProfileParametersResponseV5 struct { + Response []ProfileParameterV5 `json:"response"` + Alerts +} + +// ProfileParameterResponseV5 is a single ProfileParameter response for Create to +// depict what changed. +// swagger:response ProfileParameterResponse +// in: body +type ProfileParameterResponseV5 struct { + // in: body + Response ProfileParameterV5 `json:"response"` + Alerts +} + +// ProfileParameterV5 is the latest minor version of the major version 5 +type ProfileParameterV5 ProfileParameterV50 + +// ProfileParameterV50 is a representation of a relationship between a Parameter +// and a Profile to which it is assigned. +// +// Note that not all unique identifiers for each represented object in this +// relationship structure are guaranteed to be populated by the Traffic Ops +// API. +type ProfileParameterV50 struct { + LastUpdated time.Time `json:"lastUpdated"` + Profile string `json:"profile"` + ProfileID int `json:"profileId"` + Parameter string `json:"parameter"` + ParameterID int `json:"parameterId"` +} + +// ProfileParameterNullableV5 is the latest minor version of the major version 5 +type ProfileParameterNullableV5 ProfileParameterNullableV50 + +// ProfileParameterNullableV50 is identical to ProfileParameter, except that its +// fields are reference values, which allows them to be nil. +type ProfileParameterNullableV50 struct { + LastUpdated *time.Time `json:"lastUpdated" db:"last_updated"` + Profile *string `json:"profile" db:"profile"` + ProfileID *int `json:"profileId" db:"profile_id"` + Parameter *string `json:"parameter" db:"parameter"` + ParameterID *int `json:"parameterId" db:"parameter_id"` +} diff --git a/traffic_ops/testing/api/v5/cdn_locks_test.go b/traffic_ops/testing/api/v5/cdn_locks_test.go index 583d22cb41..04e36a2293 100644 --- a/traffic_ops/testing/api/v5/cdn_locks_test.go +++ b/traffic_ops/testing/api/v5/cdn_locks_test.go @@ -326,7 +326,7 @@ func TestCDNLocks(t *testing.T) { "profileId": GetProfileID(t, "EDGEInCDN2")(), "parameterId": GetParameterID(t, "CONFIG proxy.config.admin.user_id", "records.config", "STRING ats")(), }, - Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)), + Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusCreated)), }, "FORBIDDEN when ADMIN USER DOESNT OWN LOCK": { ClientSession: TOSession, diff --git a/traffic_ops/testing/api/v5/profile_parameters_test.go b/traffic_ops/testing/api/v5/profile_parameters_test.go index d1bb2576a9..16976a8ef3 100644 --- a/traffic_ops/testing/api/v5/profile_parameters_test.go +++ b/traffic_ops/testing/api/v5/profile_parameters_test.go @@ -68,7 +68,7 @@ func TestProfileParameters(t *testing.T) { }, }, }, - Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)), + Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusCreated)), }, "BAD REQUEST when INVALID PROFILEID and PARAMETERID": { ClientSession: TOSession, diff --git a/traffic_ops/testing/api/v5/traffic_control_test.go b/traffic_ops/testing/api/v5/traffic_control_test.go index 4d9db708b5..6fa619b368 100644 --- a/traffic_ops/testing/api/v5/traffic_control_test.go +++ b/traffic_ops/testing/api/v5/traffic_control_test.go @@ -41,7 +41,7 @@ type TrafficControl struct { Origins []tc.Origin `json:"origins"` Profiles []tc.Profile `json:"profiles"` Parameters []tc.Parameter `json:"parameters"` - ProfileParameters []tc.ProfileParameter `json:"profileParameters"` + ProfileParameters []tc.ProfileParameterV5 `json:"profileParameters"` PhysLocations []tc.PhysLocationV5 `json:"physLocations"` Regions []tc.RegionV5 `json:"regions"` Roles []tc.RoleV4 `json:"roles"` diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go index c70056279b..464502c2d2 100644 --- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go +++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go @@ -2304,3 +2304,18 @@ func DeleteCoordinate(tx *sql.Tx, cacheGroupID int, coordinateID int) error { } return nil } + +// ProfileParameterExists confirms whether the ProfileParameter exists, and an error (if one occurs). +func ProfileParameterExists(tx *sql.Tx, profileID string, parameterID string) (bool, error) { + var count int + if err := tx.QueryRow("SELECT count(*) FROM profile_parameter WHERE profile=$1 and parameter=$2", profileID, parameterID).Scan(&count); err != nil { + return false, fmt.Errorf("error getting profile_parameter info: %w", err) + } + if count == 0 { + return false, nil + } + if count != 1 { + return false, fmt.Errorf("getting profile_parameter info - expected row count: 1, actual: %d", count) + } + return true, nil +} diff --git a/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go b/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go index 85846682f3..926ea5584f 100644 --- a/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go +++ b/traffic_ops/traffic_ops_golang/profileparameter/profile_parameters.go @@ -20,16 +20,23 @@ package profileparameter */ import ( + "database/sql" + "encoding/json" "errors" + "fmt" + "io" "net/http" + "reflect" "strconv" "time" + "github.com/apache/trafficcontrol/lib/go-log" "github.com/apache/trafficcontrol/lib/go-tc" "github.com/apache/trafficcontrol/lib/go-tc/tovalidate" "github.com/apache/trafficcontrol/lib/go-util" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers" + "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/util/ims" validation "github.com/go-ozzo/ozzo-validation" ) @@ -212,3 +219,301 @@ func deleteQuery() string { WHERE profile=:profile_id and parameter=:parameter_id` return query } + +func GetProfileParameter(w http.ResponseWriter, r *http.Request) { + var runSecond bool + var maxTime time.Time + inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil) + tx := inf.Tx + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, tx.Tx, errCode, userErr, sysErr) + return + } + defer inf.Close() + + // Query Parameters to Database Query column mappings + queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{ + "profileId": {Column: "pp.profile"}, + "parameterId": {Column: "pp.parameter"}, + "lastUpdated": {Column: "pp.last_updated"}, + } + if _, ok := inf.Params["orderby"]; !ok { + inf.Params["orderby"] = "parameter" + } + where, orderBy, pagination, queryValues, errs := dbhelpers.BuildWhereAndOrderByAndPagination(inf.Params, queryParamsToQueryCols) + if len(errs) > 0 { + api.HandleErr(w, r, tx.Tx, http.StatusBadRequest, util.JoinErrs(errs), nil) + } + + if inf.Config.UseIMS { + runSecond, maxTime = ims.TryIfModifiedSinceQuery(tx, r.Header, queryValues, selectMaxLastUpdatedQuery(where)) + if !runSecond { + log.Debugln("IMS HIT") + api.AddLastModifiedHdr(w, maxTime) + w.WriteHeader(http.StatusNotModified) + return + } + log.Debugln("IMS MISS") + } else { + log.Debugln("Non IMS request") + } + + query := selectQuery() + where + orderBy + pagination + rows, err := tx.NamedQuery(query, queryValues) + if err != nil { + api.HandleErr(w, r, tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("Profile Parameter read: error getting Profile Parameter(s): %w", err)) + return + } + defer log.Close(rows, "unable to close DB connection") + + profileParams := tc.ProfileParametersNullableV5{} + profileParamsList := []tc.ProfileParametersNullableV5{} + for rows.Next() { + if err = rows.Scan(&profileParams.LastUpdated, &profileParams.Parameter, &profileParams.Profile); err != nil { + api.HandleErr(w, r, tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("error getting profile parameter(s): %w", err)) + return + } + + profileParamsList = append(profileParamsList, profileParams) + } + + api.WriteResp(w, r, profileParamsList) + return +} + +func CreateProfileParameter(w http.ResponseWriter, r *http.Request) { + inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil) + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr) + return + } + defer inf.Close() + tx := inf.Tx.Tx + + body, err := io.ReadAll(r.Body) + if err != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, errors.New("error reading request body"), nil) + return + } + defer r.Body.Close() + + // Initial Unmarshal to validate request body + var data interface{} + err = json.Unmarshal(body, &data) + if err != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, errors.New("invalid request format"), nil) + return + } + + // This code block decides if the request body is a slice of parameters or a single object. + var profileParams []tc.ProfileParameterCreationRequest + switch reflect.TypeOf(data).Kind() { + case reflect.Slice: + if err := json.Unmarshal(body, &profileParams); err != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, errors.New("error unmarshalling slice"), nil) + return + } + case reflect.Map: + // If it is a single object it is still converted to a slice for code simplicity. + var profileParam tc.ProfileParameterCreationRequest + if err := json.Unmarshal(body, &profileParam); err != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, errors.New("error unmarshalling single object"), nil) + return + } + profileParams = append(profileParams, profileParam) + default: + api.HandleErr(w, r, tx, http.StatusBadRequest, errors.New("invalid request format"), nil) + return + } + + // Validate all objects of the every profile parameter from the request slice + for _, profileParameter := range profileParams { + readValErr := validateRequestProfileParameter(profileParameter) + if readValErr != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, readValErr, nil) + return + } + } + + // Check user Permissions on all Profiles requested + for _, profileParameter := range profileParams { + cdnName, err := dbhelpers.GetCDNNameFromProfileID(tx, profileParameter.ProfileID) + if err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, err, nil) + return + } + userErr, sysErr, errCode = dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName) + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, tx, errCode, userErr, sysErr) + return + } + } + + // Check if any of the profile parameter from the request slice already exists + for _, profileParameter := range profileParams { + var count int + err = tx.QueryRow("SELECT count(*) from profile_parameter where profile = $1 and parameter = $2", profileParameter.ProfileID, profileParameter.ParameterID).Scan(&count) + if err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, fmt.Errorf("error: %w, when checking if profile parameter with profile_id %d and parameter_id %d exists", err, profileParameter.ProfileID, profileParameter.ParameterID)) + return + } + if count == 1 { + api.HandleErr(w, r, tx, http.StatusBadRequest, fmt.Errorf("profile parameter with profile_id %d and parameter_id %d already exists", profileParameter.ProfileID, profileParameter.ParameterID), nil) + return + } + } + + // Create all profile parameters from the request slice + var objProfileParams []tc.ProfileParameterV5 + for _, profileParameter := range profileParams { + query := ` + INSERT INTO profile_parameter ( + profile, + parameter + ) VALUES ( + $1, $2 + ) RETURNING profile, parameter, last_updated +` + var objProfileParam tc.ProfileParameterV5 + err = tx.QueryRow( + query, + profileParameter.ProfileID, + profileParameter.ParameterID, + ).Scan( + &objProfileParam.ProfileID, + &objProfileParam.ParameterID, + &objProfileParam.LastUpdated, + ) + + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + api.HandleErr(w, r, tx, http.StatusInternalServerError, fmt.Errorf("error: %w in profile_parameter with with profile_id %d and parameter_id %d", err, profileParameter.ProfileID, profileParameter.ParameterID), nil) + return + } + usrErr, sysErr, code := api.ParseDBError(err) + api.HandleErr(w, r, tx, code, usrErr, sysErr) + return + } + + // Fetch the Profile Name from ID to insert in type ProfileParameterV5 + profileName, ok, err := dbhelpers.GetProfileNameFromID(profileParameter.ProfileID, tx) + if err != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting profile name from id: "+err.Error())) + return + } else if !ok { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, errors.New("profile not found"), nil) + return + } + + // Fetch the Parameter Name from ID to insert in type ProfileParameterV5 + parameterName, ok, err := dbhelpers.GetParamNameByID(tx, profileParameter.ParameterID) + if err != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting parameter name from id: "+err.Error())) + return + } else if !ok { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, errors.New("parameter not found"), nil) + return + } + + objProfileParam.Profile = profileName + objProfileParam.Parameter = parameterName + objProfileParams = append(objProfileParams, objProfileParam) + } + alerts := tc.CreateAlerts(tc.SuccessLevel, "All Requested ProfileParameters were created.") + api.WriteAlertsObj(w, r, http.StatusCreated, alerts, objProfileParams) + return + +} + +func DeleteProfileParameter(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, tx, errCode, userErr, sysErr) + return + } + defer inf.Close() + + profileID := inf.Params["profileId"] + parameterID := inf.Params["parameterId"] + + if profileID == "" || parameterID == "" { + api.HandleErr(w, r, tx, http.StatusBadRequest, fmt.Errorf("couldn't delete Profile_Parameter. profileID & parameterID Cannot be empty for Delete Operation"), nil) + return + } + + intProfileID, convErrProfile := strconv.Atoi(profileID) + if convErrProfile != nil { + api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, fmt.Errorf("profile_parameter delete error: %w, while converting from string to int", convErrProfile), nil) + } + + cdnName, err := dbhelpers.GetCDNNameFromProfileID(tx, intProfileID) + if err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, err, nil) + return + } + userErr, sysErr, errCode = dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName) + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, tx, errCode, userErr, sysErr) + return + } + + exists, err := dbhelpers.ProfileParameterExists(tx, profileID, parameterID) + if err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, err) + return + } + if !exists { + api.HandleErr(w, r, tx, http.StatusNotFound, fmt.Errorf("no profile_parameter exists by profile_id: %s & parameter_id: %s", profileID, parameterID), nil) + return + } + + res, err := tx.Exec("DELETE FROM profile_parameter AS pp WHERE pp.profile=$1 and parameter=$2", profileID, parameterID) + if err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, err) + return + } + rowsAffected, err := res.RowsAffected() + if err != nil { + api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, fmt.Errorf("error determining rows affected for delete profile_parameter: %w", err)) + return + } + if rowsAffected == 0 { + api.HandleErr(w, r, tx, http.StatusInternalServerError, fmt.Errorf("no rows deleted for profile_parameter"), nil) + return + } + alerts := tc.CreateAlerts(tc.SuccessLevel, "profile_parameter"+ + " was deleted.") + api.WriteAlerts(w, r, http.StatusOK, alerts) + return +} + +func selectMaxLastUpdatedQuery(where string) string { + return ` + SELECT max(t) from ( + SELECT max(pp.last_updated) as t FROM profile_parameter pp + JOIN profile prof ON prof.id = pp.profile + JOIN parameter param ON param.id = pp.parameter ` + where + + ` UNION ALL + SELECT max(last_updated) as t FROM last_deleted l WHERE l.table_name = 'profile_parameter' + ) as res + ` +} + +// validateRequestProfileParameter validate the JSON objects +func validateRequestProfileParameter(profileParameter tc.ProfileParameterCreationRequest) error { + errs := make(map[string]error) + + errs[ProfileIDQueryParam] = validation.Validate(profileParameter.ProfileID, validation.Required) + errs[ParameterIDQueryParam] = validation.Validate(profileParameter.ParameterID, validation.Required) + + if len(errs) > 0 { + var errorSlice []error + for _, err := range errs { + errorSlice = append(errorSlice, err) + } + userErr := util.JoinErrs(errorSlice) + return userErr + } + return nil +} diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go b/traffic_ops/traffic_ops_golang/routing/routes.go index 0a6285cca1..8412bf74f7 100644 --- a/traffic_ops/traffic_ops_golang/routing/routes.go +++ b/traffic_ops/traffic_ops_golang/routing/routes.go @@ -438,11 +438,11 @@ func Routes(d ServerData) ([]Route, http.Handler, error) { {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodGet, Path: `profiles/name/{name}/parameters/?$`, Handler: profileparameter.GetProfileName, RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 426773783231}, {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `profiles/name/{name}/parameters/?$`, Handler: profileparameter.PostProfileParamsByName, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:UPDATE", "PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 435594558231}, {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `profiles/{id}/parameters/?$`, Handler: profileparameter.PostProfileParamsByID, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:UPDATE", "PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 41681870831}, - {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodGet, Path: `profileparameters/?$`, Handler: api.ReadHandler(&profileparameter.TOProfileParameter{}), RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 45060980531}, - {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `profileparameters/?$`, Handler: api.CreateHandler(&profileparameter.TOProfileParameter{}), RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ", "PROFILE:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 42880969331}, - {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `profileparameter/?$`, Handler: profileparameter.PostProfileParam, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ", "PROFILE:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 42427531}, {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `parameterprofile/?$`, Handler: profileparameter.PostParamProfile, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:UPDATE", "PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 408061086131}, - {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodDelete, Path: `profileparameters/{profileId}/{parameterId}$`, Handler: api.DeleteHandler(&profileparameter.TOProfileParameter{}), RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:UPDATE", "PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 42483952931}, + {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `profileparameter/?$`, Handler: profileparameter.PostProfileParam, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ", "PROFILE:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 42427531}, + {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodGet, Path: `profileparameters/?$`, Handler: profileparameter.GetProfileParameter, RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 45060980531}, + {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodPost, Path: `profileparameters/?$`, Handler: profileparameter.CreateProfileParameter, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:READ", "PARAMETER:READ", "PROFILE:UPDATE"}, Authenticated: Authenticated, Middlewares: nil, ID: 42880969331}, + {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodDelete, Path: `profileparameters/{profileId}/{parameterId}$`, Handler: profileparameter.DeleteProfileParameter, RequiredPrivLevel: auth.PrivLevelOperations, RequiredPermissions: []string{"PROFILE:UPDATE", "PROFILE:READ", "PARAMETER:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 42483952931}, //Tenants {Version: api.Version{Major: 5, Minor: 0}, Method: http.MethodGet, Path: `tenants/?$`, Handler: api.ReadHandler(&apitenant.TOTenant{}), RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: []string{"TENANT:READ"}, Authenticated: Authenticated, Middlewares: nil, ID: 467796781431}, diff --git a/traffic_ops/v5-client/profile_parameter.go b/traffic_ops/v5-client/profile_parameter.go index e0adfcbb6e..d0720520b8 100644 --- a/traffic_ops/v5-client/profile_parameter.go +++ b/traffic_ops/v5-client/profile_parameter.go @@ -56,8 +56,8 @@ func (to *Session) CreateProfileWithMultipleParameters(pps tc.PostProfileParam, } // GetProfileParameters retrieves associations between Profiles and Parameters. -func (to *Session) GetProfileParameters(opts RequestOptions) (tc.ProfileParametersAPIResponse, toclientlib.ReqInf, error) { - var data tc.ProfileParametersAPIResponse +func (to *Session) GetProfileParameters(opts RequestOptions) (tc.ProfileParametersAPIResponseV5, toclientlib.ReqInf, error) { + var data tc.ProfileParametersAPIResponseV5 reqInf, err := to.get(apiProfileParameters, opts, &data) return data, reqInf, err }