class DeployKey(object):
    """Interface for the /deploy-keys endpoints.

    This class allows you to interract with your deployments keys.

    This class has the following behavior:
      * When loaded it will cache some data in self.cached_data (it will
        cache its json representation according to the API)
      * Everytime you want to get data from the object, like key.fingerprint,
        the cache will be used, so make sure to call reload_datas if updates has been done.
      * Dictionnary lookup is done via the __getattr__ overloaded method. It
        is a bit hacky but it does the job. For instance to get the public part
        of your key, you can type `key.public`, this will query the
        cached value in the object

    An example json representation of what this class may look like :
    .. code-block:: json
        {
            "created_at": "2015-12-07T13:28:28",
            "name": "github",
            "fingerprint": "69:2f:e1:29:82:10:66:fa:59:a7:1e:22:40:66:1a",
            "public": "ssh-rsa AAAAB3NzaC1yc2EAAAAD[...]XP1BmhOtTOw=="
        }
    """
    def __init__(self, name, cached_data):
        """Creates a new object representing an *existing* deploy key

        :param name: The name of the deploy key you want to load
        :type name: str
        :param cached_data: Cached data to instantiate the master
        :type cached_data: dict

        :Example:

        >>> ppaas.DeployKey('thomas')
        <Deploy Key thomas>
        >>> ppaas.DeployKey('thomas').fingerprint
        u'52:35:1c:6c:12:57:5f:64:48:3b:ef:89:4c:c5:08:f9'
        >>> ppaas.DeployKey('Idontexist').fingerprint
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          File "ppaas/deploy_key.py", line 36, in __init__
            self.cached_data, _ = self.client.get('/deploy-keys/%s' % (self.name))
          File "ppaas/client.py", line 72, in get
            return self.call('GET', self.endpoint + url, params=params)
          File "ppaas/client.py", line 112, in call
            raise ResourceNotFoundError(result)
        ppaas.client.ResourceNotFoundError: {u'message': u'The requested resource could not be found.'}

        .. seealso:: get_deploy_keys(), create_deploy_key()
        """
        self.client = ApiClient()
        self.name = name
        self.reload_data(cached_data)

    def reload_data(self, refreshed_datas=None):
        """Reloads datas in the cached_data properties of a deploy key

        :param refreshed_datas: Data to use to reload cached_data property of deploy key
        :type refreshed_datas: dict

        """
        if refreshed_datas:
            self.cached_data = refreshed_datas
        else:
            self.cached_data, _ = self.client.get('/deploy-keys/%s' % (self.name))

    @staticmethod
    def get_deploy_keys(client=None):
        """Retrieves all your deployment keys.

        :param client: A client object you want to pass, if empty a new one will be created
        :type client: ApiClient

        :return: The list of your deployment keys
        :rtype: List of DeployKey objects

        :Example:

        >>> ppaas.DeployKey.get_deploy_keys()
        [<Deploy Key github>, <Deploy Key thomas>]
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/deploy-keys')
        keys = []
        for key in result['deploy_keys']:
            keys.append(DeployKey(key['name'], key))
        return keys

    @staticmethod
    def create_deploy_key(name, client=None):
        """Creates a new deployment key with a given name.

        :param name: Name of the new key
        :type name: str

        :return: The newly created key
        :rtype: DeployKey

        :Example:

        >>> ppaas.DeployKey.create_deploy_key('fookey')
        <Deploy Key fookey>
        """
        if not client:
            client = ApiClient()
        result, status = client.post('/deploy-keys', data={'name': name})
        return DeployKey(name, result)

    def delete(self):
        """Deletes the current instance of DeployKey.

        :Exemple:

        >>> ppaas.DeployKey.get_deploy_keys()
        [<Deploy Key github>, <Deploy Key thomas>]
        >>> ppaas.DeployKey('github').delete()
        >>> ppaas.DeployKey.get_deploy_keys()
        [<Deploy Key thomas>]

        .. warnings:: This action is irreversible.
        """
        result, status = self.client.delete('/deploy-keys/%s' % (self.name))
        return result

    def __repr__(self):
        """String representation of the object"""
        return "<Deploy Key %s>" % (self.name)

    def __getattr__(self, name):
        """Retrieves an attribute of the class.

        This is kind of a hack. We use the __getattr__ method to access fields of the
        json representation of the class. For instance if my class is represented by

        {
            "foo": "bar",
            "lel": true
        }

        Then obj.foo will return be "bar" eventough the property has not been defined
        in an explicit way.

        :param name: Name of the attribute you want to retrieve
        :type name: str

        :return: The value of the field
        :rtype: Any primitive type
        """
        if name in self.cached_data:
            return self.cached_data[name]
        return super(DeployKey, self).__getattr__(name)
class Certificate(object):
    """Interface for the /masters/<masterId>/certs endpoints.

    This class allows you to interract with your agent certificates.

    This class has the following behavior:
      * When loaded it will cache some data in self.cached_data (it will
        cache its json representation according to the API)
      * Everytime you want to get data from the object, like certificate.fingerprint,
        an HTTP call will be issued, so make sure to use the cache if needed.
      * Dictionnary lookup is done via the __getattr__ overloaded method. It
        is a bit hacky but it does the job. For instance to get the fingerprint
        of your certificate, you can type `cert.fingerprint`, this will issue an
        HTTP request and return the corresponding dictionary value

    An example json representation of what this class may look like :
    .. code-block:: json
        {
            "created_at": "2015-12-07T13:28:28",
            "fingerprint": "A7:DA:BE:17:09:9E:18:7D:E6:24:25:7C:65:48:EF",
            "hostname": "web.domain.tld",
            "revoked_at": null,
            "serial_number": null,
            "signed_at": null,
            "status": {
                "code": 0,
                "message": "SIGNATURE PENDING"
            }
        }
    """
    def __init__(self, master, hostname):
        """Creates a new object representing an *existing* agent certificate

        :param master: The Master the wanted certificate is attached to
        :param hostname: The hostname of the agent
        :type master: ppaas.Master
        :type hostname: str

        :Example:
        >>> ppaas.Master.get_masters()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        >>> master = _[0]
        >>> ppaas.Certificate(master, 'machine.maurice.fr')
        <Agent Certificate machine.maurice.fr@0e85b81f-5a29-4e2b-a46c-e024049acb07>

        .. note:: You will probably never call this directly and instead use the
                  ppaas.Master.certificate() method instead
        .. seealso:: get_certificates(), ppaas.Master.certificate()
        """
        self.client = ApiClient()
        self.hostname = hostname
        self.master = master
        self.cached_data, _ = self.client.get('/masters/%s/certs/%s' % (self.master.uuid, hostname))

    @staticmethod
    def get_certificates(master, client=None):
        """Returns all the agent certificates for a Master

        :param master: The master in question
        :param client: The ApiClient to use
        :type master: ppaas.Master
        :type client: ppaas.ApiClient

        :Example:

        >>> ppaas.Master.get_masters()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        >>> master = _[0]
        >>> ppaas.Certificate.get_certificates(master)
        [<Agent Certificate machine.maurice.fr@0e85b81f-5a29-4e2b-a46c-e024049acb07>]

        .. note:: You will probably never use this method neither and use the one
                  shipped with the Master class I guess.
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/masters/%s/certs' % master.uuid)
        certificates = []
        for certificate in result['certs']:
            certificates.append(Certificate(master, certificate['hostname']))
        return certificates

    def to_dict(self):
        """Returns the JSON representation of the object"

        :return: A dictionary containing the object as served by the API
        :rtype: dict

        :Example:

        >>> ppaas.Certificate(master, 'machine.maurice.fr').to_dict()
        {u'revoked_at': None, u'signed_at': None, u'created_at': u'2016-02-21T11:21:58', u'hostname': u'machine.maurice.fr', u'status': {u'message': u'SIGNATURE PENDING', u'code': 0}, u'fingerprint': u'9F:1F:B2:C6:8F:D2:62:26:7B:A3:49:00:45:6F:D6:81:3A:28:D8:ED:42:C4:23:F6:FF:82:64:F9:60:7F:36:9B', u'serial_number': None}
        """
        result, status = self.client.get('/masters/%s/certs/%s' % (self.master.uuid, self.hostname))
        return result

    def delete(self):
        """Deletes a certificate.

        If the certificate has not been revoked yet it will be revoked and deleted.

        :return: None, or raises an exception
        :rtype: None
        """
        result, status = self.client.delete('/masters/%s/certs/%s' % (self.master.uuid, self.hostname))
        return result

    def revoke(self):
        """Revokes a certificate.

        :return: None, or raises an exception
        :rtype: None
        """
        result, status = self.client.post('/masters/%s/certs/%s/revoke' % (self.master.uuid, self.hostname))
        return result

    def sign(self):
        """Signes a certificate.

        :return: None, or raises an exception
        :rtype: None
        """
        result, status = self.client.post('/masters/%s/certs/%s/sign' % (self.master.uuid, self.hostname))
        return result

    def __repr__(self):
        """String representation of the object"""
        return "<Agent Certificate %s@%s>" % (self.hostname, self.master.uuid)

    def __getattr__(self, name):
        """Retrieves an attribute of the class.

        This is kind of a hack. We use the __getattr__ method to access fields of the
        json representation of the class. For instance if my class is represented by

        {
            "foo": "bar",
            "lel": true
        }

        Then obj.foo will return be "bar" eventough the property has not been defined
        in an explicit way.

        :param name: Name of the attribute you want to retrieve
        :type name: str

        :return: The value of the field
        :rtype: Any primitive type
        """
        data, status = self.client.get('/masters/%s/certs/%s' % (self.master.uuid, self.hostname))
        if name in data:
            return data[name]
        return super(Certificate, self).__getattr__(name)
Example #3
0
class Certificate(object):
    """Interface for the /masters/<masterId>/certs endpoints.

    This class allows you to interract with your agent certificates.

    This class has the following behavior:
      * When loaded it will cache some data in self.cached_data (it will
        cache its json representation according to the API)
      * Everytime you want to get data from the object, like certificate.fingerprint,
        an HTTP call will be issued, so make sure to use the cache if needed.
      * Dictionnary lookup is done via the __getattr__ overloaded method. It
        is a bit hacky but it does the job. For instance to get the fingerprint
        of your certificate, you can type `cert.fingerprint`, this will issue an
        HTTP request and return the corresponding dictionary value

    An example json representation of what this class may look like :
    .. code-block:: json
        {
            "created_at": "2015-12-07T13:28:28",
            "fingerprint": "A7:DA:BE:17:09:9E:18:7D:E6:24:25:7C:65:48:EF",
            "hostname": "web.domain.tld",
            "revoked_at": null,
            "serial_number": null,
            "signed_at": null,
            "status": {
                "code": 0,
                "message": "SIGNATURE PENDING"
            }
        }
    """
    def __init__(self, master, hostname):
        """Creates a new object representing an *existing* agent certificate

        :param master: The Master the wanted certificate is attached to
        :param hostname: The hostname of the agent
        :type master: ppaas.Master
        :type hostname: str

        :Example:
        >>> ppaas.Master.get_masters()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        >>> master = _[0]
        >>> ppaas.Certificate(master, 'machine.maurice.fr')
        <Agent Certificate machine.maurice.fr@0e85b81f-5a29-4e2b-a46c-e024049acb07>

        .. note:: You will probably never call this directly and instead use the
                  ppaas.Master.certificate() method instead
        .. seealso:: get_certificates(), ppaas.Master.certificate()
        """
        self.client = ApiClient()
        self.hostname = hostname
        self.master = master
        self.cached_data, _ = self.client.get('/masters/%s/certs/%s' %
                                              (self.master.uuid, hostname))

    @staticmethod
    def get_certificates(master, client=None):
        """Returns all the agent certificates for a Master

        :param master: The master in question
        :param client: The ApiClient to use
        :type master: ppaas.Master
        :type client: ppaas.ApiClient

        :Example:

        >>> ppaas.Master.get_masters()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        >>> master = _[0]
        >>> ppaas.Certificate.get_certificates(master)
        [<Agent Certificate machine.maurice.fr@0e85b81f-5a29-4e2b-a46c-e024049acb07>]

        .. note:: You will probably never use this method neither and use the one
                  shipped with the Master class I guess.
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/masters/%s/certs' % master.uuid)
        certificates = []
        for certificate in result['certs']:
            certificates.append(Certificate(master, certificate['hostname']))
        return certificates

    def to_dict(self):
        """Returns the JSON representation of the object"

        :return: A dictionary containing the object as served by the API
        :rtype: dict

        :Example:

        >>> ppaas.Certificate(master, 'machine.maurice.fr').to_dict()
        {u'revoked_at': None, u'signed_at': None, u'created_at': u'2016-02-21T11:21:58', u'hostname': u'machine.maurice.fr', u'status': {u'message': u'SIGNATURE PENDING', u'code': 0}, u'fingerprint': u'9F:1F:B2:C6:8F:D2:62:26:7B:A3:49:00:45:6F:D6:81:3A:28:D8:ED:42:C4:23:F6:FF:82:64:F9:60:7F:36:9B', u'serial_number': None}
        """
        result, status = self.client.get('/masters/%s/certs/%s' %
                                         (self.master.uuid, self.hostname))
        return result

    def delete(self):
        """Deletes a certificate.

        If the certificate has not been revoked yet it will be revoked and deleted.

        :return: None, or raises an exception
        :rtype: None
        """
        result, status = self.client.delete('/masters/%s/certs/%s' %
                                            (self.master.uuid, self.hostname))
        return result

    def revoke(self):
        """Revokes a certificate.

        :return: None, or raises an exception
        :rtype: None
        """
        result, status = self.client.post('/masters/%s/certs/%s/revoke' %
                                          (self.master.uuid, self.hostname))
        return result

    def sign(self):
        """Signes a certificate.

        :return: None, or raises an exception
        :rtype: None
        """
        result, status = self.client.post('/masters/%s/certs/%s/sign' %
                                          (self.master.uuid, self.hostname))
        return result

    def __repr__(self):
        """String representation of the object"""
        return "<Agent Certificate %s@%s>" % (self.hostname, self.master.uuid)

    def __getattr__(self, name):
        """Retrieves an attribute of the class.

        This is kind of a hack. We use the __getattr__ method to access fields of the
        json representation of the class. For instance if my class is represented by

        {
            "foo": "bar",
            "lel": true
        }

        Then obj.foo will return be "bar" eventough the property has not been defined
        in an explicit way.

        :param name: Name of the attribute you want to retrieve
        :type name: str

        :return: The value of the field
        :rtype: Any primitive type
        """
        data, status = self.client.get('/masters/%s/certs/%s' %
                                       (self.master.uuid, self.hostname))
        if name in data:
            return data[name]
        return super(Certificate, self).__getattr__(name)