Skip to content

Commit

Permalink
Update to use new api paths and names
Browse files Browse the repository at this point in the history
Also adds new required cred_type and source_type fields.

Closes #86
  • Loading branch information
kdelee committed Dec 8, 2017
1 parent 42ab8c5 commit 5dce16c
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 118 deletions.
54 changes: 29 additions & 25 deletions camayoc/qcs_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,19 @@ def delete(self, **kwargs):
return self.client.delete(self.path(), **kwargs)


class HostCredential(QCSObject):
class Credential(QCSObject):
"""A class to aid in CRUD tests of Host Credentials on the QCS server.
Host credentials can be created by instantiating a HostCredential
Host credentials can be created by instantiating a Credential
object. A unique name and username are provided by default.
In order to create a valid host credential you must specify either a
password or ssh_keyfile.
Example::
>>> from camayoc import api
>>> from camayoc.qcs_models import HostCredential
>>> from camayoc.qcs_models import Credential
>>> client = api.QCSClient()
>>> cred = HostCredential(password='foo')
>>> cred = Credential(cred_type='network', password='foo')
>>> # The create method automatically sets the credential's `_id`
>>> cred.create()
>>> actual_cred = cred.read().json()
Expand All @@ -163,13 +163,14 @@ def __init__(
password=None,
ssh_keyfile=None,
sudo_password=None,
cred_type=None,
_id=None):
"""Create a host credential with given data.
If no arguments are passed, then a api.Client will be initialized and a
uuid4 generated for the name and username.
For a HostCredential to be successfully created on the QCS server,
For a Credential to be successfully created on the QCS server,
a password XOR a ssh_keyfile must be provided.
"""
super().__init__(client=client, _id=_id)
Expand All @@ -179,23 +180,24 @@ def __init__(
self.password = password
self.ssh_keyfile = ssh_keyfile
self.sudo_password = sudo_password
self.cred_type = cred_type

def equivalent(self, other):
"""Return true if both objects are equal.
:param other: This can be either another HostCredential or a dictionary
:param other: This can be either another Credential or a dictionary
or json object returned from the QCS server (or crafted by hand.)
If `other` is a HostCredential instance, the two object's fields()
If `other` is a Credential instance, the two object's fields()
will be compared. Otherwise, we expect the password to have been
masked by the server.
"""
if isinstance(other, HostCredential):
if isinstance(other, Credential):
return self.fields() == other.fields()

if not isinstance(other, dict):
raise TypeError(
'Objects of type HostCredential can only be compared to'
'HostCredential objects or dictionaries.'
'Objects of type Credential can only be compared to'
'Credential objects or dictionaries.'
)

password_matcher = re.compile(MASKED_PASSWORD_OUTPUT)
Expand All @@ -209,20 +211,20 @@ def equivalent(self, other):
return True


class NetworkProfile(QCSObject):
class Source(QCSObject):
"""A class to aid in CRUD test cases for network profiles.
Network profiles can be created on the quipucords server by
instantiating a NetworkProfile object. A unique name and username are
instantiating a Source object. A unique name and username are
provided by default. In order to create a valid network profile,
you must specify at least one existing host credential and one host.
Example::
>>> from camayoc.qcs_models import NetworkProfile
>>> from camayoc.qcs_models import Source
>>>
>>> hostcred = HostCredential(password='foo')
>>> hostcred = Credential(cred_type='network',password='foo')
>>> hostcred.create()
>>> netprof = NetworkProfile(hosts=['0.0.0.0'],
>>> netprof = Source( source_type='network', hosts=['0.0.0.0'],
credential_ids=[hostcred._id])
>>> netprof.create()
>>> actual_prof = netprof.read().json()
Expand All @@ -238,8 +240,9 @@ def __init__(
hosts=None,
ssh_port=22,
credential_ids=None,
source_type=None,
_id=None):
"""Iniitalize a NetworkProfile object with given data.
"""Iniitalize a Source object with given data.
If no ssh_port is supplied, it will be set to 22 by default.
A uuid4 name and api.Client are also supplied if none are provided.
Expand All @@ -250,32 +253,33 @@ def __init__(
self.hosts = hosts
self.ssh_port = ssh_port
self.credentials = credential_ids
self.source_type = source_type

def equivalent(self, other):
"""Return true if both objects are equivalent.
:param other: This can be either another NetworkProfile or a dictionary
:param other: This can be either another Source or a dictionary
or json object returned from the QCS server (or crafted by hand.)
If `other` is a NetworkProfile instance, the two object's fields()
If `other` is a Source instance, the two object's fields()
will be compared. Otherwise, we must extract the credential id's
from the json returned by the server into a list, because that is
all the data that we use to generate the network profile.
"""
if isinstance(other, NetworkProfile):
if isinstance(other, Source):
return self.fields() == other.fields()

if not isinstance(other, dict):
raise TypeError(
'Objects of type NetworkProfile can only be compared to'
'NetworkProfiles objects or dictionaries.'
'Objects of type Source can only be compared to'
'Sources objects or dictionaries.'
)

for key, value in self.fields().items():
if key == 'credentials':
other_creds = other.get('credentials')
cred_ids = []
# the server returns a list of dictionaries
# one for each credential associated with the NetworkProfile
# one for each credential associated with the Source
# we extract from this all the id's and then compare it with
# the list of id's we used to create the Network Profile
for cred in other_creds:
Expand All @@ -294,13 +298,13 @@ class Scan(QCSObject):
Scan jobs can be created on the quipucords server by instantiating a Scan
object and then calling its create() method.
The id of an existing NetworkProfile is necessary to create a scan
The id of an existing Source is necessary to create a scan
job.
Example::
>>> hostcred = HostCredential(password='foo')
>>> hostcred = Credential(cred_type='network', password='foo')
>>> hostcred.create()
>>> netprof = NetworkProfile(hosts=['0.0.0.0'],
>>> netprof = Source( source_type='network', hosts=['0.0.0.0'],
credential_ids=[hostcred._id])
>>> netprof.create()
>>> scan = Scan(profile_id=netprof._id)
Expand Down
88 changes: 55 additions & 33 deletions camayoc/tests/qcs/test_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pathlib import Path

from camayoc import api
from camayoc.qcs_models import HostCredential
from camayoc.qcs_models import Credential
from camayoc.utils import uuid4
from camayoc.tests.qcs.utils import assert_matches_server

Expand All @@ -26,7 +26,10 @@ def test_create_with_password(shared_client, cleanup):
:steps: Send POST with necessary data to documented api endpoint.
:expectedresults: A new host credential entry is created with the data.
"""
cred = HostCredential(client=shared_client, password=uuid4())
cred = Credential(
cred_type='network',
client=shared_client,
password=uuid4())
cred.create()
# add the credential to the list to destroy after the test is done
cleanup.append(cred)
Expand All @@ -45,7 +48,10 @@ def test_update_username(shared_client, cleanup):
3) Confirm host credential has been updated.
:expectedresults: The host credential is updated.
"""
cred = HostCredential(shared_client, password=uuid4())
cred = Credential(
cred_type='network',
client=shared_client,
password=uuid4())
cred.create()
# add the id to the list to destroy after the test is done
cleanup.append(cred)
Expand All @@ -70,7 +76,10 @@ def test_update_password_to_sshkeyfile(
3) Confirm host credential has been updated.
:expectedresults: The host credential is updated.
"""
cred = HostCredential(shared_client, password=uuid4())
cred = Credential(
cred_type='network',
client=shared_client,
password=uuid4())
cred.create()
# add the id to the list to destroy after the test is done
cleanup.append(cred)
Expand Down Expand Up @@ -102,10 +111,10 @@ def test_update_sshkey_to_password(
ssh_keyfile = Path(uuid4())
ssh_keyfile.touch()

cred = HostCredential(
shared_client,
ssh_keyfile=str(ssh_keyfile.resolve()),
)
cred = Credential(cred_type='network',
client=shared_client,
ssh_keyfile=str(ssh_keyfile.resolve()),
)
cred.create()
# add the id to the list to destroy after the test is done
cleanup.append(cred)
Expand Down Expand Up @@ -136,10 +145,10 @@ def test_negative_update_to_invalid(
ssh_keyfile = Path(uuid4())
ssh_keyfile.touch()

cred = HostCredential(
shared_client,
ssh_keyfile=str(ssh_keyfile.resolve()),
)
cred = Credential(cred_type='network',
client=shared_client,
ssh_keyfile=str(ssh_keyfile.resolve()),
)
cred.create()
# add the id to the list to destroy after the test is done
cleanup.append(cred)
Expand Down Expand Up @@ -183,10 +192,10 @@ def test_create_with_sshkey(
ssh_keyfile = Path(uuid4())
ssh_keyfile.touch()

cred = HostCredential(
shared_client,
ssh_keyfile=str(ssh_keyfile.resolve()),
)
cred = Credential(cred_type='network',
client=shared_client,
ssh_keyfile=str(ssh_keyfile.resolve()),
)
cred.create()
# add the id to the list to destroy after the test is done
cleanup.append(cred)
Expand All @@ -207,11 +216,11 @@ def test_negative_create_key_and_pass(cleanup, isolated_filesystem):
ssh_keyfile.touch()

client = api.Client(api.echo_handler)
cred = HostCredential(
client,
ssh_keyfile=str(ssh_keyfile.resolve()),
password=uuid4(),
)
cred = Credential(cred_type='network',
client=client,
ssh_keyfile=str(ssh_keyfile.resolve()),
password=uuid4(),
)
response = cred.create()
assert response.status_code == 400
assert cred._id is None
Expand All @@ -228,11 +237,11 @@ def test_negative_create_no_name(cleanup):
:expectedresults: Error is thrown and no new host credential is created.
"""
client = api.Client(api.echo_handler)
cred = HostCredential(
client,
username='',
password=uuid4(),
)
cred = Credential(cred_type='network',
client=client,
username='',
password=uuid4(),
)
response = cred.create()
assert response.status_code == 400
assert cred._id is None
Expand All @@ -249,7 +258,7 @@ def test_negative_create_no_key_or_pass(cleanup):
:expectedresults: Error is thrown and no new host credential is created.
"""
client = api.Client(api.echo_handler)
cred = HostCredential(client)
cred = Credential(cred_type='network', client=client)
response = cred.create()
assert response.status_code == 400
assert cred._id is None
Expand All @@ -270,14 +279,17 @@ def test_read_all(shared_client, cleanup):
"""
host_credentials = []
for _ in range(random.randint(2, 5)):
cred = HostCredential(client=shared_client, password=uuid4())
cred = Credential(
cred_type='network',
client=shared_client,
password=uuid4())
cred.create()
# add the credential to the list to destroy after the test is done
cleanup.append(cred)
assert_matches_server(cred)
host_credentials.append(cred)

remote_host_credentials = HostCredential().list().json()
remote_host_credentials = Credential(cred_type='network', ).list().json()
for local, remote in zip(host_credentials, remote_host_credentials):
local.equivalent(remote)

Expand All @@ -297,15 +309,20 @@ def test_read_indv(shared_client, cleanup):
"""
host_credentials = []
for _ in range(random.randint(2, 5)):
cred = HostCredential(client=shared_client, password=uuid4())
cred = Credential(
cred_type='network',
client=shared_client,
password=uuid4())
cred.create()
# add the credential to the list to destroy after the test is done
cleanup.append(cred)
assert_matches_server(cred)
host_credentials.append(cred)

for host_credential in host_credentials:
remote = HostCredential(_id=host_credential._id).read().json()
remote = Credential(
cred_type='network',
_id=host_credential._id).read().json()
host_credential.equivalent(remote)


Expand All @@ -326,7 +343,10 @@ def test_delete(shared_client, cleanup):
"""
host_credentials = []
for _ in range(random.randint(2, 5)):
cred = HostCredential(client=shared_client, password=uuid4())
cred = Credential(
cred_type='network',
client=shared_client,
password=uuid4())
cred.create()
# add the credential to the list to destroy after the test is done
cleanup.append(cred)
Expand All @@ -340,5 +360,7 @@ def test_delete(shared_client, cleanup):
selected.delete()

for host_credential in host_credentials:
remote = HostCredential(_id=host_credential._id).read().json()
remote = Credential(
cred_type='network',
_id=host_credential._id).read().json()
host_credential.equivalent(remote)
Loading

0 comments on commit 5dce16c

Please sign in to comment.