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
Esempio n. 2
0
    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
Esempio n. 3
0
def run():
    try:
        client = ApiClient('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET')
        result = client.get(
            'v2/astrology/kundli/advanced', {
                'ayanamsa': 1,
                'coordinates': '23.1765,75.7885',
                'datetime': '2020-10-19T12:31:14+00:00',
            })
        print json.dumps(result, indent=4)
    except ValidationError as e:
        for msg in e.getValidationMessages():
            print(msg['detail'])
    except AuthenticationError as e:
        print(e.message)
Esempio n. 4
0
def run():
    try:
        client = ApiClient('a995b0ff-2269-45bf-a96e-07233c2aa03c',
                           'iqxjWqVzDUObnVTMgVdUGKVPhdFhE6qCRIF6oG8u')
        result = client.get(
            'v2/astrology/planet-position', {
                'ayanamsa': 1,
                'coordinates': '23.1765,75.7885',
                'datetime': '1975-04-25T14:10:00+00:00',
                'chart_type': 'lagna',
                'chart_style': 'north-indian'
            })
        # print json.dumps(result, indent=4)
        print(result)
    except ValidationError as e:
        for msg in e.getValidationMessages():
            print(msg['detail'])
    except AuthenticationError as e:
        print(e.message)
    def get_masters(client=None):
        """Retrieves all your puppet masters

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

        :return: The list of your puppet masters
        :rtype: List of Master objects

        :Example:

        >>> ppaas.Master.get_masters()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/masters')
        masters = []
        for master in result['masters']:
            masters.append(Master(master['id'], master))
        return masters
    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
Esempio n. 7
0
    def get_masters(client=None):
        """Retrieves all your puppet masters

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

        :return: The list of your puppet masters
        :rtype: List of Master objects

        :Example:

        >>> ppaas.Master.get_deploy_keys()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/masters')
        masters = []
        for master in result['masters']:
            masters.append(Master(master['id']))
        return masters
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)
class Master(object):
    """Interface for the /masters/<masterId> endpoints.

    This class allows you to interract with your Puppet Masters

    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,
        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 hostname
        of your master, you can type `master.hostname`, this will query the
        cached value in the object


    An example json representation of what this class may look like :
    .. code-block:: json
        {
            "allowed_networks": [
                "0.0.0.0/0"
            ],
            "ca_certificate": "-----BEGIN [.]CATE-----",
            "created_at": "2015-12-07T13:28:28",
            "deploy_key": "github",
            "hierarchy": [],
            "hieras": [],
            "hostname": "master1.user.puppet.runabove.io",
            "id": "1e42115b-34f9-4f86-a4a7-67e30a24a825",
            "name": "master1",
            "nb": 1,
            "servers": {},
            "source": "[email protected]:puppet/puppet.git",
            "status": {
                "code": 0,
                "msg": "Deploying server"
            },
            "token": "d4K1cxIPklE",
            "type": "eg-7",
            "vars": {}
        }
    """
    def __init__(self, uuid, cached_data=None):
        """Creates a new object representing an *existing* puppet master

        :param uuid: UUID of the master
        :type uuid: str
        :param cached_data: Cached data to instantiate the master
        :type cached_data: dict


        :Example:
        >>> ppaas.Master('0e85b81f-5a29-4e2b-a46c-e024049acb07')
        <Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>
        >>> master.name
        'thomas'

        .. seealso:: get_masters()
        """
        self.client = ApiClient()
        self.uuid = uuid
        self.reload_data(cached_data)

    def reload_data(self, refreshed_datas=None):
        """Reloads datas in the cached_data properties of the pupet master

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

        """
        if refreshed_datas:
            self.cached_data = refreshed_datas
        else:
            self.cached_data, _ = self.client.get('/masters/%s' % self.uuid)

    @staticmethod
    def create_master(name, source, deploy_key, vars={}, nb=1, type=None, hierarchy=[], hieras=[], client=None):
        """ Creates a Pupper master

        :param name: Name of the puppet master
        :type name: str
        :param source: Source git repository of the puppet master
        :type source: str
        :param deploy_key: Deploy key to link with your puppet master
        :type deploy_key: ppaas.DeployKey
        :param nb: Number of servers for the master
        :type nb: int
        :param type: Kind of server to use
        :type type: str
        :param hierarchy: Array of hierarchies
        :type hierarchy: list
        :param hieras: Array of hiera backend
        :type hieras: list
        :param client: A client object you want to pass, if empty a new one will be created
        :type client: ppaas.ApiClient

        :return: The newly created puppet master
        :rtype: Master

        :Example:
        >>> ppaas.Master.create_master("master1", "[email protected]:puppet/puppet.git", "github")
        <Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>
        >>> master.name
        'master1'

        """
        payload = {"name": name, "source": source, "deploy_key": deploy_key, "nb": nb,
                "hierarchy": hierarchy, "hieras": hieras, "vars": vars}
        if type:
            payload["type"] = type

        if not client:
            client = ApiClient()

        result, _ = client.post("/masters", data=payload)
        return Master(result["id"], result)

    @staticmethod
    def get_masters(client=None):
        """Retrieves all your puppet masters

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

        :return: The list of your puppet masters
        :rtype: List of Master objects

        :Example:

        >>> ppaas.Master.get_masters()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/masters')
        masters = []
        for master in result['masters']:
            masters.append(Master(master['id'], master))
        return masters

    @staticmethod
    def get_master(name, client=None):
        """Gets a master by name, because who the hell can remember uuids ?

        :param name: Name of the Puppet Master you want to retrieve
        :param client: A client object you want to pass, if empty a new one will be created
        :type name: str
        :type client: ppaas.ApiClient

        :return: A Master object, or None if no matching master was found
        :rtype: ppaas.Master, or None

        :Example:

        >>> ppaas.Master.get_master('thomas')
        <Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>
        """
        if not client:
            client = ApiClient()
        masters = Master.get_masters(client)
        for master in masters:
            if master.cached_data['name'] == name:
                return master
        return None

    def get_certificates(self, status=None):
        """Returns all the certificates attached to a master

        Optionally you can specify a `status` for the certificates. The statuses can either be
          * "SIGNATURE PENDING"
          * "SIGNED"
          * "REVOKED"
        If status is None, all the certifictes will be returned regardless of their status

        Note that it is just for conveinence that this option is provided. From the API's point
        of view we will issue the same request anyway.

        :param status: The status of the certificates
        :type status: str

        :return: A list of matching certificates
        :rtype: List of ppaas.Certificate

        """
        certificates = Certificate.get_certificates(self, self.client)
        if status is None:
            return certificates
        else:
            return [cert for cert in certificates if cert.status['message'] == status]

    def __repr__(self):
        """String representation of the object"""
        return "<Puppet Master %s>" % self.uuid

    def refresh(self):
        """Asks the master to refresh itself.

        You usually want to do it to trigger the pull of your git repository

        :return: Wether the refresh has been accepted
        :rtype: boolean

        .. note:: The API can answer False if a refresh is already in progress.
        """
        try:
            self.client.post('/masters/%s/refresh' % self.uuid)
            return True
        except:
            return False

    def restart(self):
        """Asks the master to restart

        You usually want to do it when you have edited your hiera or your
        custom puppet functions

        :return: Wether the restart has been accepted
        :rtype: boolean
        """
        try:
            self.client.post('/masters/%s/restart' % self.uuid)
            return True
        except:
            return False

    def certificate(self, hostname):
        """Returns the certificate of a particular hostname

        :param hostname: The hostname you want the certificate of
        :type hostname: str

        :return: The ppaas.Certificate object, or raises an exception
        :rtype: ppaas.Certificate
        """
        return Certificate(self, hostname)

    @property
    def crl(self):
        """Gets the CRL of the master

        :return: The CRL
        :rtype: str
        """
        data, result = self.client.get('/masters/%s/crl' % self.uuid)
        return data['crl']

    @property
    def certificates(self):
        """Gets all the certificates of the master

        :return: The list of the certificates
        :rtype: List of dicts !!!

        .. warnings:: Does not return an object, but a dict
        """
        data, result = self.client.get('/masters/%s/certs' % self.uuid)
        return data['certs']

    @property
    def environments(self):
        """Gets the environments

        It can look like :
        .. code-block:: json
            {
                "environments": {
                    "production": {
                        "settings": {
                            "config_version": "",
                            "environment_timeout": 0,
                            "manifest": "environments/production/manifests",
                            "modulepath": [
                                "/etc/puppet/environments/production/modules",
                                "/etc/puppet/modules",
                                "/usr/share/puppet/modules"
                            ]
                        }
                    }
                }
            }

        :return: The environments of the master
        :rtype: dictionary
        """
        data, result = self.client.get('/masters/%s/environments' % self.uuid)
        return data['environments']

    @property
    def last_update(self):
        """Gets the last update of the master

        Can look like: "2015-12-07T13:28:28"

        :return: Last master update
        :rtype: str
        """
        data, result = self.client.get('/masters/%s/last-update' % self.uuid)
        return data['result']

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

        :return: A dictionary containing the object as served by the API
        :rtype: dict
        """
        result, status = self.client.get('/masters')
        return result

    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(Master, self).__getattr__(name)
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)
Esempio n. 11
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)
Esempio n. 12
0
class Master(object):
    """Interface for the /masters/<masterId> endpoints.

    This class allows you to interract with your Puppet Masters

    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 hostname
        of your master, you can type `master.hostname`, 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
        {
            "allowed_networks": [
                "0.0.0.0/0"
            ],
            "ca_certificate": "-----BEGIN [.]CATE-----",
            "created_at": "2015-12-07T13:28:28",
            "deploy_key": "github",
            "hierarchy": [],
            "hieras": [],
            "hostname": "master1.user.puppet.runabove.io",
            "id": "1e42115b-34f9-4f86-a4a7-67e30a24a825",
            "name": "master1",
            "nb": 1,
            "servers": {},
            "source": "[email protected]:puppet/puppet.git",
            "status": {
                "code": 0,
                "msg": "Deploying server"
            },
            "token": "d4K1cxIPklE",
            "type": "eg-7",
            "vars": {}
        }
    """
    def __init__(self, uuid):
        """Creates a new object representing an *existing* puppet master

        :param uuid: UUID of the master
        :type uuid: str

        :Example:
        >>> ppaas.Master('0e85b81f-5a29-4e2b-a46c-e024049acb07')
        <Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>
        >>> master.name
        'thomas'

        .. seealso:: get_masters()
        """
        self.client = ApiClient()
        self.uuid = uuid
        self.cached_data, _ = self.client.get('/masters/%s' % self.uuid)

    @staticmethod
    def get_masters(client=None):
        """Retrieves all your puppet masters

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

        :return: The list of your puppet masters
        :rtype: List of Master objects

        :Example:

        >>> ppaas.Master.get_deploy_keys()
        [<Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>]
        """
        if not client:
            client = ApiClient()
        result, status = client.get('/masters')
        masters = []
        for master in result['masters']:
            masters.append(Master(master['id']))
        return masters

    @staticmethod
    def get_master(name, client=None):
        """Gets a master by name, because who the hell can remember uuids ?

        :param name: Name of the Puppet Master you want to retrieve
        :param client: A client object you want to pass, if empty a new one will be created
        :type name: str
        :type client: ppaas.ApiClient

        :return: A Master object, or None if no matching master was found
        :rtype: ppaas.Master, or None

        :Example:

        >>> ppaas.Master.get_master('thomas')
        <Puppet Master 0e85b81f-5a29-4e2b-a46c-e024049acb07>
        """
        if not client:
            client = ApiClient()
        masters = Master.get_masters(client)
        for master in masters:
            if master.cached_data['name'] == name:
                return master
        return None

    def get_certificates(self, status=None):
        """Returns all the certificates attached to a master

        Optionally you can specify a `status` for the certificates. The statuses can either be
          * "SIGNATURE PENDING"
          * "SIGNED"
          * "REVOKED"
        If status is None, all the certifictes will be returned regardless of their status

        Note that it is just for conveinence that this option is provided. From the API's point
        of view we will issue the same request anyway.

        :param status: The status of the certificates
        :type status: str

        :return: A list of matching certificates
        :rtype: List of ppaas.Certificate

        """
        if status is None:
            return Certificate.get_certificates(self, self.client)
        else:
            certificates = Certificate.get_certificates(self, self.client)
            return [
                cert for cert in certificates
                if cert.status['message'] == status
            ]

    def __repr__(self):
        """String representation of the object"""
        return "<Puppet Master %s>" % self.uuid

    def refresh(self):
        """Asks the master to refresh itself.

        You usually want to do it to trigger the pull of your git repository

        :return: Wether the refresh has been accepted
        :rtype: boolean

        .. note:: The API can answer False if a refresh is already in progress.
        """
        try:
            self.client.post('/masters/%s/refresh' % self.uuid)
            return True
        except:
            return False

    def restart(self):
        """Asks the master to restart

        You usually want to do it when you have edited your hiera or your
        custom puppet functions

        :return: Wether the restart has been accepted
        :rtype: boolean
        """
        try:
            self.client.post('/masters/%s/restart' % self.uuid)
            return True
        except:
            return False

    def certificate(self, hostname):
        """Returns the certificate of a particular hostname

        :param hostname: The hostname you want the certificate of
        :type hostname: str

        :return: The ppaas.Certificate object, or raises an exception
        :rtype: ppaas.Certificate
        """
        return Certificate(self, hostname)

    @property
    def crl(self):
        """Gets the CRL of the master

        :return: The CRL
        :rtype: str
        """
        data, result = self.client.get('/masters/%s/crl' % self.uuid)
        return data['crl']

    @property
    def certificates(self):
        """Gets all the certificates of the master

        :return: The list of the certificates
        :rtype: List of dicts !!!

        .. warnings:: Does not return an object, but a dict
        """
        data, result = self.client.get('/masters/%s/certs' % self.uuid)
        return data['certs']

    @property
    def environments(self):
        """Gets the environments

        It can look like :
        .. code-block:: json
            {
                "environments": {
                    "production": {
                        "settings": {
                            "config_version": "",
                            "environment_timeout": 0,
                            "manifest": "environments/production/manifests",
                            "modulepath": [
                                "/etc/puppet/environments/production/modules",
                                "/etc/puppet/modules",
                                "/usr/share/puppet/modules"
                            ]
                        }
                    }
                }
            }

        :return: The environments of the master
        :rtype: dictionary
        """
        data, result = self.client.get('/masters/%s/environments' % self.uuid)
        return data['environments']

    @property
    def last_update(self):
        """Gets the last update of the master

        Can look like: "2015-12-07T13:28:28"

        :return: Last master update
        :rtype: str
        """
        data, result = self.client.get('/masters/%s/last-update' % self.uuid)
        return data['result']

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

        :return: A dictionary containing the object as served by the API
        :rtype: dict
        """
        result, status = self.client.get('/masters')
        return result

    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' % self.uuid)
        if name in data:
            return data[name]
        return super(Master, self).__getattr__(name)