You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ro...@apache.org on 2018/05/07 18:59:10 UTC
[incubator-trafficcontrol] branch master updated (d5ddd6c ->
fa6518e)
This is an automated email from the ASF dual-hosted git repository.
rob pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git.
from d5ddd6c Fix TO Go ASNs unit tests for renamed symbols
new 394ba97 added DeliveryServicesService Get API in Go
new b50539c added api to DeliveryserviceServer Get in Go
new fa6518e removed unimplemented routes and unneeded comments
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
lib/go-tc/deliveryservice_servers.go | 80 ++++++++
lib/go-tc/deliveryservices.go | 13 --
.../servers/servers.go} | 220 ++++++++++++---------
.../deliveryservice/servers/servers_test.go | 8 +-
traffic_ops/traffic_ops_golang/routes.go | 4 +
5 files changed, 219 insertions(+), 106 deletions(-)
create mode 100644 lib/go-tc/deliveryservice_servers.go
copy traffic_ops/traffic_ops_golang/{profileparameter/profile_parameters.go => deliveryservice/servers/servers.go} (50%)
copy traffic_portal/app/src/assets/css/custom.css => traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go (95%)
--
To stop receiving notification emails like this one, please contact
rob@apache.org.
[incubator-trafficcontrol] 01/03: added DeliveryServicesService Get
API in Go
Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git
commit 394ba97e884517e9621582dcc30201cefd4da3ee
Author: ASchmidt <An...@comcast.com>
AuthorDate: Fri May 4 14:53:55 2018 -0600
added DeliveryServicesService Get API in Go
---
lib/go-tc/deliveryservice_servers.go | 193 +++++++++++++
.../deliveryservice/servers/servers.go | 300 +++++++++++++++++++++
.../deliveryservice/servers/servers_test.go | 111 ++++++++
3 files changed, 604 insertions(+)
diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go
new file mode 100644
index 0000000..9c7e6ae
--- /dev/null
+++ b/lib/go-tc/deliveryservice_servers.go
@@ -0,0 +1,193 @@
+package tc
+
+/*
+
+ 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 (
+ "database/sql/driver"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+
+ log "github.com/apache/incubator-trafficcontrol/lib/go-log"
+)
+
+// IDNoMod type is used to suppress JSON unmarshalling
+type IDNoMod int
+
+// DeliveryServiceRequest is used as part of the workflow to create,
+// modify, or delete a delivery service.
+type DeliveryServiceRequest struct {
+ AssigneeID int `json:"assigneeId,omitempty"`
+ Assignee string `json:"assignee,omitempty"`
+ AuthorID IDNoMod `json:"authorId"`
+ Author string `json:"author"`
+ ChangeType string `json:"changeType"`
+ CreatedAt *TimeNoMod `json:"createdAt"`
+ ID int `json:"id"`
+ LastEditedBy string `json:"lastEditedBy,omitempty"`
+ LastEditedByID IDNoMod `json:"lastEditedById,omitempty"`
+ LastUpdated *TimeNoMod `json:"lastUpdated"`
+ DeliveryService DeliveryService `json:"deliveryService"`
+ Status RequestStatus `json:"status"`
+ XMLID string `json:"-" db:"xml_id"`
+}
+
+// DeliveryServiceRequestNullable is used as part of the workflow to create,
+// modify, or delete a delivery service.
+type DeliveryServiceRequestNullable struct {
+ AssigneeID *int `json:"assigneeId,omitempty" db:"assignee_id"`
+ Assignee *string `json:"assignee,omitempty"`
+ AuthorID *IDNoMod `json:"authorId" db:"author_id"`
+ Author *string `json:"author"`
+ ChangeType *string `json:"changeType" db:"change_type"`
+ CreatedAt *TimeNoMod `json:"createdAt" db:"created_at"`
+ ID *int `json:"id" db:"id"`
+ LastEditedBy *string `json:"lastEditedBy"`
+ LastEditedByID *IDNoMod `json:"lastEditedById" db:"last_edited_by_id"`
+ LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"`
+ DeliveryService *DeliveryServiceNullable `json:"deliveryService" db:"deliveryservice"`
+ Status *RequestStatus `json:"status" db:"status"`
+ XMLID *string `json:"-" db:"xml_id"`
+}
+
+// UnmarshalJSON implements the json.Unmarshaller interface to suppress unmarshalling for IDNoMod
+func (a *IDNoMod) UnmarshalJSON([]byte) error {
+ return nil
+}
+
+// RequestStatus captures where in the workflow this request is
+type RequestStatus string
+
+const (
+ // RequestStatusInvalid -- invalid state
+ RequestStatusInvalid = RequestStatus("invalid")
+ // RequestStatusDraft -- newly created; not ready to be reviewed
+ RequestStatusDraft = RequestStatus("draft")
+ // RequestStatusSubmitted -- newly created; ready to be reviewed
+ RequestStatusSubmitted = RequestStatus("submitted")
+ // RequestStatusRejected -- reviewed, but problems found
+ RequestStatusRejected = RequestStatus("rejected")
+ // RequestStatusPending -- reviewed and locked; ready to be implemented
+ RequestStatusPending = RequestStatus("pending")
+ // RequestStatusComplete -- implemented and locked
+ RequestStatusComplete = RequestStatus("complete")
+)
+
+// RequestStatuses -- user-visible string associated with each of the above
+var RequestStatuses = []RequestStatus{
+ // "invalid" -- don't list here..
+ "draft",
+ "submitted",
+ "rejected",
+ "pending",
+ "complete",
+}
+
+// UnmarshalJSON implements json.Unmarshaller
+func (r *RequestStatus) UnmarshalJSON(b []byte) error {
+ u, err := strconv.Unquote(string(b))
+ if err != nil {
+ return err
+ }
+
+ // just check to see if the string represents a valid requeststatus
+ _, err = RequestStatusFromString(u)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(b, (*string)(r))
+}
+
+// MarshalJSON implements json.Marshaller
+func (r RequestStatus) MarshalJSON() ([]byte, error) {
+ return json.Marshal(string(r))
+}
+
+// Value implements driver.Valuer
+func (r *RequestStatus) Value() (driver.Value, error) {
+ v, err := json.Marshal(r)
+ log.Debugf("value is %v; err is %v", v, err)
+ v = []byte(strings.Trim(string(v), `"`))
+ return v, err
+}
+
+// Scan implements sql.Scanner
+func (r *RequestStatus) Scan(src interface{}) error {
+ b, ok := src.([]byte)
+ if !ok {
+ return fmt.Errorf("expected requeststatus in byte array form; got %T", src)
+ }
+ b = []byte(`"` + string(b) + `"`)
+ return json.Unmarshal(b, r)
+}
+
+// RequestStatusFromString gets the status enumeration from a string
+func RequestStatusFromString(rs string) (RequestStatus, error) {
+ if rs == "" {
+ return RequestStatusDraft, nil
+ }
+ for _, s := range RequestStatuses {
+ if string(s) == rs {
+ return s, nil
+ }
+ }
+ return RequestStatusInvalid, errors.New(rs + " is not a valid RequestStatus name")
+}
+
+// ValidTransition returns nil if the transition is allowed for the workflow, an error if not
+func (r RequestStatus) ValidTransition(to RequestStatus) error {
+ if r == RequestStatusRejected || r == RequestStatusComplete {
+ // once rejected or completed, no changes allowed
+ return errors.New(string(r) + " request cannot be changed")
+ }
+
+ if r == to {
+ // no change -- always allowed
+ return nil
+ }
+
+ // indicate if valid transitioning to this RequestStatus
+ switch to {
+ case RequestStatusDraft:
+ // can go back to draft if submitted or rejected
+ if r == RequestStatusSubmitted {
+ return nil
+ }
+ case RequestStatusSubmitted:
+ // can go be submitted if draft or rejected
+ if r == RequestStatusDraft {
+ return nil
+ }
+ case RequestStatusRejected:
+ // only submitted can be rejected
+ if r == RequestStatusSubmitted {
+ return nil
+ }
+ case RequestStatusPending:
+ // only submitted can move to pending
+ if r == RequestStatusSubmitted {
+ return nil
+ }
+ case RequestStatusComplete:
+ // only pending can be completed. Completed can never change.
+ if r == RequestStatusPending {
+ return nil
+ }
+ }
+ return errors.New("invalid transition from " + string(r) + " to " + string(to))
+}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
new file mode 100644
index 0000000..463ff06
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -0,0 +1,300 @@
+package profileparameter
+
+/*
+ * 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"
+ tc "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+ "github.com/apache/incubator-trafficcontrol/lib/go-tc/v13"
+ "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/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tovalidate"
+ validation "github.com/go-ozzo/ozzo-validation"
+
+ "github.com/jmoiron/sqlx"
+ "github.com/lib/pq"
+)
+
+const (
+ ProfileIDQueryParam = "profileId"
+ ParameterIDQueryParam = "parameterId"
+)
+
+//we need a type alias to define functions on
+type TOProfileParameter v13.ProfileParameterNullable
+
+//the refType is passed into the handlers where a copy of its type is used to decode the json.
+var refType = TOProfileParameter(v13.ProfileParameterNullable{})
+
+func GetRefType() *TOProfileParameter {
+ return &refType
+}
+
+func (pp TOProfileParameter) GetKeyFieldsInfo() []api.KeyFieldInfo {
+ return []api.KeyFieldInfo{{ProfileIDQueryParam, api.GetIntKey}, {ParameterIDQueryParam, api.GetIntKey}}
+}
+
+//Implementation of the Identifier, Validator interface functions
+func (pp TOProfileParameter) GetKeys() (map[string]interface{}, bool) {
+ if pp.ProfileID == nil {
+ return map[string]interface{}{ProfileIDQueryParam: 0}, false
+ }
+ if pp.ParameterID == nil {
+ return map[string]interface{}{ParameterIDQueryParam: 0}, false
+ }
+ keys := make(map[string]interface{})
+ profileID := *pp.ProfileID
+ parameterID := *pp.ParameterID
+
+ keys[ProfileIDQueryParam] = profileID
+ keys[ParameterIDQueryParam] = parameterID
+ return keys, true
+}
+
+func (pp *TOProfileParameter) GetAuditName() string {
+ if pp.ProfileID != nil {
+ return strconv.Itoa(*pp.ProfileID) + "-" + strconv.Itoa(*pp.ParameterID)
+ }
+ return "unknown"
+}
+
+func (pp *TOProfileParameter) GetType() string {
+ return "profileParameter"
+}
+
+func (pp *TOProfileParameter) SetKeys(keys map[string]interface{}) {
+ profId, _ := keys[ProfileIDQueryParam].(int) //this utilizes the non panicking type assertion, if the thrown away ok variable is false i will be the zero of the type, 0 here.
+ pp.ProfileID = &profId
+
+ paramId, _ := keys[ParameterIDQueryParam].(int) //this utilizes the non panicking type assertion, if the thrown away ok variable is false i will be the zero of the type, 0 here.
+ pp.ParameterID = ¶mId
+}
+
+// Validate fulfills the api.Validator interface
+func (pp *TOProfileParameter) Validate(db *sqlx.DB) []error {
+
+ errs := validation.Errors{
+ "profile": validation.Validate(pp.ProfileID, validation.Required),
+ "parameter": validation.Validate(pp.ParameterID, validation.Required),
+ }
+
+ return tovalidate.ToErrors(errs)
+}
+
+//The TOProfileParameter implementation of the Creator interface
+//all implementations of Creator should use transactions and return the proper errorType
+//ParsePQUniqueConstraintError is used to determine if a profileparameter 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 profile and lastUpdated values of the newly inserted profileparameter and have
+//to be added to the struct
+func (pp *TOProfileParameter) 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(), pp)
+ if err != nil {
+ if pqErr, ok := err.(*pq.Error); ok {
+ err, eType := dbhelpers.ParsePQUniqueConstraintError(pqErr)
+ if eType == tc.DataConflictError {
+ return errors.New("a parameter 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 profile int
+ var parameter int
+ var lastUpdated tc.TimeNoMod
+ rowsAffected := 0
+ for resultRows.Next() {
+ rowsAffected++
+ if err := resultRows.Scan(&profile, ¶meter, &lastUpdated); err != nil {
+ log.Error.Printf("could not scan profile from insert: %s\n", err)
+ return tc.DBError, tc.SystemError
+ }
+ }
+ if rowsAffected == 0 {
+ err = errors.New("no profile_parameter was inserted, no profile+parameter was returned")
+ log.Errorln(err)
+ return tc.DBError, tc.SystemError
+ }
+ if rowsAffected > 1 {
+ err = errors.New("too many ids returned from parameter insert")
+ log.Errorln(err)
+ return tc.DBError, tc.SystemError
+ }
+
+ pp.SetKeys(map[string]interface{}{ProfileIDQueryParam: profile, ParameterIDQueryParam: parameter})
+ pp.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
+}
+
+func insertQuery() string {
+ query := `INSERT INTO profile_parameter (
+profile,
+parameter) VALUES (
+:profile_id,
+:parameter_id) RETURNING profile, parameter, last_updated`
+ return query
+}
+
+func (pp *TOProfileParameter) 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{
+ "profileId": dbhelpers.WhereColumnInfo{"pp.profile", nil},
+ "parameterId": dbhelpers.WhereColumnInfo{"pp.parameter", nil},
+ "lastUpdated": dbhelpers.WhereColumnInfo{"pp.last_updated", nil},
+ }
+
+ 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 Parameters: %v", err)
+ return nil, []error{tc.DBError}, tc.SystemError
+ }
+ defer rows.Close()
+
+ params := []interface{}{}
+ for rows.Next() {
+ var p v13.ProfileParameterNullable
+ if err = rows.StructScan(&p); err != nil {
+ log.Errorf("error parsing pp rows: %v", err)
+ return nil, []error{tc.DBError}, tc.SystemError
+ }
+ params = append(params, p)
+ }
+
+ return params, []error{}, tc.NoError
+
+}
+
+//The Parameter implementation of the Deleter interface
+//all implementations of Deleter should use transactions and return the proper errorType
+func (pp *TOProfileParameter) 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 parameter: %++v", deleteQuery(), pp)
+ result, err := tx.NamedExec(deleteQuery(), pp)
+ 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 parameter 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 selectQuery() string {
+
+ query := `SELECT
+pp.last_updated,
+pp.profile profile_id,
+pp.parameter parameter_id,
+prof.name profile,
+param.name parameter
+FROM profile_parameter pp
+JOIN profile prof ON prof.id = pp.profile
+JOIN parameter param ON param.id = pp.parameter`
+ return query
+}
+
+func updateQuery() string {
+ query := `UPDATE
+profile_parameter SET
+profile=:profile_id,
+parameter=:parameter_id
+WHERE profile=:profile_id AND
+ parameter = :parameter_id
+ RETURNING last_updated`
+ return query
+}
+
+func deleteQuery() string {
+ query := `DELETE FROM profile_parameter
+ WHERE profile=:profile_id and parameter=:parameter_id`
+ return query
+}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
new file mode 100644
index 0000000..9e7ce20
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
@@ -0,0 +1,111 @@
+package profileparameter
+
+/*
+ * 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 (
+ "testing"
+ "time"
+
+ "github.com/apache/incubator-trafficcontrol/lib/go-tc"
+ "github.com/apache/incubator-trafficcontrol/lib/go-tc/v13"
+ "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"
+
+ sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+func getTestProfileParameters() []v13.ProfileParameterNullable {
+ pps := []v13.ProfileParameterNullable{}
+ lastUpdated := tc.TimeNoMod{}
+ lastUpdated.Scan(time.Now())
+ profileID := 1
+ parameterID := 1
+
+ pp := v13.ProfileParameterNullable{
+ LastUpdated: &lastUpdated,
+ ProfileID: &profileID,
+ ParameterID: ¶meterID,
+ }
+ pps = append(pps, pp)
+
+ pp2 := pp
+ pp2.ProfileID = &profileID
+ pp2.ParameterID = ¶meterID
+ pps = append(pps, pp2)
+
+ return pps
+}
+
+func TestGetProfileParameters(t *testing.T) {
+ mockDB, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer mockDB.Close()
+
+ db := sqlx.NewDb(mockDB, "sqlmock")
+ defer db.Close()
+
+ testPPs := getTestProfileParameters()
+ cols := test.ColsFromStructByTag("db", v13.ProfileParameterNullable{})
+ rows := sqlmock.NewRows(cols)
+
+ for _, ts := range testPPs {
+ rows = rows.AddRow(
+ ts.LastUpdated,
+ ts.Profile,
+ ts.ProfileID,
+ ts.Parameter,
+ ts.ParameterID,
+ )
+ }
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+ v := map[string]string{"profile": "1"}
+
+ pps, errs, _ := refType.Read(db, v, auth.CurrentUser{})
+ if len(errs) > 0 {
+ t.Errorf("profileparameter.Read expected: no errors, actual: %v", errs)
+ }
+
+ if len(pps) != 2 {
+ t.Errorf("profileparameter.Read expected: len(pps) == 2, actual: %v", len(pps))
+ }
+
+}
+
+func TestInterfaces(t *testing.T) {
+ var i interface{}
+ i = &TOProfileParameter{}
+
+ if _, ok := i.(api.Creator); !ok {
+ t.Errorf("ProfileParameter must be Creator")
+ }
+ if _, ok := i.(api.Reader); !ok {
+ t.Errorf("ProfileParameter must be Reader")
+ }
+ if _, ok := i.(api.Deleter); !ok {
+ t.Errorf("ProfileParameter must be Deleter")
+ }
+ if _, ok := i.(api.Identifier); !ok {
+ t.Errorf("ProfileParameter must be Identifier")
+ }
+}
--
To stop receiving notification emails like this one, please contact
rob@apache.org.
[incubator-trafficcontrol] 03/03: removed unimplemented routes and
unneeded comments
Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git
commit fa6518ecff3e0bc6a8cece1048a0d8d8ba57bb99
Author: ASchmidt <An...@comcast.com>
AuthorDate: Mon May 7 11:46:09 2018 -0600
removed unimplemented routes and unneeded comments
---
lib/go-tc/deliveryservice_servers.go | 21 ---------------------
.../deliveryservice/servers/servers.go | 19 -------------------
traffic_ops/traffic_ops_golang/routes.go | 4 +---
3 files changed, 1 insertion(+), 43 deletions(-)
diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go
index bf6a3f2..aa0ec99 100644
--- a/lib/go-tc/deliveryservice_servers.go
+++ b/lib/go-tc/deliveryservice_servers.go
@@ -17,21 +17,6 @@ import "time"
limitations under the License.
*/
-/*
-# get all delivery services associated with a server (from deliveryservice_server table)
-$r->get( "/api/$version/servers/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'Deliveryservice#get_deliveryservices_by_serverId', namespace => $namespace );
-
-# delivery service / server assignments
-$r->post("/api/$version/deliveryservices/:xml_id/servers")->over( authenticated => 1, not_ldap => 1 )
-->to( 'Deliveryservice#assign_servers', namespace => $namespace );
-$r->delete("/api/$version/deliveryservice_server/:dsId/:serverId" => [ dsId => qr/\d+/, serverId => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#remove_server_from_ds', namespace => $namespace );
- # -- DELIVERYSERVICES: SERVERS
- # Supports ?orderby=key
- $r->get("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#index', namespace => $namespace );
- $r->post("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#assign_servers_to_ds', namespace => $namespace );
-
-*/
-
// DeliveryServiceServerResponse ...
type DeliveryServiceServerResponse struct {
Response []DeliveryServiceServer `json:"response"`
@@ -93,9 +78,3 @@ type DssServer struct {
TypeID *int `json:"typeId" db:"server_type_id"`
UpdPending *bool `json:"updPending" db:"upd_pending"`
}
-
-// UnmarshalJSON implements the json.Unmarshaller interface to suppress unmarshalling for IDNoMod
-//func (a *IDNoMod) UnmarshalJSON([]byte) error {
- //return nil
-//}
-
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index 768dab0..f212937 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -46,25 +46,6 @@ func GetRefType() *TODeliveryServiceServer {
return &refType
}
-/*
-# get all delivery services associated with a server (from deliveryservice_server table)
-$r->get( "/api/$version/servers/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'Deliveryservice#get_deliveryservices_by_serverId', namespace => $namespace );
-
-# delivery service / server assignments
-$r->post("/api/$version/deliveryservices/:xml_id/servers")->over( authenticated => 1, not_ldap => 1 )
-->to( 'Deliveryservice#assign_servers', namespace => $namespace );
-$r->delete("/api/$version/deliveryservice_server/:dsId/:serverId" => [ dsId => qr/\d+/, serverId => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#remove_server_from_ds', namespace => $namespace );
- # -- DELIVERYSERVICES: SERVERS
- # Supports ?orderby=key
- $r->get("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#index', namespace => $namespace );
- $r->post("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#assign_servers_to_ds', namespace => $namespace );
-
- {1.2, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
- {1.2, http.MethodGet, `deliveryservices/{id}/unassigned_servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
- {1.2, http.MethodGet, `deliveryservices/{id}/servers/eligible$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
-
-*/
-
func (dss TODeliveryServiceServer) GetKeyFieldsInfo() []api.KeyFieldInfo {
return []api.KeyFieldInfo{{"deliveryservice", api.GetIntKey}, {"server", api.GetIntKey}}
}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 125f7ef..5763f70 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -150,9 +150,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
{1.1, http.MethodDelete, `regions/{id}$`, api.DeleteHandler(region.GetRefType(), d.DB), auth.PrivLevelOperations, Authenticated, nil},
// get all edge servers associated with a delivery service (from deliveryservice_server table)
- {1.2, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
- {1.2, http.MethodGet, `deliveryservices/{id}/unassigned_servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
- {1.2, http.MethodGet, `deliveryservices/{id}/servers/eligible$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.1, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
//Server
{1.1, http.MethodGet, `servers/checks$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
--
To stop receiving notification emails like this one, please contact
rob@apache.org.
[incubator-trafficcontrol] 02/03: added api to
DeliveryserviceServer Get in Go
Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-trafficcontrol.git
commit b50539c49e61b7ec189f9b71511166f822e73625
Author: ASchmidt <An...@comcast.com>
AuthorDate: Fri May 4 15:03:15 2018 -0600
added api to DeliveryserviceServer Get in Go
---
lib/go-tc/deliveryservice_servers.go | 240 +++++++--------------
lib/go-tc/deliveryservices.go | 13 --
.../deliveryservice/servers/servers.go | 239 ++++++++++++--------
.../deliveryservice/servers/servers_test.go | 91 +-------
traffic_ops/traffic_ops_golang/routes.go | 6 +
5 files changed, 230 insertions(+), 359 deletions(-)
diff --git a/lib/go-tc/deliveryservice_servers.go b/lib/go-tc/deliveryservice_servers.go
index 9c7e6ae..bf6a3f2 100644
--- a/lib/go-tc/deliveryservice_servers.go
+++ b/lib/go-tc/deliveryservice_servers.go
@@ -1,5 +1,7 @@
package tc
+import "time"
+
/*
Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,179 +17,85 @@ package tc
limitations under the License.
*/
-import (
- "database/sql/driver"
- "encoding/json"
- "errors"
- "fmt"
- "strconv"
- "strings"
-
- log "github.com/apache/incubator-trafficcontrol/lib/go-log"
-)
-
-// IDNoMod type is used to suppress JSON unmarshalling
-type IDNoMod int
-
-// DeliveryServiceRequest is used as part of the workflow to create,
-// modify, or delete a delivery service.
-type DeliveryServiceRequest struct {
- AssigneeID int `json:"assigneeId,omitempty"`
- Assignee string `json:"assignee,omitempty"`
- AuthorID IDNoMod `json:"authorId"`
- Author string `json:"author"`
- ChangeType string `json:"changeType"`
- CreatedAt *TimeNoMod `json:"createdAt"`
- ID int `json:"id"`
- LastEditedBy string `json:"lastEditedBy,omitempty"`
- LastEditedByID IDNoMod `json:"lastEditedById,omitempty"`
- LastUpdated *TimeNoMod `json:"lastUpdated"`
- DeliveryService DeliveryService `json:"deliveryService"`
- Status RequestStatus `json:"status"`
- XMLID string `json:"-" db:"xml_id"`
-}
-
-// DeliveryServiceRequestNullable is used as part of the workflow to create,
-// modify, or delete a delivery service.
-type DeliveryServiceRequestNullable struct {
- AssigneeID *int `json:"assigneeId,omitempty" db:"assignee_id"`
- Assignee *string `json:"assignee,omitempty"`
- AuthorID *IDNoMod `json:"authorId" db:"author_id"`
- Author *string `json:"author"`
- ChangeType *string `json:"changeType" db:"change_type"`
- CreatedAt *TimeNoMod `json:"createdAt" db:"created_at"`
- ID *int `json:"id" db:"id"`
- LastEditedBy *string `json:"lastEditedBy"`
- LastEditedByID *IDNoMod `json:"lastEditedById" db:"last_edited_by_id"`
- LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"`
- DeliveryService *DeliveryServiceNullable `json:"deliveryService" db:"deliveryservice"`
- Status *RequestStatus `json:"status" db:"status"`
- XMLID *string `json:"-" db:"xml_id"`
-}
-
-// UnmarshalJSON implements the json.Unmarshaller interface to suppress unmarshalling for IDNoMod
-func (a *IDNoMod) UnmarshalJSON([]byte) error {
- return nil
-}
-
-// RequestStatus captures where in the workflow this request is
-type RequestStatus string
-
-const (
- // RequestStatusInvalid -- invalid state
- RequestStatusInvalid = RequestStatus("invalid")
- // RequestStatusDraft -- newly created; not ready to be reviewed
- RequestStatusDraft = RequestStatus("draft")
- // RequestStatusSubmitted -- newly created; ready to be reviewed
- RequestStatusSubmitted = RequestStatus("submitted")
- // RequestStatusRejected -- reviewed, but problems found
- RequestStatusRejected = RequestStatus("rejected")
- // RequestStatusPending -- reviewed and locked; ready to be implemented
- RequestStatusPending = RequestStatus("pending")
- // RequestStatusComplete -- implemented and locked
- RequestStatusComplete = RequestStatus("complete")
-)
-
-// RequestStatuses -- user-visible string associated with each of the above
-var RequestStatuses = []RequestStatus{
- // "invalid" -- don't list here..
- "draft",
- "submitted",
- "rejected",
- "pending",
- "complete",
-}
-
-// UnmarshalJSON implements json.Unmarshaller
-func (r *RequestStatus) UnmarshalJSON(b []byte) error {
- u, err := strconv.Unquote(string(b))
- if err != nil {
- return err
- }
+/*
+# get all delivery services associated with a server (from deliveryservice_server table)
+$r->get( "/api/$version/servers/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'Deliveryservice#get_deliveryservices_by_serverId', namespace => $namespace );
+
+# delivery service / server assignments
+$r->post("/api/$version/deliveryservices/:xml_id/servers")->over( authenticated => 1, not_ldap => 1 )
+->to( 'Deliveryservice#assign_servers', namespace => $namespace );
+$r->delete("/api/$version/deliveryservice_server/:dsId/:serverId" => [ dsId => qr/\d+/, serverId => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#remove_server_from_ds', namespace => $namespace );
+ # -- DELIVERYSERVICES: SERVERS
+ # Supports ?orderby=key
+ $r->get("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#index', namespace => $namespace );
+ $r->post("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#assign_servers_to_ds', namespace => $namespace );
- // just check to see if the string represents a valid requeststatus
- _, err = RequestStatusFromString(u)
- if err != nil {
- return err
- }
- return json.Unmarshal(b, (*string)(r))
-}
+*/
-// MarshalJSON implements json.Marshaller
-func (r RequestStatus) MarshalJSON() ([]byte, error) {
- return json.Marshal(string(r))
+// DeliveryServiceServerResponse ...
+type DeliveryServiceServerResponse struct {
+ Response []DeliveryServiceServer `json:"response"`
+ Size int `json:"size"`
+ OrderBy string `json:"orderby"`
+ Limit int `json:"limit"`
}
-// Value implements driver.Valuer
-func (r *RequestStatus) Value() (driver.Value, error) {
- v, err := json.Marshal(r)
- log.Debugf("value is %v; err is %v", v, err)
- v = []byte(strings.Trim(string(v), `"`))
- return v, err
+// DeliveryServiceServer ...
+type DeliveryServiceServer struct {
+ Server *int `json:"server"`
+ DeliveryService *int `json:"deliveryService"`
+ LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"`
}
-// Scan implements sql.Scanner
-func (r *RequestStatus) Scan(src interface{}) error {
- b, ok := src.([]byte)
- if !ok {
- return fmt.Errorf("expected requeststatus in byte array form; got %T", src)
- }
- b = []byte(`"` + string(b) + `"`)
- return json.Unmarshal(b, r)
-}
-// RequestStatusFromString gets the status enumeration from a string
-func RequestStatusFromString(rs string) (RequestStatus, error) {
- if rs == "" {
- return RequestStatusDraft, nil
- }
- for _, s := range RequestStatuses {
- if string(s) == rs {
- return s, nil
- }
- }
- return RequestStatusInvalid, errors.New(rs + " is not a valid RequestStatus name")
+type DssServer struct {
+ Cachegroup *string `json:"cachegroup" db:"cachegroup"`
+ CachegroupID *int `json:"cachegroupId" db:"cachegroup_id"`
+ CDNID *int `json:"cdnId" db:"cdn_id"`
+ CDNName *string `json:"cdnName" db:"cdn_name"`
+ DeliveryServices *map[string][]string `json:"deliveryServices,omitempty"`
+ DomainName *string `json:"domainName" db:"domain_name"`
+ FQDN *string `json:"fqdn,omitempty"`
+ FqdnTime time.Time `json:"-"`
+ GUID *string `json:"guid" db:"guid"`
+ HostName *string `json:"hostName" db:"host_name"`
+ HTTPSPort *int `json:"httpsPort" db:"https_port"`
+ ID *int `json:"id" db:"id"`
+ ILOIPAddress *string `json:"iloIpAddress" db:"ilo_ip_address"`
+ ILOIPGateway *string `json:"iloIpGateway" db:"ilo_ip_gateway"`
+ ILOIPNetmask *string `json:"iloIpNetmask" db:"ilo_ip_netmask"`
+ ILOPassword *string `json:"iloPassword" db:"ilo_password"`
+ ILOUsername *string `json:"iloUsername" db:"ilo_username"`
+ InterfaceMtu *int `json:"interfaceMtu" db:"interface_mtu"`
+ InterfaceName *string `json:"interfaceName" db:"interface_name"`
+ IP6Address *string `json:"ip6Address" db:"ip6_address"`
+ IP6Gateway *string `json:"ip6Gateway" db:"ip6_gateway"`
+ IPAddress *string `json:"ipAddress" db:"ip_address"`
+ IPGateway *string `json:"ipGateway" db:"ip_gateway"`
+ IPNetmask *string `json:"ipNetmask" db:"ip_netmask"`
+ LastUpdated *TimeNoMod `json:"lastUpdated" db:"last_updated"`
+ MgmtIPAddress *string `json:"mgmtIpAddress" db:"mgmt_ip_address"`
+ MgmtIPGateway *string `json:"mgmtIpGateway" db:"mgmt_ip_gateway"`
+ MgmtIPNetmask *string `json:"mgmtIpNetmask" db:"mgmt_ip_netmask"`
+ OfflineReason *string `json:"offlineReason" db:"offline_reason"`
+ PhysLocation *string `json:"physLocation" db:"phys_location"`
+ PhysLocationID *int `json:"physLocationId" db:"phys_location_id"`
+ Profile *string `json:"profile" db:"profile"`
+ ProfileDesc *string `json:"profileDesc" db:"profile_desc"`
+ ProfileID *int `json:"profileId" db:"profile_id"`
+ Rack *string `json:"rack" db:"rack"`
+ RouterHostName *string `json:"routerHostName" db:"router_host_name"`
+ RouterPortName *string `json:"routerPortName" db:"router_port_name"`
+ Status *string `json:"status" db:"status"`
+ StatusID *int `json:"statusId" db:"status_id"`
+ TCPPort *int `json:"tcpPort" db:"tcp_port"`
+ Type string `json:"type" db:"server_type"`
+ TypeID *int `json:"typeId" db:"server_type_id"`
+ UpdPending *bool `json:"updPending" db:"upd_pending"`
}
-// ValidTransition returns nil if the transition is allowed for the workflow, an error if not
-func (r RequestStatus) ValidTransition(to RequestStatus) error {
- if r == RequestStatusRejected || r == RequestStatusComplete {
- // once rejected or completed, no changes allowed
- return errors.New(string(r) + " request cannot be changed")
- }
-
- if r == to {
- // no change -- always allowed
- return nil
- }
+// UnmarshalJSON implements the json.Unmarshaller interface to suppress unmarshalling for IDNoMod
+//func (a *IDNoMod) UnmarshalJSON([]byte) error {
+ //return nil
+//}
- // indicate if valid transitioning to this RequestStatus
- switch to {
- case RequestStatusDraft:
- // can go back to draft if submitted or rejected
- if r == RequestStatusSubmitted {
- return nil
- }
- case RequestStatusSubmitted:
- // can go be submitted if draft or rejected
- if r == RequestStatusDraft {
- return nil
- }
- case RequestStatusRejected:
- // only submitted can be rejected
- if r == RequestStatusSubmitted {
- return nil
- }
- case RequestStatusPending:
- // only submitted can move to pending
- if r == RequestStatusSubmitted {
- return nil
- }
- case RequestStatusComplete:
- // only pending can be completed. Completed can never change.
- if r == RequestStatusPending {
- return nil
- }
- }
- return errors.New("invalid transition from " + string(r) + " to " + string(to))
-}
diff --git a/lib/go-tc/deliveryservices.go b/lib/go-tc/deliveryservices.go
index c352882..a01b921 100644
--- a/lib/go-tc/deliveryservices.go
+++ b/lib/go-tc/deliveryservices.go
@@ -281,17 +281,4 @@ type DeliveryServiceRouting struct {
RegionalDenied int `json:"regionalDenied"`
}
-// DeliveryServiceServerResponse ...
-type DeliveryServiceServerResponse struct {
- Response []DeliveryServiceServer `json:"response"`
- Size int `json:"size"`
- OrderBy string `json:"orderby"`
- Limit int `json:"limit"`
-}
-// DeliveryServiceServer ...
-type DeliveryServiceServer struct {
- LastUpdated string `json:"lastUpdated"`
- Server int `json:"server"`
- DeliveryService int `json:"deliveryService"`
-}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index 463ff06..768dab0 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -1,4 +1,4 @@
-package profileparameter
+package servers
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -25,92 +25,105 @@ import (
"strconv"
"github.com/apache/incubator-trafficcontrol/lib/go-log"
- tc "github.com/apache/incubator-trafficcontrol/lib/go-tc"
- "github.com/apache/incubator-trafficcontrol/lib/go-tc/v13"
+ "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/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tovalidate"
- validation "github.com/go-ozzo/ozzo-validation"
+ "github.com/go-ozzo/ozzo-validation"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
)
-const (
- ProfileIDQueryParam = "profileId"
- ParameterIDQueryParam = "parameterId"
-)
-
-//we need a type alias to define functions on
-type TOProfileParameter v13.ProfileParameterNullable
+// TODeliveryServiceRequest provides a type alias to define functions on
+type TODeliveryServiceServer tc.DeliveryServiceServer
//the refType is passed into the handlers where a copy of its type is used to decode the json.
-var refType = TOProfileParameter(v13.ProfileParameterNullable{})
+var refType = TODeliveryServiceServer(tc.DeliveryServiceServer{})
-func GetRefType() *TOProfileParameter {
+func GetRefType() *TODeliveryServiceServer {
return &refType
}
-func (pp TOProfileParameter) GetKeyFieldsInfo() []api.KeyFieldInfo {
- return []api.KeyFieldInfo{{ProfileIDQueryParam, api.GetIntKey}, {ParameterIDQueryParam, api.GetIntKey}}
+/*
+# get all delivery services associated with a server (from deliveryservice_server table)
+$r->get( "/api/$version/servers/:id/deliveryservices" => [ id => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'Deliveryservice#get_deliveryservices_by_serverId', namespace => $namespace );
+
+# delivery service / server assignments
+$r->post("/api/$version/deliveryservices/:xml_id/servers")->over( authenticated => 1, not_ldap => 1 )
+->to( 'Deliveryservice#assign_servers', namespace => $namespace );
+$r->delete("/api/$version/deliveryservice_server/:dsId/:serverId" => [ dsId => qr/\d+/, serverId => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#remove_server_from_ds', namespace => $namespace );
+ # -- DELIVERYSERVICES: SERVERS
+ # Supports ?orderby=key
+ $r->get("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#index', namespace => $namespace );
+ $r->post("/api/$version/deliveryserviceserver")->over( authenticated => 1, not_ldap => 1 )->to( 'DeliveryServiceServer#assign_servers_to_ds', namespace => $namespace );
+
+ {1.2, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.2, http.MethodGet, `deliveryservices/{id}/unassigned_servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.2, http.MethodGet, `deliveryservices/{id}/servers/eligible$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+
+*/
+
+func (dss TODeliveryServiceServer) GetKeyFieldsInfo() []api.KeyFieldInfo {
+ return []api.KeyFieldInfo{{"deliveryservice", api.GetIntKey}, {"server", api.GetIntKey}}
}
//Implementation of the Identifier, Validator interface functions
-func (pp TOProfileParameter) GetKeys() (map[string]interface{}, bool) {
- if pp.ProfileID == nil {
- return map[string]interface{}{ProfileIDQueryParam: 0}, false
+func (dss TODeliveryServiceServer) GetKeys() (map[string]interface{}, bool) {
+ if dss.DeliveryService == nil {
+ return map[string]interface{}{"deliveryservice": 0}, false
}
- if pp.ParameterID == nil {
- return map[string]interface{}{ParameterIDQueryParam: 0}, false
+ if dss.Server == nil {
+ return map[string]interface{}{"server": 0}, false
}
keys := make(map[string]interface{})
- profileID := *pp.ProfileID
- parameterID := *pp.ParameterID
+ ds_id := *dss.DeliveryService
+ server_id := *dss.Server
- keys[ProfileIDQueryParam] = profileID
- keys[ParameterIDQueryParam] = parameterID
+ keys["deliveryservice"] = ds_id
+ keys["server"] = server_id
return keys, true
}
-func (pp *TOProfileParameter) GetAuditName() string {
- if pp.ProfileID != nil {
- return strconv.Itoa(*pp.ProfileID) + "-" + strconv.Itoa(*pp.ParameterID)
+func (dss *TODeliveryServiceServer) GetAuditName() string {
+ if dss.DeliveryService != nil {
+ return strconv.Itoa(*dss.DeliveryService) + "-" + strconv.Itoa(*dss.Server)
}
return "unknown"
}
-func (pp *TOProfileParameter) GetType() string {
- return "profileParameter"
+func (dss *TODeliveryServiceServer) GetType() string {
+ return "deliveryserviceServers"
}
-func (pp *TOProfileParameter) SetKeys(keys map[string]interface{}) {
- profId, _ := keys[ProfileIDQueryParam].(int) //this utilizes the non panicking type assertion, if the thrown away ok variable is false i will be the zero of the type, 0 here.
- pp.ProfileID = &profId
+func (dss *TODeliveryServiceServer) SetKeys(keys map[string]interface{}) {
+ ds_id, _ := keys["deliveryservice"].(int) //this utilizes the non panicking type assertion, if the thrown away ok variable is false i will be the zero of the type, 0 here.
+ dss.DeliveryService = &ds_id
- paramId, _ := keys[ParameterIDQueryParam].(int) //this utilizes the non panicking type assertion, if the thrown away ok variable is false i will be the zero of the type, 0 here.
- pp.ParameterID = ¶mId
+ server_id, _ := keys["server"].(int) //this utilizes the non panicking type assertion, if the thrown away ok variable is false i will be the zero of the type, 0 here.
+ dss.Server = &server_id
}
// Validate fulfills the api.Validator interface
-func (pp *TOProfileParameter) Validate(db *sqlx.DB) []error {
+func (dss *TODeliveryServiceServer) Validate(db *sqlx.DB) []error {
errs := validation.Errors{
- "profile": validation.Validate(pp.ProfileID, validation.Required),
- "parameter": validation.Validate(pp.ParameterID, validation.Required),
+ "deliveryservice": validation.Validate(dss.DeliveryService, validation.Required),
+ "server": validation.Validate(dss.Server, validation.Required),
}
return tovalidate.ToErrors(errs)
}
-//The TOProfileParameter implementation of the Creator interface
+//The TODeliveryServiceServer implementation of the Creator interface
//all implementations of Creator should use transactions and return the proper errorType
//ParsePQUniqueConstraintError is used to determine if a profileparameter 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 profile and lastUpdated values of the newly inserted profileparameter and have
//to be added to the struct
-func (pp *TOProfileParameter) Create(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) {
+func (dss *TODeliveryServiceServer) Create(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) {
rollbackTransaction := true
tx, err := db.Beginx()
defer func() {
@@ -127,7 +140,7 @@ func (pp *TOProfileParameter) Create(db *sqlx.DB, user auth.CurrentUser) (error,
log.Error.Printf("could not begin transaction: %v", err)
return tc.DBError, tc.SystemError
}
- resultRows, err := tx.NamedQuery(insertQuery(), pp)
+ resultRows, err := tx.NamedQuery(insertQuery(), dss)
if err != nil {
if pqErr, ok := err.(*pq.Error); ok {
err, eType := dbhelpers.ParsePQUniqueConstraintError(pqErr)
@@ -141,19 +154,19 @@ func (pp *TOProfileParameter) Create(db *sqlx.DB, user auth.CurrentUser) (error,
}
defer resultRows.Close()
- var profile int
- var parameter int
+ var ds_id int
+ var server_id int
var lastUpdated tc.TimeNoMod
rowsAffected := 0
for resultRows.Next() {
rowsAffected++
- if err := resultRows.Scan(&profile, ¶meter, &lastUpdated); err != nil {
- log.Error.Printf("could not scan profile from insert: %s\n", err)
+ if err := resultRows.Scan(&ds_id, &server_id, &lastUpdated); err != nil {
+ log.Error.Printf("could not scan dss from insert: %s\n", err)
return tc.DBError, tc.SystemError
}
}
if rowsAffected == 0 {
- err = errors.New("no profile_parameter was inserted, no profile+parameter was returned")
+ err = errors.New("no deliveryServiceServer was inserted, nothing to return")
log.Errorln(err)
return tc.DBError, tc.SystemError
}
@@ -163,8 +176,8 @@ func (pp *TOProfileParameter) Create(db *sqlx.DB, user auth.CurrentUser) (error,
return tc.DBError, tc.SystemError
}
- pp.SetKeys(map[string]interface{}{ProfileIDQueryParam: profile, ParameterIDQueryParam: parameter})
- pp.LastUpdated = &lastUpdated
+ dss.SetKeys(map[string]interface{}{"deliveryservice": ds_id, "server": server_id})
+ dss.LastUpdated = &lastUpdated
err = tx.Commit()
if err != nil {
log.Errorln("Could not commit transaction: ", err)
@@ -175,57 +188,59 @@ func (pp *TOProfileParameter) Create(db *sqlx.DB, user auth.CurrentUser) (error,
}
func insertQuery() string {
- query := `INSERT INTO profile_parameter (
-profile,
-parameter) VALUES (
-:profile_id,
-:parameter_id) RETURNING profile, parameter, last_updated`
+ query := `INSERT INTO deliveryservice_server (
+deliveryservice,
+server) VALUES (
+:ds_id,
+:server_id) RETURNING deliveryservice, server, last_updated`
return query
}
-func (pp *TOProfileParameter) Read(db *sqlx.DB, parameters map[string]string, user auth.CurrentUser) ([]interface{}, []error, tc.ApiErrorType) {
- var rows *sqlx.Rows
+func (dss *TODeliveryServiceServer) Read(db *sqlx.DB, params map[string]string, user auth.CurrentUser) ([]interface{}, []error, tc.ApiErrorType) {
+ idstr, ok := params["id"]
- // Query Parameters to Database Query column mappings
- // see the fields mapped in the SQL query
- queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{
- "profileId": dbhelpers.WhereColumnInfo{"pp.profile", nil},
- "parameterId": dbhelpers.WhereColumnInfo{"pp.parameter", nil},
- "lastUpdated": dbhelpers.WhereColumnInfo{"pp.last_updated", nil},
+ if !ok {
+ log.Errorf("Deliveryservice Server Id missing")
+ return nil, []error{errors.New("Deliverservice id is required.")}, tc.DataMissingError
}
+ id, err := strconv.Atoi(idstr)
- where, orderBy, queryValues, errs := dbhelpers.BuildWhereAndOrderBy(parameters, queryParamsToQueryCols)
- if len(errs) > 0 {
- return nil, errs, tc.DataConflictError
+ if err != nil {
+ log.Errorf("Deliveryservice Server Id is not an integer")
+ return nil, []error{errors.New("Deliverservice id is not an integer.")}, tc.SystemError
}
- query := selectQuery() + where + orderBy
+ query := selectQuery()
log.Debugln("Query is ", query)
- rows, err := db.NamedQuery(query, queryValues)
+ rows, err := db.Queryx(query, id)
if err != nil {
- log.Errorf("Error querying Parameters: %v", err)
+ log.Errorf("Error querying DeliveryserviceServers: %v", err)
return nil, []error{tc.DBError}, tc.SystemError
}
defer rows.Close()
- params := []interface{}{}
+ servers := []interface{}{}
for rows.Next() {
- var p v13.ProfileParameterNullable
- if err = rows.StructScan(&p); err != nil {
- log.Errorf("error parsing pp rows: %v", err)
+ var s tc.DssServer
+ if err = rows.StructScan(&s); err != nil {
+ log.Errorf("error parsing dss rows: %v", err)
return nil, []error{tc.DBError}, tc.SystemError
}
- params = append(params, p)
+ hiddenField := ""
+ if user.PrivLevel < auth.PrivLevelAdmin {
+ s.ILOPassword = &hiddenField
+ }
+ servers = append(servers, s)
}
- return params, []error{}, tc.NoError
+ return servers, []error{}, tc.NoError
}
//The Parameter implementation of the Deleter interface
//all implementations of Deleter should use transactions and return the proper errorType
-func (pp *TOProfileParameter) Delete(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) {
+func (dss *TODeliveryServiceServer) Delete(db *sqlx.DB, user auth.CurrentUser) (error, tc.ApiErrorType) {
rollbackTransaction := true
tx, err := db.Beginx()
defer func() {
@@ -242,8 +257,8 @@ func (pp *TOProfileParameter) Delete(db *sqlx.DB, user auth.CurrentUser) (error,
log.Error.Printf("could not begin transaction: %v", err)
return tc.DBError, tc.SystemError
}
- log.Debugf("about to run exec query: %s with parameter: %++v", deleteQuery(), pp)
- result, err := tx.NamedExec(deleteQuery(), pp)
+ log.Debugf("about to run exec query: %s with parameter: %++v", deleteQuery(), dss)
+ result, err := tx.NamedExec(deleteQuery(), dss)
if err != nil {
log.Errorf("received error: %++v from delete execution", err)
return tc.DBError, tc.SystemError
@@ -267,27 +282,71 @@ func (pp *TOProfileParameter) Delete(db *sqlx.DB, user auth.CurrentUser) (error,
rollbackTransaction = false
return nil, tc.NoError
}
-
func selectQuery() string {
- query := `SELECT
-pp.last_updated,
-pp.profile profile_id,
-pp.parameter parameter_id,
-prof.name profile,
-param.name parameter
-FROM profile_parameter pp
-JOIN profile prof ON prof.id = pp.profile
-JOIN parameter param ON param.id = pp.parameter`
- return query
+ const JumboFrameBPS = 9000
+
+ // COALESCE is needed to default values that are nil in the database
+ // because Go does not allow that to marshal into the struct
+ selectStmt := `SELECT
+ cg.name as cachegroup,
+ s.cachegroup as cachegroup_id,
+ s.cdn_id,
+ cdn.name as cdn_name,
+ s.domain_name,
+ s.guid,
+ s.host_name,
+ s.https_port,
+ s.id,
+ s.ilo_ip_address,
+ s.ilo_ip_gateway,
+ s.ilo_ip_netmask,
+ s.ilo_password,
+ s.ilo_username,
+ COALESCE(s.interface_mtu, ` + strconv.Itoa(JumboFrameBPS) + `) as interface_mtu,
+ s.interface_name,
+ s.ip6_address,
+ s.ip6_gateway,
+ s.ip_address,
+ s.ip_gateway,
+ s.ip_netmask,
+ s.last_updated,
+ s.mgmt_ip_address,
+ s.mgmt_ip_gateway,
+ s.mgmt_ip_netmask,
+ s.offline_reason,
+ pl.name as phys_location,
+ s.phys_location as phys_location_id,
+ p.name as profile,
+ p.description as profile_desc,
+ s.profile as profile_id,
+ s.rack,
+ s.router_host_name,
+ s.router_port_name,
+ st.name as status,
+ s.status as status_id,
+ s.tcp_port,
+ t.name as server_type,
+ s.type as server_type_id,
+ s.upd_pending as upd_pending
+ FROM server s
+ JOIN cachegroup cg ON s.cachegroup = cg.id
+ JOIN cdn cdn ON s.cdn_id = cdn.id
+ JOIN phys_location pl ON s.phys_location = pl.id
+ JOIN profile p ON s.profile = p.id
+ JOIN status st ON s.status = st.id
+ JOIN type t ON s.type = t.id
+ WHERE s.id in (select server from deliveryservice_server where deliveryservice = $1)`
+
+ return selectStmt
}
func updateQuery() string {
query := `UPDATE
-profile_parameter SET
-profile=:profile_id,
-parameter=:parameter_id
-WHERE profile=:profile_id AND
+ profile_parameter SET
+ profile=:profile_id,
+ parameter=:parameter_id
+ WHERE profile=:profile_id AND
parameter = :parameter_id
RETURNING last_updated`
return query
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
index 9e7ce20..58d556e 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers_test.go
@@ -1,4 +1,4 @@
-package profileparameter
+package servers
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,93 +19,4 @@ package profileparameter
* under the License.
*/
-import (
- "testing"
- "time"
- "github.com/apache/incubator-trafficcontrol/lib/go-tc"
- "github.com/apache/incubator-trafficcontrol/lib/go-tc/v13"
- "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"
-
- sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
-)
-
-func getTestProfileParameters() []v13.ProfileParameterNullable {
- pps := []v13.ProfileParameterNullable{}
- lastUpdated := tc.TimeNoMod{}
- lastUpdated.Scan(time.Now())
- profileID := 1
- parameterID := 1
-
- pp := v13.ProfileParameterNullable{
- LastUpdated: &lastUpdated,
- ProfileID: &profileID,
- ParameterID: ¶meterID,
- }
- pps = append(pps, pp)
-
- pp2 := pp
- pp2.ProfileID = &profileID
- pp2.ParameterID = ¶meterID
- pps = append(pps, pp2)
-
- return pps
-}
-
-func TestGetProfileParameters(t *testing.T) {
- mockDB, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer mockDB.Close()
-
- db := sqlx.NewDb(mockDB, "sqlmock")
- defer db.Close()
-
- testPPs := getTestProfileParameters()
- cols := test.ColsFromStructByTag("db", v13.ProfileParameterNullable{})
- rows := sqlmock.NewRows(cols)
-
- for _, ts := range testPPs {
- rows = rows.AddRow(
- ts.LastUpdated,
- ts.Profile,
- ts.ProfileID,
- ts.Parameter,
- ts.ParameterID,
- )
- }
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
- v := map[string]string{"profile": "1"}
-
- pps, errs, _ := refType.Read(db, v, auth.CurrentUser{})
- if len(errs) > 0 {
- t.Errorf("profileparameter.Read expected: no errors, actual: %v", errs)
- }
-
- if len(pps) != 2 {
- t.Errorf("profileparameter.Read expected: len(pps) == 2, actual: %v", len(pps))
- }
-
-}
-
-func TestInterfaces(t *testing.T) {
- var i interface{}
- i = &TOProfileParameter{}
-
- if _, ok := i.(api.Creator); !ok {
- t.Errorf("ProfileParameter must be Creator")
- }
- if _, ok := i.(api.Reader); !ok {
- t.Errorf("ProfileParameter must be Reader")
- }
- if _, ok := i.(api.Deleter); !ok {
- t.Errorf("ProfileParameter must be Deleter")
- }
- if _, ok := i.(api.Identifier); !ok {
- t.Errorf("ProfileParameter must be Identifier")
- }
-}
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index b82fa59..125f7ef 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -38,6 +38,7 @@ import (
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/coordinate"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/crconfig"
dsrequest "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/request"
+ dsserver "github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/servers"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice/request/comment"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/division"
"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/hwinfo"
@@ -148,6 +149,11 @@ 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},
+ // get all edge servers associated with a delivery service (from deliveryservice_server table)
+ {1.2, http.MethodGet, `deliveryservices/{id}/servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.2, http.MethodGet, `deliveryservices/{id}/unassigned_servers$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+ {1.2, http.MethodGet, `deliveryservices/{id}/servers/eligible$`, api.ReadHandler(dsserver.GetRefType(), d.DB),auth.PrivLevelReadOnly, Authenticated, nil},
+
//Server
{1.1, http.MethodGet, `servers/checks$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
{1.1, http.MethodGet, `servers/details$`, handlerToFunc(proxyHandler), 0, NoAuth, []Middleware{}},
--
To stop receiving notification emails like this one, please contact
rob@apache.org.