Browse Source

User context tracing through logging

This PS adds entry in log for user id and passes on the context
maker to other Airship components from Shipyard during API call.

This will ensure easy tracing of user and context through log
tracing.

Change-Id: Ib9bfa8f20b641f8bb6c2dca967d9388e30d5735c
Smruti Soumitra Khuntia 2 months ago
parent
commit
9c5270b616
21 changed files with 180 additions and 51 deletions
  1. 28
    2
      src/bin/shipyard_airflow/shipyard_airflow/control/action/action_validators.py
  2. 6
    3
      src/bin/shipyard_airflow/shipyard_airflow/control/action/actions_api.py
  3. 2
    1
      src/bin/shipyard_airflow/shipyard_airflow/control/helpers/configdocs_helper.py
  4. 21
    18
      src/bin/shipyard_airflow/shipyard_airflow/control/helpers/deckhand_client.py
  5. 3
    1
      src/bin/shipyard_airflow/shipyard_airflow/control/helpers/status_helper.py
  6. 1
    1
      src/bin/shipyard_airflow/shipyard_airflow/control/logging/logging_config.py
  7. 1
    1
      src/bin/shipyard_airflow/shipyard_airflow/control/logging/request_logging.py
  8. 1
    0
      src/bin/shipyard_airflow/shipyard_airflow/control/middleware/logging_mw.py
  9. 9
    3
      src/bin/shipyard_airflow/shipyard_airflow/control/service_clients.py
  10. 7
    3
      src/bin/shipyard_airflow/shipyard_airflow/plugins/armada_base_operator.py
  11. 13
    1
      src/bin/shipyard_airflow/shipyard_airflow/plugins/deckhand_base_operator.py
  12. 3
    2
      src/bin/shipyard_airflow/shipyard_airflow/plugins/deckhand_client_factory.py
  13. 22
    6
      src/bin/shipyard_airflow/shipyard_airflow/plugins/deployment_configuration_operator.py
  14. 2
    0
      src/bin/shipyard_airflow/shipyard_airflow/plugins/drydock_base_operator.py
  15. 4
    1
      src/bin/shipyard_airflow/shipyard_airflow/plugins/drydock_validate_design.py
  16. 10
    1
      src/bin/shipyard_airflow/shipyard_airflow/plugins/promenade_base_operator.py
  17. 4
    1
      src/bin/shipyard_airflow/shipyard_airflow/plugins/promenade_validate_site_design.py
  18. 10
    4
      src/bin/shipyard_airflow/shipyard_airflow/plugins/service_endpoint.py
  19. 3
    2
      src/bin/shipyard_airflow/shipyard_airflow/plugins/service_session.py
  20. 2
    0
      src/bin/shipyard_airflow/shipyard_airflow/plugins/ucp_base_operator.py
  21. 28
    0
      src/bin/shipyard_airflow/shipyard_airflow/shipyard_const.py

+ 28
- 2
src/bin/shipyard_airflow/shipyard_airflow/control/action/action_validators.py View File

@@ -29,10 +29,34 @@ from shipyard_airflow.control.validators.validate_target_nodes import \
29 29
     ValidateTargetNodes
30 30
 from shipyard_airflow.control.validators.validate_test_cleanup import \
31 31
     ValidateTestCleanup
32
+from shipyard_airflow.shipyard_const import CustomHeaders
32 33
 
33 34
 LOG = logging.getLogger(__name__)
34 35
 
35 36
 
37
+addl_headers_map = {
38
+    'context_marker': CustomHeaders.CONTEXT_MARKER.value,
39
+    'user': CustomHeaders.END_USER.value
40
+}
41
+
42
+
43
+def _get_additional_headers(action):
44
+    """
45
+    Populates additional headers from action dict. The headers sets
46
+    context_marker and end_user for audit trace logging
47
+    :param dict action: action info available
48
+    :returns: dict additional_headers
49
+    """
50
+    addl_headers = {}
51
+
52
+    for key, header in addl_headers_map.items():
53
+        header_value = action.get(key)
54
+        if header_value:
55
+            addl_headers.update({header: header_value})
56
+
57
+    return addl_headers
58
+
59
+
36 60
 def validate_committed_revision(action, **kwargs):
37 61
     """Invokes a validation that the committed revision of site design exists
38 62
     """
@@ -50,8 +74,9 @@ def validate_deployment_action_full(action, **kwargs):
50 74
           - If the deployment strategy is specified, but is missing, error.
51 75
           - Check that there are no cycles in the groups
52 76
     """
77
+    addl_headers = _get_additional_headers(action)
53 78
     validator = ValidateDeploymentAction(
54
-        dh_client=service_clients.deckhand_client(),
79
+        dh_client=service_clients.deckhand_client(addl_headers=addl_headers),
55 80
         action=action,
56 81
         full_validation=True
57 82
     )
@@ -65,8 +90,9 @@ def validate_deployment_action_basic(action, **kwargs):
65 90
       - The deployment configuration from Deckhand using the design version
66 91
           - If the deployment configuration is missing, error
67 92
     """
93
+    addl_headers = _get_additional_headers(action)
68 94
     validator = ValidateDeploymentAction(
69
-        dh_client=service_clients.deckhand_client(),
95
+        dh_client=service_clients.deckhand_client(addl_headers=addl_headers),
70 96
         action=action,
71 97
         full_validation=False
72 98
     )

+ 6
- 3
src/bin/shipyard_airflow/shipyard_airflow/control/action/actions_api.py View File

@@ -145,6 +145,8 @@ class ActionsResource(BaseResource):
145 145
         action['user'] = context.user
146 146
         # add current timestamp (UTC) to the action.
147 147
         action['timestamp'] = str(datetime.utcnow())
148
+        # add external marker that is the passed with request context
149
+        action['context_marker'] = context.request_id
148 150
         # validate that action is supported.
149 151
         LOG.info("Attempting action: %s", action['name'])
150 152
         action_mappings = _action_mappings()
@@ -187,10 +189,11 @@ class ActionsResource(BaseResource):
187 189
         action['dag_execution_date'] = dag_execution_date
188 190
         action['dag_status'] = 'SCHEDULED'
189 191
 
190
-        # context_marker is the uuid from the request context
191
-        action['context_marker'] = context.request_id
192
-
193 192
         # insert the action into the shipyard db
193
+        # TODO(b-str): When invoke_airflow_dag triggers a DAG but fails to
194
+        #    respond properly, no record is inserted, so there is a running
195
+        #    process with no tracking in the Shipyard database. This is not
196
+        #    ideal.
194 197
         self.insert_action(action=action)
195 198
         notes_helper.make_action_note(
196 199
             action_id=action['id'],

+ 2
- 1
src/bin/shipyard_airflow/shipyard_airflow/control/helpers/configdocs_helper.py View File

@@ -78,7 +78,8 @@ class ConfigdocsHelper(object):
78 78
         Sets up this Configdocs helper with the supplied
79 79
         request context
80 80
         """
81
-        self.deckhand = DeckhandClient(context.external_marker)
81
+        self.deckhand = DeckhandClient(context.request_id,
82
+                                       end_user=context.user)
82 83
         self.ctx = context
83 84
         # The revision_dict indicates the revisions that are
84 85
         # associated with the buffered and committed doc sets. There

+ 21
- 18
src/bin/shipyard_airflow/shipyard_airflow/control/helpers/deckhand_client.py View File

@@ -24,6 +24,7 @@ import yaml
24 24
 from shipyard_airflow.control.service_endpoints import (Endpoints,
25 25
                                                         get_endpoint,
26 26
                                                         get_token)
27
+from shipyard_airflow.shipyard_const import CustomHeaders
27 28
 
28 29
 CONF = cfg.CONF
29 30
 LOG = logging.getLogger(__name__)
@@ -49,11 +50,12 @@ class DeckhandClient(object):
49 50
     """
50 51
     A rudimentary client for deckhand in lieu of a provided client
51 52
     """
52
-    def __init__(self, context_marker):
53
+    def __init__(self, context_marker, end_user=None):
53 54
         """
54 55
         Sets up this Deckhand client with the supplied context marker
55 56
         """
56 57
         self.context_marker = context_marker
58
+        self.end_user = end_user
57 59
 
58 60
     _deckhand_svc_url = None
59 61
 
@@ -294,6 +296,17 @@ class DeckhandClient(object):
294 296
     # content-type: application/x-yaml
295 297
     # X-Context-Marker: {the context marker}
296 298
     # X-Auth-Token: {a current auth token}
299
+    # X-End-User: {current Shipyard user}
300
+
301
+    def _get_headers(self):
302
+        # Populate HTTP headers
303
+        headers = {
304
+            CustomHeaders.CONTEXT_MARKER.value: self.context_marker,
305
+            CustomHeaders.END_USER.value: self.end_user,
306
+            'X-Auth-Token': get_token()
307
+        }
308
+
309
+        return headers
297 310
 
298 311
     @staticmethod
299 312
     def _log_request(method, url, params=None):
@@ -310,10 +323,8 @@ class DeckhandClient(object):
310 323
         # invokes a PUT against the specified URL with the
311 324
         # supplied document_data body
312 325
         try:
313
-            headers = {
314
-                'X-Context-Marker': self.context_marker,
315
-                'X-Auth-Token': get_token()
316
-            }
326
+            headers = self._get_headers()
327
+
317 328
             if document_data is not None:
318 329
                 headers['content-type'] = 'application/x-yaml'
319 330
 
@@ -338,11 +349,8 @@ class DeckhandClient(object):
338 349
     def _get_request(self, url, params=None):
339 350
         # invokes a GET against the specified URL
340 351
         try:
341
-            headers = {
342
-                'content-type': 'application/x-yaml',
343
-                'X-Context-Marker': self.context_marker,
344
-                'X-Auth-Token': get_token()
345
-            }
352
+            headers = self._get_headers()
353
+            headers['content-type'] = 'application/x-yaml'
346 354
 
347 355
             if not params:
348 356
                 params = None
@@ -368,10 +376,8 @@ class DeckhandClient(object):
368 376
         # invokes a POST against the specified URL with the
369 377
         # supplied document_data body
370 378
         try:
371
-            headers = {
372
-                'X-Context-Marker': self.context_marker,
373
-                'X-Auth-Token': get_token()
374
-            }
379
+            headers = self._get_headers()
380
+
375 381
             if document_data is not None:
376 382
                 headers['content-type'] = 'application/x-yaml'
377 383
 
@@ -396,10 +402,7 @@ class DeckhandClient(object):
396 402
     def _delete_request(self, url, params=None):
397 403
         # invokes a DELETE against the specified URL
398 404
         try:
399
-            headers = {
400
-                'X-Context-Marker': self.context_marker,
401
-                'X-Auth-Token': get_token()
402
-            }
405
+            headers = self._get_headers()
403 406
 
404 407
             DeckhandClient._log_request('DELETE', url, params)
405 408
             response = requests.delete(

+ 3
- 1
src/bin/shipyard_airflow/shipyard_airflow/control/helpers/status_helper.py View File

@@ -130,7 +130,9 @@ class StatusHelper(object):
130 130
 
131 131
         # get Drydock client
132 132
         if not self.drydock:
133
-            self.drydock = sc.drydock_client()
133
+            self.drydock = sc.drydock_client(
134
+                context_marker=self.ctx.request_id,
135
+                end_user=self.ctx.user)
134 136
 
135 137
         statuses = {}
136 138
         # iterate through filters to invoke required fun

+ 1
- 1
src/bin/shipyard_airflow/shipyard_airflow/control/logging/logging_config.py View File

@@ -41,7 +41,7 @@ class LoggingConfig():
41 41
 
42 42
     _default_log_format = (
43 43
         "%(asctime)s %(levelname)-8s %(req_id)s %(external_ctx)s %(user)s "
44
-        "%(module)s(%(lineno)d) %(funcName)s - %(message)s")
44
+        "%(user_id)s %(module)s(%(lineno)d) %(funcName)s - %(message)s")
45 45
 
46 46
     def __init__(self,
47 47
                  level,

+ 1
- 1
src/bin/shipyard_airflow/shipyard_airflow/control/logging/request_logging.py View File

@@ -39,7 +39,7 @@ except ImportError:
39 39
 # logging - these fields need not be set up independently as opposed to the
40 40
 # additional_fields parameter used below, which allows for more fields beyond
41 41
 # this default set.
42
-BASE_ADDL_FIELDS = ['req_id', 'external_ctx', 'user']
42
+BASE_ADDL_FIELDS = ['req_id', 'external_ctx', 'user', 'user_id']
43 43
 LOG = logging.getLogger(__name__)
44 44
 
45 45
 

+ 1
- 0
src/bin/shipyard_airflow/shipyard_airflow/control/middleware/logging_mw.py View File

@@ -34,6 +34,7 @@ class LoggingMiddleware(object):
34 34
         request_logging.set_logvar('req_id', req.context.request_id)
35 35
         request_logging.set_logvar('external_ctx', req.context.external_marker)
36 36
         request_logging.set_logvar('user', req.context.user)
37
+        request_logging.set_logvar('user_id', req.context.user_id)
37 38
         if not req.url.endswith(HEALTH_URL):
38 39
             # Log requests other than the health check.
39 40
             LOG.info("Request %s %s", req.method, req.url)

+ 9
- 3
src/bin/shipyard_airflow/shipyard_airflow/control/service_clients.py View File

@@ -28,9 +28,13 @@ CONF = cfg.CONF
28 28
 #
29 29
 # Deckhand Client
30 30
 #
31
-def deckhand_client():
31
+def deckhand_client(addl_headers=None):
32 32
     """Retrieve a Deckhand client"""
33
-    return dh_client.Client(session=svc_endpoints.get_session(),
33
+    session = svc_endpoints.get_session()
34
+    if addl_headers:
35
+        session.additional_headers.update(addl_headers)
36
+
37
+    return dh_client.Client(session=session,
34 38
                             endpoint_type='internal')
35 39
 
36 40
 
@@ -41,7 +45,7 @@ def _auth_gen():
41 45
     return [('X-Auth-Token', svc_endpoints.get_token())]
42 46
 
43 47
 
44
-def drydock_client():
48
+def drydock_client(context_marker=None, end_user=None):
45 49
     """Retreive a Drydock client"""
46 50
     # Setup the drydock session
47 51
     endpoint = svc_endpoints.get_endpoint(Endpoints.DRYDOCK)
@@ -50,6 +54,8 @@ def drydock_client():
50 54
         dd_url.hostname,
51 55
         port=dd_url.port,
52 56
         auth_gen=_auth_gen,
57
+        marker=context_marker,
58
+        end_user=end_user,
53 59
         timeout=(CONF.requests_config.drydock_client_connect_timeout,
54 60
                  CONF.requests_config.drydock_client_read_timeout))
55 61
     return dd_client.DrydockClient(session)

+ 7
- 3
src/bin/shipyard_airflow/shipyard_airflow/plugins/armada_base_operator.py View File

@@ -85,11 +85,14 @@ class ArmadaBaseOperator(UcpBaseOperator):
85 85
         # Set up armada client
86 86
         self.armada_client = self._init_armada_client(
87 87
             self.endpoints.endpoint_by_name(service_endpoint.ARMADA),
88
-            self.svc_token
88
+            self.svc_token,
89
+            self.context_marker,
90
+            self.user
89 91
         )
90 92
 
91 93
     @staticmethod
92
-    def _init_armada_client(armada_svc_endpoint, svc_token):
94
+    def _init_armada_client(armada_svc_endpoint, svc_token,
95
+                            ext_marker, end_user):
93 96
 
94 97
         LOG.info("Armada endpoint is %s", armada_svc_endpoint)
95 98
 
@@ -103,7 +106,8 @@ class ArmadaBaseOperator(UcpBaseOperator):
103 106
                                           port=armada_url.port,
104 107
                                           scheme='http',
105 108
                                           token=svc_token,
106
-                                          marker=None)
109
+                                          marker=ext_marker,
110
+                                          end_user=end_user)
107 111
 
108 112
         # Raise Exception if we are not able to set up the session
109 113
         if a_session:

+ 13
- 1
src/bin/shipyard_airflow/shipyard_airflow/plugins/deckhand_base_operator.py View File

@@ -28,6 +28,7 @@ except ImportError:
28 28
     from shipyard_airflow.plugins import service_endpoint
29 29
     from shipyard_airflow.plugins.service_token import shipyard_service_token
30 30
     from shipyard_airflow.plugins.ucp_base_operator import UcpBaseOperator
31
+from shipyard_airflow.shipyard_const import CustomHeaders
31 32
 
32 33
 LOG = logging.getLogger(__name__)
33 34
 
@@ -95,11 +96,22 @@ class DeckhandBaseOperator(UcpBaseOperator):
95 96
         LOG.info("Executing Shipyard Action %s",
96 97
                  self.action_id)
97 98
 
99
+        # Create additional headers dict to pass context marker
100
+        # and end user
101
+        addl_headers = {
102
+            CustomHeaders.CONTEXT_MARKER.value: self.context_marker,
103
+            CustomHeaders.END_USER.value: self.user
104
+        }
105
+
98 106
         # Retrieve Endpoint Information
99 107
         self.deckhand_svc_endpoint = self.endpoints.endpoint_by_name(
100
-            service_endpoint.DECKHAND
108
+            service_endpoint.DECKHAND,
109
+            addl_headers=addl_headers
101 110
         )
102 111
 
112
+        # update additional headers
113
+        self.svc_session.additional_headers.update(addl_headers)
114
+
103 115
         LOG.info("Deckhand endpoint is %s",
104 116
                  self.deckhand_svc_endpoint)
105 117
 

+ 3
- 2
src/bin/shipyard_airflow/shipyard_airflow/plugins/deckhand_client_factory.py View File

@@ -36,7 +36,7 @@ class DeckhandClientFactory(object):
36 36
         self.config = configparser.ConfigParser()
37 37
         self.config.read(shipyard_conf)
38 38
 
39
-    def get_client(self):
39
+    def get_client(self, addl_headers=None):
40 40
         """Retrieve a deckhand client"""
41 41
 
42 42
         """
@@ -57,7 +57,8 @@ class DeckhandClientFactory(object):
57 57
 
58 58
         # Set up keystone session
59 59
         auth = keystone_v3.Password(**keystone_auth)
60
-        sess = keystone_session.Session(auth=auth)
60
+        sess = keystone_session.Session(auth=auth,
61
+                                        additional_headers=addl_headers)
61 62
 
62 63
         LOG.info("Setting up Deckhand client with parameters")
63 64
         for attr in keystone_auth:

+ 22
- 6
src/bin/shipyard_airflow/shipyard_airflow/plugins/deployment_configuration_operator.py View File

@@ -25,10 +25,13 @@ from airflow.utils.decorators import apply_defaults
25 25
 
26 26
 try:
27 27
     from deckhand_client_factory import DeckhandClientFactory
28
+    from xcom_puller import XcomPuller
28 29
 except ImportError:
29 30
     from shipyard_airflow.plugins.deckhand_client_factory import (
30 31
         DeckhandClientFactory
31 32
     )
33
+    from shipyard_airflow.plugins.xcom_puller import XcomPuller
34
+from shipyard_airflow.shipyard_const import CustomHeaders
32 35
 
33 36
 LOG = logging.getLogger(__name__)
34 37
 
@@ -90,6 +93,7 @@ class DeploymentConfigurationOperator(BaseOperator):
90 93
         super(DeploymentConfigurationOperator, self).__init__(*args, **kwargs)
91 94
         self.main_dag_name = main_dag_name
92 95
         self.shipyard_conf = shipyard_conf
96
+        self.action_info = {}
93 97
 
94 98
     def execute(self, context):
95 99
         """Perform Deployment Configuration extraction"""
@@ -104,13 +108,12 @@ class DeploymentConfigurationOperator(BaseOperator):
104 108
         """Get the revision id from xcom"""
105 109
         if task_instance:
106 110
             LOG.debug("task_instance found, extracting design version")
111
+            # Get XcomPuller instance
112
+            self.xcom_puller = XcomPuller(self.main_dag_name, task_instance)
107 113
             # Set the revision_id to the revision on the xcom
108
-            action_info = task_instance.xcom_pull(
109
-                task_ids='action_xcom',
110
-                dag_id=self.main_dag_name,
111
-                key='action')
114
+            self.action_info = self.xcom_puller.get_action_info()
112 115
 
113
-            revision_id = action_info['committed_rev_id']
116
+            revision_id = self.action_info['committed_rev_id']
114 117
 
115 118
             if revision_id:
116 119
                 LOG.info("Revision is set to: %s for deployment configuration",
@@ -132,8 +135,21 @@ class DeploymentConfigurationOperator(BaseOperator):
132 135
             "schema": "shipyard/DeploymentConfiguration/v1",
133 136
             "metadata.name": "deployment-configuration"
134 137
         }
138
+
139
+        # Create additional headers dict to pass context marker
140
+        # and end user
141
+        addl_headers = None
142
+        if self.action_info:
143
+            context_marker = self.action_info['context_marker']
144
+            end_user = self.action_info['user']
145
+            addl_headers = {
146
+                CustomHeaders.CONTEXT_MARKER.value: context_marker,
147
+                CustomHeaders.END_USER.value: end_user
148
+            }
149
+
135 150
         try:
136
-            dhclient = DeckhandClientFactory(self.shipyard_conf).get_client()
151
+            dhclient = DeckhandClientFactory(
152
+                self.shipyard_conf).get_client(addl_headers=addl_headers)
137 153
             LOG.info("Deckhand Client acquired")
138 154
             doc = dhclient.revisions.documents(revision_id,
139 155
                                                rendered=True,

+ 2
- 0
src/bin/shipyard_airflow/shipyard_airflow/plugins/drydock_base_operator.py View File

@@ -153,6 +153,8 @@ class DrydockBaseOperator(UcpBaseOperator):
153 153
             drydock_url.hostname,
154 154
             port=drydock_url.port,
155 155
             auth_gen=self._auth_gen,
156
+            marker=self.context_marker,
157
+            end_user=self.user,
156 158
             timeout=(self.drydock_client_connect_timeout,
157 159
                      self.drydock_client_read_timeout))
158 160
 

+ 4
- 1
src/bin/shipyard_airflow/shipyard_airflow/plugins/drydock_validate_design.py View File

@@ -24,6 +24,7 @@ try:
24 24
 except ImportError:
25 25
     from shipyard_airflow.plugins.drydock_base_operator import \
26 26
         DrydockBaseOperator
27
+from shipyard_airflow.shipyard_const import CustomHeaders
27 28
 
28 29
 LOG = logging.getLogger(__name__)
29 30
 
@@ -48,7 +49,9 @@ class DrydockValidateDesignOperator(DrydockBaseOperator):
48 49
         # Define Headers and Payload
49 50
         headers = {
50 51
             'Content-Type': 'application/json',
51
-            'X-Auth-Token': self.svc_token
52
+            'X-Auth-Token': self.svc_token,
53
+            CustomHeaders.CONTEXT_MARKER.value: self.context_marker,
54
+            CustomHeaders.END_USER.value: self.user
52 55
         }
53 56
 
54 57
         payload = {

+ 10
- 1
src/bin/shipyard_airflow/shipyard_airflow/plugins/promenade_base_operator.py View File

@@ -24,6 +24,7 @@ except ImportError:
24 24
     from shipyard_airflow.plugins import service_endpoint
25 25
     from shipyard_airflow.plugins.service_token import shipyard_service_token
26 26
     from shipyard_airflow.plugins.ucp_base_operator import UcpBaseOperator
27
+from shipyard_airflow.shipyard_const import CustomHeaders
27 28
 
28 29
 LOG = logging.getLogger(__name__)
29 30
 
@@ -64,9 +65,17 @@ class PromenadeBaseOperator(UcpBaseOperator):
64 65
         # Logs uuid of Shipyard action
65 66
         LOG.info("Executing Shipyard Action %s", self.action_id)
66 67
 
68
+        # Create additional headers dict to pass context marker
69
+        # and end user
70
+        addl_headers = {
71
+            CustomHeaders.CONTEXT_MARKER.value: self.context_marker,
72
+            CustomHeaders.END_USER.value: self.user
73
+        }
74
+
67 75
         # Retrieve promenade endpoint
68 76
         self.promenade_svc_endpoint = self.endpoints.endpoint_by_name(
69
-            service_endpoint.PROMENADE
77
+            service_endpoint.PROMENADE,
78
+            addl_headers=addl_headers
70 79
         )
71 80
 
72 81
         LOG.info("Promenade endpoint is %s", self.promenade_svc_endpoint)

+ 4
- 1
src/bin/shipyard_airflow/shipyard_airflow/plugins/promenade_validate_site_design.py View File

@@ -24,6 +24,7 @@ try:
24 24
 except ImportError:
25 25
     from shipyard_airflow.plugins.promenade_base_operator import \
26 26
         PromenadeBaseOperator
27
+from shipyard_airflow.shipyard_const import CustomHeaders
27 28
 
28 29
 LOG = logging.getLogger(__name__)
29 30
 
@@ -48,7 +49,9 @@ class PromenadeValidateSiteDesignOperator(PromenadeBaseOperator):
48 49
         # Define Headers and Payload
49 50
         headers = {
50 51
             'Content-Type': 'application/json',
51
-            'X-Auth-Token': self.svc_token
52
+            'X-Auth-Token': self.svc_token,
53
+            CustomHeaders.CONTEXT_MARKER.value: self.context_marker,
54
+            CustomHeaders.END_USER.value: self.user
52 55
         }
53 56
 
54 57
         payload = {

+ 10
- 4
src/bin/shipyard_airflow/shipyard_airflow/plugins/service_endpoint.py View File

@@ -32,14 +32,15 @@ PROMENADE = 'promenade'
32 32
 LOG = logging.getLogger(__name__)
33 33
 
34 34
 
35
-def _ucp_service_endpoint(shipyard_conf, svc_type):
35
+def _ucp_service_endpoint(shipyard_conf, svc_type, addl_headers=None):
36 36
 
37 37
     # Initialize variables
38 38
     retry = 0
39 39
     int_endpoint = None
40 40
 
41 41
     # Retrieve Keystone Session
42
-    sess = ucp_keystone_session(shipyard_conf)
42
+    sess = ucp_keystone_session(shipyard_conf,
43
+                                additional_headers=addl_headers)
43 44
 
44 45
     # We will allow 1 retry in getting the Keystone Endpoint with a
45 46
     # backoff interval of 10 seconds in case there is a temporary
@@ -78,7 +79,7 @@ class ServiceEndpoints():
78 79
         self.config = configparser.ConfigParser()
79 80
         self.config.read(self.shipyard_conf)
80 81
 
81
-    def endpoint_by_name(self, svc_name):
82
+    def endpoint_by_name(self, svc_name, addl_headers=None):
82 83
         """Return the service endpoint for the named service.
83 84
 
84 85
         :param svc_name: name of the service from which the service type will
@@ -86,7 +87,12 @@ class ServiceEndpoints():
86 87
             module provide names that can be used with an expectation that they
87 88
             work with a standard/complete configuration file.
88 89
             E.g.: service_endpoint.DRYDOCK
90
+        :param dict addl_headers: Additional headers that should be attached
91
+            to every request passing through the session.
92
+            Headers of the same name specified per request will take priority.
89 93
         """
90 94
         LOG.info("Looking up service endpoint for: %s", svc_name)
91 95
         svc_type = self.config.get(svc_name, 'service_type')
92
-        return _ucp_service_endpoint(self.shipyard_conf, svc_type)
96
+        return _ucp_service_endpoint(self.shipyard_conf,
97
+                                     svc_type,
98
+                                     addl_headers=addl_headers)

+ 3
- 2
src/bin/shipyard_airflow/shipyard_airflow/plugins/service_session.py View File

@@ -22,7 +22,7 @@ from keystoneauth1.identity import v3 as keystone_v3
22 22
 from keystoneauth1 import session as keystone_session
23 23
 
24 24
 
25
-def ucp_keystone_session(shipyard_conf):
25
+def ucp_keystone_session(shipyard_conf, additional_headers=None):
26 26
 
27 27
     # Read and parse shiyard.conf
28 28
     config = configparser.ConfigParser()
@@ -46,7 +46,8 @@ def ucp_keystone_session(shipyard_conf):
46 46
         # Set up keystone session
47 47
         logging.info("Get Keystone Session")
48 48
         auth = keystone_v3.Password(**keystone_auth)
49
-        sess = keystone_session.Session(auth=auth)
49
+        sess = keystone_session.Session(auth=auth,
50
+                                        additional_headers=additional_headers)
50 51
 
51 52
         # Retry if we fail to get keystone session
52 53
         if sess:

+ 2
- 0
src/bin/shipyard_airflow/shipyard_airflow/plugins/ucp_base_operator.py View File

@@ -160,6 +160,8 @@ class UcpBaseOperator(BaseOperator):
160 160
         self.task_id = self.task_instance.task_id
161 161
         self.revision_id = self.action_info['committed_rev_id']
162 162
         self.action_params = self.action_info.get('parameters', {})
163
+        self.context_marker = self.action_info['context_marker']
164
+        self.user = self.action_info['user']
163 165
         self.design_ref = self._deckhand_design_ref()
164 166
         self._setup_target_nodes()
165 167
 

+ 28
- 0
src/bin/shipyard_airflow/shipyard_airflow/shipyard_const.py View File

@@ -0,0 +1,28 @@
1
+# Copyright 2019 AT&T Intellectual Property.  All other rights reserved.
2
+#
3
+# Licensed under the Apache License, Version 2.0 (the "License");
4
+# you may not use this file except in compliance with the License.
5
+# You may obtain a copy of the License at
6
+#
7
+#     http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS,
11
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+# See the License for the specific language governing permissions and
13
+# limitations under the License.
14
+"""Constants definition module for Shipyard.
15
+
16
+"""
17
+import enum
18
+
19
+
20
+class CustomHeaders(enum.Enum):
21
+    """
22
+    Enumerations of Custom HTTP Headers key.
23
+    """
24
+    END_USER = 'X-End-User'
25
+    CONTEXT_MARKER = 'X-Context-Marker'
26
+
27
+# TODO: Other constants that are used across modules in Shipyard
28
+# to be defined here for better maintainability

Loading…
Cancel
Save