Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
itminedu
synnefo
Commits
a0b9f620
Commit
a0b9f620
authored
May 23, 2013
by
Sofia Papagiannaki
Browse files
astakos: provide get_endpoints api call
parent
c8ada5c2
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
snf-astakos-app/astakos/api/tokens.py
0 → 100644
View file @
a0b9f620
# Copyright 2011-2013 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from
urlparse
import
urlunsplit
,
urlsplit
from
django.http
import
urlencode
from
snf_django.lib
import
api
from
astakos.im.models
import
Service
from
.util
import
user_from_token
,
rename_meta_key
,
json_response
,
xml_response
import
logging
logger
=
logging
.
getLogger
(
__name__
)
@
api
.
api_method
(
http_method
=
"GET"
,
token_required
=
True
,
user_required
=
False
,
logger
=
logger
)
@
user_from_token
# Authenticate user!!
def
get_endpoints
(
request
,
token
):
if
token
!=
api
.
get_token
(
request
):
raise
api
.
faults
.
Forbidden
()
belongsTo
=
request
.
GET
.
get
(
'belongsTo'
)
if
belongsTo
and
belongsTo
!=
request
.
user
.
uuid
:
raise
api
.
faults
.
BadRequest
()
marker
=
request
.
GET
.
get
(
'marker'
,
0
)
limit
=
request
.
GET
.
get
(
'limit'
,
10000
)
endpoints
=
list
(
Service
.
objects
.
all
().
order_by
(
'id'
).
\
filter
(
id__gt
=
marker
)[:
limit
].
\
values
(
'name'
,
'url'
,
'api_url'
,
'id'
,
'type'
))
for
e
in
endpoints
:
e
[
'api_url'
]
=
e
[
'api_url'
]
or
e
[
'url'
]
e
[
'internalURL'
]
=
e
[
'url'
]
e
[
'region'
]
=
e
[
'name'
]
rename_meta_key
(
e
,
'api_url'
,
'adminURL'
)
rename_meta_key
(
e
,
'url'
,
'publicURL'
)
if
endpoints
:
parts
=
list
(
urlsplit
(
request
.
path
))
params
=
{
'marker'
:
endpoints
[
-
1
][
'id'
],
'limit'
:
limit
}
parts
[
3
]
=
urlencode
(
params
)
next_page_url
=
urlunsplit
(
parts
)
endpoint_links
=
[{
'href'
:
next_page_url
,
'rel'
:
'next'
}]
else
:
endpoint_links
=
[]
result
=
{
'endpoints'
:
endpoints
,
'endpoint_links'
:
endpoint_links
}
if
request
.
serialization
==
'xml'
:
return
xml_response
(
result
,
'api/endpoints.xml'
)
else
:
return
json_response
(
result
)
snf-astakos-app/astakos/api/urls.py
View file @
a0b9f620
...
...
@@ -56,3 +56,8 @@ urlpatterns += patterns(
'astakos.api.service'
,
url
(
r
'^service/user_catalogs/?$'
,
'get_uuid_displayname_catalogs'
),
)
urlpatterns
+=
patterns
(
'astakos.api.tokens'
,
url
(
r
'tokens/(?P<token>.+?)/endpoints'
,
'get_endpoints'
),
)
snf-astakos-app/astakos/api/util.py
View file @
a0b9f620
...
...
@@ -36,6 +36,7 @@ from time import time, mktime
from
django.http
import
HttpResponse
from
django.utils
import
simplejson
as
json
from
django.template.loader
import
render_to_string
from
astakos.im.models
import
AstakosUser
,
Service
from
snf_django.lib.api
import
faults
...
...
@@ -60,6 +61,17 @@ def json_response(content, status_code=None):
return
response
def
xml_response
(
content
,
template
,
status_code
=
None
):
response
=
HttpResponse
()
if
status_code
is
not
None
:
response
.
status_code
=
status_code
response
.
content
=
render_to_string
(
template
,
content
)
response
[
'Content-Type'
]
=
'application/xml; charset=UTF-8'
response
[
'Content-Length'
]
=
len
(
response
.
content
)
return
response
def
is_integer
(
x
):
return
isinstance
(
x
,
(
int
,
long
))
...
...
@@ -174,3 +186,10 @@ def send_feedback(request, email_template_name='im/feedback_mail.txt'):
except
:
return
HttpResponse
(
status
=
502
)
return
HttpResponse
(
status
=
200
)
def
rename_meta_key
(
d
,
old
,
new
):
if
old
not
in
d
:
return
d
[
new
]
=
d
[
old
]
del
(
d
[
old
])
snf-astakos-app/astakos/im/management/commands/service-add.py
View file @
a0b9f620
...
...
@@ -31,7 +31,10 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from
optparse
import
make_option
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.db.utils
import
IntegrityError
from
astakos.im.models
import
Service
...
...
@@ -40,29 +43,32 @@ class Command(BaseCommand):
args
=
"<name> <service URL> <API URL> "
help
=
"Register a service"
option_list
=
BaseCommand
.
option_list
+
(
make_option
(
'--type'
,
dest
=
'type'
,
help
=
"Service type"
),
)
def
handle
(
self
,
*
args
,
**
options
):
if
len
(
args
)
<
2
:
raise
CommandError
(
"Invalid number of arguments"
)
name
=
args
[
0
]
api_url
=
args
[
1
]
url
=
args
[
2
]
try
:
s
=
Service
.
objects
.
get
(
name
=
name
)
m
=
"There already exists service named '%s'."
%
name
raise
CommandError
(
m
)
except
Service
.
DoesNotExist
:
pass
kwargs
=
dict
(
name
=
args
[
0
],
api_url
=
args
[
1
],
url
=
args
[
2
])
if
options
[
'type'
]:
kwargs
[
'type'
]
=
options
[
'type'
]
services
=
list
(
Service
.
objects
.
filter
(
api_url
=
api_url
))
services
=
list
(
Service
.
objects
.
filter
(
api_url
=
kwargs
[
'
api_url
'
]
))
if
services
:
m
=
"URL '%s' is registered for another service."
%
api_url
m
=
"URL '%s' is registered for another service."
%
\
kwargs
[
'api_url'
]
raise
CommandError
(
m
)
try
:
s
=
Service
.
objects
.
create
(
name
=
name
,
api_url
=
api_url
,
url
=
url
)
except
BaseException
as
e
:
s
=
Service
.
objects
.
create
(
**
kwargs
)
except
IntegrityError
:
m
=
"There already exists service named '%s'."
%
kwargs
[
'name'
]
raise
CommandError
(
m
)
except
BaseException
:
raise
CommandError
(
"Failed to create service."
)
else
:
self
.
stdout
.
write
(
'Token: %s
\n
'
%
s
.
auth_token
)
snf-astakos-app/astakos/im/management/commands/service-list.py
View file @
a0b9f620
...
...
@@ -47,6 +47,7 @@ class Command(ListCommand):
"token"
:
(
"auth_token"
,
"Authentication token"
),
"created"
:
(
"auth_token_created"
,
"Token creation date"
),
"expires"
:
(
"auth_token_expires"
,
"Token expiration date"
),
"type"
:
(
"type"
,
"Service type"
),
}
fields
=
[
"id"
,
"name"
,
"url"
,
"api_url"
,
"token"
,
"created"
,
"expires"
]
snf-astakos-app/astakos/im/management/commands/service-modify.py
View file @
a0b9f620
...
...
@@ -64,6 +64,10 @@ class Command(BaseCommand):
dest
=
'renew_token'
,
default
=
False
,
help
=
"Renew service auth token"
),
make_option
(
'--type'
,
dest
=
'type'
,
default
=
None
,
help
=
"Modify service type"
),
)
def
handle
(
self
,
*
args
,
**
options
):
...
...
@@ -81,6 +85,7 @@ class Command(BaseCommand):
url
=
options
.
get
(
'url'
)
auth_token
=
options
.
get
(
'auth_token'
)
renew_token
=
options
.
get
(
'renew_token'
)
type
=
options
.
get
(
'type'
)
if
name
:
service
.
name
=
name
...
...
@@ -97,6 +102,9 @@ class Command(BaseCommand):
if
renew_token
and
not
auth_token
:
service
.
renew_token
()
if
type
:
service
.
type
=
type
service
.
save
()
if
renew_token
:
...
...
snf-astakos-app/astakos/im/migrations/0032_auto__add_field_service_type.py
0 → 100644
View file @
a0b9f620
This diff is collapsed.
Click to expand it.
snf-astakos-app/astakos/im/models.py
View file @
a0b9f620
...
...
@@ -99,6 +99,7 @@ class Service(models.Model):
url
=
models
.
CharField
(
_
(
'Service url'
),
max_length
=
255
,
null
=
True
,
help_text
=
_
(
"URL the service is accessible from"
))
api_url
=
models
.
CharField
(
_
(
'Service API url'
),
max_length
=
255
,
null
=
True
)
type
=
models
.
CharField
(
_
(
'Type'
),
max_length
=
255
,
null
=
True
,
blank
=
'True'
)
auth_token
=
models
.
CharField
(
_
(
'Authentication Token'
),
max_length
=
32
,
null
=
True
,
blank
=
True
)
auth_token_created
=
models
.
DateTimeField
(
_
(
'Token creation date'
),
...
...
snf-astakos-app/astakos/im/templates/api/endpoints.xml
0 → 100644
View file @
a0b9f620
<?xml version="1.0" encoding="UTF-8"?>
{% load get_type %}
<endpoints
xmlns=
"http://docs.openstack.org/identity/api/v2.0"
>
{% for e in endpoints %}
<endpoint
{%for
k,v
in
e.items
%}{%
if
v
%}"{{k}}"="{{v}}"
{%
endif
%}{%endfor%}
/>
{% endfor %}
</endpoints>
<endpoint_links>
{% for l in endpoint_links %}
<endpoint_link
{%for
k,v
in
l.items
%}"{{k}}"="{{v}}"
{%endfor%}
/>
{% endfor %}
</endpoint_links>
snf-astakos-app/astakos/im/tests/api.py
View file @
a0b9f620
...
...
@@ -32,8 +32,15 @@
# or implied, of GRNET S.A.
from
astakos.im.tests.common
import
*
from
django.test
import
TestCase
from
urllib
import
quote
from
urlparse
import
urlparse
,
parse_qs
#from xml.dom import minidom
import
json
ROOT
=
'/astakos/api/'
u
=
lambda
url
:
ROOT
+
url
...
...
@@ -361,3 +368,94 @@ class QuotaAPITest(TestCase):
r11
=
system_quota
[
resource11
[
'name'
]]
self
.
assertEqual
(
r11
[
'usage'
],
102
)
self
.
assertEqual
(
r11
[
'pending'
],
101
)
class
TokensApiTest
(
TestCase
):
def
setUp
(
self
):
self
.
user1
=
AstakosUser
.
objects
.
create
(
email
=
'test1'
,
is_active
=
True
)
self
.
user2
=
AstakosUser
.
objects
.
create
(
email
=
'test2'
,
is_active
=
True
)
Service
(
name
=
'service1'
,
url
=
'http://localhost/service1'
,
api_url
=
'http://localhost/api/service1'
).
save
()
Service
(
name
=
'service2'
,
url
=
'http://localhost/service2'
,
api_url
=
'http://localhost/api/service2'
).
save
()
Service
(
name
=
'service3'
,
url
=
'http://localhost/service3'
,
api_url
=
'http://localhost/api/service3'
).
save
()
def
test_get_endpoints
(
self
):
client
=
Client
()
# Check unauthorized request
url
=
'/astakos/api/tokens/%s/endpoints'
%
quote
(
self
.
user1
.
auth_token
)
r
=
client
.
get
(
url
)
self
.
assertEqual
(
r
.
status_code
,
401
)
# Check bad request method
url
=
'/astakos/api/tokens/%s/endpoints'
%
quote
(
self
.
user1
.
auth_token
)
r
=
client
.
post
(
url
)
self
.
assertEqual
(
r
.
status_code
,
400
)
# Check forbidden
url
=
'/astakos/api/tokens/%s/endpoints'
%
quote
(
self
.
user1
.
auth_token
)
headers
=
{
'HTTP_X_AUTH_TOKEN'
:
self
.
user2
.
auth_token
}
r
=
client
.
get
(
url
,
**
headers
)
self
.
assertEqual
(
r
.
status_code
,
403
)
url
=
'/astakos/api/tokens/%s/endpoints'
%
quote
(
self
.
user1
.
auth_token
)
headers
=
{
'HTTP_X_AUTH_TOKEN'
:
self
.
user1
.
auth_token
}
r
=
client
.
get
(
url
,
**
headers
)
self
.
assertEqual
(
r
.
status_code
,
200
)
self
.
assertEqual
(
r
[
'Content-Type'
],
'application/json; charset=UTF-8'
)
try
:
body
=
json
.
loads
(
r
.
content
)
except
:
self
.
fail
(
'json format expected'
)
endpoints
=
body
.
get
(
'endpoints'
)
self
.
assertEqual
(
len
(
endpoints
),
3
)
# Check belongsTo BadRequest
url
=
'/astakos/api/tokens/%s/endpoints?belongsTo=%s'
%
(
quote
(
self
.
user1
.
auth_token
),
quote
(
self
.
user2
.
uuid
))
headers
=
{
'HTTP_X_AUTH_TOKEN'
:
self
.
user1
.
auth_token
}
r
=
client
.
get
(
url
,
**
headers
)
self
.
assertEqual
(
r
.
status_code
,
400
)
# Check xml serialization
url
=
'/astakos/api/tokens/%s/endpoints?format=xml'
%
\
quote
(
self
.
user1
.
auth_token
)
headers
=
{
'HTTP_X_AUTH_TOKEN'
:
self
.
user1
.
auth_token
}
r
=
client
.
get
(
url
,
**
headers
)
self
.
assertEqual
(
r
.
status_code
,
200
)
self
.
assertEqual
(
r
[
'Content-Type'
],
'application/xml; charset=UTF-8'
)
# try:
# body = minidom.parseString(r.content)
# except Exception, e:
# self.fail('xml format expected')
endpoints
=
body
.
get
(
'endpoints'
)
self
.
assertEqual
(
len
(
endpoints
),
3
)
# Check limit
url
=
'/astakos/api/tokens/%s/endpoints?limit=2'
%
\
quote
(
self
.
user1
.
auth_token
)
headers
=
{
'HTTP_X_AUTH_TOKEN'
:
self
.
user1
.
auth_token
}
r
=
client
.
get
(
url
,
**
headers
)
self
.
assertEqual
(
r
.
status_code
,
200
)
body
=
json
.
loads
(
r
.
content
)
endpoints
=
body
.
get
(
'endpoints'
)
self
.
assertEqual
(
len
(
endpoints
),
2
)
endpoint_link
=
body
.
get
(
'endpoint_links'
,
[])[
0
]
next
=
endpoint_link
.
get
(
'href'
)
p
=
urlparse
(
next
)
params
=
parse_qs
(
p
.
query
)
self
.
assertTrue
(
'limit'
in
params
)
self
.
assertTrue
(
'marker'
in
params
)
self
.
assertEqual
(
params
[
'marker'
][
0
],
'2'
)
# Check marker
headers
=
{
'HTTP_X_AUTH_TOKEN'
:
self
.
user1
.
auth_token
}
r
=
client
.
get
(
next
,
**
headers
)
self
.
assertEqual
(
r
.
status_code
,
200
)
body
=
json
.
loads
(
r
.
content
)
endpoints
=
body
.
get
(
'endpoints'
)
self
.
assertEqual
(
len
(
endpoints
),
1
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment