Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
synnefo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
itminedu
synnefo
Commits
c7efef71
Commit
c7efef71
authored
May 31, 2013
by
Georgios D. Tsoukalas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
astakosclient: add service catalog
parent
76275e79
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
310 additions
and
16 deletions
+310
-16
astakosclient/astakosclient/__init__.py
astakosclient/astakosclient/__init__.py
+7
-2
astakosclient/astakosclient/keypath.py
astakosclient/astakosclient/keypath.py
+216
-0
astakosclient/astakosclient/services.py
astakosclient/astakosclient/services.py
+65
-0
snf-cyclades-app/synnefo/cyclades_settings.py
snf-cyclades-app/synnefo/cyclades_settings.py
+22
-14
No files found.
astakosclient/astakosclient/__init__.py
View file @
c7efef71
...
...
@@ -43,6 +43,11 @@ from astakosclient.utils import \
from
astakosclient.errors
import
\
AstakosClientException
,
Unauthorized
,
BadRequest
,
NotFound
,
Forbidden
,
\
NoUserName
,
NoUUID
,
BadValue
,
QuotaLimit
,
InvalidResponse
from
.keypath
import
get_path
from
.services
import
astakos_services
# Customize astakos_services here?
def
join_urls
(
a
,
b
):
...
...
@@ -51,7 +56,7 @@ def join_urls(a, b):
# --------------------------------------------------------------------
# Astakos API urls
ACCOUNTS_PREFIX
=
'accounts'
ACCOUNTS_PREFIX
=
get_path
(
astakos_services
,
'astakos_account.prefix'
)
API_AUTHENTICATE
=
join_urls
(
ACCOUNTS_PREFIX
,
"authenticate"
)
API_USERCATALOGS
=
join_urls
(
ACCOUNTS_PREFIX
,
"user_catalogs"
)
API_SERVICE_USERCATALOGS
=
join_urls
(
ACCOUNTS_PREFIX
,
"service/user_catalogs"
)
...
...
@@ -65,7 +70,7 @@ API_FEEDBACK = join_urls(ACCOUNTS_PREFIX, "feedback")
# --------------------------------------------------------------------
# Astakos Keystone API urls
KEYSTONE_PREFIX
=
'keystone'
KEYSTONE_PREFIX
=
get_path
(
astakos_services
,
'astakos_keystone.prefix'
)
API_TOKENS
=
join_urls
(
KEYSTONE_PREFIX
,
"tokens"
)
TOKENS_ENDPOINTS
=
join_urls
(
API_TOKENS
,
"endpoints"
)
...
...
astakosclient/astakosclient/keypath.py
0 → 100644
View file @
c7efef71
# Copyright 2012, 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.
def
dict_merge
(
a
,
b
):
"""
http://www.xormedia.com/recursively-merge-dictionaries-in-python/
"""
if
not
isinstance
(
b
,
dict
):
return
b
result
=
copy
.
deepcopy
(
a
)
for
k
,
v
in
b
.
iteritems
():
if
k
in
result
and
isinstance
(
result
[
k
],
dict
):
result
[
k
]
=
dict_merge
(
result
[
k
],
v
)
else
:
result
[
k
]
=
copy
.
deepcopy
(
v
)
return
result
def
lookup_path
(
container
,
path
,
sep
=
'.'
,
createpath
=
False
):
"""
return (['a','b'],
[container['a'], container['a']['b']],
'c') where path=sep.join(['a','b','c'])
"""
names
=
path
.
split
(
sep
)
dirnames
=
names
[:
-
1
]
basename
=
names
[
-
1
]
node
=
container
name_path
=
[]
node_path
=
[
node
]
for
name
in
dirnames
:
name_path
.
append
(
name
)
if
name
not
in
node
:
if
not
createpath
:
m
=
"'{0}': path not found"
.
format
(
sep
.
join
(
name_path
))
raise
KeyError
(
m
)
node
[
name
]
=
{}
try
:
node
=
node
[
name
]
except
TypeError
as
e
:
m
=
"'{0}': cannot traverse path beyond this node: {1}"
m
=
m
.
format
(
sep
.
join
(
name_path
),
str
(
e
))
raise
ValueError
(
m
)
node_path
.
append
(
node
)
return
name_path
,
node_path
,
basename
def
walk_paths
(
container
):
for
name
,
node
in
container
.
iteritems
():
if
not
hasattr
(
node
,
'items'
):
yield
[
name
],
[
node
]
else
:
for
names
,
nodes
in
walk_paths
(
node
):
yield
[
name
]
+
names
,
[
node
]
+
nodes
def
list_paths
(
container
,
sep
=
'.'
):
"""
>>> sorted(list_paths({'a': {'b': {'c': 'd'}}}))
[('a.b.c', 'd')]
>>> sorted(list_paths({'a': {'b': {'c': 'd'}, 'e': 3}}))
[('a.b.c', 'd'), ('a.e', 3)]
>>> sorted(list_paths({'a': {'b': {'c': 'd'}, 'e': {'f': 3}}}))
[('a.b.c', 'd'), ('a.e.f', 3)]
>>> list_paths({})
[]
"""
return
[(
sep
.
join
(
name_path
),
node_path
[
-
1
])
for
name_path
,
node_path
in
walk_paths
(
container
)]
def
del_path
(
container
,
path
,
sep
=
'.'
,
collect
=
True
):
"""
del container['a']['b']['c'] where path=sep.join(['a','b','c'])
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, 'a.b.c'); d
{}
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, 'a.b.c', collect=False); d
{'a': {'b': {}}}
>>> d = {'a': {'b': {'c': 'd'}}}; del_path(d, 'a.b.c.d')
Traceback (most recent call last):
ValueError: 'a.b.c': cannot traverse path beyond this node:
\
'str' object does not support item deletion
"""
name_path
,
node_path
,
basename
=
\
lookup_path
(
container
,
path
,
sep
=
sep
,
createpath
=
False
)
lastnode
=
node_path
.
pop
()
lastname
=
basename
try
:
if
basename
in
lastnode
:
del
lastnode
[
basename
]
except
(
TypeError
,
KeyError
)
as
e
:
m
=
"'{0}': cannot traverse path beyond this node: {1}"
m
=
m
.
format
(
sep
.
join
(
name_path
),
str
(
e
))
raise
ValueError
(
m
)
if
collect
:
while
node_path
and
not
lastnode
:
basename
=
name_path
.
pop
()
lastnode
=
node_path
.
pop
()
del
lastnode
[
basename
]
def
get_path
(
container
,
path
,
sep
=
'.'
):
"""
return container['a']['b']['c'] where path=sep.join(['a','b','c'])
>>> get_path({'a': {'b': {'c': 'd'}}}, 'a.b.c.d')
Traceback (most recent call last):
ValueError: 'a.b.c.d': cannot traverse path beyond this node:
\
string indices must be integers, not str
>>> get_path({'a': {'b': {'c': 1}}}, 'a.b.c.d')
Traceback (most recent call last):
ValueError: 'a.b.c.d': cannot traverse path beyond this node:
\
'int' object is unsubscriptable
>>> get_path({'a': {'b': {'c': 1}}}, 'a.b.c')
1
>>> get_path({'a': {'b': {'c': 1}}}, 'a.b')
{'c': 1}
"""
name_path
,
node_path
,
basename
=
\
lookup_path
(
container
,
path
,
sep
=
sep
,
createpath
=
False
)
name_path
.
append
(
basename
)
node
=
node_path
[
-
1
]
try
:
return
node
[
basename
]
except
TypeError
as
e
:
m
=
"'{0}': cannot traverse path beyond this node: {1}"
m
=
m
.
format
(
sep
.
join
(
name_path
),
str
(
e
))
raise
ValueError
(
m
)
except
KeyError
as
e
:
m
=
"'{0}': path not found: {1}"
m
=
m
.
format
(
sep
.
join
(
name_path
),
str
(
e
))
raise
KeyError
(
m
)
def
set_path
(
container
,
path
,
value
,
sep
=
'.'
,
createpath
=
False
,
overwrite
=
True
):
"""
container['a']['b']['c'] = value where path=sep.join(['a','b','c'])
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.c.d', 1)
Traceback (most recent call last):
ValueError: 'a.b.c.d': cannot traverse path beyond this node:
\
'str' object does not support item assignment
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.x.d', 1)
Traceback (most recent call last):
KeyError: "'a.b.x': path not found"
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.x.d', 1, createpath=True)
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.c', 1)
>>> set_path({'a': {'b': {'c': 'd'}}}, 'a.b.c', 1, overwrite=False)
Traceback (most recent call last):
ValueError: will not overwrite path 'a.b.c'
"""
name_path
,
node_path
,
basename
=
\
lookup_path
(
container
,
path
,
sep
=
sep
,
createpath
=
createpath
)
name_path
.
append
(
basename
)
node
=
node_path
[
-
1
]
if
basename
in
node
and
not
overwrite
:
m
=
"will not overwrite path '{0}'"
.
format
(
path
)
raise
ValueError
(
m
)
try
:
node
[
basename
]
=
value
except
TypeError
as
e
:
m
=
"'{0}': cannot traverse path beyond this node: {1}"
m
=
m
.
format
(
sep
.
join
(
name_path
),
str
(
e
))
raise
ValueError
(
m
)
if
__name__
==
'__main__'
:
import
doctest
doctest
.
testmod
()
astakosclient/astakosclient/services.py
0 → 100644
View file @
c7efef71
# Copyright (C) 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.
astakos_services
=
{
'astakos_account'
:
{
'type'
:
'account'
,
'component'
:
'astakos'
,
'prefix'
:
'account'
,
'public'
:
True
,
'endpoints'
:
[
{
'version'
:
'v1.0'
,
'publicURL'
:
None
},
]},
'astakos_keystone'
:
{
'type'
:
'identity'
,
'component'
:
'astakos'
,
'prefix'
:
'identity'
,
'public'
:
True
,
'endpoints'
:
[
{
'version'
:
'v2.0'
,
'publicURL'
:
None
},
]},
'astakos_ui'
:
{
'type'
:
'astakos_ui'
,
'component'
:
'astakos'
,
'prefix'
:
'ui'
,
'public'
:
False
,
'endpoints'
:
[
{
'version'
:
'v1.0'
,
'publicURL'
:
None
},
]},
}
snf-cyclades-app/synnefo/cyclades_settings.py
View file @
c7efef71
...
...
@@ -35,29 +35,22 @@ from django.conf import settings
from
synnefo.lib
import
join_urls
,
parse_base_url
from
synnefo.util.keypath
import
get_path
from
synnefo.api.services
import
cyclades_services
as
vanilla_cyclades_services
from
astakosclient
import
astakos_services
as
vanilla_astakos_services
from
astakosclient
import
astakos_services
from
copy
import
deepcopy
# Process Cyclades settings
BASE_URL
=
getattr
(
settings
,
'CYCLADES_BASE_URL'
,
'https://compute.example.synnefo.org/compute/'
)
BASE_HOST
,
BASE_PATH
=
parse_base_url
(
BASE_URL
)
ASTAKOS_BASE_URL
=
getattr
(
settings
,
'ASTAKOS_BASE_URL'
,
'https://accounts.example.synnefo.org/astakos/'
)
ASTAKOS_BASE_HOST
,
ASTAKOS_BASE_PATH
=
parse_base_url
(
ASTAKOS_BASE_URL
)
CUSTOMIZE_SERVICES
=
getattr
(
settings
,
'CYCLADES_CUSTOMIZE_SERVICES'
,
())
cyclades_services
=
deepcopy
(
vanilla_cyclades_services
)
for
path
,
value
in
CUSTOMIZE_SERVICES
:
set_path
(
cyclades_services
,
path
,
value
,
createpath
=
True
)
astakos_services
=
deepcopy
(
vanilla_astakos_services
)
CUSTOMIZE_ASTAKOS_SERVICES
=
\
getattr
(
settings
,
'CYCLADES_CUSTOMIZE_ASTAKOS_SERVICES'
,
())
for
path
,
value
in
CUSTOMIZE_ASTAKOS_SERVICES
:
set_path
(
astakos_services
,
path
,
value
,
createpath
=
True
)
COMPUTE_PREFIX
=
get_path
(
cyclades_services
,
'cyclades_compute.prefix'
)
VMAPI_PREFIX
=
get_path
(
cyclades_services
,
'cyclades_vmapi.prefix'
)
PLANKTON_PREFIX
=
get_path
(
cyclades_services
,
'cyclades_plankton.prefix'
)
...
...
@@ -65,13 +58,28 @@ HELPDESK_PREFIX = get_path(cyclades_services, 'cyclades_helpdesk.prefix')
UI_PREFIX
=
get_path
(
cyclades_services
,
'cyclades_ui.prefix'
)
USERDATA_PREFIX
=
get_path
(
cyclades_services
,
'cyclades_userdata.prefix'
)
COMPUTE_ROOT_URL
=
join_urls
(
BASE_URL
,
COMPUTE_PREFIX
)
# Process Astakos settings
ASTAKOS_BASE_URL
=
getattr
(
settings
,
'ASTAKOS_BASE_URL'
,
'https://accounts.example.synnefo.org/astakos/'
)
ASTAKOS_BASE_HOST
,
ASTAKOS_BASE_PATH
=
parse_base_url
(
ASTAKOS_BASE_URL
)
# Patch astakosclient directly, otherwise it will not see any customization
#astakos_services = deepcopy(vanilla_astakos_services)
CUSTOMIZE_ASTAKOS_SERVICES
=
\
getattr
(
settings
,
'CYCLADES_CUSTOMIZE_ASTAKOS_SERVICES'
,
())
for
path
,
value
in
CUSTOMIZE_ASTAKOS_SERVICES
:
set_path
(
astakos_services
,
path
,
value
,
createpath
=
True
)
ASTAKOS_ACCOUNTS_PREFIX
=
get_path
(
astakos_services
,
'astakos_account.prefix'
)
ASTAKOS_VIEWS_PREFIX
=
get_path
(
astakos_services
,
'astakos_ui.prefix'
)
ASTAKOS_KEYSTONE_PREFIX
=
get_path
(
astakos_services
,
'astakos_keystone.prefix'
)
# The API implementation needs to accept and return absolute references
# to its resources. Thus, it needs to know its public URL.
COMPUTE_ROOT_URL
=
join_urls
(
BASE_URL
,
COMPUTE_PREFIX
)
# Proxy Astakos settings
BASE_ASTAKOS_PROXY_PATH
=
getattr
(
settings
,
'CYCLADES_BASE_ASTAKOS_PROXY_PATH'
,
...
...
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