Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d4ad7fd
Rewrote capabilities endpoints to GO
ocket8888 Aug 5, 2019
5068b25
Fixed incorrect parameter contraint
ocket8888 Aug 13, 2019
ad39fd5
Added godoc
ocket8888 Aug 13, 2019
b0d2294
Added support in the Go Client for capabilities
ocket8888 Aug 13, 2019
7da227f
Added API/client tests
ocket8888 Aug 13, 2019
e0e9e9a
Added Python client support
ocket8888 Aug 14, 2019
6939eb0
Updated docs
ocket8888 Aug 15, 2019
42ae23e
Added changelog updates
ocket8888 Aug 15, 2019
f47dea2
Traffic Portal changes to reflect deprecation
ocket8888 Aug 15, 2019
0786c0d
Fix API route definition for consistency
ocket8888 Oct 11, 2019
aef5700
Remove unnecessary debug line
ocket8888 Oct 11, 2019
9182cda
Use Fatalf when warranted
ocket8888 Oct 11, 2019
91e1d6a
Use API functions to write responses
ocket8888 Oct 11, 2019
3c1becf
fix compilation error
ocket8888 Oct 11, 2019
d61f28d
Switch URL building to use proper net/url encoding
ocket8888 Oct 11, 2019
c85c365
add db struct tags
ocket8888 Oct 11, 2019
d314d88
Add page/where/orderby/limit support
ocket8888 Oct 11, 2019
3af65e6
Removed new PUT/DELETE handlers
ocket8888 Jan 6, 2020
8a2b23a
Removed Python client methods for removed handlers
ocket8888 Jan 6, 2020
2df73e5
Fixed missing format arg
ocket8888 Jan 6, 2020
a571629
Added deprecation notice
ocket8888 Jan 6, 2020
f6d56ad
Updated documentation
ocket8888 Jan 7, 2020
166848c
Properly removed capabilities from withobjs
ocket8888 Jan 8, 2020
0e4b3c4
fixed teardown order
ocket8888 Jan 8, 2020
78e826e
setting up API capabilities
ocket8888 Jan 8, 2020
0c74ecf
Added missing capabilities
ocket8888 Jan 8, 2020
124543f
Added new static capabilities
ocket8888 Jan 8, 2020
8eba7e7
Removed premature deprecation notice in the docs
ocket8888 Jan 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 60 additions & 34 deletions docs/source/api/capabilities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,41 +29,64 @@ Get all capabilities.

Request Structure
-----------------
No available parameters
.. table:: Request Query Parameters

+-----------+----------+---------------------------------------------------------------------------------------------------------------------+
| Name | Required | Description |
+===========+==========+=====================================================================================================================+
| name | no | Return only the capability that has this name |
+-----------+----------+---------------------------------------------------------------------------------------------------------------------+
| orderby | no | Choose the ordering of the results - must be the name of one of the fields of the objects in the ``response`` array |
+-----------+----------+---------------------------------------------------------------------------------------------------------------------+
| sortOrder | no | Changes the order of sorting. Either ascending (default or "asc") or descending ("desc") |
+-----------+----------+---------------------------------------------------------------------------------------------------------------------+
| limit | no | Choose the maximum number of results to return |
+-----------+----------+---------------------------------------------------------------------------------------------------------------------+
| offset | no | The number of results to skip before beginning to return results. Must use in conjunction with ``limit`` |
+-----------+----------+---------------------------------------------------------------------------------------------------------------------+
| page | no | Return the n\ :sup:`th` page of results, where "n" is the value of this parameter, pages are ``limit`` long and the |
| | | first page is 1. If ``offset`` was defined, this query parameter has no effect. ``limit`` must be defined to make |
| | | use of ``page``. |
+-----------+----------+---------------------------------------------------------------------------------------------------------------------+


.. code-block:: http
:caption: Request Example

GET /api/1.4/capabilities?name=test HTTP/1.1
Host: trafficops.infra.ciab.test
User-Agent: curl/7.47.0
Accept: */*
Cookie: mojolicious=...

Response Structure
------------------
:name: Name of the capability
:description: Describes the APIs covered by the capability.
:lastUpdated: Date and time of the last update made to this capability, in ISO format
:description: Describes the permissions covered by the capability.
:lastUpdated: Date and time of the last update made to this capability, in an ISO-like format

.. 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
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: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json
Date: Wed, 14 Nov 2018 20:26:19 GMT
Server: Mojolicious (Perl)
Set-Cookie: mojolicious=...; Path=/; Expires=Mon, 18 Nov 2019 17:40:54 GMT; Max-Age=3600; HttpOnly
Vary: Accept-Encoding
Whole-Content-Sha512: zmjsQO3Y4r1/xCFOHB+E+8+bbgDyVcvoR0d4gKqqsWTFaUnxp2flIzuFqWjXf+wb4Bbd1e2Ojse4nQKnyIFKGw==
Transfer-Encoding: chunked
Set-Cookie: mojolicious=...; Path=/; Expires=Mon, 18 Nov 2019 17:40:54 GMT; Max-Age=3600; HttpOnly
Whole-Content-Sha512: c18+GtX2ZI8PoCSwuAzBhl+6w3vDpKQTa/cDJC0WHxdpguOL378KBxGWW5PCSyZfJUb7wPyOL5qKMn6NNTufhg==
X-Server-Name: traffic_ops_golang/
Date: Thu, 15 Aug 2019 17:20:20 GMT
Content-Length: 161

{ "response": [
{
"name": "cdn-read",
"description": "View CDN configuration",
"lastUpdated": "2017-04-02 08:22:43"
},
{
"name": "cdn-write",
"description": "Create, edit or delete CDN configuration",
"lastUpdated": "2017-04-02 08:22:43"
"description": "This is only a test. If this were a real capability, it might do something",
"lastUpdated": "2019-08-15 17:18:03+00",
"name": "test"
}
]}

Expand All @@ -89,44 +112,47 @@ Request Structure
User-Agent: curl/7.47.0
Accept: */*
Cookie: mojolicious=...
Content-Length: 109
Content-Length: 73
Content-Type: application/json

{
"name": "test",
"description": "This is only a test. If this were a real capability, it might do something"
"name": "testquest",
"description": "A test capability for API examples"
}

Response Structure
------------------
:description: Describes the APIs covered by the capability.
:description: Describes the permissions covered by the capability.
:lastUpdated: Date and time of the last update made to this capability, in an ISO-like format
:name: Name of the 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
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: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json
Date: Wed, 14 Nov 2018 20:33:00 GMT
Server: Mojolicious (Perl)
Set-Cookie: mojolicious=...; Path=/; Expires=Mon, 18 Nov 2019 17:40:54 GMT; Max-Age=3600; HttpOnly
Vary: Accept-Encoding
Whole-Content-Sha512: HhhQzw3JBLv90lOeeSGj75uknADanz3fUnQt1E266HAKPTFuTjuIJpf8ni9fb9Chv9LN7mt16utcHMbP8MBHZw==
Content-Length: 183
Set-Cookie: mojolicious=...; Path=/; Expires=Tue, 07 Jan 2020 20:06:18 GMT; Max-Age=3600; HttpOnly
X-Server-Name: traffic_ops_golang/
Date: Tue, 07 Jan 2020 19:06:18 GMT
Content-Length: 225

{ "alerts": [
{
"level": "success",
"text": "Capability was created."
"text": "Capability created.",
Comment thread
ocket8888 marked this conversation as resolved.
Outdated
"level": "success"
},
{
"text": "This endpoint is deprecated, and will be removed in the future",
"level": "warning"
}
],
"response": {
"name": "test",
"description": "This is only a test. If this were a real capability, it might do something"
"description": "A test capability for API examples",
"lastUpdated": "2020-01-07 19:06:18+00",
"name": "testquest"
}}

38 changes: 38 additions & 0 deletions lib/go-tc/capabilities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tc

/*
* 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.
*/

// Capability reflects the ability of a user in ATC to perform some operation.
//
// In practice, they are assigned to relevant Traffic Ops API endpoints - to describe the
// capabilites of said endpoint - and to user permission Roles - to describe the capabilities
// afforded by said Role. Note that enforcement of Capability-based permisions is not currently
// implemented.
type Capability struct {
Description string `json:"description" db:"description"`
LastUpdated TimeNoMod `json:"lastUpdated" db:"last_updated"`
Name string `json:"name" db:"name"`
}

// CapabilitiesResponse models the structure of a minimal response from the Capabilities API in
// Traffic Ops.
type CapabilitiesResponse struct {
Response []Capability `json:"response"`
}
25 changes: 25 additions & 0 deletions traffic_control/clients/python/trafficops/tosession.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,31 @@ def get_cache_stats(self, query_params=None):
:raises: Union[LoginError, OperationError]
"""

#
# Capabilities
#
@api_request(u'get', u'capabilities', (u'1.1', u'1.2', u'1.3', u'1.4'))
def get_capabilities(self, query_params=None):
"""
Retrieves capabilities
:ref:`to-api-capabilities`
:param query_params: See API page for more information on accepted parameters
:type query_params: Dict[str, Any]
:rtype: Tuple[Union[Dict[str, Any], List[Dict[str, Any]]], requests.Response]
:raises: Union[LoginError, OperationError]
"""

@api_request(u'post', u'capabilities', (u'1.1', u'1.2', u'1.3', u'1.4'))
def create_capability(self, data=None):
"""
Creates a capability
:ref:`to-api-capabilities`
:param data: See API page for more information on accepted request body data
:type data: Any
:rtype: Tuple[Union[Dict[str, Any], List[Dict[str, Any]]], requests.Response]
:raises: Union[LoginError, OperationError]
"""

#
# CDN
#
Expand Down
84 changes: 84 additions & 0 deletions traffic_ops/client/capability.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package client

/*
* 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 "encoding/json"
import "errors"
import "net"
import "net/http"
import "net/url"

import "github.com/apache/trafficcontrol/lib/go-tc"

const API_v14_CAPABILITIES = "/api/1.4/capabilities"

// CreateCapability creates the passed capability.
func (to *Session) CreateCapability(c tc.Capability) (tc.Alerts, ReqInf, error) {
var remoteAddr net.Addr
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}

reqBody, err := json.Marshal(c)
if err != nil {
return tc.Alerts{}, reqInf, err
}

resp, remoteAddr, err := to.request(http.MethodPost, API_v14_CAPABILITIES, reqBody)
if err != nil {
return tc.Alerts{}, reqInf, err
}
defer resp.Body.Close()
reqInf.RemoteAddr = remoteAddr

var alerts tc.Alerts
err = json.NewDecoder(resp.Body).Decode(&alerts)
return alerts, reqInf, err
}

// GetCapabilities retrieves all capabilities.
func (to *Session) GetCapabilities() ([]tc.Capability, ReqInf, error) {
resp, remoteAddr, err := to.request(http.MethodGet, API_v14_CAPABILITIES, nil)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
if err != nil {
return nil, reqInf, err
}
defer resp.Body.Close()

var data tc.CapabilitiesResponse
err = json.NewDecoder(resp.Body).Decode(&data)
return data.Response, reqInf, err
}

// GetCapability retrieves only the capability named 'c'
func (to *Session) GetCapability(c string) (tc.Capability, ReqInf, error) {
var v url.Values
v.Add("name", c)
endpoint := API_v14_CAPABILITIES + "?" + v.Encode()
resp, remoteAddr, err := to.request(http.MethodGet, endpoint, nil)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr: remoteAddr}
if err != nil {
return tc.Capability{}, reqInf, err
}
defer resp.Body.Close()

var data tc.CapabilitiesResponse
err = json.NewDecoder(resp.Body).Decode(&data)
if err != nil {
return tc.Capability{}, reqInf, err
} else if data.Response == nil || len(data.Response) < 1 {
return tc.Capability{}, reqInf, errors.New("Invalid response - no capability returned!")
}

return data.Response[0], reqInf, nil
}
10 changes: 10 additions & 0 deletions traffic_ops/testing/api/v1/tc-fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -2616,5 +2616,15 @@
"statValue": 1000,
"summaryTime": "2019-01-01T00:00:00-06:00"
}
],
"capabilities": [
{
"name": "test",
"description": "quest"
},
{
"name": "foo",
"description": "bar"
}
]
}
25 changes: 25 additions & 0 deletions traffic_ops/testing/api/v1/todb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ func SetupTestData(*sql.DB) error {
os.Exit(1)
}

err = SetupAPICapabilities(db)
if err != nil {
fmt.Printf("\nError setting up APICapabilities %s - %s, %v\n", Config.TrafficOps.URL, Config.TrafficOps.Users.Admin, err)
os.Exit(1)
}

err = SetupTenants(db)
if err != nil {
fmt.Printf("\nError setting up tenant %s - %s, %v\n", Config.TrafficOps.URL, Config.TrafficOps.Users.Admin, err)
Expand Down Expand Up @@ -131,6 +137,9 @@ func SetupCapabilities(db *sql.DB) error {
INSERT INTO capability (name, description) VALUES ('all-read','Full read access') ON CONFLICT DO NOTHING;
INSERT INTO capability (name, description) VALUES ('all-write','Full write access') ON CONFLICT DO NOTHING;
INSERT INTO capability (name, description) VALUES ('cdn-read','View CDN configuration') ON CONFLICT DO NOTHING;
INSERT INTO capability (name, description) VALUES ('asns-read', 'Read ASNs') ON CONFLICT DO NOTHING;
INSERT INTO capability (name, description) VALUES ('asns-write', 'Write ASNs') ON CONFLICT DO NOTHING;
INSERT INTO capability (name, description) VALUES ('cache-groups-read', 'Read CGs') ON CONFLICT DO NOTHING;
`
err := execSQL(db, sqlStmt, "capability")
if err != nil {
Expand All @@ -139,6 +148,20 @@ INSERT INTO capability (name, description) VALUES ('cdn-read','View CDN configur
return nil
}

func SetupAPICapabilities(db *sql.DB) error {
sqlStmt := `
INSERT INTO api_capability (http_method, route, capability) VALUES ('GET', '/asns', 'asns-read') ON CONFLICT DO NOTHING;
INSERT INTO api_capability (http_method, route, capability) VALUES ('POST', '/asns', 'asns-write') ON CONFLICT DO NOTHING;
INSERT INTO api_capability (http_method, route, capability) VALUES ('GET', '/cachegroups', 'cache-groups-read') ON CONFLICT DO NOTHING;
`

err := execSQL(db, sqlStmt, "api_capability")
if err != nil {
return fmt.Errorf("exec failed %v", err)
}
return nil
}

func SetupRoleCapabilities(db *sql.DB) error {
sqlStmt := `
INSERT INTO role_capability (role_id, cap_name) VALUES (4,'all-write') ON CONFLICT DO NOTHING;
Expand Down Expand Up @@ -280,6 +303,7 @@ INSERT INTO to_extension (name, version, info_url, isactive, script_file, server
func Teardown(db *sql.DB) error {

sqlStmt := `
DELETE FROM api_capability;
DELETE FROM deliveryservices_required_capability;
DELETE FROM server_server_capability;
DELETE FROM server_server_capability;
Expand All @@ -294,6 +318,7 @@ func Teardown(db *sql.DB) error {
DELETE FROM deliveryservice_tmuser;
DELETE FROM tm_user;
DELETE FROM role;
DELETE FROM capability;
ALTER SEQUENCE role_id_seq RESTART WITH 1;
DELETE FROM deliveryservice_regex;
DELETE FROM regex;
Expand Down
1 change: 1 addition & 0 deletions traffic_ops/testing/api/v1/traffic_control_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type TrafficControl struct {
CDNs []tc.CDN `json:"cdns"`
CacheGroups []tc.CacheGroupNullable `json:"cachegroups"`
CacheGroupParameterRequests []tc.CacheGroupParameterRequest `json:"cachegroupParameters"`
Capabilities []tc.Capability `json:"capability"`
Coordinates []tc.Coordinate `json:"coordinates"`
DeliveryServiceRequests []tc.DeliveryServiceRequest `json:"deliveryServiceRequests"`
DeliveryServiceRequestComments []tc.DeliveryServiceRequestComment `json:"deliveryServiceRequestComments"`
Expand Down
Loading