Completed
Pull Request — master (#473)
by Manas
02:22
created

ThirdPartyResource.run()   A

Complexity

Conditions 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 4
dl 0
loc 18
rs 9.2
1
import ast
2
import json
3
import sys
4
5
import requests
6
from requests.auth import HTTPBasicAuth
7
8
from st2reactor.sensor.base import Sensor
9
10
11
class ThirdPartyResource(Sensor):
12
    def __init__(self, sensor_service, config=None):
13
        super(ThirdPartyResource, self).__init__(sensor_service=sensor_service,
14
                                                 config=config)
15
        self._log = self._sensor_service.get_logger(__name__)
16
        self.TRIGGER_REF = 'kubernetes.thirdpartyobject'
17
        self.client = None
18
19
    def setup(self):
20
        try:
21
            extension = self._config['extension_url']
22
            KUBERNETES_API_URL = self._config['kubernetes_api_url'] + extension
23
            user = self._config['user']
24
            password = self._config['password']
25
            verify = self._config['verify']
26
        except KeyError:
27
            self._log.exception('Configuration file does not contain required fields.')
28
            raise
29
        self._log.debug('Connecting to Kubernetes endpoint %s via api_client.' %
30
                        KUBERNETES_API_URL)
31
        self.client = requests.get(KUBERNETES_API_URL, auth=HTTPBasicAuth(user, password),
32
                                   verify=verify, stream=True)
33
34
    def run(self):
35
        self._log.debug('Watch Kubernetes for thirdpartyresource information')
36
        r = self.client
37
        lines = r.iter_lines()
38
        # Save the first line for later or just skip it
39
        # first_line = next(lines)
40
41
        for line in lines:
42
            try:
43
                trigger_payload = self._get_trigger_payload_from_line(line)
44
            except:
45
                msg = ('Failed generating trigger payload from line %s. Aborting sensor!!!' %
46
                    line)
47
                self._log.exception(msg)
48
                sys.exit(1)
49
            else:
50
                self._log.debug('Triggering Dispatch Now')
51
                self._sensor_service.dispatch(trigger=self.TRIGGER_REF, payload=trigger_payload)
52
53
    def _get_trigger_payload_from_line(self, line):
54
        k8s_object = self._fix_utf8_enconding_and_eval(line)
55
        self._log.debug('Incoming k8s object (from API response): %s', k8s_object)
56
        payload = self._k8s_object_to_st2_trigger(k8s_object)
57
        return payload
58
59
    def _fix_utf8_enconding_and_eval(self, line):
60
        # need to perform a json dump due to uft8 error prior to performing a json.load
61
        io = json.dumps(line)
62
        n = json.loads(io)
63
        line = ast.literal_eval(n)
64
        return line
65
66
    def _k8s_object_to_st2_trigger(self, k8s_object):
67
        # Define some variables
68
        try:
69
            resource_type = k8s_object['type']
70
            object_kind = k8s_object['object']['kind']
71
            name = k8s_object['object']['metadata']['name']
72
            namespace = k8s_object['object']['metadata']['namespace']
73
            uid = k8s_object['object']['metadata']['uid']
74
            labels_data = k8s_object['object']['metadata']['labels']
75
        except KeyError:
76
            msg = 'One of "type", "kind", "name", "namespace" or "uid" or "labels" ' + \
77
                  'do not exist in the object. Incoming object=%s' % k8s_object
78
            self._log.exception(msg)
79
            raise
80
        else:
81
            payload = self._build_a_trigger(resource_type=resource_type, name=name,
82
                                    labels=labels_data, namespace=namespace,
83
                                    object_kind=object_kind, uid=uid)
84
            self._log.debug('Trigger payload: %s.' % payload)
85
            return payload
86
87
    def _build_a_trigger(self, resource_type, name, labels, namespace, object_kind, uid):
88
        payload = {
89
            'resource': resource_type,
90
            'name': name,
91
            'labels': labels,
92
            'namespace': namespace,
93
            'object_kind': object_kind,
94
            'uid': uid
95
        }
96
97
        return payload
98
99
    def cleanup(self):
100
        pass
101
102
    def add_trigger(self, trigger):
103
        pass
104
105
    def update_trigger(self, trigger):
106
        pass
107
108
    def remove_trigger(self, trigger):
109
        pass
110