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
feudalBackend
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
16
Issues
16
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
feudal
feudalBackend
Commits
075de076
Commit
075de076
authored
Nov 22, 2018
by
Lukas Burgey
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update tests
parent
0790aab5
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
302 additions
and
322 deletions
+302
-322
example-config/home/feudal/config/django_settings.py
example-config/home/feudal/config/django_settings.py
+6
-2
feudal/backend/models/test_models.py
feudal/backend/models/test_models.py
+16
-166
feudal/backend/models/test_users.py
feudal/backend/models/test_users.py
+10
-11
feudal/backend/tests.py
feudal/backend/tests.py
+126
-0
feudal/backend/views/test_views.py
feudal/backend/views/test_views.py
+28
-0
feudal/backend/views/test_webpage.py
feudal/backend/views/test_webpage.py
+83
-108
feudal/backend/views/webpage.py
feudal/backend/views/webpage.py
+33
-35
No files found.
example-config/home/feudal/config/django_settings.py
View file @
075de076
...
...
@@ -8,10 +8,10 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DEBUG
=
True
DEBUG_AUTH
=
False
DEBUG_CREDENTIALS
=
Tru
e
DEBUG_CREDENTIALS
=
Fals
e
ALLOWED_HOSTS
=
[
'hdf-portal.data.kit.edu'
,
'hdf-portal
-dev
.data.kit.edu'
,
]
AUTH_USER_MODEL
=
'backend.User'
...
...
@@ -40,6 +40,7 @@ STATIC_ROOT = 'static'
INSTALLED_APPS
=
[
'django.contrib.admin'
,
'django.contrib.auth'
,
'polymorphic'
,
'django.contrib.contenttypes'
,
'django.contrib.sessions'
,
'django.contrib.messages'
,
...
...
@@ -48,6 +49,7 @@ INSTALLED_APPS = [
'feudal.backend'
,
'corsheaders'
,
'django_mysql'
,
'django_nose'
,
]
MIDDLEWARE
=
[
...
...
@@ -207,3 +209,5 @@ LOGGING = {
},
},
}
TEST_RUNNER
=
'django_nose.NoseTestSuiteRunner'
feudal/backend/models/test_models.py
View file @
075de076
# pylint: disable=line-too-long,invalid-name
import
logging
from
django.test
import
TestCase
from
django.contrib.auth.models
import
Group
from
feudal.backend
import
models
from
feudal.backend.auth.v1
import
models
as
auth_models
from
feudal.backend
import
tests
,
models
LOGGER
=
logging
.
getLogger
(
__name__
)
TEST_NAME
=
'test_name'
TEST_EMAIL
=
'test@hdf.org'
TEST_SUB
=
'fb0fa558-cfa2-49f9-b847-5c651d1f6135'
TEST_KEY
=
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC/7NWc1pxCxi1f/+DtgCenIC9DDiT6l1cQSz4vJc1ecJA/gEUkd6CF/uR1Zl+yalWZej9UII5902Dm8WkIsIrHdRXevyt0QSzMbzZvaUAdJWcmWpqEKxJT6KGkd50O+qAJBXd5WZ2jUstmbHjoXio9eBY4hDcOofLD8vJT73DrZAEurd3F2S4s04oSt+onUmQ0inqeN38oqYOZGJhe/zZsDj65ctiTpj85rjglndNq+K7IHETGWXg9ht13FH9trjtEpLmAmR9UZGFkof+P+LiIUSYa05sVh6/MPFCgz7gzMCXw99lxoMz4lX2/wV/jnJ0+itn1WByWFWuqbDXUnH4pjk7K+YalFi2lA7F4ckWSn51IQRnh8Qp3CMuvid/Y3Q0qYa4Mtq5zhDnj+uGAUltoENqQCIKLp2KaCRQSbiDudYHXq9dufGRuAsls3rXnRhRJ26wOW+sggjfhB6LhGD20vSdJbuQQwUxZtRLB+y6uP6HXq/eqq+N+f8lfsw64b16xTOYFSpDniV/OE+PuDSNUFlO1V91FWhhiFWCyi+q6dTW5PTWBnnksXhR/LRaivA+UuNxPPbEfefBWmu7/y3jcqAn+CXSzbnvOrVXCU3E7DKBCR3d8TjBQj2No1qTNz6ZOD+dXEQvvjhl2lXkdGazG18hpaWN2hApzBpUulukg9Q== TEST_KEY'
TEST_USERINFO
=
{
'email'
:
TEST_EMAIL
,
'name'
:
TEST_NAME
,
'sub'
:
TEST_SUB
,
}
TEST_PASSWORD
=
'asnoteuhsn'
TEST_SERVICE
=
'test_service'
TEST_SERVICE_2
=
'test_service_2'
TEST_SERVICE_3
=
'test_service_3'
BROKEN_SERVICE
=
'broken_service'
TEST_SITE
=
'test_site'
TEST_SITE_2
=
'test_site_2'
# Has no service
GROUP_NO_SERVICES
=
'test_group_no'
# Has a service
GROUP_ONE_SERVICE
=
'test_group_one'
# Has two services
GROUP_MULTIPLE_SERVICES
=
'test_group_multiple'
GROUP_FOR_BROKEN
=
'test_group_for_broken'
def
setup_fixture
():
idp
=
auth_models
.
OIDCConfig
(
name
=
TEST_NAME
,
client_id
=
''
,
client_secret
=
''
,
redirect_uri
=
''
,
issuer_uri
=
''
,
)
idp
.
save
()
user
=
models
.
User
(
username
=
TEST_NAME
,
sub
=
TEST_NAME
,
user_type
=
'oidcuser'
,
userinfo
=
{
'email'
:
TEST_EMAIL
,
'sub'
:
TEST_NAME
,
},
idp
=
idp
,
)
user
.
set_password
(
TEST_PASSWORD
)
user
.
save
()
group_no
=
Group
(
name
=
GROUP_NO_SERVICES
)
group_no
.
save
()
group_one
=
Group
(
name
=
GROUP_ONE_SERVICE
)
group_one
.
save
()
group_mult
=
Group
(
name
=
GROUP_MULTIPLE_SERVICES
)
group_mult
.
save
()
group_for_broken
=
Group
(
name
=
GROUP_FOR_BROKEN
)
group_for_broken
.
save
()
site
=
models
.
Site
(
name
=
TEST_SITE
,
)
site
.
save
()
site2
=
models
.
Site
(
name
=
TEST_SITE_2
,
)
site2
.
save
()
service
=
models
.
Service
.
get_service
(
TEST_SERVICE
,
site
,
)
service
.
save
()
service2
=
models
.
Service
.
get_service
(
TEST_SERVICE_2
,
site
,
vos
=
[
group_one
,
group_mult
,
],
)
service2
.
save
()
service3
=
models
.
Service
.
get_service
(
TEST_SERVICE_3
,
site
,
vos
=
[
group_mult
],
)
service3
.
save
()
models
.
SSHPublicKey
(
name
=
TEST_NAME
,
key
=
TEST_KEY
,
user
=
user
,
).
save
()
def
teardown_fixture
():
models
.
SSHPublicKey
.
objects
.
get
(
name
=
TEST_NAME
).
delete
()
models
.
User
.
objects
.
get
(
username
=
TEST_NAME
).
delete
()
for
g
in
Group
.
objects
.
all
():
g
.
delete
()
for
g
in
models
.
Service
.
objects
.
all
():
g
.
delete
()
for
g
in
models
.
Site
.
objects
.
all
():
g
.
delete
()
auth_models
.
OIDCConfig
.
objects
.
get
(
name
=
TEST_NAME
).
delete
()
class
DeploymentTest
(
TestCase
):
@
classmethod
def
setUp
(
cls
):
setup_fixture
()
delayed_service
=
models
.
Service
(
name
=
'DELAYED_SERVICE'
)
delayed_service
.
save
()
delayed_service
.
site
.
add
(
models
.
Site
.
objects
.
get
(
name
=
TEST_SITE
))
# def setUp(self):
# setup_fixture()
# delayed_service = models.Service(name='DELAYED_SERVICE')
# delayed_service.save()
# delayed_service.site.add(models.Site.objects.get(name=TEST_SITE))
# def tearDown(self):
# for svc in models.Service.objects.(name='DELAYED_SERVICE').delete()
# #teardown_fixture()
def
setUpTestData
(
cls
):
tests
.
setup_class_fixture
(
cls
)
def
deployment_run
(
self
,
deployment
,
service_count
):
self
.
assertIsNotNone
(
deployment
)
...
...
@@ -165,8 +40,6 @@ class DeploymentTest(TestCase):
item
.
client_response
({
'state'
:
models
.
DEPLOYED
})
self
.
assertEqual
(
item
.
state
,
models
.
DEPLOYED
)
self
.
assertEqual
(
deployment
.
state
,
models
.
DEPLOYED
)
self
.
assertTrue
(
deployment
.
target_reached
)
...
...
@@ -206,8 +79,11 @@ class DeploymentTest(TestCase):
self
.
assertTrue
(
deployment
.
target_reached
)
# add service
delayed_service
=
models
.
Service
.
objects
.
get
(
name
=
'DELAYED_SERVICE'
)
delayed_service
.
vos
.
add
(
group
)
delayed_service
=
models
.
Service
.
get_service
(
'DELAYED_SERVICE'
,
self
.
site
,
vos
=
[
group
],
)
deployment
.
service_added
(
delayed_service
)
for
item
in
deployment
.
state_items
.
all
():
...
...
@@ -235,44 +111,18 @@ class DeploymentTest(TestCase):
self
.
assertEqual
(
deployment
.
state
,
models
.
NOT_DEPLOYED
)
def
test_service
(
self
):
user
=
models
.
User
.
objects
.
get
(
username
=
TEST_NAME
)
service
=
models
.
Service
.
objects
.
get
(
name
=
TEST_SERVICE
)
deployment
=
models
.
Deployment
.
get_deployment
(
user
,
service
=
service
,
)
self
.
deployment_run
(
deployment
,
1
)
def
test_group_with_delayed_service
(
self
):
user
=
models
.
User
.
objects
.
get
(
username
=
TEST_NAME
)
group
=
Group
.
objects
.
get
(
name
=
GROUP_NO_SERVICES
)
deployment
=
models
.
Deployment
.
get_deployment
(
user
,
group
=
group
,
)
deployment
=
models
.
Deployment
.
get_deployment
(
self
.
user
,
self
.
group
)
self
.
deployment_run
(
deployment
,
0
)
self
.
deployment_run_delayed_service
(
deployment
,
group
,
0
)
self
.
deployment_run_delayed_service
(
deployment
,
self
.
group
,
0
)
def
test_group_with_service
(
self
):
user
=
models
.
User
.
objects
.
get
(
username
=
TEST_NAME
)
group
=
Group
.
objects
.
get
(
name
=
GROUP_ONE_SERVICE
)
deployment
=
models
.
Deployment
.
get_deployment
(
user
,
group
=
group
,
)
# self.group3 has one service
deployment
=
models
.
Deployment
.
get_deployment
(
self
.
user
,
self
.
group3
)
self
.
deployment_run
(
deployment
,
1
)
def
test_group_with_multiple_services
(
self
):
user
=
models
.
User
.
objects
.
get
(
username
=
TEST_NAME
)
group
=
Group
.
objects
.
get
(
name
=
GROUP_MULTIPLE_SERVICES
)
deployment
=
models
.
Deployment
.
get_deployment
(
user
,
group
=
group
,
)
def
test_group_with_two_services
(
self
):
# self.group2 has two services
deployment
=
models
.
Deployment
.
get_deployment
(
self
.
user
,
self
.
group2
)
self
.
deployment_run
(
deployment
,
2
)
feudal/backend/models/test_users.py
View file @
075de076
import
logging
from
django.contrib
import
auth
from
django.test
import
TestCase
from
django.contrib.auth
import
authenticate
from
feudal.backend
import
models
from
feudal.backend.auth.v1
import
models
as
auth_models
from
feudal.backend.models.test_models
import
setup_fixture
,
TEST_NAME
,
TEST_PASSWORD
,
TEST_USERINFO
from
feudal.backend
import
models
,
tests
LOGGER
=
logging
.
getLogger
(
__name__
)
class
UserTest
(
TestCase
):
def
setUp
(
self
):
setup_fixture
(
)
tests
.
setup_class_fixture
(
self
)
def
test_user
(
self
):
user
=
auth
.
auth
enticate
(
username
=
TEST_NAME
,
password
=
TEST_PASSWORD
,
user
=
authenticate
(
username
=
self
.
user_name
,
password
=
self
.
user_password
,
)
self
.
assertIsNotNone
(
user
)
self
.
assertTrue
(
user
.
is_active
)
...
...
@@ -28,10 +28,9 @@ class UserTest(TestCase):
self
.
assertTrue
(
user
.
is_active
)
def
test_user_construction
(
self
):
idp
=
auth_models
.
OIDCConfig
.
objects
.
get
(
name
=
TEST_NAME
)
user
=
models
.
User
.
get_user
(
TEST_USERINFO
,
idp
,
tests
.
TEST_USERINFO
,
self
.
idp
,
)
user
.
save
()
self
.
assertIsNotNone
(
user
)
feudal/backend/tests.py
0 → 100644
View file @
075de076
# pylint: disable=line-too-long,invalid-name
import
logging
from
django.contrib.auth
import
authenticate
from
django.test
import
Client
from
feudal.backend
import
models
from
feudal.backend.auth.v1.models
import
OIDCConfig
from
feudal.backend.auth.v1.models.vo
import
Group
,
Entitlement
LOGGER
=
logging
.
getLogger
(
__name__
)
TEST_NAME
=
'test_name'
TEST_PASSWORD
=
'asnoteuhsn'
TEST_EMAIL
=
'test@hdf.org'
TEST_SUB
=
'fb0fa558-cfa2-49f9-b847-5c651d1f6135'
TEST_KEY
=
'ssh-rsa AAAAB3NzaC1yhApzBpUulukg9Q== TEST_KEY'
TEST_USERINFO
=
{
'email'
:
TEST_EMAIL
,
'name'
:
TEST_NAME
,
'sub'
:
TEST_SUB
,
'ssh_key'
:
TEST_KEY
,
}
# Has no service
GROUP_NO_SERVICES
=
'test_group_no'
# Has a service
GROUP_ONE_SERVICE
=
'test_group_one'
# Has two services
GROUP_MULTIPLE_SERVICES
=
'test_group_multiple'
def
setup_client
(
self
):
self
.
client
=
Client
()
user
=
authenticate
(
username
=
self
.
user_name
,
password
=
self
.
user_password
,
)
self
.
assertIsNotNone
(
user
)
self
.
client
.
force_login
(
user
=
user
,
)
def
setup_class_fixture
(
cls
):
cls
.
user_name
=
TEST_NAME
cls
.
user_password
=
TEST_PASSWORD
cls
.
idp
=
OIDCConfig
(
name
=
'test_idp_name'
,
client_id
=
'test_idp_client_id'
,
client_secret
=
''
,
redirect_uri
=
''
,
issuer_uri
=
''
,
scopes
=
[],
userinfo_field_entitlements
=
'eduperson_entitlement'
,
userinfo_field_groups
=
'eduperson_groups'
,
)
cls
.
idp
.
save
()
cls
.
entitlement
=
Entitlement
.
get_entitlement
(
name
=
'test_entitlement'
,
idp
=
cls
.
idp
)
cls
.
entitlement
.
save
()
cls
.
group
=
Group
.
get_group
(
name
=
'test_group'
,
idp
=
cls
.
idp
)
cls
.
group
.
save
()
cls
.
group2
=
Group
.
get_group
(
name
=
'test_group_2'
,
idp
=
cls
.
idp
)
cls
.
group2
.
save
()
cls
.
group3
=
Group
.
get_group
(
name
=
'test_group_3'
,
idp
=
cls
.
idp
)
cls
.
group3
.
save
()
cls
.
user
=
models
.
User
(
username
=
TEST_NAME
,
sub
=
TEST_NAME
,
user_type
=
'oidcuser'
,
userinfo
=
TEST_USERINFO
,
idp
=
cls
.
idp
,
)
cls
.
user
.
set_password
(
TEST_PASSWORD
)
cls
.
user
.
save
()
cls
.
user
.
vos
.
add
(
cls
.
group
)
cls
.
site
=
models
.
Site
(
name
=
'test_site'
)
cls
.
site
.
save
()
cls
.
site2
=
models
.
Site
(
name
=
'test_site_2'
)
cls
.
site2
.
save
()
cls
.
service
=
models
.
Service
.
get_service
(
'test_service'
,
cls
.
site
,
)
cls
.
service2
=
models
.
Service
.
get_service
(
'test_service_2'
,
cls
.
site
,
vos
=
[
cls
.
group2
,
],
)
cls
.
service3
=
models
.
Service
.
get_service
(
'test_service_3'
,
cls
.
site
,
vos
=
[
cls
.
group2
,
cls
.
group3
,
],
)
models
.
SSHPublicKey
(
name
=
TEST_NAME
,
key
=
TEST_KEY
,
user
=
cls
.
user
,
).
save
()
def
teardown_fixture
():
models
.
SSHPublicKey
.
objects
.
get
(
name
=
TEST_NAME
).
delete
()
models
.
User
.
objects
.
get
(
username
=
TEST_NAME
).
delete
()
for
g
in
Group
.
objects
.
all
():
g
.
delete
()
for
g
in
models
.
Service
.
objects
.
all
():
g
.
delete
()
for
g
in
models
.
Site
.
objects
.
all
():
g
.
delete
()
OIDCConfig
.
objects
.
get
(
name
=
TEST_NAME
).
delete
()
feudal/backend/views/test_views.py
0 → 100644
View file @
075de076
import
logging
from
django.test
import
TestCase
from
feudal.backend
import
tests
LOGGER
=
logging
.
getLogger
(
__name__
)
class
ViewTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
tests
.
setup_class_fixture
(
cls
)
def
setUp
(
self
):
tests
.
setup_client
(
self
)
def
test_deployment_complete
(
self
):
# I: webpage view: user requests deployment
# II: client view: client fetches
# III: client view: client responds with credentials
# IV: webpage view: state represents the change
pass
feudal/backend/views/test_webpage.py
View file @
075de076
import
logging
from
django.contrib
import
auth
from
django.contrib.auth.models
import
Group
from
django.test
import
Client
from
django.test
import
TestCase
from
feudal.backend
import
models
from
feudal.backend.models
import
test_models
from
feudal.backend
import
models
,
tests
LOGGER
=
logging
.
getLogger
(
__name__
)
def
get_user
():
return
auth
.
authenticate
(
username
=
test_models
.
TEST_NAME
,
password
=
test_models
.
TEST_PASSWORD
,
)
def
get_client
(
user
):
client
=
Client
()
client
.
force_login
(
user
=
user
)
return
client
class
StateViewTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
test_models
.
setup_fixture
()
tests
.
setup_class_fixture
(
cls
)
def
setUp
(
self
):
tests
.
setup_client
(
self
)
def
test_api_state
(
self
):
user
=
get_user
()
client
=
get_client
(
user
)
response
=
self
.
client
.
get
(
'/backend/api/state'
)
response
=
client
.
get
(
'/backend/api/state'
)
self
.
assertTrue
(
'services'
in
response
.
json
())
self
.
assertTrue
(
'user_state'
in
response
.
json
())
self
.
assertTrue
(
'user'
in
response
.
json
())
self
.
assertEqual
(
response
.
json
()[
'user'
][
'userinfo'
][
'email'
],
test_models
.
TEST_EMAIL
)
LOGGER
.
info
(
'response: %s'
,
response
.
json
())
user
=
response
.
json
()[
'user'
]
self
.
assertIsNotNone
(
user
)
for
key
in
[
'services'
,
'ssh_keys'
,
'userinfo'
,
'vos'
,
'id'
,
'deployments'
,
'profile_name'
]:
self
.
assertTrue
(
key
in
user
)
self
.
assertEqual
(
user
[
'userinfo'
][
'email'
],
tests
.
TEST_EMAIL
)
class
SSHPublicKeyViewTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
test
_models
.
setup_fixture
(
)
test
s
.
setup_class_fixture
(
cls
)
def
test_error
(
self
):
user
=
get_user
()
client
=
get_client
(
user
)
def
setUp
(
self
):
tests
.
setup_client
(
self
)
response
=
client
.
post
(
def
test_error
(
self
):
response
=
self
.
client
.
post
(
'/backend/api/sshkey'
,
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
response
.
json
()[
'error'
],
'malformed request'
)
def
test_add_success
(
self
):
user
=
get_user
()
client
=
get_client
(
user
)
response
=
client
.
post
(
response
=
self
.
client
.
post
(
'/backend/api/sshkey'
,
data
=
{
'type'
:
'add'
,
...
...
@@ -71,10 +57,11 @@ class SSHPublicKeyViewTest(TestCase):
},
content_type
=
'application/json'
,
)
LOGGER
.
debug
(
'response: %s'
,
response
)
self
.
assertEqual
(
response
.
status_code
,
200
)
try
:
key
=
user
.
ssh_keys
.
get
(
name
=
'key_name'
)
key
=
self
.
user
.
ssh_keys
.
get
(
name
=
'key_name'
)
self
.
assertIsNotNone
(
key
)
self
.
assertEqual
(
key
.
name
,
'key_name'
)
self
.
assertEqual
(
key
.
key
,
'key_value'
)
...
...
@@ -82,12 +69,10 @@ class SSHPublicKeyViewTest(TestCase):
self
.
fail
(
'User did not receive the key'
)
def
test_remove_success
(
self
):
user
=
get_user
()
sshkey
=
models
.
SSHPublicKey
(
name
=
'key_name'
,
key
=
'key_value'
,
user
=
user
)
sshkey
=
models
.
SSHPublicKey
(
name
=
'key_name'
,
key
=
'key_value'
,
user
=
self
.
user
)
sshkey
.
save
()
client
=
get_client
(
user
)
response
=
client
.
post
(
response
=
self
.
client
.
post
(
'/backend/api/sshkey'
,
data
=
{
'type'
:
'remove'
,
...
...
@@ -98,37 +83,30 @@ class SSHPublicKeyViewTest(TestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
with
self
.
assertRaises
(
models
.
SSHPublicKey
.
DoesNotExist
):
user
.
ssh_keys
.
get
(
name
=
'key_name'
)
self
.
user
.
ssh_keys
.
get
(
name
=
'key_name'
)
class
DeploymentsViewTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
test_models
.
setup_fixture
()
group
=
Group
(
name
=
'test_group'
)
group
.
save
()
get_user
().
vos
.
add
(
group
)
tests
.
setup_class_fixture
(
cls
)
def
test_error
(
self
):
user
=
get_user
()
client
=
get_client
(
user
)
def
setUp
(
self
):
tests
.
setup_client
(
self
)
response
=
client
.
post
(
def
test_error
(
self
):
response
=
self
.
client
.
post
(
'/backend/api/deployments'
,
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
response
.
json
()[
'error'
],
'malformed request'
)
def
test_group_add_success
(
self
):
user
=
get_user
()
client
=
get_client
(
user
)
group
=
Group
.
objects
.
get
(
name
=
'test_group'
)
response
=
client
.
post
(
response
=
self
.
client
.
post
(
'/backend/api/deployments'
,
data
=
{
'type'
:
'add'
,
'
group'
:
group
.
id
,
'
vo'
:
self
.
group
.
id
,
},
content_type
=
'application/json'
,
)