Skip to content

Commit

Permalink
add domain class
Browse files Browse the repository at this point in the history
  • Loading branch information
joelee2012 committed Aug 25, 2023
1 parent 4198565 commit ce451a0
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 28 deletions.
3 changes: 1 addition & 2 deletions api4jenkins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@ def version(self):
def credentials(self):
'''An object for managing credentials.
see :class:`Credentials <api4jenkins.credential.Credentials>`'''
return Credentials(self,
f'{self.url}credentials/store/system/domain/_/')
return Credentials(self, f'{self.url}credentials/store/system/')

@property
def views(self):
Expand Down
77 changes: 65 additions & 12 deletions api4jenkins/credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,34 @@

class Credentials(Item):

def get(self, name):
for key in self.api_json(tree='domains[urlName]')['domains'].keys():
if key == name:
return Domain(self.jenkins, f'{self.url}store/system/domain/{key}/')
return None

def create(self, xml):
self.handle_req('POST', 'createDomain',
headers=self.headers, content=xml)

def __iter__(self):
for key in self.api_json(tree='domains[urlName]')['domains'].keys():
yield Domain(self.jenkins, f'{self.url}store/system/domain/{key}/')

def __getitem__(self, name):
return self.get(name)

@property
def global_domain(self):
return self['_']


class Domain(Item, ConfigurationMixIn, DeletionMixIn):

def get(self, id):
for item in self.api_json(tree='credentials[id]')['credentials']:
if item['id'] == id:
return Credential(self.jenkins,
f'{self.url}credential/{id}/')
return Credential(self.jenkins, f'{self.url}credential/{id}/')
return None

def create(self, xml):
Expand All @@ -20,33 +43,63 @@ def create(self, xml):

def __iter__(self):
for item in self.api_json(tree='credentials[id]')['credentials']:
yield Credential(self.jenkins,
f'{self.url}credential/{item["id"]}/')
yield Credential(self.jenkins, f'{self.url}credential/{item["id"]}/')

def __getitem__(self, id):
return self.get(id)


class Credential(Item, ConfigurationMixIn, DeletionMixIn):
pass


# async class


class AsyncCredentials(AsyncItem):

async def get(self, name):
data = await self.api_json(tree='domains[urlName]')
for key in data['domains'].keys():
if key == name:
return AsyncDomain(self.jenkins, f'{self.url}store/system/domain/{key}/')
return None

async def create(self, xml):
await self.handle_req('POST', 'createDomain',
headers=self.headers, content=xml)

async def __aiter__(self):
data = await self.api_json(tree='domains[urlName]')
for key in data['domains'].keys():
yield Domain(self.jenkins, f'{self.url}store/system/domain/{key}/')

async def __getitem__(self, name):
return await self.get(name)

@property
async def global_domain(self):
return await self['_']


class AsyncDomain(AsyncItem, AsyncConfigurationMixIn, AsyncDeletionMixIn):

async def get(self, id):
for item in (await self.api_json(tree='credentials[id]'))['credentials']:
data = await self.api_json(tree='credentials[id]')
for item in data['credentials']:
if item['id'] == id:
return AsyncCredential(self.jenkins,
f'{self.url}credential/{id}/')
return AsyncCredential(self.jenkins, f'{self.url}credential/{id}/')
return None

async def create(self, xml):
await self.handle_req('POST', 'createCredentials',
headers=self.headers, content=xml)

async def __aiter__(self):
for item in (await self.api_json(tree='credentials[id]'))['credentials']:
yield AsyncCredential(self.jenkins,
f'{self.url}credential/{item["id"]}/')
data = await self.api_json(tree='credentials[id]')
for item in data['credentials']:
yield AsyncCredential(self.jenkins, f'{self.url}credential/{item["id"]}/')

async def __getitem__(self, id):
return await self.get(id)


class AsyncCredential(AsyncItem, AsyncConfigurationMixIn, AsyncDeletionMixIn):
Expand Down
3 changes: 1 addition & 2 deletions api4jenkins/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ def views(self):

@property
def credentials(self):
return Credentials(self.jenkins,
f'{self.url}credentials/store/folder/domain/_/')
return Credentials(self.jenkins, f'{self.url}credentials/store/folder/')

Check warning on line 98 in api4jenkins/job.py

View check run for this annotation

Codecov / codecov/patch

api4jenkins/job.py#L98

Added line #L98 was not covered by tests

def __iter__(self):
yield from self.iter()
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from api4jenkins import AsyncJenkins, Jenkins
from api4jenkins.build import FreeStyleBuild, WorkflowRun, AsyncWorkflowRun, AsyncFreeStyleBuild
from api4jenkins.credential import Credential, Credentials, AsyncCredentials, AsyncCredential
from api4jenkins.credential import AsyncDomain, Credential, Credentials, AsyncCredentials, AsyncCredential, Domain
from api4jenkins.item import Item, AsyncItem
from api4jenkins.job import Folder, WorkflowJob, WorkflowMultiBranchProject, AsyncFolder, AsyncWorkflowJob, AsyncWorkflowMultiBranchProject
from api4jenkins.node import Node, Nodes, AsyncNode, AsyncNodes
Expand All @@ -29,6 +29,8 @@ def _api_json(self, tree='', depth=0):
elif isinstance(self, (FreeStyleBuild, AsyncFreeStyleBuild)):
return load_json('run/freestylebuild.json')
elif isinstance(self, (Credentials, AsyncCredentials)):
return load_json('credential/domains.json')
elif isinstance(self, (Domain, AsyncDomain)):
return load_json('credential/credentials.json')
elif isinstance(self, (Credential, AsyncCredential)):
return load_json('credential/user_psw.json')
Expand Down
64 changes: 53 additions & 11 deletions tests/unit/test_credential.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
# encoding: utf-8

import pytest
from api4jenkins.credential import AsyncCredential, Credential
from api4jenkins.credential import AsyncCredential, AsyncDomain, Credential, Domain


@pytest.fixture
def global_domain(jenkins):
return jenkins.credentials.global_domain


@pytest.fixture
async def async_global_domain(async_jenkins):
return await async_jenkins.credentials.global_domain


class TestCredentials:

@pytest.mark.parametrize('id_, obj', [('not exist', type(None)), ('test-user', Credential)])
def test_get(self, jenkins, id_, obj):
assert isinstance(jenkins.credentials.get(id_), obj)
def test_get(self, jenkins):
assert isinstance(jenkins.credentials['_'], Domain)
assert jenkins.credentials['x'] is None

def test_create(self, jenkins, respx_mock):
req_url = f'{jenkins.credentials.url}createCredentials'
req_url = f'{jenkins.credentials.url}createDomain'
respx_mock.post(req_url)
jenkins.credentials.create('xml')
assert respx_mock.calls[0].request.url == req_url

def test_iter(self, jenkins):
creds = list(jenkins.credentials)
assert len(list(jenkins.credentials)) == 3


class TestDomain:

@pytest.mark.parametrize('id_, obj', [('not exist', type(None)), ('test-user', Credential)])
def test_get(self, global_domain, id_, obj):
assert isinstance(global_domain[id_], obj)

def test_create(self, global_domain, respx_mock):
req_url = f'{global_domain.url}createCredentials'
respx_mock.post(req_url)
global_domain.create('xml')
assert respx_mock.calls[0].request.url == req_url

def test_iter(self, global_domain):
creds = list(global_domain)
assert len(creds) == 2
assert all(isinstance(c, Credential) for c in creds)

Expand All @@ -43,17 +69,33 @@ def test_configure(self, credential, respx_mock, req, xml, body):

class TestAsyncCredentials:

@pytest.mark.parametrize('id_, obj', [('not exist', type(None)), ('test-user', AsyncCredential)])
async def test_get(self, async_jenkins, id_, obj):
assert isinstance(await async_jenkins.credentials.get(id_), obj)
async def test_get(self, async_jenkins):
assert isinstance(await async_jenkins.credentials['_'], AsyncDomain)
assert await async_jenkins.credentials['x'] is None

async def test_create(self, async_jenkins, respx_mock):
req_url = f'{async_jenkins.credentials.url}createCredentials'
req_url = f'{async_jenkins.credentials.url}createDomain'
respx_mock.post(req_url)
await async_jenkins.credentials.create('xml')
assert respx_mock.calls[0].request.url == req_url

async def test_iter(self, async_jenkins):
creds = [c async for c in async_jenkins.credentials]
assert len([c async for c in async_jenkins.credentials]) == 3


class TestAsyncDomain:

@pytest.mark.parametrize('id_, obj', [('not exist', type(None)), ('test-user', AsyncCredential)])
async def test_get(self, async_global_domain, id_, obj):
assert isinstance(await async_global_domain[id_], obj)

async def test_create(self, async_global_domain, respx_mock):
req_url = f'{async_global_domain.url}createCredentials'
respx_mock.post(req_url)
await async_global_domain.create('xml')
assert respx_mock.calls[0].request.url == req_url

async def test_iter(self, async_global_domain):
creds = [c async for c in async_global_domain]
assert len(creds) == 2
assert all(isinstance(c, AsyncCredential) for c in creds)
11 changes: 11 additions & 0 deletions tests/unit/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,14 @@ def test_enable_disable(self, jenkins, respx_mock, action):
respx_mock.post(req_url)
getattr(jenkins.system, snake(action))()
assert respx_mock.calls[0].request.url == req_url


class TestAsyncSystem:

@pytest.mark.parametrize('action', ['restart', 'safeRestart', 'quietDown',
'cancelQuietDown', 'exit', 'safeExit'])
async def test_enable_disable(self, async_jenkins, respx_mock, action):
req_url = f'{async_jenkins.system.url}{action}'
respx_mock.post(req_url)
await getattr(async_jenkins.system, snake(action))()
assert respx_mock.calls[0].request.url == req_url
17 changes: 17 additions & 0 deletions tests/unit/tests_data/credential/domains.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"_class": "com.cloudbees.hudson.plugins.folder.properties.FolderCredentialsProvider$FolderCredentialsProperty$CredentialsStoreActionImpl",
"domains": {
"_": {
"_class": "com.cloudbees.plugins.credentials.CredentialsStoreAction$DomainWrapper",
"urlName": "_"
},
"production": {
"_class": "com.cloudbees.plugins.credentials.CredentialsStoreAction$DomainWrapper",
"urlName": "production"
},
"testing": {
"_class": "com.cloudbees.plugins.credentials.CredentialsStoreAction$DomainWrapper",
"urlName": "testing"
}
}
}

0 comments on commit ce451a0

Please sign in to comment.